使用 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 -->
我正在寻找扫描一组 .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 -->