在 roslyn 中解析 C# 条件编译语句

Parsing C# Conditional Compilation statements in roslyn

如何使用 Roslyn 解析 C# 条件编译语句。

在下面的代码中,我想让Roslyn给出Conditional compilation statement节点。

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",不是完整的条件编译语句

有人能给我指出正确的方向吗?

如果您通过访问者 (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 为您的条件生成的内容。

更新

我检查了一下,这里确实有点复杂,因为它当然不是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);

如果没有 Kind,您可以通过更多方式找到它,但我认为它已经足够好了。

注意,这只是一个例子。我return这里只有第一个琐事。

在您的实际代码中,您可以编写更优雅的解决方案(甚至可能是扩展方法)以获得例如 AllTriviaOfKind 或其他符合您要求的东西。 此外,您可以 return 令牌琐事或父节点,如果琐事本身对您没有用,无论您 want\need.

希望对您有所帮助。

I don't get conditional compilation node in SyntaxTree and neither it is part of LeadingTrivia of } or TrailingTrivia of {

其实就是在return 2;中的return关键字的LeadingTrivia中。 return 的主要琐事是:

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