解决了: mike z是对的,我没有正确地调用基数来继续递归.谢谢,迈克
我正在使用Roslyn进行一些代码重写,通过实现一个SyntaxRewriter.
我遇到的奇怪的事情是,当覆盖时SyntaxNode.VisitInvocationExpression(InvocationExpressionSyntax),它不会访问InvocationExpressionSyntax树中的所有节点.(我认为所有SyntaxNode类型都是一样的)
例如,给定此调用表达式:
controller.Add(5, 6).ToString();
Run Code Online (Sandbox Code Playgroud)
它只访问整个表达式的节点,即使有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;
}
Run Code Online (Sandbox Code Playgroud)
在调试中单步调试代码确认InvocationExpressionNodefor controller.Add(5, 6).ToString();确实有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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
822 次 |
| 最近记录: |