gpt4 book ai didi

c# - SyntaxRewriter.Visit* 不会访问所有类型的节点 *

转载 作者:行者123 更新时间:2023-11-30 13:48:42 24 4
gpt4 key购买 nike

已解决:mike z 是对的,我没有正确地调用 base 来继续递归。谢谢,迈克

我正在通过实现 SyntaxRewriter 使用 Roslyn 重写一些代码。

我遇到的奇怪事情是,当覆盖 SyntaxNode.VisitInvocationExpression(InvocationExpressionSyntax) 时,它不会访问树中的所有 InvocationExpressionSyntax 节点。 (我假设所有 SyntaxNode 类型都是一样的)

例如,给定这个调用表达式:

  controller.Add(5, 6).ToString();

它只访问整个表达式的节点,即使那里有 2 个调用。

虽然我当然可以编写递归函数或类似函数来解析子/嵌套 InvocationExpression 节点,但这似乎不一致且不方便。
为什么不访问整棵树中*类型的所有节点?

这是我的覆盖:

    public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node)
{
IdentifierNameSyntax ident = node.ChildNodes().OfType<IdentifierNameSyntax>().FirstOrDefault();
if (ident == null)
return node;//In my test case, the example above returns here when it's node is encountered. Shouldn't this then allow the walker to continue deeper into the node,
// finding the deeper nested Invocations?

string name = ident.PlainName;
if (!TempStore.ConstructedInvocations.ContainsKey(name))//not replacing this then
return node;

InvocationExpressionSyntax newInvocation = ((InvocationExpressionSyntax)TempStore.ConstructedInvocations[name]).WithArgumentList(node.ArgumentList);
return newInvocation;
}

在调试中单步执行该代码确认 controller.Add(5, 6).ToString();InvocationExpressionNode 确实有子 InvocationExpressionNodes 嵌套在里面。

最佳答案

我在使用 Roslyn API 时遇到了类似的问题。 Visit 方法在 Visit* 方法的基类实现中被递归调用。一旦您覆盖其中一个,您将负责访问所有子节点。您可以通过在您正在重写的节点上调用 base.Visit* 方法或在每个子节点上调用 Visit 来完成此操作。

这是一些示例代码,我在其中通过交换逻辑运算符 && 和 || 来重写它们。我使用不同的运算符构造一个新节点,然后调用 base.VisitBinaryExpression 以确保访问所有子节点。否则,我们只会重写表达式的一部分,如 var1 && (var2 || var3)。另一种可能的实现方式是在 node.Left 和 node.Right 上调用 Visit,然后根据这些结果构建新节点。

public class LogicalOperatorRewriter : SyntaxRewriter
{
public override SyntaxNode VisitBinaryExpression(BinaryExpressionSyntax node)
{
SyntaxKind newExpressionKind = GetNewKind(node.Kind);
BinaryExpressionSyntax newNode = (BinaryExpressionSyntax)Syntax.BinaryExpression(newExpressionKind, left: node.Left, right: node.Right).Format().GetFormattedRoot();
return base.VisitBinaryExpression(newNode);
}

private SyntaxKind GetNewKind(SyntaxKind kind)
{
switch (kind)
{
case SyntaxKind.LogicalAndExpression:
return SyntaxKind.LogicalOrExpression;
case SyntaxKind.LogicalOrExpression:
return SyntaxKind.LogicalAndExpression;
default: return kind;
}
}
}

关于c# - SyntaxRewriter.Visit* 不会访问所有类型的节点 *,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11707051/

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