【问题标题】:How can I have all references of a method in Roslyn (method is called by other classes)?如何在 Roslyn 中获取方法的所有引用(方法被其他类调用)?
【发布时间】:2022-02-09 00:00:07
【问题描述】:

感谢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 ? 

【问题讨论】:

    标签: c# roslyn roslyn-code-analysis


    【解决方案1】:

    您正在寻找SymbolFinder class 上的FindReferencesAsync() 方法。

    【讨论】:

    • 我尝试通过 SymbolFinder 查找位置,但每次都没有返回任何内容,但有几个参考请您可以通过代码回答我吗?我也测试了stackoverflow.com/questions/34340828/…这种方法,但不起作用
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-06-03
        • 2011-01-17
        • 1970-01-01
        • 2017-06-25
        • 1970-01-01
        • 2013-12-26
        • 1970-01-01
        相关资源
        最近更新 更多