vim-lspのCallHierarchyをツリーっぽく表示する
リファクタリングしたりコードを調べたりする時、呼び出し元を探すのにLspReferences
やLspCallHierarchyIncoming
を使っていた。
ただ、どちらも1階層分しか表示してくれず、呼び出し元が遠いと影響範囲が把握しにくかったのでquickfixに結果をマージして表示するコマンドを作ってみた。
command! AppendCallTree call s:append_tree(':LspCallHierarchyIncoming') command! AppendRefTree call s:append_tree(':LspReferences') augroup AppendTree autocmd! augroup END function! s:append_tree(cmd) abort autocmd AppendTree BufWinEnter quickfix let s:lsp_done = 1 copen " quickfixに移動し、 let l:pos = line('.') " 現在の行番号と、 let l:parent_tree = getqflist() " 内容を取得し、 call setqflist([]) " いったん空する let l:level = count(l:parent_tree[l:pos-1].text, '⬅️ ') wincmd p " 元のバッファで指定したコマンドを実行し、 let s:lsp_done = 0 execute a:cmd " 完了するかある程度時間が経過するまで待つ let l:cnt = 0 while !s:lsp_done && l:cnt < 100 sleep 10m let l:cnt += 1 endwhile let l:child = getqflist() if len(l:child) != 0 " 新たに取得した分は先頭に⬅️を付けて元の位置の下に挿入する call extend(l:parent_tree, map(l:child, 'extend(v:val, {"text": repeat("⬅️ ", l:level+1) . v:val.text})'), l:pos) endif " 結果(取得できなかった場合は元の内容)をquickfixに表示し、 " 次の場所にジャンプする call setqflist(l:parent_tree) execute 'cc ' . string(l:pos + 1) autocmd! AppendTree endfunction
AppendCallTree
実行後は@:
などで繰り返せるので調査が楽になった。
- LSPを直接呼ぶのは面倒なのでコマンドを実行する形式にした
- 特にCallHierarchy...
- 専用バッファよりquickfixの方が何かと扱いやすいのでやらなかった
- 何も考えずにジャンプできるし
- フィルタも簡単だし