使用 Roslyn 查找对方法的所有引用

Finding all references to a method with Roslyn

我正在寻找扫描一组 .cs 文件以查看哪些调用了 Nullable<T>Value 属性(查找所有引用)。例如,这将匹配:

class Program
{
    static void Main()
    {
        int? nullable = 123;
        int value = nullable.Value;
    }
}

我了解了 Roslyn 并查看了一些示例,但其中很多已经过时并且 API 很大。我该怎么做?

解析语法树后卡住了。这是我目前所拥有的:

public static void Analyze(string sourceCode)
{
    var tree = CSharpSyntaxTree.ParseText(sourceCode);

    tree./* ??? What goes here? */
}

您可能正在寻找 SymbolFinder class and specifically the FindAllReferences 方法。

听起来您在熟悉 Roslyn 时遇到了一些困难。我有一系列博客文章可以帮助人们了解 Roslyn,名为 Learn Roslyn Now

正如@SLaks 提到的,您将需要访问我在 Part 7: Introduction to the Semantic Model

中介绍的语义模型

这是一个向您展示如何使用 API 的示例。如果可以,我会使用 MSBuildWorkspace 并从磁盘加载项目,而不是像这样在 AdHocWorkspace 中创建项目。

var mscorlib = PortableExecutableReference.CreateFromAssembly(typeof(object).Assembly);
var ws = new AdhocWorkspace();
//Create new solution
var solId = SolutionId.CreateNewId();
var solutionInfo = SolutionInfo.Create(solId, VersionStamp.Create());
//Create new project
var project = ws.AddProject("Sample", "C#");
project = project.AddMetadataReference(mscorlib);
//Add project to workspace
ws.TryApplyChanges(project.Solution);
string text = @"
class C
{
    void M()
    {
        M();
        M();
    }
}";
var sourceText = SourceText.From(text);
//Create new document
var doc = ws.AddDocument(project.Id, "NewDoc", sourceText);
//Get the semantic model
var model = doc.GetSemanticModelAsync().Result;
//Get the syntax node for the first invocation to M()
var methodInvocation = doc.GetSyntaxRootAsync().Result.DescendantNodes().OfType<InvocationExpressionSyntax>().First();
var methodSymbol = model.GetSymbolInfo(methodInvocation).Symbol;
//Finds all references to M()
var referencesToM = SymbolFinder.FindReferencesAsync(methodSymbol,  doc.Project.Solution).Result;

问题和最终修复的日志,我让 Roslyn 与 VS2017 一起工作:

挂接到 MSBuildWorkspace WorkspaceFailed 事件后,空 VS2017 项目的原因变得可见。

第一轮失败是:

MSB0001:内部 MSBuild 错误:Microsoft.Build.Utilities.ToolLocationHelper 的类型信息作为 Microsoft.Build.Utilities.ToolLocationHelper、Microsoft.Build.Utilities.Core、Version=15.1.0.0、Culture=neutral、PublicKeyToken= 存在于白名单缓存中b03f5f7f11d50a3a 但无法加载类型。意外为空])

已通过安装 NuGet 包解决此问题 Microsoft.Build.Locator 1.1.2 & Microsoft.Build.Utilities.Core 15.9.20

第二轮失败是:

Msbuild 在处理文件 'C:\Users...vbproj' 时失败并显示消息: C:\Program 文件 (x86)\Microsoft Visual Studio17\Enterprise\MSBuild.0\Bin\Microsoft.Common.CurrentVersion.targets: (1491, 5): 无法从程序集 Microsoft.Build.Tasks.Core、版本=15.1.0.0、文化=中性、PublicKeyToken=b03f5f7f11d50a3a 加载“Microsoft.Build.Tasks.AssignProjectConfiguration”任务。 无法加载文件或程序集 'Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' 或其依赖项之一。 该系统找不到指定的文件。确认声明正确,程序集及其所有依赖项可用,并且任务包含实现 Microsoft.Build.Framework.ITask.])

的 public class

已通过添加 NuGet Microsoft.Build.Tasks.Core 15.9.20

解决此问题

第三轮失败是: === Msbuild 在处理文件 'C:\Users...vbproj' 时失败并显示消息: C:\Program 文件 (x86)\Microsoft Visual Studio17\Enterprise\MSBuild.0\Bin\Microsoft.Common.CurrentVersion.targets: (1657, 5): 无法从程序集中实例化“GetReferenceNearestTargetFrameworkTask”任务 “C:\Program Files (x86)\Microsoft Visual Studio17\Enterprise\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.Build.Tasks.dll”。 请确认任务程序集是使用与您计算机上安装的程序集相同版本的 Microsoft.Build.Framework 程序集构建的 并且您的主机应用程序没有缺少 Microsoft.Build.Framework 的绑定重定向。 无法将类型 'NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask' 的对象转换为类型 'Microsoft.Build.Framework.ITask'。])

请注意项目的 Microsoft.Build.Framework.dll = 15.1.0.0 但消息中提到“MSBuild.0\Bin”

添加到 app.config - 已修复! cf enter link description here 我现在可以从 VS2017 解决方案加载项目

  <!-- vvv Roslyn manual fixup https://github.com/Microsoft/msbuild/issues/2369 -->
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Build.Framework" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Build" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Build.Utilities.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Build.Tasks.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
  </dependentAssembly>
  <!-- ^^^ Roslyn manual fixup https://github.com/Microsoft/msbuild/issues/2369 -->