在roslyn

时间:2016-12-01 13:23:12

标签: c# parsing roslyn conditional-compilation

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

在下面的代码中,我希望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",这不是完整的条件编译声明。

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

2 个答案:

答案 0 :(得分: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为您的条件生成的内容。

<强>更新

我查了一下,确实在这里很复杂,因为它当然不是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或其他内容。 此外,您可以返回令牌琐事或父节点,如果琐事本身对您无用,无论您想要什么\需要。

我希望能有所帮助。

答案 1 :(得分:2)

  

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

的一部分

事实上,它位于LeadingTriviareturn关键字的return 2;return的主要琐事是:

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