efm-langserver General purpose Language Server that can use specified error message format generated...
https://github.com/mattn/efm-langserver
以下でインストール出来ます。
go get github.com/mattn/efm-langserver/cmd/efm-langserver
仕組みは haya14busa さんが reviewdog の Vim script 対応の際に Vim のオプション、errorformat をパースするライブラリ errorformat を作っておられたので、各 Lint コマンドが出力する行番号、列番号、メッセージをパース、その情報を Language Server Protocol でテキストエディタに教えてあげようという物です。なので
grep 形式の出力をする Lint ツールであれば Language Server になれてしまう訳です。
この記事は、Go 言語歴10年になる僕がこれまで愛用してきた Go 言語のコード補完ソフトウェア gocode の歴史と功績、そして今、gocode 自らがその役割を終えようとしている姿をぜひ皆さんに知って頂きたいという思いから Go Advent Calendar 2018 の記事として起こしました。この記事では gocode が歩んできた歴史と苦悩を少しでも皆さんに分かる様に解説させて頂きつつ、そして次にやってくる Go 言語のコード補完の未来についてご紹介したいと思います。Vim について多めに書かれていますが、Visual Studio Code での Go 開発にも影響する話です。
An autocompletion daemon for the Go programming language VERY IMPORTANT: this project is not maintai...
https://github.com/nsf/gocode
GitHub スターの数を見て貰えると分かる通り、gocode は多くのユーザに使われてきました。Go 言語はコンパイル型言語にも拘わらずスクリプト言語並みのコンパイルの速さでユーザを魅了してきたのですが、多くのユーザが gocode により助けられ開発速度を保てていたという事実はもはや説明するまでもありません。Visual Studio Code を使っておられる方であれば、その . をタイプして Go のコード補完候補を出していたのは gocode なのです。(最近は go-langserver が使われていますが、あれも最近まで中身が gocode でした)
gocode は開発初期こそ Vim と Emacs のみをサポートして来ましたが、最終的にはあらゆるテキストエディタや IDE で使われました。
Vim/NeoVim (vim-go)
Emacs (go-autocomplete.el)
goclipse
SublimeText 2 (GoSublime)
godev
godit
Wide
Visual Studio Code (vscode-go)
僕と gocode
gocode は僕の Go 言語プログラミングの右腕でした。趣味でも仕事でも常に使ってきました。一部の方であればご存じかもしれませんが、僕は Vim というテキストエディタを愛用しています。10年前となるともちろん Go 言語のコード補完はどの環境向けにも作られておらず、Go 言語のユーザ達は全てのコードを自分でタイプしていました。僕もその一人でしたし、それが普通だと思っていました。
そして gocode の本体に含まれていた Vim プラグインが vim-go に移り、今や Vim を使う Go ユーザの多くが vim-go ユーザでもあります。僕も今では vim-go が無いと Go が開発出来ないという程に vim-go のヘビーユーザです。そんな事もあり僕は Go の環境をセットアップする時はいつもまず gocode をインストールして来ました。
今思えば僕が Go のコードをこれほどまで量産してこれたのも、gocode が助けてくれていたからかも知れません。
gocode の仕組み
gocode はコード補完サーバ兼クライアントです。テキストエディタは Go のソースコードを開くと同時にその拡張やプラグインがバックグラウンドで gocode を起動します。そしてコード補完を行うタイミングで編集中のソースコードがテンポラリファイルに一旦書き込まれ、gocode のクライアントを経由してサーバに対してリクエストが送り込まれます。gocode サーバはソースを解析し、補完の候補を作ると各テキストエディタ向けのフォーマットで応答を返します。例えば Vim であれば Vim script のリスト形式を返しました。Emacs であればS式を返しました。その後、ユーザ数の拡大に合わせ各種フォーマットに対応しました。
vim
emacs
nice
csv
csv-with-package
json
godit
一見、json だけあれば十分ですし無駄な努力であった様にも見えますが Vim がまだ JSON を扱う事が出来なかった頃の話なので、これはあって当然の実装だったのです。
gocode が取り組んだ事
さまざまなテキストエディタや IDE から使われ、gocode は Go でのコード補完機能のデファクトスタンダードとしてのポジションに君臨して来ました。
gocode は Go 本体のコードの一部をベースとして作られており、ソースの一部からも取り込み当初の Go のコードが残る物になっています。元々は gocode も Go のソースをパースしソースコードから補完候補を作る仕組みでした。Go のユーザ数が増え、開発される規模も大きくなり、状況も変わってきました。そこで nsf 氏はバイナリをサポートし始めます。Go は go install するとパッケージをバイナリとして保持します。そして gocode はそのバイナリをパースしコード補完を高速化する事に成功しました。この時のコード補完の速度はとても速く素晴らしい物でした。そしてそれを gocode 標準の機能としたのです。
しかしながら多くのバージョンに対応するという事は色々な問題を抱える事にもなります。複数のバイナリをサポートするという事だけでも大変な作業なのです。さらに Go コンパイラが新しいバイナリを生成する様になると、gocode は途端にクラッシュしてしまいます。僕の様に常に最新の Go を使っているユーザだと、Go コンパイラが新しいバイナリのバージョンをサポートし始めると gocode がそのバージョンをサポートするまではコード補完が使えない状態となるのです。
The go build command now maintains a cache of recently built packages, separate from the installed p...
https://github.com/nsf/gocode/issues/500
一方その頃、Visual Studio Code は Language Server をサポートし始めました。Language Server は言語に依存しないコード解析仕様で、コード補完や定義位置ジャンプ等を提供します。各 Language Server は Language Server Protocol (LSP) に従って各言語版の実装する事で、Language Server Client からは透過的に各言語を扱えるという物です。これにより、一旦テキストエディタが Language Server Client を実装さえしてしまえばそれ以降は各言語が Language Server を実装すればテキストエディタは無改造(もしくは少量の変更のみ)で対応する事が出来るのです。Go 言語にもその実装 go-langserver が誕生しました。
Yes, it sucks. With gocode you have to use "go install" anyway and that package cache feature is useless to you. Sadly there are no plans on my side to workaround it. I talked a bit about it a few times. A proper autocompletion service should use source files instead of package files. Somebody should make one. My enthusiasm for gocode is long gone.
I would suggest looking for alternatives. However I'm unaware of their state. I know there were few attempts of making "language server protocol" servers for Go. Have no idea how good they are. Sadly proper autocompletion tool of a kind should reimplement all language semantic analysis, because working with code that is being actively edited is a slightly different task that doing compilation or static analysis. I think I know how to make a proper service here, but... There's always but.. Maybe one day.
github.com/stamblerre/gocode This version of gocode works with Go Modules. An autocompletion daemon ...
https://github.com/stamblerre/gocode
gocode の終わり
gocode が fork され、fork の存在を知らない一部の Go ユーザから「nsf/gocode が使えなくなった」との報告が出始めました。fork の存在を知っているユーザからは「org で1か所で開発すべきでは」と言った意見も出てきました。同じころ Visual Studio Code の Go 拡張は Language Server への移行を行っていましたが go-langserver も内部では gocode を使っているのですから、Visual Studio Code でも動くはずがありません。Go のコード補完にどんよりとした空気が漂っていました。
golsp の誕生
これはまずいなと思っていた頃、Go 開発者チームが Go のサブリポジトリである golang.org/x で LSP をサポートする動きを見せ始めました。2018年9月の話ですから今から3ヶ月前の話です。
つまり Language Server Client が実装されているテキストエディタであれば、go-langserver の代わりに golsp を使う事で正常なコード補完が使える様になるのです。とても喜ばしい事です。そして幸運な事に、僕が愛用する Vim には Language Server Protocol を実装したプラグイン、vim-lsp があり、これは実行する LSP コマンドを簡単に差し替えられる様になっています。
もちろん即答でOKを出し、先日 vim-lsp のコントリビュータにして頂きました。LSP は Go 言語に限った機能ではありません。今後 Vim の Language Server Protocol サポートを vim-lsp のコントリビュータとしてサポートして行きたいです。
さて、golsp ももちろん Vim の為だけの機能ではありません。Visual Studio Code も golsp の恩恵を受ける事が出来ます。Visual Studio Code の場合は標準で go-langserver を使う様になっているのですが、go-langserver の代替ソフトウェアを設定できる方法があります。
こうする事で go-langserver の代わりに golsp が使われます。筆者の手元でも問題なく Go のコード補完が出来ている事が確認出来ています。
bingo の誕生
さらに嬉しい事に、別の Go Language Server も登場しました。Language Server Protocol の機能の実装内容では golsp よりも多い様です。Vim および Visual Studio Code での設定内容は上記 golsp を bingo に変えるだけで OK です。
Hi @saibing ! I'm one of the people currently working on golang.org/x/tools/cmd/golsp . We recently ...
https://github.com/saibing/bingo/issues/13
もしこれが実現すれば、一時はどんよりとしていた Go のコード補完に新たな光が見え始める事になります。とても嬉しい状況ですね。
本家が発展する事が一番望ましい事だと思っています。
Go のコード補完のこれから
golang.org/x は拡張用のリポジトリとは言えど、Go 言語がオフィシャルとして Language Server のサポートをし始めたと言って良いでしょう。今後 Go 自身のパーサに変更が加えられたとしても、Go 言語開発者が golsp も追従させて行くでしょう。とは言え golsp もまだ発展途上です。Language Server の数ある機能の中、以下の機能が未実装です。
監視ファイルの変更イベント
シンボル一覧
コード補完処理の一部
参照元検索
ドキュメントのハイライト
コードアクション
インタフェースから実装の生成
コードレンズ
色のプレゼンテーション
リネーム
他
中には Go 言語には必要ない物もありますが、コード補完の一部は未だ改善の余地があります。Go 言語開発者に任せる事も出来ますが、皆さんからのコントリビューションにより、Go 言語のコード補完がより良くなっていきます。ぜひ golsp にコントリビューションしてみて下さい。vim-lsp も pull-request をお待ちしています。
gocode は開発を停止し、これから他の物が使われていくでしょう。もしかすると nsf 氏が gocode2 として復活させるかもしれないし、また別のコード補完ソフトウェアが誕生するかもしれない。しかしこれまで gocode が多くの Go 言語プログラマに与えてきた大きな貢献に対して、最後にももう一度言いたい。