【问题标题】:Re-writing if-statements: One of these statements ended up with one too many pair of braces重写 if 语句:其中一个语句以一对太多的大括号结束
【发布时间】:2016-01-13 16:58:44
【问题描述】:

我想编写一个方法来确保我的树中的所有 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;
    }
}

这是我的输出:

类程序 { 静态无效主() { 如果(真){{
Console.WriteL ine("这是真的!"); }}
如果(假){
Console.WriteLi ne("它是假的!"); }
} }

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

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

【问题讨论】:

    标签: c# roslyn


    【解决方案1】:

    您混合了两件事:要么使用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 的具体任务。

    为什么只有第一个语句有两个大括号?

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


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

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

    【讨论】:

    • 非常感谢您的帮助!你能解释一下你为什么建议我应该应用格式吗?
    • 因为如果你在没有注释的情况下打印它,它看起来像这样:i.imgur.com/0cvpZaR.png 这不是很漂亮;-) 使用注释你会得到这个:i.imgur.com/uXZAQ8k.png
    猜你喜欢
    • 2012-05-03
    • 2014-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-02
    • 1970-01-01
    • 2015-02-13
    • 2018-05-22
    相关资源
    最近更新 更多