2016-12-01 6 views
6

Как разобрать оператор условной компиляции C# с использованием Roslyn.Parsing C# Условные инструкции компиляции в roslyn

В следующем коде я хочу, чтобы Roslyn предоставил узел инструкции условной компиляции.

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

Я не получаю условный узел компиляции в SyntaxTree и ни он не является частью LeadingTrivia из } или TrailingTrivia из {

Что я получаю в LeadingTrivia из } является "\t\t#endif\r\n\t\t" и TrailingTrivia из { является "\r\n", который не является полным условным компилятором.

Может ли кто-нибудь указать мне в правильном направлении?

+0

Если вы готовы рассмотреть решение, не Roslyn, я могу описывают, где этот процесс чрезвычайно прост. –

+0

@ ira-baxter это должно быть roslyn specificc – adeel41

ответ

2

Если разобрать узлы с помощью посетителя (CSharpSyntaxRewriter \ Walker), необходимо переопределить:

public override SyntaxNode VisitIfDirectiveTrivia(IfDirectiveTriviaSyntax node) 
{ 
} 

public override SyntaxNode VisitElseDirectiveTrivia(ElseDirectiveTriviaSyntax node) 
{ 
} 

public override SyntaxNode VisitEndIfDirectiveTrivia(EndIfDirectiveTriviaSyntax node) 
{ 
} 

Если вы хотите, чтобы получить это не через посетителей, вы можете сделать это:

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

Вы можете посмотреть here, чтобы узнать, что Roslyn генерирует для вашего условного.

Update

Я проверил это, и в самом деле его вид сложных здесь, потому что его не Node конечно. Узел просто return 2 или если вы напишите #define DEBUG его return 1.

Таким образом, в случае, если у вас есть, что условная директива внутри метода вы можете сделать что-то вроде этого:

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

И называть это так:

GetConditionalDirectiveTrivia(method, SyntaxKind.IfDirectiveTrivia); 

Вы можете найти его в более способами без Добрый, но я думаю, что он достаточно хорош.

Обратите внимание, что это только пример. Я возвращаю сюда только первые мелочи.

В вашем реальном коде вы можете написать более элегантное решение (возможно, даже метод расширения), чтобы получить, например, AllTriviaOfKind или что-то еще, что соответствует вашим требованиям. Кроме того, вы можете вернуть пустые значения маркера или родительский узел, если сами пустяки бесполезны для вас, независимо от того, что вам нужно.

Я надеюсь его помощь.

+0

Я не пользуюсь посетителями, поэтому я попробовал вызывать DescendantNodesAndSelf на узле Method, но я не вижу ConditionalDirectiveTriviaSyntax в списке, вместо этого есть BlockSyntax (который является слишком общим) – adeel41

+0

@ adeel41 ' BlockSyntax' является родителем всего тела вашего метода. Внутри этого блока вы найдете заявления, и тогда вы найдете то, что вам нужно. Поэтому, если ваш исходный узел является 'MethodDeclerationSyntax', вам нужно углубиться, чтобы найти то, что вы хотите. –

+0

@ adeel41 Я пишу с моего телефона сейчас .. Я могу быстро обновить свой ответ и показать вам, как это сделать (если вам нужно) –

2

Я не получаю условный узел компиляции в SyntaxTree и ни он не является частью LeadingTrivia из } или TrailingTrivia из {

В самом деле, это в LeadingTrivia от return ключевого слова в return 2;.Свинцовые мелочи для return является:

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

Спасибо, что предоставил мне некоторую информацию о том, как найти эту информацию, но не уверен, что я сделаю так, потому что, похоже, мне приходится разбираться много. – adeel41

 Смежные вопросы

  • Нет связанных вопросов^_^