Skip to content

Commit f0cc162

Browse files
authored
Merge pull request #3438 from ylabade/yla/fix/SA1208-file-scoped-namespace
Add file-scoped namespace support to SA1208
2 parents b1dc37a + e477fbd commit f0cc162

File tree

5 files changed

+78
-10
lines changed

5 files changed

+78
-10
lines changed

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace StyleCop.Analyzers.OrderingRules
1010
using Microsoft.CodeAnalysis;
1111
using Microsoft.CodeAnalysis.CSharp;
1212
using Microsoft.CodeAnalysis.CSharp.Syntax;
13+
using StyleCop.Analyzers.Lightup;
1314

1415
/// <summary>
1516
/// Implements a code fix for all misaligned using statements.
@@ -123,12 +124,12 @@ internal TreeTextSpan GetContainingSpan(SyntaxNode node)
123124

124125
private static void ProcessNodeMembers(TreeTextSpan.Builder builder, SyntaxList<MemberDeclarationSyntax> members)
125126
{
126-
foreach (var namespaceDeclaration in members.OfType<NamespaceDeclarationSyntax>())
127+
foreach (var namespaceDeclaration in members.Where(member => BaseNamespaceDeclarationSyntaxWrapper.IsInstance(member)))
127128
{
128129
var childBuilder = builder.AddChild(namespaceDeclaration.FullSpan.Start);
129130
childBuilder.SetEnd(namespaceDeclaration.FullSpan.End);
130131

131-
ProcessNodeMembers(childBuilder, namespaceDeclaration.Members);
132+
ProcessNodeMembers(childBuilder, ((BaseNamespaceDeclarationSyntaxWrapper)namespaceDeclaration).Members);
132133
}
133134
}
134135

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -467,10 +467,10 @@ private bool StartsWithSystemUsingDirectiveIdentifier(NameSyntax name)
467467

468468
private void ProcessMembers(SyntaxList<MemberDeclarationSyntax> members)
469469
{
470-
foreach (var namespaceDeclaration in members.OfType<NamespaceDeclarationSyntax>())
470+
foreach (var namespaceDeclaration in members.Where(member => BaseNamespaceDeclarationSyntaxWrapper.IsInstance(member)))
471471
{
472-
this.ProcessUsingDirectives(namespaceDeclaration.Usings);
473-
this.ProcessMembers(namespaceDeclaration.Members);
472+
this.ProcessUsingDirectives(((BaseNamespaceDeclarationSyntaxWrapper)namespaceDeclaration).Usings);
473+
this.ProcessMembers(((BaseNamespaceDeclarationSyntaxWrapper)namespaceDeclaration).Members);
474474
}
475475
}
476476

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ namespace StyleCop.Analyzers.OrderingRules
1616
using Microsoft.CodeAnalysis.CSharp;
1717
using Microsoft.CodeAnalysis.CSharp.Syntax;
1818
using StyleCop.Analyzers.Helpers;
19+
using StyleCop.Analyzers.Lightup;
1920
using StyleCop.Analyzers.Settings.ObjectModel;
2021

2122
/// <summary>
@@ -134,7 +135,7 @@ private static string DetermineIndentation(CompilationUnitSyntax compilationUnit
134135

135136
if (usingDirectivesPlacement == UsingDirectivesPlacement.InsideNamespace)
136137
{
137-
var rootNamespace = compilationUnit.Members.OfType<NamespaceDeclarationSyntax>().First();
138+
var rootNamespace = compilationUnit.Members.First(member => BaseNamespaceDeclarationSyntaxWrapper.IsInstance(member));
138139
var indentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, rootNamespace);
139140
usingsIndentation = IndentationHelper.GenerateIndentationString(indentationSettings, indentationLevel + 1);
140141
}
@@ -185,9 +186,9 @@ private static int CountNamespaces(SyntaxList<MemberDeclarationSyntax> members)
185186
{
186187
var result = 0;
187188

188-
foreach (var namespaceDeclaration in members.OfType<NamespaceDeclarationSyntax>())
189+
foreach (var namespaceDeclaration in members.Where(member => BaseNamespaceDeclarationSyntaxWrapper.IsInstance(member)))
189190
{
190-
result += 1 + CountNamespaces(namespaceDeclaration.Members);
191+
result += 1 + CountNamespaces(((BaseNamespaceDeclarationSyntaxWrapper)namespaceDeclaration).Members);
191192
}
192193

193194
return result;
@@ -267,7 +268,7 @@ private static int CompareSpanStart(UsingDirectiveSyntax left, UsingDirectiveSyn
267268

268269
private static SyntaxNode AddUsingsToNamespace(SyntaxNode newSyntaxRoot, UsingsSorter usingsHelper, string usingsIndentation, bool hasConditionalDirectives)
269270
{
270-
var rootNamespace = ((CompilationUnitSyntax)newSyntaxRoot).Members.OfType<NamespaceDeclarationSyntax>().First();
271+
var rootNamespace = (BaseNamespaceDeclarationSyntaxWrapper)((CompilationUnitSyntax)newSyntaxRoot).Members.First(member => BaseNamespaceDeclarationSyntaxWrapper.IsInstance(member));
271272
var withTrailingBlankLine = hasConditionalDirectives || rootNamespace.Members.Any() || rootNamespace.Externs.Any();
272273

273274
var groupedUsings = usingsHelper.GenerateGroupedUsings(TreeTextSpan.Empty, usingsIndentation, withTrailingBlankLine, qualifyNames: false);

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

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

44
namespace StyleCop.Analyzers.Test.CSharp10.OrderingRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
68
using StyleCop.Analyzers.Test.CSharp9.OrderingRules;
9+
using Xunit;
10+
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
11+
StyleCop.Analyzers.OrderingRules.SA1208SystemUsingDirectivesMustBePlacedBeforeOtherUsingDirectives,
12+
StyleCop.Analyzers.OrderingRules.UsingCodeFixProvider>;
713

814
public class SA1208CSharp10UnitTests : SA1208CSharp9UnitTests
915
{
16+
[Fact]
17+
[WorkItem(3437, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3437")]
18+
public async Task TestWhenSystemUsingDirectivesAreNotOnTopInFileScopedNamespaceAsync()
19+
{
20+
await new CSharpTest
21+
{
22+
TestSources =
23+
{
24+
"namespace Xyz {}",
25+
"namespace AnotherNamespace {}",
26+
@"
27+
namespace Test;
28+
29+
using Xyz;
30+
{|#0:using System;|}
31+
{|#1:using System.IO;|}
32+
using AnotherNamespace;
33+
{|#2:using System.Threading.Tasks;|}
34+
35+
class A
36+
{
37+
}",
38+
},
39+
FixedSources =
40+
{
41+
"namespace Xyz {}",
42+
"namespace AnotherNamespace {}",
43+
@"
44+
namespace Test;
45+
using System;
46+
using System.IO;
47+
using System.Threading.Tasks;
48+
using AnotherNamespace;
49+
using Xyz;
50+
51+
class A
52+
{
53+
}",
54+
},
55+
ExpectedDiagnostics =
56+
{
57+
Diagnostic().WithLocation(0).WithArguments("System", "Xyz"),
58+
Diagnostic().WithLocation(1).WithArguments("System.IO", "Xyz"),
59+
Diagnostic().WithLocation(2).WithArguments("System.Threading.Tasks", "Xyz"),
60+
},
61+
}.RunAsync(CancellationToken.None).ConfigureAwait(false);
62+
}
1063
}
1164
}

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

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

1516
/// <summary>
@@ -40,6 +41,7 @@ internal class SA1208SystemUsingDirectivesMustBePlacedBeforeOtherUsingDirectives
4041

4142
private static readonly Action<SyntaxNodeAnalysisContext, StyleCopSettings> CompilationUnitAction = HandleCompilationUnit;
4243
private static readonly Action<SyntaxNodeAnalysisContext, StyleCopSettings> NamespaceDeclarationAction = HandleNamespaceDeclaration;
44+
private static readonly Action<SyntaxNodeAnalysisContext, StyleCopSettings> FileScopedNamespaceDeclarationAction = HandleFileScopedNamespaceDeclaration;
4345

4446
/// <inheritdoc/>
4547
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } =
@@ -53,6 +55,7 @@ public override void Initialize(AnalysisContext context)
5355

5456
context.RegisterSyntaxNodeAction(CompilationUnitAction, SyntaxKind.CompilationUnit);
5557
context.RegisterSyntaxNodeAction(NamespaceDeclarationAction, SyntaxKind.NamespaceDeclaration);
58+
context.RegisterSyntaxNodeAction(FileScopedNamespaceDeclarationAction, SyntaxKindEx.FileScopedNamespaceDeclaration);
5659
}
5760

5861
private static void HandleCompilationUnit(SyntaxNodeAnalysisContext context, StyleCopSettings settings)
@@ -77,9 +80,19 @@ private static void HandleNamespaceDeclaration(SyntaxNodeAnalysisContext context
7780
}
7881

7982
var namespaceDeclaration = (NamespaceDeclarationSyntax)context.Node;
80-
8183
var usings = namespaceDeclaration.Usings;
84+
ProcessUsingsAndReportDiagnostic(usings, context);
85+
}
86+
87+
private static void HandleFileScopedNamespaceDeclaration(SyntaxNodeAnalysisContext context, StyleCopSettings settings)
88+
{
89+
if (!settings.OrderingRules.SystemUsingDirectivesFirst)
90+
{
91+
return;
92+
}
8293

94+
var namespaceDeclaration = (FileScopedNamespaceDeclarationSyntaxWrapper)context.Node;
95+
var usings = namespaceDeclaration.Usings;
8396
ProcessUsingsAndReportDiagnostic(usings, context);
8497
}
8598

0 commit comments

Comments
 (0)