Skip to content

Commit b70ab3f

Browse files
committed
Fix SA1119 handling of switch expression within member access expressions
Fixes #3200
1 parent cf2cd83 commit b70ab3f

2 files changed

Lines changed: 60 additions & 0 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/MaintainabilityRules/SA1119CSharp8UnitTests.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,5 +116,43 @@ public void TestMethod(int n, object a, object b)
116116

117117
await VerifyCSharpFixAsync(LanguageVersion.CSharp8, testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
118118
}
119+
120+
[Theory]
121+
[InlineData(".ToString()")]
122+
[InlineData("?.ToString()")]
123+
[InlineData("[0]")]
124+
[InlineData("?[0]")]
125+
[WorkItem(3171, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3171")]
126+
public async Task TestSwitchExpressionFollowedByDereferenceAsync(string operation)
127+
{
128+
string testCode = $@"
129+
public class Foo
130+
{{
131+
public object TestMethod(int n, string a, string b)
132+
{{
133+
return (n switch {{ 1 => a, 2 => b }}){operation};
134+
}}
135+
}}
136+
";
137+
138+
await VerifyCSharpDiagnosticAsync(LanguageVersion.CSharp8, testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
139+
}
140+
141+
[Fact]
142+
[WorkItem(3171, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3171")]
143+
public async Task TestSwitchExpressionFollowedByPointerDereferenceAsync()
144+
{
145+
string testCode = @"
146+
public class Foo
147+
{
148+
public unsafe string TestMethod(int n, byte* a, byte* b)
149+
{
150+
return (n switch { 1 => a, 2 => b })->ToString();
151+
}
152+
}
153+
";
154+
155+
await VerifyCSharpDiagnosticAsync(LanguageVersion.CSharp8, testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
156+
}
119157
}
120158
}

StyleCop.Analyzers/StyleCop.Analyzers/MaintainabilityRules/SA1119StatementMustNotUseUnnecessaryParenthesis.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace StyleCop.Analyzers.MaintainabilityRules
1010
using Microsoft.CodeAnalysis.CSharp;
1111
using Microsoft.CodeAnalysis.CSharp.Syntax;
1212
using Microsoft.CodeAnalysis.Diagnostics;
13+
using StyleCop.Analyzers.DocumentationRules;
1314
using StyleCop.Analyzers.Helpers;
1415
using StyleCop.Analyzers.Lightup;
1516

@@ -132,6 +133,11 @@ private static void HandleParenthesizedExpression(SyntaxNodeAnalysisContext cont
132133
return;
133134
}
134135

136+
if (IsSwitchExpressionExpressionOfMemberAccess(node))
137+
{
138+
return;
139+
}
140+
135141
ReportDiagnostic(context, node);
136142
}
137143
else
@@ -221,6 +227,22 @@ private static bool IsSwitchExpressionPrecededByTypeCast(ParenthesizedExpression
221227
return previousToken.IsKind(SyntaxKind.CloseParenToken) && previousToken.Parent.IsKind(SyntaxKind.CastExpression);
222228
}
223229

230+
private static bool IsSwitchExpressionExpressionOfMemberAccess(ParenthesizedExpressionSyntax node)
231+
{
232+
if (!node.Expression.IsKind(SyntaxKindEx.SwitchExpression))
233+
{
234+
return false;
235+
}
236+
237+
return node.Parent switch
238+
{
239+
MemberAccessExpressionSyntax memberAccessExpression => memberAccessExpression.Expression == node,
240+
ConditionalAccessExpressionSyntax conditionalAccessExpression => conditionalAccessExpression.Expression == node,
241+
ElementAccessExpressionSyntax elementAccessExpression => elementAccessExpression.Expression == node,
242+
_ => false,
243+
};
244+
}
245+
224246
private static void ReportDiagnostic(SyntaxNodeAnalysisContext context, ParenthesizedExpressionSyntax node)
225247
{
226248
context.ReportDiagnostic(Diagnostic.Create(Descriptor, node.GetLocation()));

0 commit comments

Comments
 (0)