SymbolFinder.FindReferencesAsync 没有找到任何东西

SymbolFinder.FindReferencesAsync doesn't find anything

我想在我的解决方案中找到所有 PropertyChangedEventHandler 事件,然后找到添加到这些事件的所有侦听器。但我似乎无法获得事件列表。

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

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() { }
    }
}

这是我用来分析它的代码。 references.Count == 1r.Locations.Count == 0,但应该恰好找到一个位置。这是怎么回事?

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

最近我做了类似的事情,我试图在完整的解决方案中找到一个方法的参考。 要使用 FindReferenceAsync,您首先要创建语义模型并从那里找到符号。获得符号后,您可以使用 FindReferenceAsync.

这是我使用的片段,它正在运行:

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

}

这里是 complete working code. If you want to visualize the Roslyn tree then you can try using Roslyn tree visualizer 查看代码结构。

更新

根据 OP 安装 Roslyn SDK 评论中的讨论解决了这个问题。假设在使用 GetCompilationAsync.

时,与 Nuget dll 相比,SDK 中可能有一些更新来生成符号信息