我正在尝试替换Roslyn语法树中的节点,它只是工作,但有一种烦恼,觉得它应该不是问题.
语法树是由脚本生成的,我要的结果是基于脚本的语法树太-但由于某些原因,在树替换节点创建与更改后的选项一种新的语法树:在Kind成为Regular代替Script.这是可以解决的,SyntaxTree.WithRootAndOptions但如果我需要调用它,感觉就像我做错了.
示例程序:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Scripting;
using System;
using System.Linq;
class Program
{
static void Main(string[] args)
{
Script script = CSharpScript.Create("Console.WriteLine(\"Before\")",
ScriptOptions.Default.AddImports("System"));
var compilation = script.GetCompilation();
var tree = compilation.SyntaxTrees.Single();
var after = SyntaxFactory.LiteralExpression(
SyntaxKind.StringLiteralExpression,
SyntaxFactory.Literal("After"));
var root = tree.GetRoot();
var before = root.DescendantNodes().OfType<LiteralExpressionSyntax>().Single();
var newRoot = root.ReplaceNode(before, after);
var fixedTree = newRoot.SyntaxTree.WithRootAndOptions(newRoot, tree.Options);
Console.WriteLine(newRoot); // Console.WriteLine("After")
Console.WriteLine(tree.Options.Kind); // Script
Console.WriteLine(newRoot.SyntaxTree.Options.Kind); // Regular
Console.WriteLine(fixedTree.Options.Kind); // Script
}
}
Run Code Online (Sandbox Code Playgroud)
(输出在评论中.)
这种解决方法实际上是正确的,还是有一些不同的方式我应该替换树中的节点?
当您替换树中的节点时,您会创建一个新的节点子树。本质上,这个新的子树并不包含在语法树中。然而,如果您观察过该节点上的 SyntaxTree 属性,您会联想到一个新的属性。当它执行此操作时,原始的 SyntaxTree 早已不复存在,因此不可能保留解析选项。即使有可能,保留选项也毫无意义,因为您不再拥有解析器生成的树。
Roslyn 创建此 SyntaxTree 的原因是,所有子树在技术上都包含在 SyntaxTree 实例中,以便 Roslyn 可以将诊断与其关联。如果您使用 SemanticModel 的探索性 API 来尝试绑定和获取当前不属于编译的树片段的语义信息,这非常有用。诊断报告错误及其位置,指示错误所在的树实例。
| 归档时间: |
|
| 查看次数: |
1510 次 |
| 最近记录: |