相关文章推荐
  • Universal Ctags 很精妙,用正则表达式跳转,因此文档编辑后仍能使用。 https://github.com/universal-ctags/ctags/blob/master/parsers/c.c 但不带引用,Vim会用二分查找,大约会有log2(size/4096)次seek。
  • Cscope 似乎已经荒废了。
  • ID Utils
  • GNU GLOBAL libparser/C.c 。用Berkeley DB存储definition/reference/path name。带有插件系统可以使用ctags idutils的parser。对于Emacs/Vim用户来说,可能是tag流派中最好用的工具了。辅以一些heuristics和 ripgrep 等,很多用户不觉得自己生活在水深火热中……
  • Elixir Cross Referencer
  • OpenGrok
  • clang流派

  • clang-tags 荒废。
  • YouCompleteMe 不够好用,因为只处理单一translation unit,无法查找引用。
  • clangd 最有前景,有大厂大项目愿意采用,Xcode会用让clangd有助益的libindexstore。但目前尚无存储系统,因此无法处理多translation units。作为 clang-tools-extra 一部分,而clang+llvm构建/贡献门槛高([https://reviews.llvm.org/])。对于这类工具类应用,贡献难易程度是个重要因素。目前有尝试引入存储模型(MarkZ3),但目前设计较为复杂,而实际上不带garbage collection的 std::vector (cquery风格)足够应对大部分使用场景。很担心他们走上歧路。
  • Google Kythe ,(mostly) language-agnostic,概念复杂,配置困难。不重视language server protocol, 当前 仅提供 ReferencesProvider,HoverProvider,DefinitionProvider ,且交互使用可能有极大延迟。大多数人并不在意C++ Haskell Python代码间无缝跳转。 https://github.com/google/kythe/tree/master/kythe/cxx/indexer/cxx
  • rtags 可以查找引用,但每个translation 6个文件 info,symbols,symnames,targets,tokens,usrs (过多),没有使用in-memory索引,查找引用请求会读项目所有translation units的文件。导致性能低下 https://github.com/Andersbakken/rtags/issues/1007 。rtags.el里应该还有很多东西可供Emacs lsp-mode学习,有经验的人介绍一下~
  • cquery 现阶段的妥协。主要数据结构为不带garbage collection(变量/函数/类型等的id不会回收)的 std::vector ( src/indexer.h )。有一些Emacs用户积极贡献 code navigation功能
  • IDE(Any sufficiently complicated IDE contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of C++.)

  • NetBeans使用 Clank
  • Eclipse用 CDT
  • cquery安装、配置

  • git clone https://github.com/jacobdufault/cquery
  • 构建language server可执行文件(Arch Linux可用 aur/cquery-git /usr/bin/cquery )
  • ./waf configure # 或用--bundled-clang=5.0.1选择 http://releases.llvm.org/ 上的release版本
  • ./waf build # 构建 build/release/bin/cquery
  • 编辑器安装language client插件(Emacs lsp-mode、Neovim LanguageClient-neovim、VSCode安装cquery/vscode-client里的插件)
  • 为你的C/C++/Objective-C项目生成 compile_commands.json ,参见下文。
  • cquery是一个C++ language server,它和编辑器端的LSP client协作流程如下:

    当编辑器打开C++文件时,language client插件启动language server进程(根据配置的language server可执行文件),用 JSON-RPC 2.0 协议通过stdio通信,协议规范见 https://microsoft.github.io/language-server-protocol/specification

    Language client插件用 initialize 请求告知language server(这里是 build/release/bin/cquery 进程)自己支持的功能(ClientCapabilities)、项目路径(rootUri)、初始化选项(initializationOptions,cquery需要知道 cacheDirectory 路径)。之后各种语言相关功能都通过与language server通信实现:

  • 光标移动时向language server发送 textDocument/hover 请求,language server返回变量/函数声明信息、注释等。VSCode使用浮动窗口显示,Emacs lsp-mode用eldoc显示
  • 查找定义发送 textDocument/definition 请求,language server返回定义所在的文件、行列号。编辑器的可能行为:单个结果时直接跳转到目标文件的指定行列,如有多个候选则用菜单显示
  • 查找引用发送 textDocument/references 请求,和查找定义类似
  • 查找当前文档定义的符号(常用与查找顶层的outline)发送 textDocument/documentSymbol 请求,language server返回符号和行列号
  • 查找项目定义的符号(只查找outline的也很有用)发送 workspace/symbol 请求
  • 补全 textDocument/completion ,language server提供候选及排序方式,是否使用snippet,如何编辑文档得到补全结果等
  • 文档编辑操作发送 textDocument/didChange ,language server据此更新自己的模型
  • cquery还支持一些Language Server Protocol之外的扩展,比如 $cquery/derived 用于查找派生的类、方法等
  • Emacs

    参照 https://github.com/jacobdufault/cquery/wiki/Emacs 配置。需要安装几个插件:

  • lsp-mode Emacs里的LSP客户端库,可用于多种language server。另有lsp-rust、lsp-haskell等,可以看作适配器,包含language server相关设置。
  • cquery项目中的 emacs/cquery.el 。地位与lsp-rust、lsp-haskell等类似,把cquery适配到lsp-mode。另外支持cquery一些Language Server Protocol之外的扩展。
  • lsp-ui lsp-mode有计划并入Emacs。其他UI相关或因协议等问题不适合在核心lsp-mode包的组件放在这里。当前有:
  • lsp-ui-flycheck 用language server的diagnostics信息实现flycheck的checker
  • lsp-ui-sideline 即时显示当前行所有标识符的 textDocument/hover 信息
  • lsp-ui-peek 基于 quick-peek find-{definitions,references,apropos}
  • 未来可能添加更多code lens功能
  • company-lsp company是一个补全引擎,company-lsp为一个backend,用 textDocument/completion 信息提供补全
  • 这些插件只有lsp-mode和cquery.el是必须的。

    lsp-mode

  • (lsp-enable-imenu) 开启,用imenu来显示 textDocument/documentSymbol 信息。跳转到当前档案的符号很方便。
  • 光标移动到标识符上会触发 textDocument/hover ,显示类型、变量、函数等的fully qualified name,有层层namespace嵌套时容易定位。对于auto specifier,能知道具体类型。
  • M-x lsp-format-buffer 发送 textDocument/formatting 。参见 cquery/wiki/Formatting
  •  
    推荐文章