c# Roslyn get IParameterSymbol from ArgumentSyntax
Asked Answered
G

2

7

I have an ArgumentSyntax in some invocation expression, how can I get corresponding IParameterSymbol in the IMethodSymbol of the invocation?

Since I have seen ArgumentSyntax.NameColonSyntax, which means the argument might have some name, I cannot use IParameterSymbol.Ordinal to match them by their index in their containing list.

Gimpel answered 22/6, 2020 at 2:48 Comment(0)
W
5

I've been trying to figure out the same process myself and after fumbling a bit I found a path forward for this. It requires access to the SemanticModel. In my case it comes from the context of a Roslyn analyzer.

SemanticModel.GetOperation(argumentSyntaxNode) should return an IArgumentOperation which has a property IParameterSymbol Parameter

Woehick answered 9/6, 2022 at 12:37 Comment(2)
By the way - is there a book or online guidance explaining the Roslyn API conceptual model? A lot of it seems to be just a matter of guessing, and playing around in the debugger, and it's not clear what all the concepts mean, such as IArgumentOperation etc..Funiculus
Note that this does not work for params arguments.Stirrup
T
2

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.

Tholos answered 22/6, 2020 at 21:46 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.