我正在尝试了解如何使用libclang完成代码。我看过“思考超出编译器”并且我查看了c-index-test,我发现了一个简单的示例程序here
我编译了那个程序并在这个样本文件上运行它,我把它掀起来像是视频中的那个:
struct List {
int Data;
struct List *Next;
};
int sumListNode(struct List *Node) {
int result = 0;
for (; Node; Node = Node->Next)
result = result + Node->
}
void test() {
sumLi
}
如果我在Node->之后将程序指向第一个不完整的空格,它会吐出几个C关键字,但它不会像视频所说的那样吐出Next或Data。
如果我将它指向sumLi之后的空格,它会打印出那些相同的C关键字。如果我将它指向sumLi中具有's'的列,我可以打印出sumListNode,但即便如此,它也会将其指定为与其他关键字相同的优先级值,所以它实际上只打印出我所有的内容可以放在那里,而不是阅读光标下的内容并试图做出明智的猜测。我只是抓住吸管,希望无论如何将光标放在片段的开头而不是结尾都会有所帮助。
我已经了解了很多关于libclang可以给我的数据类型以及如何使用doxygen进行操作,以及在c-index-test中进行操作,但我还没有学会如何制作它给我相关数据,以便我可以使用。
答案 0 :(得分:9)
首先,您应该尝试打印翻译单元的任何CXDiagnostic
输出,因为任何错误都可能导致代码丢失(在您提到的非常简单的情况下,这是非常不可能的)。
其次,请注意libclang以与您习惯的方式不同的方式定义行号和列号(即如果从文本编辑器获取行/列信息,则可能必须在列号中添加1)与clang的定义同步。)
第三,您可以使用clang编译器本身来测试编译选项和行/列信息的有效性。这样就消除了基于libclang的代码产生的不确定性。你可以,例如使用以下命令行:
clang++ -cc1 -fsyntax-only -code-completion-at FILENAME:LINE:COL CLANG_ARGS
另请注意,clang_codeCompleteAt仅在令牌的开头调用,并生成所有可能令牌的列表,客户端负责过滤结果,并且已经输入了潜在的部分令牌。文本编辑器。
从文档(重点是我的):
在翻译单元的指定位置执行代码完成。
此函数在源代码中的特定文件,行和列上执行代码完成,从而提供基于完成上下文建议潜在代码段的结果。代码完成的基本模型是Clang将解析完整的源文件,执行语法检查直到请求代码完成的位置。此时,将一个特殊的代码完成标记传递给解析器,该解析器识别此标记,并根据C / Objective-C / C ++语法中的当前位置和语义分析的状态确定要提供的完成。这些完成通过新的CXCodeCompleteResults结构返回。
代码完成本身意味着当用户输入标点字符或空格时由客户端触发,此时代码完成位置将与光标重合。例如,如果p是指针,则可以在“ - ”之后触发代码完成,然后在“>”之后触发代码完成。在p->。当代码完成位置在“>”之后时,完成结果将提供例如“p”指向的结构的成员。 客户端负责将光标放在当前键入的令牌的开头,然后根据令牌的内容过滤结果。例如,当表达式p-> get的代码完成时,客户端应该在“>”之后提供位置。 (例如,指向“g”)到这个代码完成钩子。然后,客户端可以根据当前令牌文本(“get”)过滤结果,仅显示以“get”开头的结果。 此接口的目的是将代码完成结果的相对高延迟采集与基于每个字符的结果过滤分开,这必须具有较低的延迟。
采取修改后的第二个例子:
int main (int argc, char **argv) {
int i = sumLi
// ^
}
应在标记位置(即令牌的开头)调用代码完成。然后,Clang可以提供一长串结果,例如:
argc
sumListNode(<# struct List *Node #>)
然后,您可以根据部分输入的sumLi
令牌过滤此列表,并保留唯一相关的完成情况:sumListNode
。
如果您了解elisp,则clang的源包含Emacs的自动完成库,这是这个两级实现的一个很好的例子: