Frage

Gelöst: Mike Z hatte Recht, ich habe die Basis nicht richtig aufgerufen, um die Rekursion fortzusetzen.Danke, Mike

Ich schreibe mit Roslyn etwas Code um, indem ich a SyntaxRewriter.

Das Seltsame, worauf ich stoße, ist das beim Überschreiben SyntaxNode.VisitInvocationExpression(InvocationExpressionSyntax), es besucht NICHT alle InvocationExpressionSyntax Knoten im Baum.(Ich gehe davon aus, dass es für alle gleich ist SyntaxNode Typen)

Zum Beispiel mit diesem Aufrufausdruck:

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

Es besucht den Knoten nur für den gesamten Ausdruck, obwohl es dort zwei Aufrufe gibt.

Obwohl ich sicherlich eine rekursive Funktion oder ähnliches schreiben kann, um untergeordnete/verschachtelte InvocationExpression-Knoten zu analysieren, erscheint mir dies inkonsistent und unpraktisch.
Warum werden nicht alle Knoten vom Typ * im gesamten Baum besucht?

Hier ist meine Überschreibung:

    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;
    }

Das Durchlaufen dieses Codes im Debug bestätigt, dass die InvocationExpressionNode für controller.Add(5, 6).ToString(); hat tatsächlich ein Kind InvocationExpressionNodes innen verschachtelt.

War es hilfreich?

Lösung

Ich habe mit der Roslyn-API gespielt und hatte ein ähnliches Problem.Die Visit-Methode wird in der Basisklassenimplementierung der Visit*-Methoden rekursiv aufgerufen.Sobald Sie einen davon überschreiben, übernehmen Sie die Verantwortung für den Besuch aller untergeordneten Knoten.Sie können dies tun, indem Sie entweder die Methode base.Visit* auf dem Knoten aufrufen, den Sie neu schreiben, oder Visit auf jedem der untergeordneten Knoten aufrufen.

Hier ist ein Beispielcode, in dem ich die logischen Operatoren && und || umschreibe, indem ich sie vertausche.Ich erstelle einen neuen Knoten mit einem anderen Operator und rufe dann „base.VisitBinaryExpression“ auf, um sicherzustellen, dass alle untergeordneten Knoten besucht werden.Andernfalls würden wir nur einen Teil eines Ausdrucks wie umschreiben var1 && (var2 || var3).Eine andere mögliche Implementierung wäre, Visit auf node.Left und node.Right aufzurufen und dann den neuen Knoten aus diesen Ergebnissen zu erstellen.

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;
        }
    }
}

Andere Tipps

Ich kenne die Roslyn-API nicht, aber mit Ausdrucksbäumen (ExpressionVisitor), müssen Sie die Basismethode aufrufen, um den Baum weiter unten zu durchsuchen.

Dies liegt daran, dass Ihre Methode dies möglicherweise möchte stoppen Besuch unten am Baum.Wenn Sie aufhören wollten, könnten Sie die Basismethode einfach nicht aufrufen.

Das Beispielcode scheint diese Theorie zu stützen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top