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

ade*_*l41 6 c# parsing conditional-compilation roslyn

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

在下面的代码中,我希望Roslyn提供Conditional编译语句节点.

public abstract class TestClass
{
    public int Get()
    {
    #if DEBUG
        return 1;
    #else
        return 2;
    #endif
    }
}
Run Code Online (Sandbox Code Playgroud)

我没有在SyntaxTree中获得条件编译节点,也没有它是LeadingTrivia }或TrailingTrivia的一部分{

我得到的LeadingTrivia }"\t\t#endif\r\n\t\t"和TrailingTrivia {"\r\n"它是不完整的条件编译语句.

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

Dud*_*eti 2

如果您通过访问者 (CSharpSyntaxRewriter\Walker) 解析节点,则需要覆盖:

public override SyntaxNode VisitIfDirectiveTrivia(IfDirectiveTriviaSyntax node)
{
}

public override SyntaxNode VisitElseDirectiveTrivia(ElseDirectiveTriviaSyntax node)
{
}

public override SyntaxNode VisitEndIfDirectiveTrivia(EndIfDirectiveTriviaSyntax node)
{
}
Run Code Online (Sandbox Code Playgroud)

如果您不想通过访问者获得此信息,您可以这样做:

node.DescendantNodesAndSelf().OfType<ConditionalDirectiveTriviaSyntax>();
Run Code Online (Sandbox Code Playgroud)

您可以在此处查看 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);
}
Run Code Online (Sandbox Code Playgroud)

并这样称呼它:

GetConditionalDirectiveTrivia(method, SyntaxKind.IfDirectiveTrivia);
Run Code Online (Sandbox Code Playgroud)

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

请注意,这只是一个示例。我在这里只返回第一个琐事。

在您的真实代码中,您可以编写更优雅的解决方案(甚至可能是扩展方法)来获取例如AllTriviaOfKind或其他适合您要求的东西。另外,如果琐事本身对您没有用,您可以返回令牌琐事或父节点,无论您想要什么\需要什么。

我希望它有帮助。