Vim と LSP で Java 開発

Posted on 日 12 5月 2019 in tech

Java の開発は VSCode でやっていたのだけれど、最近 Vim プラグインの調子がとてもよくない。

dd とか cc で行削除すると、カーソルが末尾に移動してしまうというもの。issue も立っていた。

こりゃ本家の Vim に頼るしかないと思って Java の開発環境を整えたメモ。

この記事でできること

Vim で

  • Java の自動補完
  • Java のシンタックスチェック
    • Lombok による生成コードも考慮する

この記事でできないこと

  • Java のインストール
  • Java のデバッグ

デバッグするときは eclim を使うといいらしい。後日試す。

環境

  • Vim 8以上。Lua 付きでインストールすること1

Mac なんかは brew install vim --with-lua で入れ直せばいいはず。 この記事では vim-lsp プラグインまわりの設定が中心になるので、深くは触れない。

用意するもの

Vim プラグイン

黙って vim-plug を入れて↓を .vimrc に書いたらいい。

Plug 'prabirshrestha/asyncomplete.vim'
Plug 'prabirshrestha/async.vim'
Plug 'prabirshrestha/vim-lsp'
Plug 'prabirshrestha/asyncomplete-lsp.vim'
let g:asyncomplete_remove_duplicates = 1
let g:asyncomplete_smart_completion = 1
let g:asyncomplete_auto_popup = 1

Plug 'w0rp/ale'

書いたらおもむろに Vim を起動して normal モードで

:PlugInstall

とすればプラグインがインストールされる。

Java 実行環境

Java の開発するなら実行環境は整ってると思うので、割愛。

eclipse.jdt.ls のダウンロード

Java のコード補完には Language Server Protocol (LSP) を使う。 そのため、Java の Language Server となる jar を vim-lsp の wiki を参考にダウンロードする。

$ mkdir -p ~/lsp/eclipse.jdt.ls
$ cd ~/lsp/eclipse.jdt.ls # お好みのフォルダで
$ curl -L https://download.eclipse.org/jdtls/milestones/0.35.0/jdt-language-server-0.35.0-201903142358.tar.gz | tar xz

jdt-language-server-* は wiki (本稿執筆時)に合わせてバージョン 0.35.0 のものを記載したけれど、下記から最新のものを探して適宜置き換えるとよい。

また上記サンプルコマンドでは wiki にならって ~/lsp/eclipse.jdt.ls のフォルダに jar 一式を展開した。もちろん変更してもよいが、その場合は以降の設定も読み替えること。

Lombok のダウンロード

Lombok によるボイラーコードも補完したいので、lombok.jar を取っておく。

$ cd ~/lsp/
$ curl -L https://projectlombok.org/downloads/lombok.jar -O

設定

wiki に記載の設定にプラスして、Lombok のシンタックスも使いたいから VSCode の設定 を参考に少し条件式やオプションを加える。以下を vimrc に追記する。

let s:lombok_path = $HOME . '/lsp/lombok.jar'
if executable('java') && filereadable(expand('~/lsp/eclipse.jdt.ls/plugins/org.eclipse.equinox.launcher_1.5.300.v20190213-1655.jar')) && filereadable(expand(s:lombok_path))

    " ale の設定
    let g:ale_java_javac_options = "-cp " . s:lombok_path

    " vim-lsp の設定
    au User lsp_setup call lsp#register_server({
        \ 'name': 'eclipse.jdt.ls',
        \ 'cmd': {server_info->[
        \     'java',
        \     '-javaagent:' . s:lombok_path,
        \     '-Xbootclasspath/a:' . s:lombok_path,
        \     '-Declipse.application=org.eclipse.jdt.ls.core.id1',
        \     '-Dosgi.bundles.defaultStartLevel=4',
        \     '-Declipse.product=org.eclipse.jdt.ls.core.product',
        \     '-Dlog.level=ALL',
        \     '-noverify',
        \     '-Dfile.encoding=UTF-8',
        \     '-Xmx1G',
        \     '-jar',
        \     expand('~/lsp/eclipse.jdt.ls/plugins/org.eclipse.equinox.launcher_1.5.300.v20190213-1655.jar'),
        \     '-configuration',
        \     expand('~/lsp/eclipse.jdt.ls/config_mac'),
        \     '-data',
        \     getcwd()
        \ ]},
        \ 'whitelist': ['java'],
        \ })
endif

""" 以下のキーマッピングは任意
" 定義へ飛ぶ
nmap <silent> <C-]> :LspDefinition<CR>
" 定義へ飛ぶ
nmap <silent> gd :LspDefinition<CR>
" 呼び出し箇所を見る
nmap <silent> gD :LspReferences<CR>

特に注意すべきは config_mac の箇所で、OS によって config_win とか config_linux とか変える必要がある。

他に変えたところを大雑把に説明すると、

  • filereadable(expand(s:lombok_path))lombok.jar の存在チェック
  • let g:ale_java_javac_options = "-cp " . s:lombok_path で ale プラグインに lombok.jar を認識させる
  • -javaagent:' . s:lombok_path'-Xbootclasspath/a:' . s:lombok_path で Language Server 起動時に lombok.jar を読み込ませる

という感じ。2

デモ

定義へ飛んだり呼び出しの一覧を出したり

まとめ

LSP で Vim の可能性がまた開かれた。Microsoft も たまには いい仕事するね。


  1. Neovim の場合は普通にインストールすればいけるはず 

  2. Neovim + LanguageClient-neovim の環境では -Xbootclasspath/a オプションではなく -Xbootclasspath/p オプションなら動くという事象が報告されている。