2016-12-01 19 views
6

Jak przetworzyć kompilację warunkowej kompilacji C# za pomocą Roslyn.Parsowanie C# Instrukcja warunkowej kompilacji w Roslyn

W poniższym kodzie, chcę, aby Roslyn nadała węzeł warunkowej instrukcji kompilacji.

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

nie dostać warunkową kompilację węzeł w SyntaxTree i nie jest częścią LeadingTrivia z } lub TrailingTrivia z {

Co dostaję w LeadingTrivia z } jest "\t\t#endif\r\n\t\t" i TrailingTrivia z { który jest "\r\n" nie jest kompletną instrukcją kompilacji warunkowej.

Czy ktoś może wskazać mi właściwy kierunek?

+0

Jeśli jesteś gotów rozważyć rozwiązanie non-Roslyn, mogę opisz jedno, gdzie ten proces jest wyjątkowo prosty. –

+0

@ ira-baxter To musi być roslyn specifc – adeel41

Odpowiedz

2

Jeśli zanalizować węzły przez użytkownika (CSharpSyntaxRewriter \ Walker) trzeba zastąpić:

public override SyntaxNode VisitIfDirectiveTrivia(IfDirectiveTriviaSyntax node) 
{ 
} 

public override SyntaxNode VisitElseDirectiveTrivia(ElseDirectiveTriviaSyntax node) 
{ 
} 

public override SyntaxNode VisitEndIfDirectiveTrivia(EndIfDirectiveTriviaSyntax node) 
{ 
} 

Jeśli chcesz dostać to nie przez odwiedzających, można to zrobić:

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

Możesz zobaczyć, co Roslyn generuje dla twojego warunku.

Aktualizacja

Sprawdziłem to i rzeczywiście tego rodzaju skomplikowanych tutaj, ponieważ jej nie Node oczywiście. Węzeł jest tylko return 2 lub jeśli napiszesz #define DEBUG jego return 1.

Tak więc, w przypadku gdy masz że dyrektywa warunkowa wewnątrz metody można zrobić coś takiego:

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

i nazwać tak:

GetConditionalDirectiveTrivia(method, SyntaxKind.IfDirectiveTrivia); 

Można go znaleźć na wiele sposobów bez The Kind, ale uważam, że jest wystarczająco dobry.

Pamiętaj, że to tylko przykład. Wracam tutaj tylko pierwsze ciekawostki.

W swoim prawdziwym kodzie możesz napisać bardziej eleganckie rozwiązanie (może nawet metodę rozszerzenia), aby uzyskać np. AllTriviaOfKind lub coś innego, co pasuje do twoich wymagań. Możesz także zwrócić drobiazgi tokenów lub węzeł nadrzędny, jeśli same ciekawostki są bezużyteczne, niezależnie od tego, czego potrzebujesz.

Mam nadzieję, że jej pomoc.

+0

Nie korzystam z odwiedzających, więc próbowałem wywoływać DescendantNodesAndSelf na węźle Method, ale nie widzę ConditionalDirectiveTriviaSyntax na liście, zamiast tego jest BlockSyntax (który jest zbyt ogólny) – adeel41

+0

@ adeel41 ' BlockSyntax' jest rodzicem całego twojego ciała metod. W tym bloku znajdziesz stwierdzenia, a następnie znajdziesz to, czego potrzebujesz. Więc jeśli twoim pierwotnym węzłem jest 'MethodDeclerationSyntax', musisz wejść w głąb, aby znaleźć to, czego szukasz. –

+0

@ adeel41 Piszę z mojego telefonu teraz .. Mogę zaktualizować moją odpowiedź wkrótce i pokażę ci dokładnie jak to zrobić (jeśli potrzebujesz) –

2

nie dostać warunkową kompilację węzeł w SyntaxTree i nie jest częścią LeadingTrivia z } lub TrailingTrivia z {

w rzeczywistości, to w LeadingTrivia słowa kluczowego return w return 2;.Przewód ciekawostki dla return jest:

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

Dzięki za udzielenie mi informacji o tym, jak znaleźć te informacje, ale nie jestem pewien, czy zrobię to w ten sposób, ponieważ wygląda na to, że muszę dużo parsować. – adeel41