sourcekit-lspの補完が遅いのを速くする
vimでLSP(Language Server Protocol)を試してます.
swiftを書くことがあるので,sourcekit-lspを使ってswiftのLSPを試したのですが,補完がめちゃくちゃ遅い・・・. そこで,パフォーマンスが改善されているsourcekit-lspの最新版を含むToolchainをインストールして使うことで速くなったので,そのメモです.
環境
- macOS: 10.15 (Catalina)
- vim: MacVim 169 (Vim 8.2)
- Xcode: 12.2
- Toolchain: swift-5.3.2-Release
vim-lspの導入
mattnさんの記事を参考に,vim-lsp-settingsを使ってvim-lspを導入しました.
cf: Big Sky :: Vim をモダンな IDE に変える LSP の設定
sourcekit-lspは自動でインストールされないので,使っているXcodeに含まれるものを指定するようにしました..vimrc の該当箇所はこんな感じです.
call dein#add('prabirshrestha/asyncomplete.vim')
call dein#add('prabirshrestha/asyncomplete-lsp.vim')
call dein#add('prabirshrestha/vim-lsp')
call dein#add('mattn/vim-lsp-settings')
call dein#add('hrsh7th/vim-vsnip')
call dein#add('hrsh7th/vim-vsnip-integ')
inoremap <expr> <Tab> pumvisible() ? "\<C-n>" : "\<Tab>"
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
inoremap <expr> <cr> pumvisible() ? asyncomplete#close_popup() : "\<cr>"
let g:lsp_signature_help_enabled = 1
let g:lsp_diagnostics_enabled = 1
let g:lsp_diagnostics_echo_cursor = 1
let g:lsp_settings = {
\ 'sourcekit-lsp': {'cmd': ['xcrun', 'sourcekit-lsp']}
\}
問題
これだけでswiftのlspがvimで使えるようにはなったんですが(vim-lsp-settingsに感謝!),補完が走ると数秒固まってしまい,キー入力も受け付けない感じでした・・・. .vimrc に次のような設定を入れてLSPのログを出しながら動かしてみると,このような感じでした.
let g:asyncomplete_auto_completeopt = 0
set completeopt=menuone,noinsert,noselect,preview
グローバルなシンボルを全部取ってきて遅くなっているような感じでした.( import Foundation
がなければ固まることはなかったです.)
おそらく以下で議論されている問題だと思います.
Xcode12.2に同梱されているsourcekit-lspには,上記イシューで追加されたオプション(-completion-server-side-filtering
, -completion-max-results
)はありませんでした.
$ xcrun sourcekit-lsp --help
OVERVIEW: Language Server Protocol implementation for Swift and C-based languages
USAGE: sourcekit-lsp [options]
OPTIONS:
--build-path Specify build/cache directory
--configuration, -c Build with configuration (debug|release) [default: debug]
--log-level Set the logging level (debug|info|warning|error) [default: info]
-Xcc Pass flag through to all C compiler invocations
-Xclangd Pass options to clangd command-line
-Xcxx Pass flag through to all C++ compiler invocations
-Xlinker Pass flag through to all linker invocations
-Xswiftc Pass flag through to all Swift compiler invocations
-index-db-path Override index-database-path from the build system
-index-store-path Override index-store-path from the build system
--help Display available options
解決策
Xcode12.2に同梱のsourcekit-lspは少し古そうなことがわかったので, パフォーマンスが改善された最新のsourcekit-lspを含むToolchainをインストールして利用しました.
Toolchainとは,swiftのバージョンに合わせた開発ツールセット (依存バージョンを合わせたコンパイラ等のセット)みたいなものです.
Toolchainのインストール
以下のページからswift 5.3.2のXcode用Toolchainをダウンロードしてインストールしました.
$ ls -l /Library/Developer/Toolchains
total 0
drwxr-xr-x 7 root wheel 224 May 29 2019 swift-3.1.1-RELEASE.xctoolchain/
drwxr-xr-x 7 root wheel 224 May 30 2019 swift-4.0-RELEASE.xctoolchain/
drwxr-xr-x 7 root wheel 224 Mar 23 2020 swift-5.0-RELEASE.xctoolchain/
drwxr-xr-x 7 root wheel 224 Jan 10 09:54 swift-5.3.2-RELEASE.xctoolchain/
lrwxr-xr-x 1 root wheel 61 Jan 10 09:54 swift-latest.xctoolchain@ -> /Library/Developer/Toolchains/swift-5.3.2-RELEASE.xctoolchain
Toolchain名の特定
インストールしたToolchainのバンドル名を特定しておきます.
$ grep -A 1 CFBundleIdentifier /Library/Developer/Toolchains/swift-5.3.2-RELEASE.xctoolchain/Info.plist
<key>CFBundleIdentifier</key>
<string>org.swift.532202012141a</string>
パフォーマンス改善対応が入っていることの確認
Toolchainの中のsourcekit-lspを実行し,先のパフォーマンス改善対応オプションが含まれることを確認します.
$ xcrun --toolchain "org.swift.532202012141a" sourcekit-lsp --help
OVERVIEW: Language Server Protocol implementation for Swift and C-based languages
USAGE: sourcekit-lsp [options]
OPTIONS:
--build-path Specify build/cache directory
--completion-max-results
When server-side filtering is enabled, the maximum number of results to return
--completion-server-side-filtering
Whether to enable server-side filtering in code-completion
--configuration, -c Build with configuration (debug|release) [default: debug]
--log-level Set the logging level (debug|info|warning|error) [default: info]
-Xcc Pass flag through to all C compiler invocations
-Xclangd Pass options to clangd command-line
-Xcxx Pass flag through to all C++ compiler invocations
-Xlinker Pass flag through to all linker invocations
-Xswiftc Pass flag through to all Swift compiler invocations
-index-db-path Override index-database-path from the build system
-index-store-path Override index-store-path from the build system
--help Display available options
入ってました.
vim-lsp-settingsの設定変更
ビルドしたsourcekit-lspを使うように,.vimrcを変更します.
let g:lsp_settings = {
\ 'sourcekit-lsp': {'cmd': ['xcrun', '--toolchain', 'org.swift.532202012141a', 'sourcekit-lsp']}
\}
補完件数がフィルタリングのデフォルトの動作なので,オプションを付けて実行する必要はありません.
対応後の動作
こんな感じに速くなりました.
ちなみに,sourcekit-lspのビルドではうまくいかなかった
はじめ,手元でsourcekit-lspをビルドしてみたのですが,補完は速くはなったものの,構文エラーなどがsourekit-lspから報告されなくなってしまいました.(LSP通信でdiagnosticsが空になる.) 試しにVSCodeで使ってみるとちゃんとエラーが報告されるので,vim-lspとの相性?かもしれません.
そのあとで,ビルドせずともToolchainの中にあるものをそのまま使えばいいことがわかり,ビルドする方法は止めました. (sourcekit-lspのREADMEにある ii の記述です.)
1. Get SourceKit-LSP with a Swift toolchain
i. If you have installed Xcode 11.4+ or the corresponding Command Line Tools package, the SourceKit-LSP server is included and can be run with xcrun sourcekit-lsp.
ii. If you are using a toolchain from Swift.org, the SourceKit-LSP server is included and can be run with xcrun --toolchain swift sourcekit-lsp on macOS, or using the full path to the sourcekit-lsp executable on Linux.
iii. If your toolchain did not come with SourceKit-LSP, see Development for how to build it from source.
ビルドしたい人は以下を参照してください.
cf: sourcekit-lsp/Development.md at main · apple/sourcekit-lsp