为什么libclang没有返回有意义的完成结果?

Joh*_*ohn 9 llvm clang llvm-clang libclang

我试图了解如何使用libclang完成代码.我看过"思考超出编译器",我查看了c-index-test,我在这里找到了一个简单的示例程序

我编译了那个程序并在这个样本文件上运行它,我把它掀起来像是视频中的那个:

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
}
Run Code Online (Sandbox Code Playgroud)

如果我在Node->之后将程序指向第一个不完整的空间,它会吐出几个C关键字,但它不会像视频所说的那样吐出Next或Data.

如果我将它指向sumLi之后的空格,它会打印出那些相同的C关键字.如果我将它指向sumLi中具有's'的列,我可以打印出sumListNode,但即便如此,它也会将其指定为与其他关键字相同的优先级值,所以它实际上只打印出我所有的内容可以放在那里,而不是阅读光标下的内容,并试图做出明智的猜测.我只是抓住吸管,希望无论如何将光标放在片段的开头而不是末尾都会有所帮助.

我已经了解了很多关于libclang可以给我的数据类型以及如何使用doxygen进行操作,以及在c-index-test中进行操作,但我还没学会如何让它给我相关数据,以便我有一些工作.

ffe*_*tte 9

首先,您应该尝试CXDiagnostic通过翻译单元打印任何输出,因为任何错误都可能导致代码丢失(这在您提到的非常简单的情况下是不太可能的).

其次,请注意libclang以与您习惯的方式不同的方式定义行号和列号(即,如果从文本编辑器获取行/列信息,则可能必须在列号中添加1与clang的定义同步).

第三,您可以使用clang编译器本身来测试编译选项和行/列信息的有效性.这样就消除了基于libclang的代码产生的不确定性.您可以使用以下命令行:

clang++ -cc1 -fsyntax-only -code-completion-at FILENAME:LINE:COL CLANG_ARGS
Run Code Online (Sandbox Code Playgroud)

另请注意,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
  //      ^
}
Run Code Online (Sandbox Code Playgroud)

应在标记位置(即令牌的开头)调用代码完成.然后,Clang可以提供一长串结果,例如:

  • argc
  • sumListNode(<# struct List *Node #>)

然后,您可以根据部分输入的sumLi令牌过滤此列表,并保留唯一相关的完成:sumListNode.

如果您了解elisp,则clang的源包含Emacs的自动完成库,这是这个两级实现的一个很好的例子:

trunk/utils/clang-completion-mode.el