c# - 重写if语句: One of these statements ended up with one too many pair of braces

标签 c# roslyn

我想编写一个方法来确保树中的所有 if 语句后面都跟着大括号代码块。这是我的代码:

class Program
{
    static void Main(string[] args)
    {
        var tree = CSharpSyntaxTree.ParseText(@"
                                                class Program
                                                {
                                                    static void main()
                                                    {
                                                        if(true)
                                                            Console.WriteLine(""It was true!"");
                                                        if(false)
                                                            Console.WriteLine(""It was false!"");
                                                    }
                                                }");

        var root = tree.GetRoot();
        var rewriter = new MyRewriter();

        var newRoot = rewriter.Visit(root);
        var ifStatements = newRoot.DescendantNodes().OfType<IfStatementSyntax>();

        foreach (var ifStatement in ifStatements)
        {
            SyntaxNode newIfStatement = rewriter.VisitIfStatement(ifStatement);
            newRoot = newRoot.ReplaceNode(ifStatement, newIfStatement);
        }

        var result = newRoot;

        Console.WriteLine(result.ToString());
        Console.ReadKey();
    }
}

public class MyRewriter: CSharpSyntaxRewriter
{
    public override SyntaxNode VisitIfStatement(IfStatementSyntax node)
    {
        var body = node.Statement;
        var block = SyntaxFactory.Block(body);
        var newIfStatement = node.WithStatement(block);

        return newIfStatement;
    }
}

这是我的输出:

class Program { static void main() { if(true) {{
Console.WriteL ine("It was true!"); }}
if(false) {
Console.WriteLi ne("It was false!"); }
} }

如您所见,第一个 if 语句后面的代码块被括起来两次(不是如预期的那样),而第二个 if 语句后面的代码块仅被括起来一次(如预期的那样) )。

我确信我对 Roslyn 的工作原理有一些错误的假设,所以有人可以告诉我哪里出了问题吗?我应该做出哪些改变?

最佳答案

您正在混合两件事:要么使用SyntaxRewriter,要么“手动”执行。现在您正在执行这两件事:首先调用重写器,然后循环遍历其所有节点并在每个 IfStatementSyntax 上再次调用重写器。

  • 修复所有 if 语句:var newRoot = rewriter.Visit(root);

  • 手动替换所有 if 语句:

var ifStatements = newRoot.DescendantNodes().OfType<IfStatementSyntax>();

foreach (var ifStatement in ifStatements)
{
    SyntaxNode newIfStatement = rewriter.VisitIfStatement(ifStatement);
    newRoot = newRoot.ReplaceNode(ifStatement, newIfStatement);
}

您可以完全省略循环:这具体是 SyntaxRewriter 的任务。

Why did only the first statement get two braces?

例如,应通过 DocumentEditor 对树进行多次修改。第一次替换后,ifStatements 集合中的第二个 IfStatementSyntax 与您因第一次替换而收到的新创建的语法树不同步。由于不同步,原始 ifStatementSyntax 的位置现在位于新创建的树中的不同位置(已添加括号 --> 根据应用的格式,这会移动所有字符至少一个位置)。 结果:第一次替换成功,第二次替换失败(静默)。


进一步说明:通过向添加的节点添加 Formatter 注解并随后调用 Formatter.Format 来应用格式化,如下所示:

var newRoot = rewriter.Visit(root).WithAdditionalAnnotations(Formatter.Annotation);
var result = Formatter.Format(newRoot, Formatter.Annotation, new AdhocWorkspace());

关于c# - 重写if语句: One of these statements ended up with one too many pair of braces,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34772602/

相关文章:

c# - 在 .isPasswordExpired 和服务器线程、版本上使用 c# 连接 mysql 时出现空引用异常

c# - Silverlight 中的 MediaElement 抛出 System.Exception 6028

c# - 正在删除程序集 : part from AssemblyInfo. cs

c# - Roslyn CTP - 如何将更改写入文件系统

c# - 通用应用未处理异常 (KERNELBASE.DLL)

c# - 跟踪在从 VB6 EXE 加载的 .NET DLL 中不起作用

c# - .Net MemoryStream关闭问题

c# - Roslyn 模型是否以 C#/VB.NET 为中心以至于现在和将来都无法进行 XAML 分析?

Roslyn:从元模型创建程序集

C# 静态分析,变量/参数的可能值