Skip to content

Commit ba57efd

Browse files
committed
Update SA1003 for pattern matching
1 parent b72b3f7 commit ba57efd

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/SpacingRules/SA1003CSharp8UnitTests.cs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,103 @@ public void TestMethod(int? x)
105105
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
106106
}
107107

108+
[Fact]
109+
[WorkItem(3003, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3003")]
110+
public async Task TestSwitchExpressionArrowsAsync()
111+
{
112+
var testCode = @"
113+
namespace TestNamespace
114+
{
115+
public class TestClass
116+
{
117+
public string TestMethod(object value)
118+
{
119+
return value switch
120+
{
121+
0{|#0:=>|}""zero"",
122+
{ }{|#1:=>|}""object"",
123+
};
124+
}
125+
}
126+
}
127+
";
128+
129+
var fixedCode = @"
130+
namespace TestNamespace
131+
{
132+
public class TestClass
133+
{
134+
public string TestMethod(object value)
135+
{
136+
return value switch
137+
{
138+
0 => ""zero"",
139+
{ } => ""object"",
140+
};
141+
}
142+
}
143+
}
144+
";
145+
146+
DiagnosticResult[] expected =
147+
{
148+
Diagnostic(DescriptorPrecededByWhitespace).WithLocation(0).WithArguments("=>"),
149+
Diagnostic(DescriptorFollowedByWhitespace).WithLocation(0).WithArguments("=>"),
150+
Diagnostic(DescriptorPrecededByWhitespace).WithLocation(1).WithArguments("=>"),
151+
Diagnostic(DescriptorFollowedByWhitespace).WithLocation(1).WithArguments("=>"),
152+
};
153+
154+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
155+
}
156+
157+
[Fact]
158+
[WorkItem(3003, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3003")]
159+
public async Task TestSwitchExpressionArrowWithWrappedArmAsync()
160+
{
161+
var testCode = @"
162+
namespace TestNamespace
163+
{
164+
public class TestClass
165+
{
166+
public string TestMethod(int[] values)
167+
{
168+
return values switch
169+
{
170+
{ Length: 1 }{|#0:=>|}
171+
""single"",
172+
_ => ""other"",
173+
};
174+
}
175+
}
176+
}
177+
";
178+
179+
var fixedCode = @"
180+
namespace TestNamespace
181+
{
182+
public class TestClass
183+
{
184+
public string TestMethod(int[] values)
185+
{
186+
return values switch
187+
{
188+
{ Length: 1 } =>
189+
""single"",
190+
_ => ""other"",
191+
};
192+
}
193+
}
194+
}
195+
";
196+
197+
DiagnosticResult[] expected =
198+
{
199+
Diagnostic(DescriptorPrecededByWhitespace).WithLocation(0).WithArguments("=>"),
200+
};
201+
202+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
203+
}
204+
108205
[Fact]
109206
[WorkItem(3822, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3822")]
110207
public async Task TestNullForgivingOperatorAsync()

StyleCop.Analyzers/StyleCop.Analyzers/SpacingRules/SA1003SymbolsMustBeSpacedCorrectly.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ internal class SA1003SymbolsMustBeSpacedCorrectly : DiagnosticAnalyzer
138138
private static readonly Action<SyntaxNodeAnalysisContext> EqualsValueClauseAction = HandleEqualsValueClause;
139139
private static readonly Action<SyntaxNodeAnalysisContext> LambdaExpressionAction = HandleLambdaExpression;
140140
private static readonly Action<SyntaxNodeAnalysisContext> ArrowExpressionClauseAction = HandleArrowExpressionClause;
141+
private static readonly Action<SyntaxNodeAnalysisContext> SwitchExpressionArmAction = HandleSwitchExpressionArm;
141142

142143
/// <summary>
143144
/// Gets the descriptor for prefix unary expression that may not be followed by a comment.
@@ -214,6 +215,7 @@ public override void Initialize(AnalysisContext context)
214215
context.RegisterSyntaxNodeAction(EqualsValueClauseAction, SyntaxKind.EqualsValueClause);
215216
context.RegisterSyntaxNodeAction(LambdaExpressionAction, SyntaxKinds.LambdaExpression);
216217
context.RegisterSyntaxNodeAction(ArrowExpressionClauseAction, SyntaxKind.ArrowExpressionClause);
218+
context.RegisterSyntaxNodeAction(SwitchExpressionArmAction, SyntaxKindEx.SwitchExpressionArm);
217219
}
218220

219221
private static void HandleConstructorDeclaration(SyntaxNodeAnalysisContext context)
@@ -381,6 +383,12 @@ private static void HandleArrowExpressionClause(SyntaxNodeAnalysisContext contex
381383
CheckToken(context, arrowExpressionClause.ArrowToken, true, true, true);
382384
}
383385

386+
private static void HandleSwitchExpressionArm(SyntaxNodeAnalysisContext context)
387+
{
388+
var switchExpressionArm = (SwitchExpressionArmSyntaxWrapper)context.Node;
389+
CheckToken(context, switchExpressionArm.EqualsGreaterThanToken, true, true, true);
390+
}
391+
384392
private static void CheckToken(SyntaxNodeAnalysisContext context, SyntaxToken token, bool withLeadingWhitespace, bool allowAtEndOfLine, bool withTrailingWhitespace, string tokenText = null)
385393
{
386394
tokenText = tokenText ?? token.Text;

documentation/SA1003.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ lambda operators. For example:
3131
int x = 4 + y;
3232
```
3333

34+
Starting with C# 8.0, the lambda operator `=>` also appears in switch expression arms. The same spacing
35+
rules apply: each arrow should have a single space on both sides.
36+
37+
```csharp
38+
var description = value switch { 0 => "zero", _ => "nonzero" };
39+
```
40+
3441
In contrast, unary operators should be preceded by a single space, but should never be followed by any space. For example:
3542

3643
```csharp

0 commit comments

Comments
 (0)