Skip to content

Commit 0812e2b

Browse files
committed
Merge pull request #1895 from sharwell/fix-1818
Fix bugs in handling of System using directives
2 parents 90708ec + 6667f2b commit 0812e2b

5 files changed

Lines changed: 52 additions & 5 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.Test/OrderingRules/SA1208UnitTests.cs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,20 @@ class A
4444
await this.VerifyCSharpDiagnosticAsync(usingsInNamespaceDeclaration, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
4545
}
4646

47+
[Fact]
48+
public async Task TestSystemUsingDirectivesWithEscapeSequenceAsync()
49+
{
50+
string usingsInNamespaceDeclaration = @"namespace Test
51+
{
52+
using @System;
53+
using System.Diagnostics;
54+
using \u0053ystem.IO;
55+
using System.Threading;
56+
}";
57+
58+
await this.VerifyCSharpDiagnosticAsync(usingsInNamespaceDeclaration, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
59+
}
60+
4761
[Fact]
4862
public async Task TestWhenSystemUsingDirectivesAreNotOnTopInCompilationAsync()
4963
{
@@ -160,9 +174,7 @@ class A
160174

161175
DiagnosticResult[] expected =
162176
{
163-
this.CSharpDiagnostic().WithLocation("Test3.cs", 2, 1).WithArguments("global::System.IO", "global::AnotherNamespace"),
164177
this.CSharpDiagnostic().WithLocation("Test3.cs", 8, 5).WithArguments("System.Threading", "Xyz"),
165-
this.CSharpDiagnostic().WithLocation("Test3.cs", 9, 5).WithArguments("global::System", "Xyz")
166178
};
167179

168180
await this.VerifyCSharpDiagnosticAsync(sources, expected, CancellationToken.None).ConfigureAwait(false);
@@ -336,6 +348,31 @@ public async Task TestPreprocessorDirectivesAsync()
336348
await this.VerifyCSharpFixAsync(testCode, fixedTestCode).ConfigureAwait(false);
337349
}
338350

351+
/// <summary>
352+
/// This is a regression test for DotNetAnalyzers/StyleCopAnalyzers#1818.
353+
/// </summary>
354+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
355+
[Fact]
356+
public async Task TestValidUsingDirectivesWithGlobalAliasAsync()
357+
{
358+
var testCode = @"
359+
namespace Foo
360+
{
361+
extern alias corlib;
362+
using System;
363+
using System.Threading;
364+
using corlib::System;
365+
using Foo;
366+
using global::Foo;
367+
using global::System;
368+
using global::System.IO;
369+
using global::System.Linq;
370+
using Microsoft;
371+
}";
372+
373+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
374+
}
375+
339376
/// <inheritdoc/>
340377
protected override IEnumerable<DiagnosticAnalyzer> GetCSharpDiagnosticAnalyzers()
341378
{

StyleCop.Analyzers/StyleCop.Analyzers.Test/OrderingRules/SA1210UnitTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ public async Task TestInvalidOrderedUsingDirectivesWithNamespaceAliasQualifierAs
182182
using global::System;
183183
using global::Foo;
184184
using Foo;
185+
using Microsoft;
185186
186187
namespace Foo
187188
{
@@ -200,6 +201,7 @@ namespace Foo
200201
using global::System;
201202
using global::System.IO;
202203
using global::System.Linq;
204+
using Microsoft;
203205
}";
204206

205207
DiagnosticResult[] expected =

StyleCop.Analyzers/StyleCop.Analyzers/Helpers/UsingDirectiveSyntaxHelpers.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ internal static class UsingDirectiveSyntaxHelpers
2121
/// </summary>
2222
/// <param name="usingDirective">The <see cref="UsingDirectiveSyntax"/> that will be checked.</param>
2323
/// <returns>Return true if the <see cref="UsingDirectiveSyntax"/>is system using directive, otherwise false.</returns>
24-
internal static bool IsSystemUsingDirective(this UsingDirectiveSyntax usingDirective) => string.Equals(SystemUsingDirectiveIdentifier, GetFirstIdentifierInUsingDirective(usingDirective)?.Text, StringComparison.Ordinal);
24+
internal static bool IsSystemUsingDirective(this UsingDirectiveSyntax usingDirective) => string.Equals(SystemUsingDirectiveIdentifier, GetFirstIdentifierInUsingDirective(usingDirective)?.ValueText, StringComparison.Ordinal);
2525

2626
/// <summary>
2727
/// Check if <see cref="UsingDirectiveSyntax"/> is preceded by a preprocessor directive.

StyleCop.Analyzers/StyleCop.Analyzers/OrderingRules/SA1208SystemUsingDirectivesMustBePlacedBeforeOtherUsingDirectives.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ private static void ProcessUsingsAndReportDiagnostic(SyntaxList<UsingDirectiveSy
9898
continue;
9999
}
100100

101-
if (usingDirective.IsSystemUsingDirective())
101+
if (usingDirective.IsSystemUsingDirective() && !usingDirective.HasNamespaceAliasQualifier())
102102
{
103103
if (systemUsingDirectivesShouldBeBeforeThisName != null)
104104
{
@@ -108,7 +108,9 @@ private static void ProcessUsingsAndReportDiagnostic(SyntaxList<UsingDirectiveSy
108108

109109
var previousUsing = usings[i - 1];
110110

111-
if (!previousUsing.IsSystemUsingDirective() || previousUsing.StaticKeyword.Kind() != SyntaxKind.None)
111+
if (!previousUsing.IsSystemUsingDirective()
112+
|| previousUsing.HasNamespaceAliasQualifier()
113+
|| previousUsing.StaticKeyword.Kind() != SyntaxKind.None)
112114
{
113115
systemUsingDirectivesShouldBeBeforeThisName = previousUsing.Name.ToNormalizedString();
114116
context.ReportDiagnostic(Diagnostic.Create(Descriptor, usingDirective.GetLocation(), usingDirective.Name.ToNormalizedString(), systemUsingDirectivesShouldBeBeforeThisName));

documentation/KnownChanges.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,12 @@ var a = new[] { 1, 2, 3 }.ToArray();
151151

152152
## Ordering Rules
153153

154+
### SA1208
155+
156+
StyleCop Analyzers only considers using directives to be "System" using directives if they are not alias-qualified,
157+
while StyleCop Classic ignored the alias. For example, `using global::System;` would be not be considered a System using
158+
directive by StyleCop Analyzers, but it would be considered a System using directive by StyleCop Classic.
159+
154160
### SA1214
155161

156162
StyleCop Classic only reports SA1214 for violations involving static fields. In StyleCop Analyzers, SA1214 and SA1215

0 commit comments

Comments
 (0)