【问题标题】:Replacing multiple nodes in Roslyn syntax tree替换 Roslyn 语法树中的多个节点
【发布时间】:2015-09-27 17:04:18
【问题描述】:

我正在尝试使用 roslyn 替换语法树中的几个节点。 但它的不变性似乎妨碍了我。

    public static string Rewrite(string content)
    {
        var tree = CSharpSyntaxTree.ParseText(content);
        var root = tree.GetRoot();

        var methods =root
            .DescendantNodes(node=>true)
            .OfType<MethodDeclarationSyntax>()
            .ToList();

        foreach(var method in methods)
        {
            var returnActions = method
                .DescendantNodes(node => true)
                .OfType<BinaryExpressionSyntax>()
                //Ok this is cheating
                .Where(node => node.OperatorToken.ValueText == "==")
                .Where(node => node.Right.ToString() == "\"#exit#\"" || node.Right.ToString() == "\"#break#\"")
                .Select(node => node.Parent as IfStatementSyntax)
                .ToList();

            var lookup = new Dictionary<StatementSyntax,StatementSyntax>();

            if (returnActions.Count > 0)
            {
                foreach(var ifStatement in returnActions)
                {
                    var mainCall = ifStatement.GetPrevious() as ExpressionStatementSyntax;                        
                    var newIfStatement = ifStatement.WithCondition(mainCall.Expression.WithoutTrivia());

                    lookup[mainCall] = null;
                    lookup[ifStatement] = newIfStatement;
                }

                //this only replace some of the nodes
                root = root.ReplaceNodes(lookup.Keys, (s, d) => lookup[s]);
            }
        }

        return root.ToFullString();
    }

问题是当我调用root.ReplaceNodes 时,只有一些节点被替换。

我猜是替换改变了树,使得其他节点不再匹配原始树,因此无法替换。

但是处理这个问题的最佳方法是什么?

一遍又一遍地循环这个过程,直到不再发生变化,感觉很糟糕:)

更改可以嵌套发生,我认为这就是导致问题的原因。 我可以以某种方式对变更集进行排序以解决这个问题,还是有一种惯用的方式来处理这里的事情?

【问题讨论】:

    标签: c# roslyn


    【解决方案1】:

    我猜是替换改变了树,使得其他节点不再匹配原始树,因此无法替换。

    你是对的。替换节点会创建全新的语法树。以前语法树中的节点无法与这些新语法树进行比较。

    有四种方法可以将多个更改应用于语法树:

    1. 使用DocumentEditor - 请参阅:https://stackoverflow.com/a/30563669/300908
    2. 使用 Annotations(第 236 和 240 行)
    3. 使用.TrackNodes()
    4. 创建一个CSharpSyntaxRewriter,以自下而上的方法替换节点。我已经在我的blog 上写过这个。

    在这些选项中,我相信DocumentEditor 以最易于使用而著称。这很可能是未来应用多项更改的惯用方式。

    【讨论】:

      猜你喜欢
      • 2017-04-23
      • 1970-01-01
      • 2017-12-29
      • 2019-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-01
      • 1970-01-01
      相关资源
      最近更新 更多