使用Roslyn访问Invocations参考

时间:2017-07-09 06:09:55

标签: c# visual-studio roslyn

我想使用 Roslyn 创建 Visual Studio扩展(VSIX)。此扩展应查找所有调用,然后查找其定义以分析在其上定义的属性。该方法的定义可以是解决方案中的任何位置。

我的第一堂课是这样的:

namespace MainProject
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(BusinessProject.Calc.AddNumbers(5, 8));
        }
    }
}

我的第二堂课如下:

namespace BusinessProject
{
    public class Calc
    {
        [CustomAttr("Do something")]
        public static long AddNumbers(int a, int b)
        {
            return a + b;
        }
    }
}

在上面的示例中,在程序类中,我调用了 AddNumbers 方法。我想1)分析代码,2)找到这个调用,3)获取类 Calc 中的引用方法的所有属性,4)进程属性参数,5)然后发出警告/错误如果需要的话。 我可以通过 RegisterCodeBlockAction 分析当前类以查找所有调用,但我不能做的是访问整个解决方案以查找调用的定义,然后访问引用的属性。

如何在 RegiserCodeBlockAction 中访问整个解决方案?

2 个答案:

答案 0 :(得分:2)

你说的是错误的方法。

您实际上希望分析器在每个方法调用上运行,而不是每个代码块都运行 因此,您应该致电RegisterSyntaxNodeAction,然后通过SyntaxKind.InvocationExpression

然后它将使用InvocationExpressionSyntax来呼叫您,其中包含您需要的所有信息(主要在语义模型中)。

答案 1 :(得分:1)

正如@SLaks在评论中提到的,通过使用 SemanticModel.Compilation.SyntaxTrees ,我们可以访问解决方案中的所有源代码。我找到了方法及其参数。但是这有一个问题,您无法使用 SemanticModel.GetTypeInfo 获取对象的TypeInfo。您必须创建一个新的语义模型,如下所示:

foreach (var tree in context.SemanticModel.Compilation.SyntaxTrees)
{
    var compilation = CSharpCompilation.Create("MyCompilation",
                    syntaxTrees: new[] { tree }, references: new List<MetadataReference>());
    var syntaxRoot = tree.GetRoot();
    var model = compilation.GetSemanticModel(tree);
    var targetMethod = syntaxRoot.DescendantNodes().OfType<MethodDeclarationSyntax>().FirstOrDefault(f => f.Identifier.ToString() == "Class name to find");
    if (targetMethod == null)
        continue;

    var typeInfo = model.GetTypeInfo(targetMethod.First().ParameterList.Parameters[i].ChildNodes().First());
    // Do any thing with typeInfo
}