使用 roslyn 检测外部 api 调用

Detect external api calls using roslyn

我想知道如何检测 InvocationExpressionSyntax 是来自我的代码还是来自外部代码。

我试图找到如何做到这一点,但没有成功。

示例:

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 ?
}

谢谢

为此,您可以检查 InvocationExpressionSyntax 下收到的 ISymbol 中的 DeclaringSyntaxReferences 是否为空。为了更清楚,您还可以通过检查 IsImplicitlyDeclared 是否为 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;
  }

当你说 "my code" 或 "external code" 时,你需要定义你的意思。

假设 "my code" 表示 "code compiled into the current assembly",外部代码表示 "code from a referenced assembly",最简单的方法是比较程序集。

假设您有一个 SyntaxNodeAnalysisContext context 和一个 InvocationExpressionSyntax node,您可以找到您正在调用的方法的符号如下:

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

请记住,该符号可能为空,因此请对其进行测试。

您现在可以比较程序集:

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

另一种选择是查看符号的位置:

bool isInMetadata = symbol.Locations.Any(loc => loc.IsInMetadata);
bool isInSource = symbol.Locations.Any(loc => loc.IsInSource);