2

我想跨不同版本的/跟踪SyntaxNodes 和s 。SyntaxTriviaSolutionWorkspace

我尝试用SyntaxAnnotations 注释一些节点。只要我不更新工作区,这就会很好。

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

  • 这让我很惊讶。为什么会这样?
  • 如何SyntaxNode跨工作区更新跟踪 s?

示例代码如下:

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?
4

1 回答 1

4

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

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

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

您可以考虑使用类似SyntaxPathRoslyn 来源的类型来尝试找到等效节点。

于 2016-01-18T18:36:42.550 回答