从新节点获取符号信息
Get symbol info from new node
我有一个覆盖 VisitMemberAccessExpression
的 CSharpSyntaxRewriter
,在那个方法中,我正在调用 MemberAccessExpressionSyntax.WithName()
,但是它 returns 的节点有一个不同的 SyntaxTree
与原始节点相比,这是一个问题,因为这意味着调用 SemanticModel.GetSymbolInfo(node)
.
时会抛出错误
有没有办法改变 MemberAccessExpressionSyntax
的 Name
但仍然有一个 SyntaxTree
可以与 SemanticModel.GetSymbolInfo(node)
一起使用?
我的代码是:
public sealed override SyntaxNode VisitNode(SyntaxNode node)
{
var nodeSyntax = (MemberAccessExpressionSyntax) node;
if (nodeSyntax.Name.ToString() == OldModifier && !HasSymbol(nodeSyntax, out _))
{
if (ModifierType == ModifierType.Damage)
nodeSyntax = nodeSyntax.WithName(IdentifierName($"GetDamage({NewModifier})"));
else
nodeSyntax = nodeSyntax.WithName(IdentifierName($"GetCritChance({NewModifier})"));
nodeSyntax = nodeSyntax.WithLeadingTrivia(node.GetLeadingTrivia()).WithTrailingTrivia(node.GetTrailingTrivia());
}
return nodeSyntax;
}
(VisitNode
从 VisitMemberAccessExpression
调用)
这里的图片显示了 SyntaxTree
中的差异:
原文:
调用 WithName
后:
有几种方法可以解决这样的问题:
改变您的访问方式
在对 VisitMemberAccessExpression 进行任何更改之前,您能否重组代码以调用 VisitNode??例如,您可以从:
var memberAccess = memberAccess.With...();
memberAccess = VisitNode(memberAccess);
return memberAccess;
至
var memberAccess = VisitNode(memberAccess);
memberAccess = memberAccess.With...();
return memberAccess;
那么这可能意味着您在完成重写之前正在访问原始节点。请注意,如果您正在执行递归操作,这仍然会很棘手。
使用替换节点
有一个 helper method 可以用来代替重写器。这将调用您传递的函数来在每一步进行重写,但是该函数将同时传递原始树中的原始节点和子节点被重写后的节点;您可以使用原始树来提出绑定问题(因为它来自原始树)并使用已重写以进行递归重写的问题。
将您的问题分成两步
做两次:首先获取所有需要更新的地方的列表,将这些 SyntaxNode 添加到 HashSet 或类似的地方,然后在更新这些地方的地方进行第二次重写。
我有一个覆盖 VisitMemberAccessExpression
的 CSharpSyntaxRewriter
,在那个方法中,我正在调用 MemberAccessExpressionSyntax.WithName()
,但是它 returns 的节点有一个不同的 SyntaxTree
与原始节点相比,这是一个问题,因为这意味着调用 SemanticModel.GetSymbolInfo(node)
.
有没有办法改变 MemberAccessExpressionSyntax
的 Name
但仍然有一个 SyntaxTree
可以与 SemanticModel.GetSymbolInfo(node)
一起使用?
我的代码是:
public sealed override SyntaxNode VisitNode(SyntaxNode node)
{
var nodeSyntax = (MemberAccessExpressionSyntax) node;
if (nodeSyntax.Name.ToString() == OldModifier && !HasSymbol(nodeSyntax, out _))
{
if (ModifierType == ModifierType.Damage)
nodeSyntax = nodeSyntax.WithName(IdentifierName($"GetDamage({NewModifier})"));
else
nodeSyntax = nodeSyntax.WithName(IdentifierName($"GetCritChance({NewModifier})"));
nodeSyntax = nodeSyntax.WithLeadingTrivia(node.GetLeadingTrivia()).WithTrailingTrivia(node.GetTrailingTrivia());
}
return nodeSyntax;
}
(VisitNode
从 VisitMemberAccessExpression
调用)
这里的图片显示了 SyntaxTree
中的差异:
原文:WithName
后:
有几种方法可以解决这样的问题:
改变您的访问方式
在对 VisitMemberAccessExpression 进行任何更改之前,您能否重组代码以调用 VisitNode??例如,您可以从:
var memberAccess = memberAccess.With...();
memberAccess = VisitNode(memberAccess);
return memberAccess;
至
var memberAccess = VisitNode(memberAccess);
memberAccess = memberAccess.With...();
return memberAccess;
那么这可能意味着您在完成重写之前正在访问原始节点。请注意,如果您正在执行递归操作,这仍然会很棘手。
使用替换节点
有一个 helper method 可以用来代替重写器。这将调用您传递的函数来在每一步进行重写,但是该函数将同时传递原始树中的原始节点和子节点被重写后的节点;您可以使用原始树来提出绑定问题(因为它来自原始树)并使用已重写以进行递归重写的问题。
将您的问题分成两步
做两次:首先获取所有需要更新的地方的列表,将这些 SyntaxNode 添加到 HashSet 或类似的地方,然后在更新这些地方的地方进行第二次重写。