Skip to content

Commit

Permalink
Fix S2225 FP: Support static virtual/abstract interface methods (#6335)
Browse files Browse the repository at this point in the history
  • Loading branch information
cristian-ambrosini-sonarsource authored Nov 18, 2022
1 parent b05c668 commit 9b87b41
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,7 @@ public override SyntaxNode RemoveParentheses(SyntaxNode node) =>

public override bool TryGetGetInterpolatedTextValue(SyntaxNode node, SemanticModel semanticModel, out string interpolatedValue) =>
Cast<InterpolatedStringExpressionSyntax>(node).TryGetGetInterpolatedTextValue(semanticModel, out interpolatedValue);

public override bool IsStatic(SyntaxNode node) =>
Cast<BaseMethodDeclarationSyntax>(node).IsStatic();
}
1 change: 1 addition & 0 deletions analyzers/src/SonarAnalyzer.Common/Facade/SyntaxFacade.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public abstract class SyntaxFacade<TSyntaxKind>
public abstract SyntaxNode RemoveParentheses(SyntaxNode node);
public abstract string NodeStringTextValue(SyntaxNode node, SemanticModel semanticModel);
public abstract bool TryGetGetInterpolatedTextValue(SyntaxNode node, SemanticModel semanticModel, out string interpolatedValue);
public abstract bool IsStatic(SyntaxNode node);

protected static T Cast<T>(SyntaxNode node) where T : SyntaxNode =>
node as T ?? throw new InvalidCastException($"A {node.GetType().Name} node can not be cast to a {typeof(T).Name} node.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,6 @@ private bool WithinToString(SyntaxNode node) =>
node.Ancestors()
.TakeWhile(x => !IsLocalOrLambda(x))
.Any(x => Language.Syntax.IsKind(x, MethodKind)
&& nameof(ToString).Equals(Language.Syntax.NodeIdentifier(x)?.ValueText, Language.NameComparison));
&& nameof(ToString).Equals(Language.Syntax.NodeIdentifier(x)?.ValueText, Language.NameComparison)
&& !Language.Syntax.IsStatic(x));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* SonarAnalyzer for .NET
* Copyright (C) 2015-2022 SonarSource SA
* mailto: contact AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

namespace SonarAnalyzer.Extensions;

public static class MethodBlockSyntaxExtensions
{
public static bool IsShared(this MethodBlockSyntax methodBlock) =>
methodBlock.SubOrFunctionStatement.Modifiers.Any(SyntaxKind.SharedKeyword);
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static ControlFlowGraph CreateCfg(this SyntaxNode block, SemanticModel mo

public static bool IsPartOfBinaryNegationOrCondition(this SyntaxNode node)
{
if (!(node.Parent is MemberAccessExpressionSyntax))
if (node.Parent is not MemberAccessExpressionSyntax)
{
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,7 @@ public override SyntaxNode RemoveParentheses(SyntaxNode node) =>

public override bool TryGetGetInterpolatedTextValue(SyntaxNode node, SemanticModel semanticModel, out string interpolatedValue) =>
Cast<InterpolatedStringExpressionSyntax>(node).TryGetGetInterpolatedTextValue(semanticModel, out interpolatedValue);

public override bool IsStatic(SyntaxNode node) =>
Cast<MethodBlockSyntax>(node).IsShared();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{
static virtual string ToString()
{
return null; // Noncompliant FP
return null; // Compliant
}
}

Expand All @@ -11,10 +11,10 @@ public interface SomeOtherInterface
static abstract string ToString();
}

public class SomeClass: SomeOtherInterface
public class SomeClass : SomeOtherInterface
{
public static string ToString()
{
return null; // Noncompliant FP
return null; // Compliant
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,12 @@ public override string ToString()
return null; // Noncompliant
}
}

public class SomeClass
{
public static string ToString()
{
return null; // Compliant
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,22 +63,30 @@ Namespace Compliant
Return String.Empty
End Function
End Structure
Class ToString
Public Function SomeMethod() As String

Class ToString

Public Function SomeMethod() As String
Return Nothing 'Compliant
End Function
End Class
Class BinaryConditionalExpressionNotSupported
Public Function SomeMethod() As String

End Class

Class BinaryConditionalExpressionNotSupported

Public Function SomeMethod() As String
Return If(Nothing, Nothing) ' Not supported, doesn't make sense
End Function

End Class

End Class

Class ToStringSharedMethod

Public Shared Function ToString() As String
Return Nothing
End Function

End Class

End Namespace

Expand All @@ -96,8 +104,8 @@ Namespace Noncompliant
End Class

Public Class ReturnsNothingConditionaly
Public Overrides Function ToString() As String

Public Overrides Function ToString() As String
If Condition.[When]() Then
Return Nothing ' Noncompliant
End If
Expand All @@ -111,15 +119,15 @@ Namespace Noncompliant
Return If(Condition.[When](), Nothing, "") ' Noncompliant
End Function
End Class
Public Class ReturnsNullViaNestedTenary
Public Overrides Function ToString() As String

Public Class ReturnsNullViaNestedTenary

Public Overrides Function ToString() As String
Return If(Condition.When(), ' Noncompliant
If(Condition.When(), Nothing , "something"),
If(Condition.When(), "something", Nothing))
End Function
If(Condition.When(), Nothing, "something"),
If(Condition.When(), "something", Nothing))
End Function

End Class

Structure StructReturnsNothing
Expand Down

0 comments on commit 9b87b41

Please sign in to comment.