はじめに
この記事は チームスピリット Advent Calendar 2017 の5日目です。
VimからApexのプロジェクトを扱う方法を探していたところ、ApexのLSP実装 1 があるらしいです。わくてかわくてか。
forcedotcom/salesforcedx-vscode: Salesforce Extensions for VS Code
VSCode のプラグインに内包しちゃってますね。スタンドアロンじゃないのかよ。そんなわけで今回は言語サーバーを立ち上げているJARをプラグインから抜いてきてVimで使います。
サーバーJARを落としてくる
$ wget 'https://github.com/forcedotcom/salesforcedx-vscode/blob/develop/packages/salesforcedx-vscode-apex/out/apex-jorje-lsp.jar?raw=true'
JARをダウンロードし、呼び出しやすいファイル名にリネームしておきます。
起動確認
$ java -cp apex-jorje-lsp.jar -Ddebug.internal.errors=true -Ddebug.semantic.errors=false apex.jorje.lsp.ApexLanguageServerLauncher
一旦シェル上で起動することを確認してみます。引数はデバッグオプションがない場合にプラグイン内部で使われるコマンドをそのまま使っています。
標準入力でリクエストを受け付けるので、入力待ちの状態でプロセスが待機状態になれば成功。
Vim の下準備
まず、VimがApexファイルであることを判別するためにApexの言語プラグインが必要です。
-
ejholmes/vim-forcedotcom: Force.com syntax highlighting in vim.
正規表現を使った構文ハイライトのみが含まれます。 -
neowit/vim-force.com: Vim plugin for force.com
補完やデプロイ機能などApexのプロジェクト管理機能も豊富ですが、Language Serverと競合する場合があるかもしれません。
正規表現を使った構文ハイライトを含み、オートインデントはJavaのものを流用しています。依存しているchannel
のAPIの仕様がVimとNeovimで異なるため、Neovimでは一部の機能が利用できません。
次に、Vim側にLanguage Serverのクライアントとなるプラグインが必要です。Neovimであれば
-
autozimu/LanguageClient-neovim: Language Server Protocol support for neovim and vim.
が実績もありおすすめです。(というか他をあまり知らない)
Vim の設定
先程のサーバー起動コマンドをVimのクライアントプラグインに設定して、Apexのファイルを開いた時にサーバーが起動されるようにします。
上記で上げたクライアントプラグインを前提としたサンプルコードです。
let g:LanguageClient_serverCommands = {
\ 'apex': ['java', '-cp', expand('/path/to/apex-jorje-lsp.jar'), '-Ddebug.internal.errors=true', '-Ddebug.semantic.errors=false', 'apex.jorje.lsp.ApexLanguageServerLauncher'],
\ }
/path/to
はJARの保存場所に適宜書き換えておいてください。
じゃじゃーん!!
取っておいたスクリーンショットが会社製品のソースコードを丸々含んでいたのでupしませんでした。
後日upしますのでお手元で試して見てください。
使ってみた感想
- VSCode版と比較もしたい(クライアントの実装状況に差があるため)が、VSCode版を使っていないので断念。
- 補完の精度の検証もしたいが、そもそもApexの言語仕様をよく分かっていないので断念。
- 正規表現ベースの構文ハイライトが時々おかしいのはLanguage Serverではどうしようもない。
- テスト/デプロイなどの機能はない。これはLSPの仕様にないため、他のプラグインで補うしかない。
- 途中まで文字を入力 -> 補完をした場合に、入力された文字を無視した補完候補を出すのだが、これはクライアント側の仕様? VSCode版使っている人がいたら教えてください。
-
タグジャンプや補完、構文チェックなどの各種言語機能を提供するサーバーの通信プロトコルのこと。 Microsoft/language-server-protocol: Defines a common protocol for language servers. ↩