9

我正在尝试了解如何使用 libclang 完成代码。我看过“Thinking beyond the compiler”,也看过 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
}

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

如果我将它指向 sumLi 之后的空格,它会打印出相同的 C 关键字。如果我将 sumListNode 指向 sumLi 中具有“s”的列,我可以让它打印出 sumListNode,但即便如此,它也会将其分配为与其他关键字相同的优先级值,所以它实际上只是打印出我的所有内容可以放在那里而不是阅读光标下的内容并尝试做出明智的猜测。我只是抓住稻草,希望将光标放在片段的开头而不是结尾会有所帮助。

我已经学到了很多关于 libclang 可以给我的数据类型以及如何从 doxygen 以及在 c-index-test 中进行操作的知识,但我只是还没有学会如何让它给我相关数据,以便我可以处理一些事情。

4

1 回答 1

9

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

其次,请注意,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”指向的结构的成员。客户端负责将光标放在当前正在键入的token的开头,然后根据token的内容过滤结果. 例如,当对表达式 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 的自动完成库,这是这个两级实现的一个很好的例子:

trunk/utils/clang-completion-mode.el

于 2013-04-08T12:15:42.887 回答