【问题标题】:Detect external api calls using roslyn使用 roslyn 检测外部 api 调用
【发布时间】:2019-04-25 20:25:44
【问题描述】:

我想知道如何检测例如 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 ?
}

谢谢

【问题讨论】:

    标签: c# roslyn roslyn-code-analysis


    【解决方案1】:

    为了实现,您可以检查在您的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;
      }
    

    【讨论】:

    【解决方案2】:

    当你说“我的代码”或“外部代码”时,你需要明确你的意思。

    假设“我的代码”是指“编译到当前程序集中的代码”,而外部代码是指“来自引用程序集的代码”,这是找出它以比较程序集的最简单方法。

    假设您有一个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);
    

    【讨论】:

    • 我认为我提供的用于定义my codeexternal code 的示例已经足够好了。我也认为已经标记的解决方案更简单一些。谢谢,我认为你的帖子也很有帮助
    • @PeterM。抱歉,“我的代码”可能表示“当前项目中的源代码”、“当前解决方案中的源代码”、“当前项目中的源代码(生成的代码除外)”甚至“我承诺的源代码”控制”。 “外部代码”更加模糊。据我所知,它可能意味着“通过 p/Invoke 调用的代码,使用 extern 关键字”。要精确。知道如何写你想要的东西的第一步是知道你想要什么。
    • 我不想和你吵架。我放在那里定义我的代码和外部代码的示例。您必须同意 Task.Delay() 是由 Microsoft 而不是我的代码提供的。所以因为Task.Delay()InvocationSyntax 我想知道如何使用Roslyn 检测我无权访问定义Task.Delay() 方法的源代码。然后将逻辑应用于所有InvocationExpressions 就足够了。谢谢。
    • @PeterM。我不是在打架,我是想帮你。从 .resx 文件生成的代码是否被视为“我的代码”?如果您的解决方案包含两个项目,其中第一个项目引用第二个项目,那么在分析第一个项目时,您是否将第二个项目中的代码视为“我的代码”?
    • 是的,您的代码对您的观点很有帮助。我保证下次我会尝试更好地写问题:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多