Skip to content

Commit 0c26aa1

Browse files
committed
Fix that SA1130 crashes on params
1 parent 1d8eb55 commit 0c26aa1

File tree

2 files changed

+68
-3
lines changed

2 files changed

+68
-3
lines changed

StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1130UnitTests.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,5 +380,47 @@ public static void TestMethod2(TestDelegate testDelegate)
380380

381381
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
382382
}
383+
384+
[Fact]
385+
public async Task TestParamsAsync()
386+
{
387+
var testCode = @"
388+
using System;
389+
public class TypeName
390+
{
391+
public void Test(params Action[] argument)
392+
{
393+
394+
}
395+
396+
public void Test()
397+
{
398+
Test(delegate { }, delegate { });
399+
}
400+
}";
401+
402+
string fixedCode = @"
403+
using System;
404+
public class TypeName
405+
{
406+
public void Test(params Action[] argument)
407+
{
408+
409+
}
410+
411+
public void Test()
412+
{
413+
Test(() => { }, () => { });
414+
}
415+
}";
416+
417+
var expected = new[]
418+
{
419+
Diagnostic().WithLocation(12, 14),
420+
Diagnostic().WithLocation(12, 28),
421+
};
422+
423+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
424+
}
383425
}
384426
}

StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1130UseLambdaSyntax.cs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,25 @@ public override void Initialize(AnalysisContext context)
5555
/// <returns>A parameter list for the delegate parameters.</returns>
5656
internal static ParameterListSyntax GetDelegateParameterList(IMethodSymbol methodSymbol, int argumentIndex)
5757
{
58-
var delegateType = (INamedTypeSymbol)methodSymbol.Parameters[argumentIndex].Type;
58+
var realIndex = Math.Min(argumentIndex, methodSymbol.Parameters.Length - 1);
59+
60+
var type = methodSymbol.Parameters[realIndex].Type;
61+
62+
if (methodSymbol.Parameters[realIndex].IsParams)
63+
{
64+
if (type is IArrayTypeSymbol arrayTypeSymbol)
65+
{
66+
type = arrayTypeSymbol.ElementType;
67+
}
68+
else
69+
{
70+
// Just to make sure that we do not crash if in future versions of the compiler other types are allowed for params.
71+
// This if statement should be extended if e.g. Span params are introduced into the language.
72+
return null;
73+
}
74+
}
75+
76+
var delegateType = (INamedTypeSymbol)type;
5977
var delegateParameters = delegateType.DelegateInvokeMethod.Parameters;
6078

6179
var syntaxParameters = GetSyntaxParametersFromSymbolParameters(delegateParameters);
@@ -95,8 +113,7 @@ private static bool HandleMethodInvocation(SemanticModel semanticModel, Anonymou
95113
// invocation -> argument list -> argument -> anonymous method
96114
var argumentListSyntax = argumentSyntax?.Parent as ArgumentListSyntax;
97115

98-
var originalInvocationExpression = argumentListSyntax?.Parent as InvocationExpressionSyntax;
99-
if (originalInvocationExpression != null)
116+
if (argumentListSyntax?.Parent is InvocationExpressionSyntax originalInvocationExpression)
100117
{
101118
SymbolInfo originalSymbolInfo = semanticModel.GetSymbolInfo(originalInvocationExpression);
102119
Location location = originalInvocationExpression.GetLocation();
@@ -106,6 +123,12 @@ private static bool HandleMethodInvocation(SemanticModel semanticModel, Anonymou
106123
// Determine the parameter list from the method that is invoked, as delegates without parameters are allowed, but they cannot be replaced by a lambda without parameters.
107124
var parameterList = GetDelegateParameterList((IMethodSymbol)originalSymbolInfo.Symbol, argumentIndex);
108125

126+
if (parameterList == null)
127+
{
128+
// This might happen if the call was using params witha type unknown to the analyzer, e.g. params Span<T>.
129+
return false;
130+
}
131+
109132
// In some cases passing a delegate as an argument to a method is required to call the right overload
110133
// When there is an other overload that takes an expression.
111134
var lambdaExpression = SyntaxFactory.ParenthesizedLambdaExpression(

0 commit comments

Comments
 (0)