Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 替换Roslyn语法树中的多个节点_C#_Roslyn - Fatal编程技术网

C# 替换Roslyn语法树中的多个节点

C# 替换Roslyn语法树中的多个节点,c#,roslyn,C#,Roslyn,我试图用roslyn替换语法树中的几个节点。 但它的永恒性似乎妨碍了我 public static string Rewrite(string content) { var tree = CSharpSyntaxTree.ParseText(content); var root = tree.GetRoot(); var methods =root .DescendantNodes(node=>tru

我试图用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时,只有部分节点被替换

我猜替换会更改树,使其他节点不再与原始树匹配,因此无法替换

但处理这一问题的最佳方式是什么

一次又一次地在流程上循环,直到不再发生变化,这感觉很糟糕:

这些变化可以嵌套发生,我认为这就是问题的原因。 我可以通过某种方式对变更集进行排序来绕过这个问题吗?或者这里有一种惯用的方式来处理事情吗

我猜替换会更改树,使其他节点不再与原始树匹配,因此无法替换

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

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

使用-请参阅: 使用第236行和第240行 使用 创建以自下而上的方式替换节点的。我已经在我的电脑上写过了。 在这些选项中,我相信DocumentEditor是最容易使用的。这很可能是未来应用多个更改的惯用方法