我想跟踪 SyntaxNode
和 SyntaxTrivia
解决方案
/工作区
的不同版本。
我尝试使用 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
实际上并未按原样重新使用您的节点。相反,它“重放”与实际解决方案的文本更改相同的更改,然后让解析器重新解析。
发生这种情况有几个原因:
- 为了避免注释随着时间的推移在树中堆积并相互干扰(考虑在应用修复后仍然存在的 CodeFixes 中使用的格式或重命名注释之类的内容)。
- 防止不往返的树出现在
CurrentSolution
中。可以构造解析器永远不会生成的树(例如考虑更改运算符优先级)。 - 为了确保更改得到实际应用,需要更改原始表示形式 - 磁盘上的文件或内存中的文本缓冲区,而不仅仅是使用工作区中的新树。
您可以考虑使用类似 SyntaxPath
的内容从 Roslyn 源中键入以尝试找到等效节点。
关于roslyn - 如何跨 Workspace.TryApplyChanges() 跟踪 SyntaxNodes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34854628/