gpt4 book ai didi

c# - 为什么 SyntaxNode.ReplaceNode 会更改 SyntaxTree 选项?

转载 作者:IT王子 更新时间:2023-10-29 04:22:19 29 4
gpt4 key购买 nike

我正在尝试替换 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
}
}

(输出在评论中。)

这个变通办法是否真的正确,或者是否有一些不同的方法我应该替换树中的节点?

最佳答案

当您替换树中的节点时,您会创建一个新的节点子树。本质上,这个新的子树不包含在 SyntaxTree 中。但是,如果您观察节点上的 SyntaxTree 属性,就会联想到一个新属性。在执行此操作时,原来的 SyntaxTree 早已不复存在,因此无法保留解析选项。即使可能,保留选项也毫无意义,因为您不再拥有解析器生成的树。

Roslyn 创建此 SyntaxTree 的原因是所有子树在技术上都包含在 SyntaxTree 实例中,以便 Roslyn 可以将诊断与其相关联。如果您使用 SemanticModel 的探索性 API 来尝试绑定(bind)和获取当前不属于编译的树片段的语义信息,这将很有用。诊断报告错误及其位置,这表示错误所在的树实例。

关于c# - 为什么 SyntaxNode.ReplaceNode 会更改 SyntaxTree 选项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44060524/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com