C # parsing Conditional compilation instructions in roslyn

How to parse C # conditional compilation operator using Roslyn.

In the following code, I want Roslyn to provide the conditional compilation operator node.

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

I don’t get conditional compilation of node in SyntaxTree and not included in LeadingTrivia from } or TrailingTrivia from {

What I get in LeadingTrivia from } is "\t\t#endif\r\n\t\t" , and TrailingTrivia of { is "\r\n" , which is not a complete conditional compilation operator.

Can someone point me in the right direction?

+6
source share
2 answers

If you are analyzing nodes through a visitor (CSharpSyntaxRewriter \ Walker), you need to override:

 public override SyntaxNode VisitIfDirectiveTrivia(IfDirectiveTriviaSyntax node) { } public override SyntaxNode VisitElseDirectiveTrivia(ElseDirectiveTriviaSyntax node) { } public override SyntaxNode VisitEndIfDirectiveTrivia(EndIfDirectiveTriviaSyntax node) { } 

If you want to get this not through visitors, you can do this:

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

You can look here to find out what Roslyn generates for your conditional.

Update

I checked this and, indeed, its complexity here, because it was not Node , of course. node is just return 2 or if you write #define DEBUG its return 1 .

So, if you have this conditional directive inside the method, you can do something like this:

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

And name it as follows:

 GetConditionalDirectiveTrivia(method, SyntaxKind.IfDirectiveTrivia); 

You can find it in many ways without Good, but I think it is good enough.

Please note that this is just an example. I return here only the first little things.

In your real code, you can write a more elegant solution (perhaps even an extension method) to get, for example, AllTriviaOfKind or something else that suits your requirements. In addition, you can return empty tokens or the parent node if the trivia itself is useless to you, no matter what you need.

I hope this helps.

+2
source

I don’t get conditional compilation of node in SyntaxTree and not included in LeadingTrivia from } or TrailingTrivia from {

In fact, it is in the LeadingTrivia return keyword in return 2; . The main trivia for return are:

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

Source: https://habr.com/ru/post/1012807/


All Articles