SymbolFinder.FindReferencesAsync未发现任何 [英] SymbolFinder.FindReferencesAsync doesn't find anything

查看:563
本文介绍了SymbolFinder.FindReferencesAsync未发现任何的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想找到我的解决方案均 PropertyChangedEventHandler 事件,然后找到所有的听众加入到这些事件。但我似乎无法得到的事件列表



这是在解决方案中的所有代码被分析:

 使用系统; 
使用System.Collections.Generic;
使用System.ComponentModel;
使用System.Linq的;
使用System.Text;使用System.Threading.Tasks
;

命名空间RoslynTarget
{
公共类实例:INotifyPropertyChanged的
{
公共事件PropertyChangedEventHandler的PropertyChanged =委托{};

公共无效DoNothing(){}
}
}

这是我分析它的代码。 references.Count == 1 r.Locations.Count == 0 ,但只有一个位置应该可以找到。这是怎么回事呢?



的Program.cs



 使用系统; 
使用System.Collections.Generic;
使用System.Linq的;
使用Microsoft.CodeAnalysis;
使用Microsoft.CodeAnalysis.CSharp.Syntax;使用Microsoft.CodeAnalysis.FindSymbols
;
使用Microsoft.CodeAnalysis.MSBuild;

命名空间RoslynTest
{
类节目
{
静态无效的主要(字串[] args)
{
常量字符串solutionPath = @C:\Users\<使用者> \Code\RoslynTarget\RoslynTarget.sln
常量字符串项目名=RoslynTarget;

VAR msWorkspace = MSBuildWorkspace.Create(新字典<字符串,字符串> {{CheckForSystemRuntimeDependency,真}});
VAR解决方案= msWorkspace.OpenSolutionAsync(solutionPath)。结果;

VAR项目=
solution.Projects
。凡(凸出=> proj.Name == PROJECTNAME)
。首先();

VAR编译= project.GetCompilationAsync()结果。
VAR EVENTTYPE = compilation.ResolveType(System.ComponentModel.PropertyChangedEventHandler)第一()。
VAR引用= SymbolFinder.FindReferencesAsync(EVENTTYPE,溶液)。结果;

的foreach(参考文献变种R)
{
的foreach(在r.Locations VAR LOC)
{
// ...
}
}
}
}
}

Extensions.cs

 使用系统; 
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;使用System.Threading.Tasks
;
使用Microsoft.CodeAnalysis;

命名空间RoslynTest
{
公共静态类扩展
{
公共静态的IEnumerable< INamedTypeSymbol> ResolveType(本汇编编译字符串classFullName)
{
返回新IAssemblySymbol [] {} compilation.Assembly
.Concat(compilation.References
。选择(compilation.GetAssemblyOrModuleSymbol)
.OfType< IAssemblySymbol>())
。选择(ASM => asm.GetTypeByMetadataName(classFullName))
。凡(CLS => CLS = NULL)!;
}
}
}


解决方案

最近我已经做了我在那里试图找到完整的解决方案的方法的参考类似的事情。
。要使用 FindReferenceAsync 您必须首先创建symantic模型,并从那里找到的符号。一旦你的符号,你可以使用 FindReferenceAsync



下面是我使用的代码片段,它的工作:

  VAR解= msWorkspace.OpenSolutionAsync(solutionPath)。结果; 
的foreach(在solution.Projects VAR项目)
{
的foreach(在project.Documents VAR文件)
{
VAR模型= document.GetSemanticModelAsync()。结果;

变种的MethodInvocation = document.GetSyntaxRootAsync()结果。
InvocationExpressionSyntax节点= NULL;

{
节点= methodInvocation.DescendantNodes()OfType< InvocationExpressionSyntax>()
。凡(X =>((MemberAccessExpressionSyntax)x.Expression).Name点。的ToString()==方法名).FirstOrDefault();

如果(节点== NULL)
继续;
}
赶上(例外的例外)
{
//燕子类型转换的异常。
//可以通过上面的LINQ较好的滤波来避免。
继续;
}

methodSymbol = model.GetSymbolInfo(节点).Symbol;
发现= TRUE;
中断;
}

如果(中)突破;
}

的foreach(在SymbolFinder.FindReferencesAsync(methodSymbol VAR项目,解决方案)。结果)
{
的foreach(在item.Locations VAR位置)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(项目大会 - > {0},location.Document.Project.AssemblyName);
Console.ResetColor();
}

}



这里的的完整的工作代码。如果你想可视化的罗斯林树,那么你可以尝试使用罗斯林树可视化以见代码结构



更新



根据讨论与OP安装的罗斯林人员固定的问题。假设由于使用时相比的NuGet DLL文件可能会有一些SDK更新生成符号信息 GetCompilationAsync


I want to find all PropertyChangedEventHandler events in my solution, and then find all listeners added to those events. But I can't seem to get a list of the events.

This is all the code in the solution being analyzed:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RoslynTarget
{
    public class Example : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged = delegate { };

        public void DoNothing() { }
    }
}

And this is my code for analyzing it. references.Count == 1 and r.Locations.Count == 0, but exactly one location should be found. What's going on here?

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.MSBuild;

namespace RoslynTest
{
    class Program
    {
        static void Main(string[] args)
        {
            const string solutionPath = @"C:\Users\<user>\Code\RoslynTarget\RoslynTarget.sln";
            const string projectName = "RoslynTarget";

            var msWorkspace = MSBuildWorkspace.Create(new Dictionary<string, string> { { "CheckForSystemRuntimeDependency", "true" } });
            var solution = msWorkspace.OpenSolutionAsync(solutionPath).Result;

            var project =
                solution.Projects
                    .Where(proj => proj.Name == projectName)
                    .First();

            var compilation = project.GetCompilationAsync().Result;
            var eventType = compilation.ResolveType("System.ComponentModel.PropertyChangedEventHandler").First();
            var references = SymbolFinder.FindReferencesAsync(eventType, solution).Result;

            foreach (var r in references)
            {
                foreach (var loc in r.Locations)
                {
                    // ...
                }
            }
        }
    }
}

Extensions.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;

namespace RoslynTest
{
    public static class Extensions
    {
        public static IEnumerable<INamedTypeSymbol> ResolveType(this Compilation compilation, string classFullName)
        {
            return new IAssemblySymbol[] { compilation.Assembly }
                .Concat(compilation.References
                    .Select(compilation.GetAssemblyOrModuleSymbol)
                    .OfType<IAssemblySymbol>())
                .Select(asm => asm.GetTypeByMetadataName(classFullName))
                .Where(cls => cls != null);
        }
    }
}

解决方案

Recently I've done similar thing where I was trying to find the reference of a method in complete solution. To use FindReferenceAsync you have create symantic model first and find the symbol from there. Once you have the symbol you can use the FindReferenceAsync.

Here's the snippet that I used and it's working:

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

        var methodInvocation = document.GetSyntaxRootAsync().Result;
        InvocationExpressionSyntax node = null;
        try
        {
            node = methodInvocation.DescendantNodes().OfType<InvocationExpressionSyntax>()
             .Where(x => ((MemberAccessExpressionSyntax)x.Expression).Name.ToString() == methodName).FirstOrDefault();

            if (node == null)
                continue;
        }
        catch(Exception exception)
        {
            // Swallow the exception of type cast. 
            // Could be avoided by a better filtering on above linq.
            continue;
        }

        methodSymbol = model.GetSymbolInfo(node).Symbol;
        found = true;
        break;
    }

    if (found) break;
}

foreach (var item in SymbolFinder.FindReferencesAsync(methodSymbol, solution).Result)
{
    foreach (var location in item.Locations)
    {
        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine("Project Assembly -> {0}", location.Document.Project.AssemblyName);
        Console.ResetColor();
    }

}

Here's the complete working code. If you want to visualize the Roslyn tree then you can try using Roslyn tree visualizer to see code structuring.

Update

As per discussion in comments with OP Installing Roslyn SDK fixed the issue. Assuming that there might be some updates in SDK to generate Symbols information as compared to Nuget dlls when using GetCompilationAsync.

这篇关于SymbolFinder.FindReferencesAsync未发现任何的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆