2016-12-01 4 views
6

Wie Parsing C# bedingte Kompilierung Anweisung mit Roslyn.Parsing C# Bedingte Compilation-Anweisungen in Roslyn

Im folgenden Code möchte ich, dass Roslyn den Anweisungsknoten Bedingte Kompilierung gibt.

public abstract class TestClass 
{ 
    public int Get() 
    { 
    #if DEBUG 
     return 1; 
    #else 
     return 2; 
    #endif 
    } 
} 

Ich habe nicht die bedingte Kompilierung Knoten in SyntaxTree und weder es ist ein Teil von LeadingTrivia von } oder TrailingTrivia von {

Was ich in LeadingTrivia von } bekommen ist "\t\t#endif\r\n\t\t" und TrailingTrivia von { ist "\r\n" die ist keine vollständige bedingte Kompilierungsanweisung.

Kann mir jemand in die richtige Richtung zeigen?

+0

Wenn Sie bereit sind, eine nicht-Roslyn Lösung zu betrachten, kann ich Beschreiben Sie eine, wo dieser Prozess extrem einfach ist. –

+0

@ ira-baxter es muss roslyn specifc sein – adeel41

Antwort

2

Wenn Sie die Knoten über Besucher (CSharpSyntaxRewriter \ Walker) analysieren müssen Sie außer Kraft zu setzen:

public override SyntaxNode VisitIfDirectiveTrivia(IfDirectiveTriviaSyntax node) 
{ 
} 

public override SyntaxNode VisitElseDirectiveTrivia(ElseDirectiveTriviaSyntax node) 
{ 
} 

public override SyntaxNode VisitEndIfDirectiveTrivia(EndIfDirectiveTriviaSyntax node) 
{ 
} 

Wenn Sie dies nicht über Besucher erhalten möchten, können Sie dies tun:

node.DescendantNodesAndSelf().OfType<ConditionalDirectiveTriviaSyntax>(); 

Sie können einen Blick auf here werfen, um zu sehen, was Roslyn für Ihre Bedingung erzeugt.

aktualisiert

Ich habe es, und in der Tat seine Art hier komplizierter, weil es nicht Node natürlich. Der Knoten ist nur return 2 oder wenn Sie schreiben #define DEBUG seine return 1.

Also, falls Sie haben, dass bedingte Direktive innerhalb Methode, die Sie so etwas tun kann:

// First get the relevant method (or any other parent block depending in the case) 
var method = root.DescendantNodes().OfType<MethodDeclarationSyntax>().First(); 

// Then, you can write method similar to this 
static SyntaxTrivia GetConditionalDirectiveTrivia(SyntaxNode node, SyntaxKind kind) 
{ 
    foreach (SyntaxNode syntaxNode in node.DescendantNodes()) 
    { 
     var trivia = syntaxNode.GetLeadingTrivia().FirstOrDefault(t => t.Kind() == kind); 
     if (trivia != default(SyntaxTrivia)) 
      return trivia; 
     GetConditionalDirectiveTrivia(syntaxNode, kind); 
    } 
    return default(SyntaxTrivia); 
} 

Und es so nennen:

GetConditionalDirectiveTrivia(method, SyntaxKind.IfDirectiveTrivia); 

Sie es in mehr Wege finden können, ohne die Art, aber ich denke, es ist gut genug.

Beachten Sie, dass es nur ein Beispiel ist. Ich komme hier nur auf die ersten Kleinigkeiten zurück.

In Ihrem echten Code können Sie elegantere Lösung (vielleicht sogar eine Erweiterungsmethode) schreiben, um zum Beispiel oder etwas anderes zu bekommen, das Ihren Anforderungen entspricht. Sie können auch die Token Trivia oder den Elternknoten zurückgeben, wenn die Trivia selbst für Sie nutzlos ist, was immer Sie wollen.

Ich hoffe es hilft.

+0

Ich benutze keine Besucher, so versuchte ich DescendantNodesAndSelf auf Method-Knoten aufrufen, aber ich sehe ConditionalDirectiveTriviaSyntax in der Liste statt gibt es eine BlockSyntax (die zu allgemein ist) – adeel41

+0

@ adeel41 ' BlockSyntax' ist das übergeordnete Element Ihres gesamten Methodenkörpers. In diesem Block finden Sie Aussagen und dann finden Sie, was Sie brauchen. Also, wenn Ihr ursprünglicher Knoten 'MethodDeclerationSyntax' ist, müssen Sie tief in das finden, was Sie wollen. –

+0

@ adeel41 Ich schreibe jetzt von meinem Handy .. Ich kann meine Antwort bald aktualisieren und Ihnen genau zeigen, wie das geht (wenn Sie brauchen) –

2

ich nicht bedingte Kompilierung Knoten in SyntaxTree erhalten und weder es ist ein Teil von LeadingTrivia von } oder TrailingTrivia von {

In der Tat ist es in den LeadingTrivia des return Stichwort in return 2;.Die Führung Trivia für return ist:

  • IfDirectiveTrivia (#if DEBUG)
  • DisableTextTrivia (return 1;)
  • ElseDirectiveTrivia (#else)
+0

Danke, dass Sie mir einige Informationen gegeben haben, wie ich diese Informationen finden kann, aber ich bin mir nicht sicher, ob ich das machen werde, weil es so aussieht, dass ich viel analysieren muss. – adeel41