From 81f99374f682e084ab89131a6e9a62522e5496a1 Mon Sep 17 00:00:00 2001 From: Sebastien Marichal Date: Mon, 1 Jul 2024 13:42:16 +0200 Subject: [PATCH 1/2] Fix S3247 FN: When cast expression contains parentheses --- .../Rules/CastShouldNotBeDuplicated.cs | 17 ++++++++++---- .../TestCases/CastShouldNotBeDuplicated.cs | 22 +++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/analyzers/src/SonarAnalyzer.CSharp/Rules/CastShouldNotBeDuplicated.cs b/analyzers/src/SonarAnalyzer.CSharp/Rules/CastShouldNotBeDuplicated.cs index f34dc41a66e..c8c9e74bb18 100644 --- a/analyzers/src/SonarAnalyzer.CSharp/Rules/CastShouldNotBeDuplicated.cs +++ b/analyzers/src/SonarAnalyzer.CSharp/Rules/CastShouldNotBeDuplicated.cs @@ -232,8 +232,8 @@ private static void ReportPatternAtCastLocation(SonarSyntaxNodeReportingContext private static bool IsEquivalentVariable(ExpressionSyntax expression, SyntaxNode typedVariable) { - var left = RemoveThisExpression(typedVariable).WithoutTrivia(); - var right = RemoveThisExpression(expression).WithoutTrivia(); + var left = CleanupExpression(typedVariable).WithoutTrivia(); + var right = CleanupExpression(expression).WithoutTrivia(); return left.IsEquivalentTo(right) || (StandaloneIdentifier(left) is { } leftIdentifier && leftIdentifier == StandaloneIdentifier(right)); @@ -245,8 +245,17 @@ static string StandaloneIdentifier(SyntaxNode node) => _ when node.IsKind(SyntaxKindEx.SingleVariableDesignation) => ((SingleVariableDesignationSyntaxWrapper)node).Identifier.ValueText, _ => null }; + } + + private static SyntaxNode CleanupExpression(SyntaxNode node) + { + while (node is ParenthesizedExpressionSyntax parenthesized) + { + node = parenthesized.Expression; + } + + node = node is MemberAccessExpressionSyntax { Expression: ThisExpressionSyntax } memberAccess ? memberAccess.Name : node; - static SyntaxNode RemoveThisExpression(SyntaxNode node) => - node is MemberAccessExpressionSyntax { Expression: ThisExpressionSyntax } memberAccess ? memberAccess.Name : node; + return node; } } diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/CastShouldNotBeDuplicated.cs b/analyzers/tests/SonarAnalyzer.Test/TestCases/CastShouldNotBeDuplicated.cs index 6f75a08ff17..834e40bde0d 100644 --- a/analyzers/tests/SonarAnalyzer.Test/TestCases/CastShouldNotBeDuplicated.cs +++ b/analyzers/tests/SonarAnalyzer.Test/TestCases/CastShouldNotBeDuplicated.cs @@ -41,6 +41,22 @@ public void IgnoreMemberAccess(Fruit arg) _ = (Fruit)differentInstance.Property; } + // https://github.com/SonarSource/sonar-dotnet/issues/9491 + if (arg.Property is Fruit) // Noncompliant + { + _ = ((Fruit)(arg.Property)).Property; // Secondary + } + + if (arg.Property is Fruit) // Noncompliant + { + _ = ((Fruit)((arg.Property))).Property; // Secondary + } + + if (arg.Property is Fruit) // Noncompliant + { + _ = ((Fruit)arg.Property).Property; // Secondary + } + if (f.Property is Fruit) // Compliant, the cast is on a different instance { _ = (Fruit)differentInstance.Property; @@ -128,6 +144,12 @@ public void TakeIdentifierIntoAccount(object x) var fruit = (Fruit)this.someField; // ^^^^^^^^^^^^^^^^^^^^^ Secondary } + + if (someField is Fruit) // Noncompliant + { + var fruit = ((Fruit)(this.someField)); +// ^^^^^^^^^^^^^^^^^^^^^^^ Secondary + } } public void UnknownFoo(object x) From 049728a06544f0559310a7c24f6218bcab37de34 Mon Sep 17 00:00:00 2001 From: mary-georgiou-sonarsource Date: Fri, 5 Jul 2024 15:15:42 +0200 Subject: [PATCH 2/2] small cleanup --- .../SonarAnalyzer.CSharp/Rules/CastShouldNotBeDuplicated.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/analyzers/src/SonarAnalyzer.CSharp/Rules/CastShouldNotBeDuplicated.cs b/analyzers/src/SonarAnalyzer.CSharp/Rules/CastShouldNotBeDuplicated.cs index c8c9e74bb18..8ab3e90dfd4 100644 --- a/analyzers/src/SonarAnalyzer.CSharp/Rules/CastShouldNotBeDuplicated.cs +++ b/analyzers/src/SonarAnalyzer.CSharp/Rules/CastShouldNotBeDuplicated.cs @@ -253,9 +253,6 @@ private static SyntaxNode CleanupExpression(SyntaxNode node) { node = parenthesized.Expression; } - - node = node is MemberAccessExpressionSyntax { Expression: ThisExpressionSyntax } memberAccess ? memberAccess.Name : node; - - return node; + return node is MemberAccessExpressionSyntax { Expression: ThisExpressionSyntax } memberAccess ? memberAccess.Name : node; } }