SymbolFinder.FindReferencesAsync找不到任何东西

时间:2015-12-17 17:33:55

标签: c# roslyn

我想在我的解决方案中找到所有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);
        }
    }
}

1 个答案:

答案 0 :(得分:5)

最近我做了类似的事情,我试图在完整的解决方案中找到方法的参考。 要使用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。如果您想要显示Roslyn树,那么您可以尝试使用Roslyn tree visualizer来查看代码结构。

更新

根据OP安装Roslyn SDK的评论中的讨论解决了这个问题。假设在使用GetCompilationAsync时,与Nuget dll相比,SDK中可能会有一些更新来生成符号信息。