关于C#:为单个文件获取Clang AST

Get Clang AST for a single file

我在代码编辑器扩展中使用Clang来实现折叠/折叠,但是遇到了问题。

我一次只解析一个文件,而不是整个翻译单元。这部分是出于速度和简便性的考虑,还因为您可以单独打开头文件,而始终不知道要解析哪个cpp。

问题在于,当clang遇到未知符号时,它就会放弃,而AST中缺少文件的整个块。考虑以下代码段

1
2
3
4
5
6
7
8
9
void Foo1()
{
    while (PeekMessageA())
    {
        switch (0)
        {
        }
    }
}

此AST只是

1
2
|-FunctionDecl 0x1fde8f67240 <Folding Test.cpp:1:1, line:9:1> line:1:6 Foo1 'void ()'
| `-CompoundStmt 0x1fde8f673f8 <line:2:1, line:9:1>

没有关于while块或switch块的信息。显然,对于clang来说,不可能知道PeekMessageA是函数调用还是对象构造等,对此我很好。我不需要它是完美的,但我确实希望能够使用while并切换块。

在这种情况下,有没有办法让clang从脸上提供更多信息?我目前正在使用LibClang,但也可以使用LibTooling。


这是一个复杂的问题,没有完美的解决方案,但是对于您的需求而言,似乎有限,您可以找到一个解决方案。之所以会出现问题,是因为C具有某些语义歧义性,与其他最多具有语法歧义性的语言(如C#)相反,因此,当文件无法编译时,clang可能无法产生完整的AST。

之所以发生这种情况,至少是因为表达式和声明之间存在歧义。 C解析器可能必须执行一些符号解析才能区分这两种语法。当该解析失败时,例如,当符号既无法解析为类型也无法解析为变量时,clang会丢弃AST的整个部分,因为它根本无法构建它。

几年前,我确实遇到过同样的问题,如果我还记得,如果if条件中发生错误,那么整个if语句都将被丢弃。因此,在这种情况下,如果要保留if语句,则必须侵入clang解析器并创建错误节点来代替条件表达式。在包含表达式或声明的所有其他语句中也会发生相同的问题。

希望这会有所帮助。