在 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
)
如何使用 Roslyn 解析 C# 条件编译语句。
在下面的代码中,我想让Roslyn给出Conditional compilation statement节点。
public abstract class TestClass
{
public int Get()
{
#if DEBUG
return 1;
#else
return 2;
#endif
}
}
我没有在 SyntaxTree 中获得条件编译节点,它也不是 }
的 LeadingTrivia 或 {
}
的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
)