Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Invoked method name in Roslyn?

Tags:

c#

roslyn

I have a code like this;

class abc{
    void A()
    {
        //Some to do statements
    }
    void B()
    {
        var obj=A();
    }
    void C()
    {
        var call=B();
    }
}

I want to find the Invoked method name using roslyn.

like here o/p will be:

  • for method B :Invoked method A
  • for method C:Invoked method A

i want something like this:

root.DescendantNodes().OfType<InvocationExpressionSyntax>().Where(md => md.Identifier.ValueText.Equals(methodName)).FirstOrDefault();

but InvocationExpression doesn't contain Identifier to access. How to get identifier name

like image 492
Ravindra Kumar Avatar asked Apr 13 '15 20:04

Ravindra Kumar


3 Answers

I agree with SLaks and would add to his answer, if what you want is:

"I want the method invocation syntax nodes where the receiver syntax -- let me emphasize SYNTAX -- is a single identifier equal to some particular string"

then the query you want is something like

var root = tree.GetRoot();
var nodes = from node in root.DescendantNodes()
                         .OfType<InvocationExpressionSyntax>()
            let id = node.Expression as IdentifierNameSyntax
            where id != null
            where id.Identifier.ValueText == methodName
            select node;

But I think that is maybe not what you want. If what you want is "I want to know exactly which method is invoked regardless of whether it is written A(...) or Foo.Bar.A(...) then you don't want to be considering the syntax at all. You'll need to use the semantic analyzer to get the symbol associated with the invocation, and then check whether that symbol identifies the method you're interested in.

Are you primarily interested in a syntactic or a semantic analysis here? Roslyn does either, but you're only looking at syntax in the code you've presented.

If what you're looking for is a semantic analysis then you want to do something like this:

var tree = CSharpSyntaxTree.ParseText(code);
var c = CSharpCompilation.Create("asm.dll");
c = c.AddSyntaxTrees(tree);
var model = c.GetSemanticModel(tree);
string methodName = "A";

var root = tree.GetRoot();
var symbols = from node in root.DescendantNodes()
                           .OfType<InvocationExpressionSyntax>()
            let symbol = model.GetSymbolInfo(node.Expression).Symbol as IMethodSymbol
            where symbol != null
            where symbol.Name = methodName
            select symbol;
like image 193
Eric Lippert Avatar answered Nov 17 '22 18:11

Eric Lippert


The reason InvocationExpressionSyntax does not have Identifier because it may have with this case var obj = this.A() so it's reason why InvocationExpressionSyntax will contain property Expression with type ExpressionSyntax (which may be IdentifierNameSyntax type),

1.So simple answer for your case is you can access property Expression like this.

foreach (var item in root.DescendantNodes()
.OfType<InvocationExpressionSyntax>())
             {
                var expr = item.Expression;
                if (expr is IdentifierNameSyntax)
                {
                    IdentifierNameSyntax identifierName = r as IdentifierNameSyntax; // identifierName is your method name
                }

                if (expr is MemberAccessExpressionSyntax)
                {
                    MemberAccessExpressionSyntax memberAccessExpressionSyntax = r as MemberAccessExpressionSyntax;
                    //memberAccessExpressionSyntax.Name is your method name
                }
            }

2.but for exact lookup the invocation method is the same with method you declared you have to use Semantic information as in this example in Roslyn project
https://github.com/dotnet/roslyn/wiki/FAQ#how-do-i-find-all-calls-in-a-compilation-into-a-particular-namespace

like image 30
nhabuiduc Avatar answered Nov 17 '22 19:11

nhabuiduc


You're misunderstanding the role of these nodes in the syntax tree.

You should use the Roslyn Syntax Visualizer in VS to see what the nodes for a method call actually look like.

In short: An InvocationExpression just means someExpression(some arguments). That expression can be a number of things, such as a constructor call, a member access, an array access, or any other expression that resolves to a method or delegate.
You need to check the Kind of the InvocationExpressionSyntax and figure out how you want to handle every possible expression.

like image 32
SLaks Avatar answered Nov 17 '22 18:11

SLaks