我在Roslyn中遇到了使用SyntaxRewriter的棘手情况。我想重写某些类型的语句,包括局部变量声明。该解决方案要求我改变的语句有问题成多个语句,如下面的小例子:SyntaxRewriter和多个语句
void method()
{
int i;
}
成为
void method()
{
int i;
Console.WriteLine("I declared a variable.");
}
我在哪里见过块用于完成其他例子类似的东西,但当然在变量声明的情况下,声明的范围将受到影响。我提出了以下解决方案,但我对此很感兴趣。它似乎过于复杂,并需要在访问者模式中断:
class Rewriter: SyntaxRewriter
{
public override SyntaxList<TNode> VisitList<TNode>(SyntaxList<TNode> list)
{
if (typeof(TNode) == typeof(StatementSyntax))
return Syntax.List<TNode>(list.SelectMany(st => RewriteStatementInList(st as StatementSyntax).Cast<TNode>()));
else
return base.VisitList<TNode>(list);
}
private IEnumerable<SyntaxNode> RewriteStatementInList(StatementSyntax node)
{
if (node is LocalDeclarationStatementSyntax)
return PerformRewrite((LocalDeclarationStatementSyntax)node);
//else if other cases (non-visitor)
return Visit(node).AsSingleEnumerableOf();
}
private IEnumerable<SyntaxNode> PerformRewrite(LocalDeclarationStatementSyntax orig)
{
yield return orig;
yield return Syntax.ParseStatement("Console.WriteLine(\"I declared a variable.\");");
}
}
我错过了什么?编辑语句并删除它们(通过空语句)似乎比重写为倍数更直接。
我采取了答案:
class Rewriter : SyntaxRewriter
{
readonly ListVisitor _visitor = new ListVisitor();
public override SyntaxList<TNode> VisitList<TNode>(SyntaxList<TNode> list)
{
var result = Syntax.List(list.SelectMany(_visitor.Visit).Cast<TNode>());
return base.VisitList(result);
}
private class ListVisitor : SyntaxVisitor<IEnumerable<SyntaxNode>>
{
protected override IEnumerable<SyntaxNode> DefaultVisit(SyntaxNode node)
{
yield return node;
}
protected override IEnumerable<SyntaxNode> VisitLocalDeclarationStatement(
LocalDeclarationStatementSyntax node)
{
yield return node;
yield return Syntax.ParseStatement("Console.WriteLine(\"I declared a variable.\");");
}
}
}
我正在考虑这样做。唯一不利的一面是IEnumerable只会在调用VisitList的时候才有意义。我认为一个建筑师/作家会是一个令人信服的答案,但我认为我过于沉迷于此:)我会在晚些时候对你们大加赞赏,显然我还没有足够的影响力。 – 2012-03-20 18:38:09
为什么只有在调用'VisitList()'时IEnumerable才有意义?无论何时用一系列节点替换一个节点是有意义的,我想这个节点应该是某个列表的一部分。 – svick 2012-03-20 19:43:21
其实,我没有注意到你只是直接调用'Visitor',只能从'VisitList'调用。我非常喜欢这个解决方案。我将把它放在我的问题中,用'yield return'来生成迭代器并嵌套列表访问者类。 – 2012-03-20 20:21:37