繁体   English   中英

我怎样才能在 Roslyn 中获得一个方法的所有引用(方法被其他类调用)?

[英]How can I have all references of a method in Roslyn (method is called by other classes)?

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

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

在此处输入图像描述

实际上我想了解哪个类/名称空间甚至程序集正在通过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 ? 

您正在寻找SymbolFinderFindReferencesAsync()方法。

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

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

我更喜欢更改以下内容以使其工作:

 var nodes = methodInvocation.DescendantNodes().OfType<InvocationExpressionSyntax>()
   .Where(x => x.Expression.ToString().Contains(methodName));

到:

var nodes = new List<InvocationExpressionSyntax>();
foreach (var methodInvocationExpression in methodInvocation.DescendantNodes().OfType<InvocationExpressionSyntax>())
{
    if(methodInvocationExpression.DescendantNodes().OfType<MemberAccessExpressionSyntax>().Any(x => x.Name.Identifier.ValueText == methodName))
    {
        nodes.Add(methodInvocationExpression);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM