0

I would like to know how detect if for example InvocationExpressionSyntax is from my code or from external code.

I tried to find how to do it, but with no success.

Example.:

public async Task MyMethodAsync1()
{
   await MyMethodAsync2(); // How to know that this 'InvocationExpressionSyntax' is mine using roslyn ?
}

public async Task MyMethodAsync2()
{
  await Task.Delay(1); // How to know that this 'InvocationExpressionSyntax' is NOT mine using roslyn ?
}

Thanks

Peter M.
  • 1,028
  • 2
  • 10
  • 27

2 Answers2

1

To achive that you can check that the DeclaringSyntaxReferences from the received ISymbol under your InvocationExpressionSyntax is empty. To be more clear you also can make sure that this symbol isn't generated by the compiler by check that the IsImplicitlyDeclared is false

  public static bool IsDeclareInMetadata(this SemanticModel semanticModel, SyntaxNode node)
  {
    var info = semanticModel.GetSymbolInfo(node);
    return !(info.Symbol is null) && info.Symbol.DeclaringSyntaxReferences.IsDefaultOrEmpty && !info.Symbol.IsImplicitlyDeclared;
  }
George Alexandria
  • 2,841
  • 2
  • 16
  • 24
  • 1
    i also find this helpful..: https://stackoverflow.com/questions/45361709/roslyn-get-method-declaration-from-invocationexpression – Peter M. Apr 20 '19 at 21:04
0

You need to define what exactly it is you mean when you say "my code" or "external code".

Assuming "my code" means "code compiled into the current assembly" and external code means "code from a referenced assembly", the easiest way to find out it to compare the assemblies.

Assuming you have a SyntaxNodeAnalysisContext context, and an InvocationExpressionSyntax node, you find the symbol for the method that you are calling as follows:

var symbol = context.SemanticModel.GetSymbolInfo(node, context.Cancellationtoken);

Remember that the symbol may be null, so test for that.

You can now compare the assemblies:

bool fromSameAssembly = context.Compilation.Assembly.Equals(symbol.ContainingAssembly);

An other option is to look at the symbol's locations:

bool isInMetadata = symbol.Locations.Any(loc => loc.IsInMetadata);
bool isInSource = symbol.Locations.Any(loc => loc.IsInSource);
Kris Vandermotten
  • 10,111
  • 38
  • 49
  • I think example i provided to define `my code`, `external code` is good enough. I also think already marked solution is a bit simpler. And thanks i think your post is also helpful – Peter M. Apr 25 '19 at 21:22
  • @PeterM. I'm sorry, but "my code" could mean "source code in the current project", "source code in the current solution", "source code in the current project except generated code" and even "source code I committed to source control". "External code" is even more vague. For all I know, it could mean "code called through p/Invoke, using the `extern` keyword". Be precise. The first step to knowing how to write what you want is knowing what you want. – Kris Vandermotten May 14 '19 at 08:04
  • I do not want to fight with you. I put there example defining my code and external code. You have to agree that `Task.Delay()` is delivered by `Microsoft` and not my code. So Because `Task.Delay()` is `InvocationSyntax` i wanted to know how to detect using Roslyn that I do not have access to source code defining `Task.Delay()` method. Then it is enough to apply logic to all `InvocationExpressions`. Thanks. – Peter M. May 15 '19 at 11:20
  • @PeterM. I'm not fighting, I'm trying to help you. Is code generated from a .resx file considered "my code"? If your solution contains two projects, where the first one references the second one, do you consider code in the second one "my code" when analyzing the first one? – Kris Vandermotten May 15 '19 at 16:01
  • Yes your code was helpful and for your points. I promise that next time I will try write question better :) – Peter M. May 18 '19 at 08:25