Let's take a look at the following snippet:
public class Foo {
public void Bar(int first, int second) {
Add(first, second);
Add(y: second, x: first);
}
public int Add(int x, int y) => x + y;
}
In this case, the Add
method is called twice, first with ordinal parameters and a second time with named parameters.
If we try to get the parameters by using the index we will not get the right result for the second call.
One way to solve this (if you know the name beforehand) is to try to get the argument by name and as a backup to use the index:
private static ArgumentSyntax GetArgument(InvocationExpressionSyntax invocation, string name, int ordinal) =>
GetArgument(invocation, name) ?? GetArgument(invocation, ordinal);
private static ArgumentSyntax GetArgument(InvocationExpressionSyntax invocation, string name) =>
invocation.ArgumentList.Arguments
.FirstOrDefault(argumentSyntax => argumentSyntax.NameColon?.Name.Identifier.Text == name);
private static ArgumentSyntax GetArgument(InvocationExpressionSyntax invocation, int ordinal) =>
invocation.ArgumentList.Arguments[ordinal];
If the parameter names are not know beforehand you can get the method symbol:
var methodSymbol = (IMethodSymbol) semanticModel.GetSymbolInfo(invocations[0].Expression).Symbol;
look at the declaring syntax references:
var methodDeclarationSyntax = methodSymbol.DeclaringSyntaxReferences.First().GetSyntax() as MethodDeclarationSyntax;
and get the parameter names from the declaration:
methodDeclarationSyntax.ParameterList.Parameters[0].Identifier.Text
but this will work only if method is declared in the same solution.