Language Server Protocolの仕組みについての概要~Goを例に~
コードエディタを使っているときに補完をしてコーディングすることが多いと思います。
例えばGoのコードを書いていてある関数内でfmt.P
と入力したときには以下のスクショのように
- Printf
- Println
などがサジェストされます。
この仕組みを支えるLanguage Server Protocol について本記事では解説していきます。
そもそもLSPとは
Language Server Protocol (以下LSP)はエディタやIDEとプログラミング言語間の通信プロトコルです。
LSPを使用するとエディタは特定のプログラミング言語の詳細を知る必要がなく、代わりにLanguage Serverと通信することで、コード補完、定義へのジャンプ、リファクタリングなどの機能を提供できます。
つまりVSCode、Zed、Vimなどのエディタそれぞれにコード補完用の機能を開発する必要がなく、共通の機能を提供できるようになっています。
だいたいの動き
LSPがサジェストを提供するまでの流れは以下のようになります。
-
エディタでコードを入力
-
エディタがLanguage Serverに対して補完リクエストを送る。リクエストには、現在のファイルのURIとカーソルの位置情報が含まれる
-
Language Serverがリクエストからファイルのソースコードを解析する(この解析はカーソルの位置情報を元に構文木を構築する)
-
Language Serverが構文木を元に可能な補完候補を計算する
-
補完候補をエディタに送信する
-
エディタが候補を表示する
Goでの例
Goではgoplsが公式でサポートしているLSPで、そのサジェストを提供する流れを以下に示します。
-
コードを入力(例えば、
fmt.P
と入力したとする) -
エディタはgoplsに対して補完リクエストを送信する
-
goplsがカーソルの位置情報を元に構文木を作成してソースコードを解析
-
goplsが構文木を元に、Goの言語仕様と標準ライブラリ、コードを元に可能な補完候補を計算する
-
計算した補完候補をエディタに送信し、エディタは候補を表示する
以上の流れにより、ユーザーはfmt.Pと入力したときに、Print、Printf、Printlnなどの補完候補を見ることができます。
AIコード補完ツールとの比較
一方でGitHub CopilotはAIベースのコード補完ツールで、大量の公開コードから学習しています。
Copilotは特定の言語の詳細を理解するのではなく、過去のコードからパターンを学習してそれを元にコード補完を提供します。
LSP | AI | |
---|---|---|
知識の源泉 | 言語の仕様とその言語のLanguage Server | 公開されているコードベース全体 |
動作の仕組み | エディタとLanguage Server間の通信 | AIモデルがユーザーの入力コードを元に補完を生成 |
対応言語 | Language Serverが存在する言語 | 学習データに含まれる言語 |
使い分けとしては
- LSPは言語の詳細を深く理解し精度の高いコード補完やリファクタリング
- Copilotは広範なコードベースから学習し新しいパターンや異なるコーディングスタイルの補完
といったところでしょうか。