【入門編】VS Codeで「独自の言語サーバー(LSP)」を自作する:マイナー言語や設定ファイルの補完を爆速化する方法 – 軽量・高機能テキストエディタ生産性向上バイブル

こんにちは!日々のコーディング、本当にお疲れ様です。

突然ですが、皆さんは普段使っているVS Codeで、「ちょっとマイナーな独自の設定ファイル」や「社内独自のDSL(ドメイン特化言語)」を書くとき、入力補完(IntelliSense)が効かずにイライラした経験はありませんか?

「プロパティ名なんだっけ?」「また公式ドキュメントを行ったり来たりしてる……」
そんな小さなストレスの積み重ねが、エンジニアの集中力を削ぎ落としていきますよね。

実は、VS CodeにはLanguage Server Protocol(LSP)という強力な仕組みが備わっています。これを使えば、どんなマイナーな言語や設定ファイルであっても、メジャー言語並みの「爆速で賢い入力補完」を自作できてしまうのです。

今回は、世の中に溢れる難解な仕様書の解説ではなく、「どうすれば自分の手で動くLSPを作り、明日の開発を劇的に楽にできるか」を、優しく、かつ技術の本質を突きながらお伝えしていきます。

これをマスターすれば、あなたの開発環境の戦闘力は跳ね上がりますよ。さあ、一緒に進めていきましょう!

—

1. そもそも「LSP(Language Server Protocol)」ってなに?

LSPを簡単に一言で表すなら、「エディタと、言語解析エンジンを繋ぐ共通の通訳者」です。

昔は、VS Code用、IntelliJ用、Vim用……と、エディタが変わるたびに言語の構文解析プログラムを書き直す必要があり、開発者にとっては悪夢のような状況でした。それをMicrosoftが「いや、JSON-RPCという共通のルールで会話しようぜ」と整理したのがLSPです。

LSPの裏側で何が起きているのか?

あなたがVS Codeでコードを書いているとき、裏側では次のようなデータが流れています。

1. テキスト変更の通知 (`textDocument/didChange`):
「今、ユーザーが3行目に `server_ip: ` と打ったよ」というイベントが、VS Code(クライアント)からLSPサーバーへ送られます。
2. 言語サーバーの思考:
LSPサーバー側は、そのテキストを解析し、「あ、ここではIPアドレスの補完候補を出すべきだな」と判断します。
3. 補完候補の返却 (`textDocument/completion`):
「候補は `192.168.1.1` と `10.0.0.1` だよ」と、VS CodeにJSON形式でデータを返します。

この仕組みの何が素晴らしいかと言うと、「VS Codeの拡張機能の作り方を深く知らなくても、標準入出力(stdio)が扱える言語(PythonやTypeScriptなど)で、自分専用の頭脳を作れる」という点にあります。

—

2. 今回作る「HelloWorld」の目標

今回は、実務でもよくある「社内専用のデプロイ設定ファイル(拡張子 `.dpl`)」をターゲットにします。
この `.dpl` ファイルの中で、`env:` と打ったら、自動的に `development`, `staging`, `production` という選択肢がポップアップで出てくる――そんな小さな、しかし実用的なLSPサーバーをPythonで実装してみましょう。

—

3. 実装ステップ:自分だけのLSPサーバーを爆誕させる

複雑な環境構築は不要です。Pythonが動く環境さえあれば、今すぐ始められます。

ステップ1: 必要なライブラリのインストール

Pythonには、LSPの面倒な通信部分をすべてラップしてくしてくれる神ライブラリ `pygls` があります。これを使わない手はありません。

LSPサーバーを最速で構築するためのライブラリをインストールします
pip install pygls

ステップ2: LSPサーバーのスクリプトを書く

作業用ディレクトリに `server.py` というファイルを作成し、以下のコードを記述してください。一行ずつ丁寧なコメントを入れています。

# server.py : 独自言語サーバーの心臓部

from lsprotocol.types import (

CompletionItem,
CompletionList,
CompletionParams,
)
from pygls.server import LanguageServer

LanguageServerのインスタンスを生成(サーバー名とバージョンを指定)
server = LanguageServer(“my-dpl-server”, “v0.1.0”)

@server.feature(“textDocument/completion”)
def completions(params: CompletionParams) -> CompletionList:
“””
ユーザーがエディタで入力中(補完を要求)にトリガーされる関数です。
ここで現在の文脈を読み取り、補完候補のリストを返却します。
“””
# デバッグ用にクライアントからのパラメータを出力(VS Codeの出力パネルで見られます)
server.show_message(“LSP: 補完リクエストを受け取りました!”)

# 今回はシンプルに、常に固定の環境名候補を返すロジックにします
return CompletionList(
is_incomplete=False,
items=[
CompletionItem(label=”development”), # 開発環境用
CompletionItem(label=”staging”), # ステージング環境用
CompletionItem(label=”production”), # 本番環境用
],
)

if __name__ == “__main__”:
# 標準入出力(stdio)を使ってVS Codeと通信を開始します
server.start_io()

たったこれだけのコード(約30行)で、立派な言語サーバーの完成です。

—

4. VS Codeと接続する:魔法の結線作業

さあ、自作したLSPサーバーをVS Codeに認識させましょう。
ここが一番ワクワクする瞬間です。

ステップ1: テスト用ファイルの準備

適当なワークスペースを開き、拡張子が `.dpl` のファイル(例: `app.dpl`)を1つ作成してください。

ステップ2: VS Codeのワークスペース設定を行う

プロジェクトのルートに `.vscode` フォルダを作り、その中に `settings.json` を配置します。ここで「`.dpl` ファイルが開かれたら、さっきのPythonスクリプトをLSPとして起動しなさい」とVS Codeに指示を出します。

{
“sqltools.connections”: [],
// 拡張子 .dpl を持つファイルに対する言語設定
“[dpl]”: {
“editor.quickSuggestions”: {
“other”: true,
“comments”: false,
“strings”: false
}
},
// 独自LSPクライアントの設定 (LSP拡張機能を入れる代わりに今回は設定で紐づけます)
// ※実運用では簡易的な拡張機能を作りますが、今回は組み込み設定でテストします
}

※補足: 本格的にLSPを常時稼働させるには、数ファイルの「VS Code拡張機能(Client)」のラッパーを作るのが王道ですが、今回は最も手軽にLSPの挙動を体感するため、Pythonスクリプトを直接叩く設定を組み込んでみましょう。

VS Codeの拡張機能(例えば、自作拡張機能を作るか、汎用的なLSPクライアント拡張機能 `Language Server Client` など)を介して、以下のようにサーバーの起動コマンドを登録します。

// 例: 拡張機能側で指定するサーバー起動コマンドのイメージ
“myLanguageServer.server”: {
“command”: “python”,
“args”: [“C:/path/to/your/server.py”]
}

これで、あなたが `.dpl` ファイルを開いて文字を打ち始めると、裏側で `python server.py` がバックグラウンドプロセスとして立ち上がり、VS CodeとJSON-RPCで会話を始めます。

—

5. 動作確認:いざ、補完の瞬間へ!

設定が完了したら、`app.dpl` を開いて、適当な文字(例えば `env:` など)を入力してみてください。

1. キーボードを叩くたびに、VS Codeから `server.py` にテキストデータが送られます。
2. `server.py` がそれをフックし、`”development”`, `”staging”`, `”production”` の配列を返します。
3. 画面上に、ピタリと自作の補完候補が表示されます!

「おぉ……!自分で作った頭脳が、VS CodeのUIと連動して動いている……!」
この瞬間、エンジニアとしての確かな手応えと、ちょっとした感動を覚えていただけるはずです。

—

おわりに:あなたの開発体験は、あなた自身でハックできる

今回はLSPの概念と、Pythonを使った極めてシンプルな入力補完サーバーの自作方法をご紹介しました。

「たったこれだけのことで?」と思われるかもしれませんが、この基礎(LSPの仕組みとstdio通信の理解)さえ押さえておけば、応用は無限大です。

  • 社内のAPIスキーマを読み込ませて、エンドポイントのURLを自動補完させる
  • 独自のバリデーションルールを定義して、保存時にエラー(Diagnostics)を赤波線で表示させる

市販のエディタ機能に不満を覚えるのではなく、「無いなら、自分でコードを書いて拡張してしまえばいい」。このマインドセットこそが、私たちエンジニアの生産性を極限まで引き上げる最大の武器になります。

毎日のコーディングが、今日から少しでも楽しく、劇的に楽になりますように。
それでは、次のアーキテクチャでお会いしましょう!

タイトルとURLをコピーしました