Skip to content

Commit 5131fde

Browse files
committed
Update SA1508/SA1509 for pattern matching
1 parent 9246f1b commit 5131fde

File tree

5 files changed

+217
-0
lines changed

5 files changed

+217
-0
lines changed

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/LayoutRules/SA1508CSharp8UnitTests.cs

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

44
namespace StyleCop.Analyzers.Test.CSharp8.LayoutRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
68
using StyleCop.Analyzers.Test.CSharp7.LayoutRules;
9+
using Xunit;
10+
11+
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
12+
StyleCop.Analyzers.LayoutRules.SA1508ClosingBracesMustNotBePrecededByBlankLine,
13+
StyleCop.Analyzers.LayoutRules.SA1508CodeFixProvider>;
714

815
public partial class SA1508CSharp8UnitTests : SA1508CSharp7UnitTests
916
{
17+
[Fact]
18+
[WorkItem(3003, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3003")]
19+
public async Task TestSwitchExpressionClosingBracePrecededByBlankLineAsync()
20+
{
21+
var testCode = @"
22+
public class TestClass
23+
{
24+
public int Test(Wrapper value)
25+
{
26+
return value switch
27+
{
28+
{ X: 1 } => 1,
29+
_ => 0,
30+
31+
{|#0:}|};
32+
}
33+
}
34+
35+
public class Wrapper
36+
{
37+
public int X { get; set; }
38+
}
39+
";
40+
var fixedCode = @"
41+
public class TestClass
42+
{
43+
public int Test(Wrapper value)
44+
{
45+
return value switch
46+
{
47+
{ X: 1 } => 1,
48+
_ => 0,
49+
};
50+
}
51+
}
52+
53+
public class Wrapper
54+
{
55+
public int X { get; set; }
56+
}
57+
";
58+
59+
var expected = Diagnostic().WithLocation(0);
60+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
61+
}
62+
63+
[Fact]
64+
[WorkItem(3003, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3003")]
65+
public async Task TestPropertyPatternClosingBracePrecededByBlankLineAsync()
66+
{
67+
var testCode = @"
68+
public class TestClass
69+
{
70+
public bool Test(Wrapper value)
71+
{
72+
return value is Wrapper
73+
{
74+
X: 1,
75+
76+
{|#0:}|};
77+
}
78+
}
79+
80+
public class Wrapper
81+
{
82+
public int X { get; set; }
83+
}
84+
";
85+
var fixedCode = @"
86+
public class TestClass
87+
{
88+
public bool Test(Wrapper value)
89+
{
90+
return value is Wrapper
91+
{
92+
X: 1,
93+
};
94+
}
95+
}
96+
97+
public class Wrapper
98+
{
99+
public int X { get; set; }
100+
}
101+
";
102+
103+
var expected = Diagnostic().WithLocation(0);
104+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
105+
}
10106
}
11107
}

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/LayoutRules/SA1509CSharp8UnitTests.cs

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

44
namespace StyleCop.Analyzers.Test.CSharp8.LayoutRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Testing;
69
using StyleCop.Analyzers.Test.CSharp7.LayoutRules;
10+
using Xunit;
11+
12+
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
13+
StyleCop.Analyzers.LayoutRules.SA1509OpeningBracesMustNotBePrecededByBlankLine,
14+
StyleCop.Analyzers.LayoutRules.SA1509CodeFixProvider>;
715

816
public partial class SA1509CSharp8UnitTests : SA1509CSharp7UnitTests
917
{
18+
[Fact]
19+
[WorkItem(3003, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3003")]
20+
public async Task TestSwitchExpressionOpeningBracePrecededByBlankLineAsync()
21+
{
22+
var testCode = @"
23+
public class TestClass
24+
{
25+
public int Test(Wrapper value)
26+
{
27+
return value switch
28+
29+
{|#0:{|}
30+
{ X: 1 } => 1,
31+
_ => 0,
32+
};
33+
}
34+
}
35+
36+
public class Wrapper
37+
{
38+
public int X { get; set; }
39+
}
40+
";
41+
var fixedCode = @"
42+
public class TestClass
43+
{
44+
public int Test(Wrapper value)
45+
{
46+
return value switch
47+
{
48+
{ X: 1 } => 1,
49+
_ => 0,
50+
};
51+
}
52+
}
53+
54+
public class Wrapper
55+
{
56+
public int X { get; set; }
57+
}
58+
";
59+
60+
var expected = Diagnostic().WithLocation(0);
61+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
62+
}
63+
64+
[Fact]
65+
[WorkItem(3003, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3003")]
66+
public async Task TestPropertyPatternOpeningBracePrecededByBlankLineAsync()
67+
{
68+
var testCode = @"
69+
public class TestClass
70+
{
71+
public bool Test(Wrapper value)
72+
{
73+
return value is Wrapper
74+
75+
{|#0:{|}
76+
X: 1,
77+
};
78+
}
79+
}
80+
81+
public class Wrapper
82+
{
83+
public int X { get; set; }
84+
}
85+
";
86+
var fixedCode = @"
87+
public class TestClass
88+
{
89+
public bool Test(Wrapper value)
90+
{
91+
return value is Wrapper
92+
{
93+
X: 1,
94+
};
95+
}
96+
}
97+
98+
public class Wrapper
99+
{
100+
public int X { get; set; }
101+
}
102+
";
103+
104+
var expected = Diagnostic().WithLocation(0);
105+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
106+
}
10107
}
11108
}

StyleCop.Analyzers/StyleCop.Analyzers/LayoutRules/SA1508ClosingBracesMustNotBePrecededByBlankLine.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace StyleCop.Analyzers.LayoutRules
1212
using Microsoft.CodeAnalysis.CSharp.Syntax;
1313
using Microsoft.CodeAnalysis.Diagnostics;
1414
using StyleCop.Analyzers.Helpers;
15+
using StyleCop.Analyzers.Lightup;
1516

1617
/// <summary>
1718
/// A closing brace within a C# element, statement, or expression is preceded by a blank line.
@@ -61,6 +62,8 @@ internal class SA1508ClosingBracesMustNotBePrecededByBlankLine : DiagnosticAnaly
6162
private static readonly Action<SyntaxNodeAnalysisContext> NamespaceDeclarationAction = HandleNamespaceDeclaration;
6263
private static readonly Action<SyntaxNodeAnalysisContext> BaseTypeDeclarationAction = HandleBaseTypeDeclaration;
6364
private static readonly Action<SyntaxNodeAnalysisContext> AccessorListAction = HandleAccessorList;
65+
private static readonly Action<SyntaxNodeAnalysisContext> SwitchExpressionAction = HandleSwitchExpression;
66+
private static readonly Action<SyntaxNodeAnalysisContext> PropertyPatternClauseAction = HandlePropertyPatternClause;
6467

6568
/// <inheritdoc/>
6669
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } =
@@ -79,6 +82,8 @@ public override void Initialize(AnalysisContext context)
7982
context.RegisterSyntaxNodeAction(NamespaceDeclarationAction, SyntaxKind.NamespaceDeclaration);
8083
context.RegisterSyntaxNodeAction(BaseTypeDeclarationAction, SyntaxKinds.BaseTypeDeclaration);
8184
context.RegisterSyntaxNodeAction(AccessorListAction, SyntaxKind.AccessorList);
85+
context.RegisterSyntaxNodeAction(SwitchExpressionAction, SyntaxKindEx.SwitchExpression);
86+
context.RegisterSyntaxNodeAction(PropertyPatternClauseAction, SyntaxKindEx.PropertyPatternClause);
8287
}
8388

8489
private static void HandleBlock(SyntaxNodeAnalysisContext context)
@@ -123,6 +128,18 @@ private static void HandleAccessorList(SyntaxNodeAnalysisContext context)
123128
AnalyzeCloseBrace(context, accessorList.CloseBraceToken);
124129
}
125130

131+
private static void HandleSwitchExpression(SyntaxNodeAnalysisContext context)
132+
{
133+
var switchExpression = (SwitchExpressionSyntaxWrapper)context.Node;
134+
AnalyzeCloseBrace(context, switchExpression.CloseBraceToken);
135+
}
136+
137+
private static void HandlePropertyPatternClause(SyntaxNodeAnalysisContext context)
138+
{
139+
var propertyPatternClause = (PropertyPatternClauseSyntaxWrapper)context.Node;
140+
AnalyzeCloseBrace(context, propertyPatternClause.CloseBraceToken);
141+
}
142+
126143
private static void AnalyzeCloseBrace(SyntaxNodeAnalysisContext context, SyntaxToken closeBraceToken)
127144
{
128145
if (closeBraceToken.IsKind(SyntaxKind.None))

documentation/SA1508.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ public bool Enabled
3939

4040
The code above would generate two instances of this violation, since there are two places where closing braces are preceded by blank lines.
4141

42+
Starting with C# 8.0, this rule also applies to closing braces in switch expressions and property patterns. If the brace
43+
belongs to a multi-line switch expression arm list or a multi-line property pattern, it still must not be preceded by a
44+
blank line.
45+
4246
## How to fix violations
4347

4448
To fix a violation of this rule, remove the blank line preceding the closing brace.

documentation/SA1509.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ public bool Enabled
5959
}
6060
```
6161

62+
This rule also applies to opening braces introduced by C# 8.0 switch expressions and property patterns. Even in these
63+
constructs, a blank line may not appear immediately before the opening brace.
64+
6265
## How to fix violations
6366

6467
To fix a violation of this rule, remove the blank line preceding the opening brace.

0 commit comments

Comments
 (0)