Skip to content

Commit 94afc4a

Browse files
0x084Evweijsters
authored andcommitted
changed reported message for SA1135
report SA1135 also for aliased namespaces and types fixed SA1135 was raised for global:: namespaces add more test for SA1135
1 parent 21c28d2 commit 94afc4a

4 files changed

Lines changed: 101 additions & 15 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1135UnitTests.cs

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ namespace StyleCop.Analyzers.Test.ReadabilityRules
77
using System.Threading;
88
using System.Threading.Tasks;
99
using Analyzers.ReadabilityRules;
10-
using Microsoft.CodeAnalysis;
1110
using Microsoft.CodeAnalysis.CodeFixes;
1211
using Microsoft.CodeAnalysis.Diagnostics;
1312
using TestHelper;
@@ -34,6 +33,8 @@ namespace System.Threading
3433
DiagnosticResult[] expected =
3534
{
3635
this.CSharpDiagnostic().WithLocation(4, 5),
36+
this.CSharpDiagnostic().WithLocation(4, 5),
37+
this.CSharpDiagnostic().WithLocation(5, 5),
3738
this.CSharpDiagnostic().WithLocation(5, 5)
3839
};
3940

@@ -42,6 +43,89 @@ namespace System.Threading
4243
await this.VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false);
4344
}
4445

46+
[Fact]
47+
public async Task TestUnqualifiedAliasedUsingsAsync()
48+
{
49+
const string testCode = @"
50+
namespace System.Threading
51+
{
52+
using NA = IO;
53+
using NB = Tasks;
54+
}";
55+
const string fixedCode = @"
56+
namespace System.Threading
57+
{
58+
using NA = System.IO;
59+
using NB = System.Threading.Tasks;
60+
}";
61+
62+
DiagnosticResult[] expected =
63+
{
64+
this.CSharpDiagnostic().WithLocation(4, 5),
65+
this.CSharpDiagnostic().WithLocation(4, 5),
66+
this.CSharpDiagnostic().WithLocation(5, 5),
67+
this.CSharpDiagnostic().WithLocation(5, 5)
68+
};
69+
70+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
71+
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
72+
await this.VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false);
73+
}
74+
75+
[Fact]
76+
public async Task TestUnqualifiedAliasedUsingTypesAsync()
77+
{
78+
const string testCode = @"
79+
namespace System.Threading
80+
{
81+
using TP = IO.Path;
82+
using TT = Tasks.Task;
83+
}";
84+
const string fixedCode = @"
85+
namespace System.Threading
86+
{
87+
using TP = System.IO.Path;
88+
using TT = System.Threading.Tasks.Task;
89+
}";
90+
91+
DiagnosticResult[] expected =
92+
{
93+
this.CSharpDiagnostic().WithLocation(4, 5),
94+
this.CSharpDiagnostic().WithLocation(4, 5),
95+
this.CSharpDiagnostic().WithLocation(5, 5),
96+
this.CSharpDiagnostic().WithLocation(5, 5)
97+
};
98+
99+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
100+
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
101+
await this.VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false);
102+
}
103+
104+
[Fact]
105+
public async Task TestGlobalUsingsAsync()
106+
{
107+
const string testCode = @"
108+
namespace System.Threading
109+
{
110+
using global::System.IO;
111+
using global::System.Threading.Tasks;
112+
}";
113+
114+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
115+
}
116+
117+
[Fact]
118+
public async Task TestStaticUsingsAsync()
119+
{
120+
const string testCode = @"
121+
namespace System.Threading
122+
{
123+
using static Console;
124+
}";
125+
126+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
127+
}
128+
45129
protected override CodeFixProvider GetCSharpCodeFixProvider()
46130
{
47131
return new SA1135CodeFixProvider();

StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.Designer.cs

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.resx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@
529529
<value>All using directives must be qualified.</value>
530530
</data>
531531
<data name="SA1135MessageFormat" xml:space="preserve">
532-
<value>The using directive '{0}' must be qualified to '{1}'</value>
532+
<value>Using directive for namespace '{0}' must be qualified</value>
533533
</data>
534534
<data name="SA1135Title" xml:space="preserve">
535535
<value>Using directives must be qualified</value>

StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1135UsingDirectivesMustBeQualified.cs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
namespace StyleCop.Analyzers.ReadabilityRules
55
{
6+
using System;
67
using System.Collections.Immutable;
78
using Microsoft.CodeAnalysis;
89
using Microsoft.CodeAnalysis.CSharp;
@@ -30,7 +31,7 @@ public class SA1135UsingDirectivesMustBeQualified : DiagnosticAnalyzer
3031
private static readonly string HelpLink = "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1135.md";
3132

3233
private static readonly DiagnosticDescriptor Descriptor =
33-
new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, AnalyzerCategory.OrderingRules, DiagnosticSeverity.Warning, AnalyzerConstants.EnabledByDefault, Description, HelpLink);
34+
new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, AnalyzerCategory.ReadabilityRules, DiagnosticSeverity.Warning, AnalyzerConstants.EnabledByDefault, Description, HelpLink);
3435

3536
private static readonly ImmutableArray<DiagnosticDescriptor> SupportedDiagnosticsValue =
3637
ImmutableArray.Create(Descriptor);
@@ -46,30 +47,31 @@ public override void Initialize(AnalysisContext context)
4647

4748
private static void HandleCompilationStart(CompilationStartAnalysisContext context)
4849
{
49-
context.RegisterSyntaxNodeActionHonorExclusions(HandleNamespaceDeclaration, SyntaxKind.NamespaceDeclaration);
50+
context.RegisterSyntaxNodeActionHonorExclusions(HandleUsingDeclaration, SyntaxKind.UsingDirective);
5051
}
5152

52-
private static void HandleNamespaceDeclaration(SyntaxNodeAnalysisContext context)
53+
private static void HandleUsingDeclaration(SyntaxNodeAnalysisContext context)
5354
{
54-
var namespaceDirective = (NamespaceDeclarationSyntax)context.Node;
55-
CheckUsingDeclarations(context, namespaceDirective.Usings);
55+
var usingDirective = (UsingDirectiveSyntax)context.Node;
56+
CheckUsingDeclaration(context, usingDirective);
5657
}
5758

58-
private static void CheckUsingDeclarations(SyntaxNodeAnalysisContext context, SyntaxList<UsingDirectiveSyntax> usingDirectives)
59+
private static void CheckUsingDeclaration(SyntaxNodeAnalysisContext context, UsingDirectiveSyntax usingDirective)
5960
{
60-
foreach (var usingDirective in usingDirectives)
61+
if (usingDirective.StaticKeyword.IsKind(SyntaxKind.None))
6162
{
62-
if (usingDirective.Alias == null && usingDirective.StaticKeyword.IsKind(SyntaxKind.None))
63+
string usingString = usingDirective.Name.ToString();
64+
65+
// Check for global qualified namepsaces.
66+
if (usingString.IndexOf("::", StringComparison.Ordinal) < 0)
6367
{
6468
SymbolInfo symbolInfo = context.SemanticModel.GetSymbolInfo(usingDirective.Name, context.CancellationToken);
65-
if (symbolInfo.Symbol != null && symbolInfo.Symbol.Kind == SymbolKind.Namespace)
69+
if (symbolInfo.Symbol != null && (symbolInfo.Symbol.Kind == SymbolKind.Namespace || symbolInfo.Symbol.Kind == SymbolKind.NamedType))
6670
{
6771
string symbolString = symbolInfo.Symbol.ToString();
68-
string usingString = usingDirective.Name.ToString();
69-
7072
if (symbolString != usingString)
7173
{
72-
context.ReportDiagnostic(Diagnostic.Create(Descriptor, usingDirective.GetLocation(), new[] { usingString, symbolString }));
74+
context.ReportDiagnostic(Diagnostic.Create(Descriptor, usingDirective.GetLocation(), symbolString));
7375
}
7476
}
7577
}

0 commit comments

Comments
 (0)