VS Code拡張開発(LSP)

拡張とLSPの関係

VS Code 拡張は [[Node.js]] 上で動くプログラムで、[[TypeScript]] で書くのが標準です。コマンドの追加や画面の装飾はエディタのAPIを直接呼べば済みます。

一方で、補完・診断(赤波線)・定義ジャンプ・ホバー説明のような言語機能は、エディタごとに書き直すと際限がありません。そこで使うのが LSP(Language Server Protocol)です。

役割実装
クライアントエディタ側。編集内容を送り、返ってきた結果を表示する拡張の中に薄く置く
サーバー言語側。解析して補完候補や診断を返すエディタから独立した別プロセス

両者は JSON-RPC というメッセージ形式でやり取りします。サーバーはエディタを知りません。 そのため同じサーバーを Neovim や他のエディタからも使えます。これがエディタごとの作り直しを避ける仕組みです。

サーバーが答える主なリクエスト

connection.onCompletion((params) => [
  { label: 'SUM', detail: '合計を求める関数' },
])

connection.onHover((params) => ({
  contents: { kind: 'markdown', value: '**SUM(範囲)** — 合計を返す' },
}))

診断だけは向きが逆で、サーバーから一方的に送りつけます。編集のたびに解析し、問題があれば範囲と重大度を通知します。[[静的解析とリンター]] の結果をエディタ上に出す経路がこれです。

別プロセスであることの意味

サーバーが別プロセスなのは設計上の要点です。

  • 重い解析でエディタが固まらない — 入力の反応とは独立して動く
  • 落ちてもエディタは生き残る — サーバーだけ再起動できる
  • 状態はサーバーが持つ — エディタは「何行目が変わった」しか送らない。ファイル全体の解析結果はサーバー側で保持する

裏返すと、エディタとサーバーで見ているファイル内容がずれると破綻します。編集内容の同期はプロトコルの根幹で、ここを自前で省略すると「保存するまで反映されない」といった不具合になります。

実務での注意点

  • 設定のスキーマを書く — 拡張の設定項目は package.json に宣言します。書式は [[JSON Schema]] 相当で、これが設定画面の入力補助になります
  • 起動条件を絞る — 全ファイルで起動する拡張は体感を悪くします。対象の言語やファイル名に限定します
  • デバッグは2プロセス — クライアントとサーバーを別々にアタッチします。サーバー側のログは専用の出力チャネルへ出します
  • [[ドキュメンテーション]] が普及を決める — 拡張は使い方が分からなければ使われません。設定項目とコマンドの一覧は README に必ず載せます

初学者向けポイント

  • まずは診断だけを返すサーバーから始めると全体像が掴めます。補完や定義ジャンプは後から足せます
  • 位置の指定は0始まりの行・桁です。エディタの表示(1始まり)とずれるため、範囲がひとつずれる不具合が起きがちです
  • ファイルの識別子はパスではなく URI です。Windows のパス区切りをそのまま渡すと一致しません

関連技術とのつながり

  • [[TypeScript]] — 拡張とサーバーの標準的な記述言語
  • [[Node.js]] — 拡張の実行環境
  • [[静的解析とリンター]] — 解析結果を診断としてエディタに出す経路
  • [[JSON Schema]] — 設定項目の宣言と入力補助の土台
  • [[ドキュメンテーション]] — 設定とコマンドを伝えないと拡張は使われない
Q: LSPでサーバーをエディタから独立させる利点はどれ?
- [ ] エディタの起動が速くなる
- [x] 同じサーバーを別のエディタからも使え、作り直しを避けられる
- [ ] 拡張の配布サイズが小さくなる
解説: サーバーはエディタを知らないため、プロトコルに対応した他のエディタからも利用できます。

Q: 診断(赤波線)のやり取りの向きはどれ?
- [ ] エディタが要求し、サーバーが応答する
- [x] サーバーが解析結果を一方的に通知する
- [ ] エディタが自分で解析して表示する
解説: 編集のたびにサーバーが解析し、問題の範囲と重大度を通知します。

Q: 言語サーバーを別プロセスにすることで避けられる問題はどれ?
- [x] 重い解析でエディタの入力が固まること
- [ ] ファイルの文字コードが化けること
- [ ] 設定項目が増えること
解説: 解析が独立して動くため入力の反応を妨げず、サーバーが落ちてもエディタは生き残ります。