简体   繁体   English

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

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

Thanks to Roslyn , having access to.Net compiler, in our project Gcop we need to have list of references where are calling a method.感谢Roslyn ,可以访问 .Net 编译器,在我们的项目Gcop中,我们需要有调用方法的引用列表。

VS IDE shows the reference places very suitable like this: VS IDE 显示参考位置非常适合这样:

在此处输入图像描述

Actually I want to understand which class/name space and even assembly is calling my method by Roslyn C# syntax.实际上我想了解哪个类/名称空间甚至程序集正在通过Roslyn C# 语法调用我的方法。

Currently I have access to MethodSymbol here:目前我可以在这里访问 MethodSymbol:

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

what should I write to get access to references of this method?我应该写什么来访问这个方法的引用?

//added recently for double check //最近添加以进行双重检查

 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()方法。

I tested this approach but is not quick , and can not find some syntax 我测试了这种方法,但是速度并不快,并且找不到一些语法

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

I prefer to change following to make it work:我更喜欢更改以下内容以使其工作:

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

To:到:

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.

相关问题 使用Roslyn查找对方法的所有引用 - Finding all references to a method with Roslyn 如何使用Roslyn的OpenSolutionAsync解决所有引用? - How can I resolve all references with Roslyn's OpenSolutionAsync? Roslyn - 如何在DiagnosticAnalyzer类中获取变量的所有引用? - Roslyn - How can I get all references of a variable at DiagnosticAnalyzer class? Roslyn 在解决方案的所有项目中查找对方法的所有引用 - Roslyn Find ALL References to a Method in ALL Projects in a Solution Roslyn - 使用调用详细信息(具体的通用参数)查找对方法的所有引用 - Roslyn - find all references to method with invocation details (concrete generic arguments) 如何在类或部分类文件中找到Roslyn中方法的所有签名(重载)? - How can I find all signatures(overloads) of a method in Roslyn in a class or partial class files? 当该方法没有符号信息时,如何使用 Roslyn 获取被调用方法的包含命名空间? - How do I get the containing namespace of a called method using Roslyn when that method has no symbol info? 如何使用roslyn向方法添加参数? - How i can add parameters to method using roslyn? 如何确保类可以在另一个类上调用方法,但其他类不能调用该方法? - How do I ensure a Class can call a method on another Class, but not other Classes can call that method? 如何仅基于使用Roslyn的接口来识别方法实现是否标记为异步/可以异步调用? - How to identify if the method implementation is marked as async / can be called asynchronously, based only on its interface using Roslyn?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM