SyntaxRewriter и множественные операторы

Я столкнулся со сложной ситуацией, используя SyntaxRewriter в Roslyn. Я хотел бы переписать некоторые виды операторов, включая объявления локальных переменных. Решение требует, чтобы я преобразовал рассматриваемые операторы в несколько операторов, как в следующем тривиальном примере:

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.\");");
        }
    }
}
6
задан Jeff Griffin 20 March 2012 в 20:25
поделиться