如何在Roslyn中获得方法的所有引用(方法由其他类调用)?

时间:2016-02-16 16:19:23

标签: c# roslyn roslyn-code-analysis

感谢Roslyn,可以访问.Net编译器,在我们的项目Gcop中,我们需要有一个调用方法的引用列表。

VS IDE显示的参考位置非常合适:

enter image description here

实际上我想了解哪个类/名称空间甚至程序集都是通过Roslyn C#语法调用我的方法。

目前我可以访问MethodSymbol:

var methodSymbol = semanticModel.GetSymbolInfo(invocation).Symbol as IMethodSymbol;

我应该写什么才能访问此方法的引用?

//最近添加了双重检查

 var solutionPath = Utilities.DteExtensions.SolutionFullPath;
 var msWorkspace = Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create();
 var solution = msWorkspace.OpenSolutionAsync(solutionPath).Result; 

 var result = new List<ReferenceLocation>();
 var refrences = SymbolFinder.FindReferencesAsync(methodSymbol, solution).Result;    

 foreach (var refernc in refrences)
  {
    foreach (var location in refernc.Locations)
     {
         result.Add(location);
     }
  }
///???????? why the result is empty ? 

2 个答案:

答案 0 :(得分:2)

您正在寻找SymbolFinder class上的debounce方法。

答案 1 :(得分:0)

我测试了这种方法,但速度不快,找不到一些语法

 protected override void Analyze(SyntaxNodeAnalysisContext context)
    {
        NodeToAnalyze = context.Node;
        Method = context.Node as MethodDeclarationSyntax;

        // only public method should be checked
        if (!IsModifiersValid) return;

        var methodSymbol = context.SemanticModel.GetDeclaredSymbol(Method) as IMethodSymbol;

        var solutionPath = Utilities.DteExtensions.SolutionFullPath;
        var msWorkspace = Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create();
        var solution = msWorkspace.OpenSolutionAsync(solutionPath).Result;

        // looking in all projects inside of one solution
        var allDocumentsInEntireSolution = solution.Projects.SelectMany(it => it.Documents);

        //skip rule when in entire solution we have web form project             
        if (allDocumentsInEntireSolution.Any(x => x.Name == "Default.aspx.cs")) return;

        //Looking for all references            

        var refrencesFound = FindAllMethodReferences(Method.GetName(), solution);

        if (refrencesFound.Count() ==0)
            ReportDiagnostic(context, Method);
        else
        {
            var xyx = refrencesFound.Count();
        }

    }

    IEnumerable<ReferenceLocation> FindAllMethodReferences(string methodName, Solution solution)
    {
        IMethodSymbol methodSymbol = null;


        bool found = false;

        foreach (var project in solution.Projects)
        {
            foreach (var document in project.Documents)
            {
                var model = document.GetSemanticModelAsync().Result;

                var methodInvocation = document.GetSyntaxRootAsync().Result;

                try
                {
                    var nodes = methodInvocation.DescendantNodes().OfType<InvocationExpressionSyntax>().Where(x => x.Expression.ToString().Contains(methodName));
                    foreach (var node in nodes)
                    {
                        if (node == null) continue;

                        var member = node?.Expression as MemberAccessExpressionSyntax;
                        if (member == null)
                            continue;

                        var name = member?.Name?.ToString();
                        if (name.IsEmpty()) continue;
                        if (name != methodName) continue;

                        methodSymbol = model.GetSymbolInfo(node).Symbol as IMethodSymbol;
                        found = true;
                        break;
                    }
                }
                catch (Exception exp)
                {
                    // Swallow the exception of type cast. 
                    // Could be avoided by a better filtering on above linq.
                    continue;
                }
            }

            if (found) break;
        }

        if (found == false) return Enumerable.Empty<ReferenceLocation>();
        if (methodSymbol == null) return Enumerable.Empty<ReferenceLocation>();

        var result = new List<ReferenceLocation>();
        var refrences = SymbolFinder.FindReferencesAsync(methodSymbol, solution).Result;

        foreach (var refernc in refrences)
        {
            foreach (var location in refernc.Locations)
            {
                result.Add(location);
            }
        }
        return result;
    }