Skip to content

Commit cca960a

Browse files
committed
Add support for file scoped namespace to SA1516.
1 parent ed67842 commit cca960a

2 files changed

Lines changed: 145 additions & 0 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp10/LayoutRules/SA1516CSharp10UnitTests.cs

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

44
namespace StyleCop.Analyzers.Test.CSharp10.LayoutRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis;
9+
using Microsoft.CodeAnalysis.CSharp;
10+
using Microsoft.CodeAnalysis.Testing;
611
using StyleCop.Analyzers.Test.CSharp9.LayoutRules;
12+
using Xunit;
13+
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
14+
StyleCop.Analyzers.LayoutRules.SA1516ElementsMustBeSeparatedByBlankLine,
15+
StyleCop.Analyzers.LayoutRules.SA1516CodeFixProvider>;
716

817
public class SA1516CSharp10UnitTests : SA1516CSharp9UnitTests
918
{
19+
private const string CorrectCode = @"extern alias corlib;
20+
21+
using System;
22+
using System.Linq;
23+
using a = System.Collections.Generic;
24+
25+
namespace Foo;
26+
27+
public class Bar
28+
{
29+
public string Test1;
30+
public string Test2;
31+
public string Test3;
32+
33+
public string TestProperty1 { get; set; }
34+
35+
public string TestProperty2 { get; set; }
36+
/// <summary>
37+
/// A summary.
38+
/// </summary>
39+
public string TestProperty3 { get; set; }
40+
41+
public string TestProperty4
42+
{
43+
get
44+
{
45+
return Test1;
46+
}
47+
48+
set
49+
{
50+
Test1 = value;
51+
}
52+
}
53+
54+
public string FooValue, BarValue;
55+
56+
[Obsolete]
57+
public enum TestEnum
58+
{
59+
Value1,
60+
Value2
61+
}
62+
}
63+
64+
public enum Foobar
65+
{
66+
67+
}
68+
";
69+
70+
/// <summary>
71+
/// Verifies that SA1516 is not reported for code with correct blank lines.
72+
/// </summary>
73+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
74+
[Fact]
75+
[WorkItem(3512, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3512")]
76+
public async Task TestFileScopedNamespaceCorrectSpacingAsync()
77+
{
78+
await VerifyCSharpDiagnosticAsync(CorrectCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
79+
}
80+
81+
/// <summary>
82+
/// Verifies that SA1516 is reported for code with missing correct blank lines.
83+
/// </summary>
84+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
85+
[Fact]
86+
[WorkItem(3512, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3512")]
87+
public async Task TestFileScopedNamespaceWrongSpacingAsync()
88+
{
89+
var testCode = @"extern alias corlib;
90+
{|#0:using|} System;
91+
using System.Linq;
92+
using a = System.Collections.Generic;
93+
{|#1:namespace|} Foo;
94+
{|#2:public|} class Bar
95+
{
96+
}
97+
{|#3:public|} enum Foobar
98+
{
99+
}
100+
";
101+
102+
var fixedCode = @"extern alias corlib;
103+
104+
using System;
105+
using System.Linq;
106+
using a = System.Collections.Generic;
107+
108+
namespace Foo;
109+
110+
public class Bar
111+
{
112+
}
113+
114+
public enum Foobar
115+
{
116+
}
117+
";
118+
119+
var test = new CSharpTest(LanguageVersion.CSharp10)
120+
{
121+
ReferenceAssemblies = ReferenceAssemblies.Net.Net50,
122+
TestState =
123+
{
124+
OutputKind = OutputKind.DynamicallyLinkedLibrary,
125+
Sources = { testCode },
126+
},
127+
FixedCode = fixedCode,
128+
};
129+
var expectedDiagnostic = new[] {
130+
Diagnostic().WithLocation(0),
131+
Diagnostic().WithLocation(1),
132+
Diagnostic().WithLocation(2),
133+
Diagnostic().WithLocation(3),
134+
};
135+
test.TestState.ExpectedDiagnostics.AddRange(expectedDiagnostic);
136+
await test.RunAsync(CancellationToken.None).ConfigureAwait(false);
137+
}
10138
}
11139
}

StyleCop.Analyzers/StyleCop.Analyzers/LayoutRules/SA1516ElementsMustBeSeparatedByBlankLine.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ namespace StyleCop.Analyzers.LayoutRules
1515
using Microsoft.CodeAnalysis.Diagnostics;
1616
using Microsoft.CodeAnalysis.Text;
1717
using StyleCop.Analyzers.Helpers;
18+
using StyleCop.Analyzers.Lightup;
1819
using StyleCop.Analyzers.Settings.ObjectModel;
1920

2021
/// <summary>
@@ -87,6 +88,7 @@ internal class SA1516ElementsMustBeSeparatedByBlankLine : DiagnosticAnalyzer
8788
private static readonly Action<SyntaxNodeAnalysisContext> TypeDeclarationAction = HandleTypeDeclaration;
8889
private static readonly Action<SyntaxNodeAnalysisContext, StyleCopSettings> CompilationUnitAction = HandleCompilationUnit;
8990
private static readonly Action<SyntaxNodeAnalysisContext, StyleCopSettings> NamespaceDeclarationAction = HandleNamespaceDeclaration;
91+
private static readonly Action<SyntaxNodeAnalysisContext, StyleCopSettings> FileScopedNamespaceDeclarationAction = HandleFileScopedNamespaceDeclaration;
9092
private static readonly Action<SyntaxNodeAnalysisContext> BasePropertyDeclarationAction = HandleBasePropertyDeclaration;
9193

9294
private static readonly ImmutableDictionary<string, string> DiagnosticProperties = ImmutableDictionary<string, string>.Empty.Add(CodeFixActionKey, InsertBlankLineValue);
@@ -127,6 +129,7 @@ public override void Initialize(AnalysisContext context)
127129
context.RegisterSyntaxNodeAction(TypeDeclarationAction, SyntaxKinds.TypeDeclaration);
128130
context.RegisterSyntaxNodeAction(CompilationUnitAction, SyntaxKind.CompilationUnit);
129131
context.RegisterSyntaxNodeAction(NamespaceDeclarationAction, SyntaxKind.NamespaceDeclaration);
132+
context.RegisterSyntaxNodeAction(FileScopedNamespaceDeclarationAction, SyntaxKindEx.FileScopedNamespaceDeclaration);
130133
context.RegisterSyntaxNodeAction(BasePropertyDeclarationAction, SyntaxKinds.BasePropertyDeclaration);
131134
}
132135

@@ -209,6 +212,20 @@ private static void HandleCompilationUnit(SyntaxNodeAnalysisContext context, Sty
209212
}
210213
}
211214

215+
private static void HandleFileScopedNamespaceDeclaration(SyntaxNodeAnalysisContext context, StyleCopSettings settings)
216+
{
217+
var namespaceDeclaration = (BaseNamespaceDeclarationSyntaxWrapper)context.Node;
218+
219+
var members = namespaceDeclaration.Members;
220+
221+
HandleMemberList(context, members);
222+
223+
if (members.Count > 0)
224+
{
225+
ReportIfThereIsNoBlankLine(context, namespaceDeclaration.Name, members[0]);
226+
}
227+
}
228+
212229
private static void HandleNamespaceDeclaration(SyntaxNodeAnalysisContext context, StyleCopSettings settings)
213230
{
214231
var namespaceDeclaration = (NamespaceDeclarationSyntax)context.Node;

0 commit comments

Comments
 (0)