Skip to content

Commit

Permalink
code smells and coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
mary-georgiou-sonarsource committed Jun 7, 2024
1 parent 7067bde commit 7614e1b
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ protected override ArgumentSyntax LastArgumentIfArrayCreation(SyntaxNode express
LastArgumentIfArrayCreation(ArgumentList(expression));

protected override ITypeSymbol ArrayElementType(SyntaxNode expression, SemanticModel model) =>
expression as ArrayCreationExpressionSyntax is { } argument
&& model.GetTypeInfo(argument.Type.ElementType).Type is { } elementType
model.GetTypeInfo(((ArrayCreationExpressionSyntax)expression).Type.ElementType).Type is var elementType
? elementType
: null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

using System.Xml.Linq;
using SonarAnalyzer.Json.Parsing;
using SonarAnalyzer.SymbolicExecution.Roslyn.OperationProcessors;

namespace SonarAnalyzer.Rules;

public abstract class ArrayPassedAsParamsBase<TSyntaxKind, TArgumentNode> : SonarDiagnosticAnalyzer<TSyntaxKind>
Expand All @@ -38,20 +42,16 @@ protected sealed override void Initialize(SonarAnalysisContext context) =>
context.RegisterNodeAction(Language.GeneratedCodeRecognizer, c =>
{
if (LastArgumentIfArrayCreation(c.Node) is { } lastArgument
&& c.SemanticModel.GetSymbolInfo(c.Node).Symbol is IMethodSymbol methodSymbol
&& ParameterSymbol(methodSymbol, c.Node, lastArgument) is { IsParams: true } param
&& !IsObjectOrArrayType(c.Node, methodSymbol, param, c.SemanticModel)
&& !IsJaggedArrayParam(param))
&& c.SemanticModel.GetSymbolInfo(c.Node).Symbol is IMethodSymbol methodSymbol
&& Language.MethodParameterLookup(c.Node, methodSymbol).TryGetSymbol(lastArgument, out var param)
&& param is { IsParams: true }
&& !IsObjectOrArrayType(c.Node, methodSymbol, param, c.SemanticModel)
&& !IsJaggedArrayParam(param))
{
c.ReportIssue(Rule, lastArgument.GetLocation());
}
}, ExpressionKinds);

private IParameterSymbol ParameterSymbol(IMethodSymbol symbol, SyntaxNode invocation, TArgumentNode argument) =>
Language.MethodParameterLookup(invocation, symbol).TryGetSymbol(argument, out var param)
? param
: null;

private static bool IsJaggedArrayParam(IParameterSymbol param) =>
param.Type is IArrayTypeSymbol { ElementType: IArrayTypeSymbol };

Expand All @@ -68,6 +68,5 @@ bool ParamArgumentsAreReferenceTypeArrays(SyntaxNode node, IMethodSymbol symbol,
&& ArrayElementType(arguments.First(), model) is { } elementType
&& elementType.IsReferenceType
&& !elementType.Is(KnownType.System_Object);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ protected override ArgumentSyntax LastArgumentIfArrayCreation(SyntaxNode express
GetLastArgumentIfArrayCreation(GetArgumentListFromExpression(expression));

protected override ITypeSymbol ArrayElementType(SyntaxNode expression, SemanticModel model) =>
expression as ArrayCreationExpressionSyntax is { } argument
&& model.GetTypeInfo(argument.Type).Type is { } elementType
model.GetTypeInfo(((ArrayCreationExpressionSyntax)expression).Type).Type is var elementType
? elementType
: null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,21 +81,22 @@ public void Method(params object[] args) { }
public void MethodArray(params Array[] args) { }
public void MethodJaggedArray(params int[][] args) { }

public void CallMethod()
public void CallMethod(dynamic d)
{
Method(new String[] { "1", "2" }); // Noncompliant, elements in args: ["1", "2"]
// The argument given for a parameter array can be a single expression that is implicitly convertible (§10.2) to the parameter array type.
// In this case, the parameter array acts precisely like a value parameter.
// see: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/classes#14625-parameter-arrays
Method(new object[] { new int[] { 1, 2} }); // FN, elements in args: [System.Int32[]]
Method(new object[] { new int[] { 1, 2 } }); // FN, elements in args: [System.Int32[]]
Method(new int[] { 1, 2, 3, }); // Compliant, Elements in args: [System.Int32[]]
Method(new String[] { "1", "2" }, new String[] { "1", "2"}); // Compliant, elements in args: [System.String[], System.String[]]
Method(new String[] { "1", "2" }, new String[] { "1", "2" }); // Compliant, elements in args: [System.String[], System.String[]]
Method(new String[] { "1", "2"}, new int[] { 1, 2}); // Compliant, elements in args: pSystem.String[], System.Int32[]]
MethodArray(new String[] { "1", "2" }, new String[] { "1", "2" }); // Compliant, elements in args: [System.String[], System.String[]]
MethodArray(new int[] { 1, 2 }, new int[] { 1, 2 }); // Compliant, elements in args: [System.Int32[], System.Int32[]]

MethodJaggedArray(new int[] { 1, 2 }); // Compliant: jagged array [System.Object[]]

Method(d); // Compliant
Method("Hello", 2); // Compliant
string.Format(CultureInfo.InvariantCulture, "{0}.{1}", new object[] { "", new object() });
}
}
Expand Down

0 comments on commit 7614e1b

Please sign in to comment.