Skip to content

Commit e202aeb

Browse files
committed
Update SA1200 for file-scoped namespaces
1 parent cc2cce6 commit e202aeb

7 files changed

Lines changed: 106 additions & 9 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/OrderingRules/UsingCodeFixProvider.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,12 @@ private static string DetermineIndentation(CompilationUnitSyntax compilationUnit
137137
{
138138
var rootNamespace = compilationUnit.Members.First(member => BaseNamespaceDeclarationSyntaxWrapper.IsInstance(member));
139139
var indentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, rootNamespace);
140-
usingsIndentation = IndentationHelper.GenerateIndentationString(indentationSettings, indentationLevel + 1);
140+
if (!rootNamespace.IsKind(SyntaxKindEx.FileScopedNamespaceDeclaration))
141+
{
142+
indentationLevel++;
143+
}
144+
145+
usingsIndentation = IndentationHelper.GenerateIndentationString(indentationSettings, indentationLevel);
141146
}
142147
else
143148
{

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp10/OrderingRules/SA1200CSharp10OutsideNamespaceUnitTests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,36 @@
33

44
namespace StyleCop.Analyzers.Test.CSharp10.OrderingRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Testing;
9+
using StyleCop.Analyzers.OrderingRules;
610
using StyleCop.Analyzers.Test.CSharp9.OrderingRules;
11+
using Xunit;
712

813
public class SA1200CSharp10OutsideNamespaceUnitTests : SA1200CSharp9OutsideNamespaceUnitTests
914
{
15+
[Fact]
16+
public async Task TestInvalidUsingStatementsInFileScopedNamespaceAsync()
17+
{
18+
var testCode = @"namespace TestNamespace;
19+
20+
{|#0:using System;|}
21+
{|#1:using System.Threading;|}
22+
";
23+
var fixedTestCode = @"using System;
24+
using System.Threading;
25+
26+
namespace TestNamespace;
27+
";
28+
29+
DiagnosticResult[] expectedResults =
30+
{
31+
Diagnostic(SA1200UsingDirectivesMustBePlacedCorrectly.DescriptorOutside).WithLocation(0),
32+
Diagnostic(SA1200UsingDirectivesMustBePlacedCorrectly.DescriptorOutside).WithLocation(1),
33+
};
34+
35+
await VerifyCSharpFixAsync(testCode, expectedResults, fixedTestCode, CancellationToken.None).ConfigureAwait(false);
36+
}
1037
}
1138
}

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp10/OrderingRules/SA1200CSharp10PreserveUnitTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,41 @@
33

44
namespace StyleCop.Analyzers.Test.CSharp10.OrderingRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Testing;
69
using StyleCop.Analyzers.Test.CSharp9.OrderingRules;
10+
using Xunit;
711

812
public class SA1200CSharp10PreserveUnitTests : SA1200CSharp9PreserveUnitTests
913
{
14+
[Fact]
15+
public async Task TestValidUsingStatementsInFileScopedNamespaceAsync()
16+
{
17+
var testCode = @"namespace TestNamespace;
18+
19+
using System;
20+
using System.Threading;
21+
";
22+
23+
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
24+
}
25+
26+
/// <summary>
27+
/// Verifies that having using statements in the compilation unit will not diagnostics, even if they could be
28+
/// moved inside a file-scoped namespace.
29+
/// </summary>
30+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
31+
[Fact]
32+
public async Task TestIgnoredUsingStatementsInCompilationUnitWithFileScopedNamespaceAsync()
33+
{
34+
var testCode = @"using System;
35+
using System.Threading;
36+
37+
namespace TestNamespace;
38+
";
39+
40+
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
41+
}
1042
}
1143
}

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp10/OrderingRules/SA1200CSharp10UnitTests.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,39 @@
33

44
namespace StyleCop.Analyzers.Test.CSharp10.OrderingRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Testing;
9+
using StyleCop.Analyzers.OrderingRules;
610
using StyleCop.Analyzers.Test.CSharp9.OrderingRules;
11+
using Xunit;
12+
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
13+
StyleCop.Analyzers.OrderingRules.SA1200UsingDirectivesMustBePlacedCorrectly,
14+
StyleCop.Analyzers.OrderingRules.UsingCodeFixProvider>;
715

816
public class SA1200CSharp10UnitTests : SA1200CSharp9UnitTests
917
{
18+
[Fact]
19+
public async Task TestInvalidUsingStatementsInCompilationUnitWithFileScopedNamespaceAsync()
20+
{
21+
var testCode = @"{|#0:using System;|}
22+
{|#1:using System.Threading;|}
23+
24+
namespace TestNamespace;
25+
";
26+
27+
var fixedTestCode = @"namespace TestNamespace;
28+
using System;
29+
using System.Threading;
30+
";
31+
32+
DiagnosticResult[] expectedResults =
33+
{
34+
Diagnostic(SA1200UsingDirectivesMustBePlacedCorrectly.DescriptorInside).WithLocation(0),
35+
Diagnostic(SA1200UsingDirectivesMustBePlacedCorrectly.DescriptorInside).WithLocation(1),
36+
};
37+
38+
await VerifyCSharpFixAsync(testCode, expectedResults, fixedTestCode, CancellationToken.None).ConfigureAwait(false);
39+
}
1040
}
1141
}

StyleCop.Analyzers/StyleCop.Analyzers.Test/OrderingRules/SA1200OutsideNamespaceUnitTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -347,10 +347,10 @@ private void Test()
347347
await VerifyCSharpFixAsync(testCode, expectedResults, fixedTestCode, CancellationToken.None).ConfigureAwait(false);
348348
}
349349

350-
private static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor)
350+
protected static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor)
351351
=> StyleCopCodeFixVerifier<SA1200UsingDirectivesMustBePlacedCorrectly, UsingCodeFixProvider>.Diagnostic(descriptor);
352352

353-
private static Task VerifyCSharpDiagnosticAsync(string source, DiagnosticResult[] expected, CancellationToken cancellationToken)
353+
protected static Task VerifyCSharpDiagnosticAsync(string source, DiagnosticResult[] expected, CancellationToken cancellationToken)
354354
{
355355
var test = new StyleCopCodeFixVerifier<SA1200UsingDirectivesMustBePlacedCorrectly, UsingCodeFixProvider>.CSharpTest
356356
{
@@ -362,7 +362,7 @@ private static Task VerifyCSharpDiagnosticAsync(string source, DiagnosticResult[
362362
return test.RunAsync(cancellationToken);
363363
}
364364

365-
private static Task VerifyCSharpFixAsync(string source, DiagnosticResult[] expected, string fixedSource, CancellationToken cancellationToken)
365+
protected static Task VerifyCSharpFixAsync(string source, DiagnosticResult[] expected, string fixedSource, CancellationToken cancellationToken)
366366
{
367367
var test = new StyleCopCodeFixVerifier<SA1200UsingDirectivesMustBePlacedCorrectly, UsingCodeFixProvider>.CSharpTest
368368
{

StyleCop.Analyzers/StyleCop.Analyzers.Test/OrderingRules/SA1200PreserveUnitTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ namespace TestNamespace
124124
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
125125
}
126126

127-
private static Task VerifyCSharpDiagnosticAsync(string source, DiagnosticResult[] expected, CancellationToken cancellationToken)
127+
protected static Task VerifyCSharpDiagnosticAsync(string source, DiagnosticResult[] expected, CancellationToken cancellationToken)
128128
{
129129
var test = new StyleCopCodeFixVerifier<SA1200UsingDirectivesMustBePlacedCorrectly, UsingCodeFixProvider>.CSharpTest
130130
{

StyleCop.Analyzers/StyleCop.Analyzers/OrderingRules/SA1200UsingDirectivesMustBePlacedCorrectly.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ namespace StyleCop.Analyzers.OrderingRules
1010
using Microsoft.CodeAnalysis.CSharp;
1111
using Microsoft.CodeAnalysis.CSharp.Syntax;
1212
using Microsoft.CodeAnalysis.Diagnostics;
13+
using StyleCop.Analyzers.Helpers;
14+
using StyleCop.Analyzers.Lightup;
1315
using StyleCop.Analyzers.Settings.ObjectModel;
1416

1517
/// <summary>
@@ -176,7 +178,7 @@ internal class SA1200UsingDirectivesMustBePlacedCorrectly : DiagnosticAnalyzer
176178
#pragma warning restore SA1202 // Elements should be ordered by access
177179

178180
private static readonly Action<SyntaxNodeAnalysisContext, StyleCopSettings> CompilationUnitAction = HandleCompilationUnit;
179-
private static readonly Action<SyntaxNodeAnalysisContext, StyleCopSettings> NamespaceDeclarationAction = HandleNamespaceDeclaration;
181+
private static readonly Action<SyntaxNodeAnalysisContext, StyleCopSettings> BaseNamespaceDeclarationAction = HandleBaseNamespaceDeclaration;
180182

181183
/// <inheritdoc/>
182184
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } =
@@ -189,7 +191,7 @@ public override void Initialize(AnalysisContext context)
189191
context.EnableConcurrentExecution();
190192

191193
context.RegisterSyntaxNodeAction(CompilationUnitAction, SyntaxKind.CompilationUnit);
192-
context.RegisterSyntaxNodeAction(NamespaceDeclarationAction, SyntaxKind.NamespaceDeclaration);
194+
context.RegisterSyntaxNodeAction(BaseNamespaceDeclarationAction, SyntaxKinds.BaseNamespaceDeclaration);
193195
}
194196

195197
/// <summary>
@@ -235,6 +237,7 @@ private static void HandleCompilationUnit(SyntaxNodeAnalysisContext context, Sty
235237

236238
case SyntaxKind.ExternAliasDirective:
237239
case SyntaxKind.NamespaceDeclaration:
240+
case SyntaxKindEx.FileScopedNamespaceDeclaration:
238241
default:
239242
continue;
240243
}
@@ -254,14 +257,14 @@ private static void HandleCompilationUnit(SyntaxNodeAnalysisContext context, Sty
254257
/// </summary>
255258
/// <param name="context">The analysis context.</param>
256259
/// <param name="settings">The effective StyleCop analysis settings.</param>
257-
private static void HandleNamespaceDeclaration(SyntaxNodeAnalysisContext context, StyleCopSettings settings)
260+
private static void HandleBaseNamespaceDeclaration(SyntaxNodeAnalysisContext context, StyleCopSettings settings)
258261
{
259262
if (settings.OrderingRules.UsingDirectivesPlacement != UsingDirectivesPlacement.OutsideNamespace)
260263
{
261264
return;
262265
}
263266

264-
NamespaceDeclarationSyntax syntax = (NamespaceDeclarationSyntax)context.Node;
267+
BaseNamespaceDeclarationSyntaxWrapper syntax = (BaseNamespaceDeclarationSyntaxWrapper)context.Node;
265268
foreach (UsingDirectiveSyntax directive in syntax.Usings)
266269
{
267270
// Using directive should appear outside a namespace declaration

0 commit comments

Comments
 (0)