忙碌的Labor Day长周末。Growth hacking(希望Hudson River
Trading用上无进展,和前clangd、Eclipse CDT开发者交谈、cdt-lsp计划,给LanguageClient-neovim
vim-lsp加wiki页面成功),增加了少量stargazers。学习clangd并悄悄改typo、摸索musl的开发模式,希望r2走上正途(C11/C99),LeetCode第一次用上std::adjacent_find
……
Language Server
Protocol中最新的textDocument/documentSymbol
可以返回DocumentSymbol[]
,带层次结构。但lsp-mode中尚未支持。
C/C++中的难点是out-of-line
definition,declaration可以和definition分离,lexical/semantic
parent的区别,可以声明多次(如namespace)。能稍微改进我的imenu显示效果,但实用性并不是特别大。
而利用document
symbol进行declaration间快速移动更有用。我决定加个方法$ccls/navigate
支持上下左右移动。实现很简单:https://github.com/MaskRay/ccls/blob/master/src/messages/ccls_navigate.cc
1 | (ccls-navigate "D") |
1 | (ccls-navigate "L") |
1 | (ccls-navigate "R") |
1 | (ccls-navigate "U") |
LanguageClient-neovim用户可以使用(我觉得x不值得一个单独的键,挪用作前缀键了)
1 | nn <silent> xh :call LanguageClient#findLocations({'method':'$ccls/navigate','direction':'L'})<cr> |
index.multiVersion
一直以来,ccls使用继承自cquery的每个文件只检索一次的模型,一个文件即使被不同方式编译(如#include前使用不同的macro),也只有一个版本被记录下来。好处是不同translation unit间索引的东西基本不重复,大大减少索引文件的尺寸。
但缺陷是对于下面的例子只能索引到一个分支:
1 |
|
1 | // a.h |
这个改动需要变更索引数据结构和pipeline,把all_symbols
outline
的构建时刻从indexer推迟到main
thread合并indexer信息时。示意:
1 | struct Reference { |
开启方式: 1
2
3
4
5
6{
"index": {
"multiVersion": 1,
"multiVersionBlacklist": ["^/usr/include"]
}
}
用blacklist让系统headers仍然只索引一遍,否则C++ headers会大幅膨胀索引文件(在一个例子中两倍体积)。
glibc中很多文件会被非PIC和PIC编译两遍,产生重复的compile_commands.json
a.c
条目,index.multiVersion: 1
并不解决这个问题。另外a.h
保存后是否所有包含它的*.c
都要重新索引呢?我现在仍然使用textDocument/didSave
时只索引一个的方案,否则太浪费。
内存和索引文件体积比较。下面RSS为索引结束后resident set size,其实如果重启language server减少内存碎片,可以少一些,ccls-cache为保存在磁盘上的索引目录的du -sh。
1 | musl |
上周用上了clangd的StoreInMemory preamble技巧改进completion速度、移除ASTUnit优化diagnostics。
有人愿意帮忙往ale(Vim插件)、eglot、Oni(Neovim GUI)、theia-ide等提issue要求支持ccls我会很感激(自己不好意思做嘛)
其他可以帮忙的地方至少有:
- 改进vscode插件。上游的vscode-cquery也很久没动了……我讨厌VSCode肯定不愿意多动vscode-ccls
- 弄清楚Windows msys2用新gcc链接llvm https://github.com/MaskRay/ccls/issues/59
- 加FreeBSD port、加Gentoo ebuild、弄MacPorts Homebrew等……
- spacemacs https://github.com/syl20bnr/spacemacs/pull/11242