roslyn - 如何跨 Workspace.TryApplyChanges() 跟踪 SyntaxNodes

标签 roslyn roslyn-code-analysis

我想跟踪 SyntaxNodeSyntaxTrivia 解决方案/工作区的不同版本。

我尝试使用 SyntaxAnnotation 注释一些节点。 只要我不更新工作区,这就可以正常工作。

调用Workspace.TryApplyChanges(成功)似乎删除 所有SyntaxAnnotation

  • 这让我很惊讶。为什么会出现这种情况?
  • 如何跟踪工作区更新中的 SyntaxNode

示例代码如下:

var workspace = new AdhocWorkspace();
var project   = workspace.AddProject("TestProject", LanguageNames.CSharp);

var klass = SyntaxFactory
           .ClassDeclaration("Klass")
           .WithAdditionalAnnotations(new SyntaxAnnotation("Foo"));

var compUnit = SyntaxFactory.CompilationUnit().AddMembers(klass);
var document = project.AddDocument("TestFile.cs", compUnit);
var docId    = document.Id;
var solution = document.Project.Solution;

var root1  = document.GetSyntaxRootAsync().Result;
var klass1 = root1.GetAnnotatedNodes("Foo").FirstOrDefault();
var eq1    = klass1.IsEquivalentTo(klass); // returns true

var apply = workspace.TryApplyChanges(solution);  // returns true

var root2  = workspace.CurrentSolution.GetDocument(docId).GetSyntaxRootAsync().Result;
var klass2 = root2.GetAnnotatedNodes("Foo").FirstOrDefault(); // returns null, why?

最佳答案

发生这种情况是因为 TryApplyChanges 实际上并未按原样重新使用您的节点。相反,它“重放”与实际解决方案的文本更改相同的更改,然后让解析器重新解析。

发生这种情况有几个原因:

  1. 为了避免注释随着时间的推移在树中堆积并相互干扰(考虑在应用修复后仍然存在的 CodeFixes 中使用的格式或重命名注释之类的内容)。
  2. 防止不往返的树出现在 CurrentSolution 中。可以构造解析器永远不会生成的树(例如考虑更改运算符优先级)。
  3. 为了确保更改得到实际应用,需要更改原始表示形式 - 磁盘上的文件或内存中的文本缓冲区,而不仅仅是使用工作区中的新树。

您可以考虑使用类似 SyntaxPath 的内容从 Roslyn 源中键入以尝试找到等效节点。

关于roslyn - 如何跨 Workspace.TryApplyChanges() 跟踪 SyntaxNodes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34854628/

相关文章:

c# - 如何将 Expression 转换为 CSharpCompilation 或 CSharpSyntaxTree?

c# - 为什么 roslyn 在放入数组时将对象包装在结构中?

c# - 我如何才能在罗斯林返回?

c# - 使用 Roslyn 在服务器端 API 上安全执行代码

roslyn - Visual Studio 2015 包扩展,未复制引用的 dll

c# - 如何在 .NET 代码分析器中获取解决方案路径

roslyn - 如何使用 Roslyn 获取 IEnumerable<T> 的基础类型?

c# - Roslyn TypeDeclarationSyntax、MethodDeclarationSyntax、FieldDeclarationSyntax 具有公共(public)属性但没有公共(public)基类或接口(interface)

c# - 使用 Roslyn SDK 生成器生成的自定义 SonarQube 规则始终发出类型 "Code Smell"

c# - 我可以在带有 .NET 4.7 的 Visual Studio 2017 中使用 "Roslyn"吗?