RustでLSPサーバを実装するなら
どうすればいい?(2023年5月現在)
https://crates.io/crates/lsp-types いろんなcrateで下回りとして使われている。
https://crates.io/crates/tower-lsp towerというサーバフレームワーク上の実装
https://crates.io/crates/async-lsp まだearly development stageとのこと
https://crates.io/crates/lsp-server "Generic LSP server scaffold"
rust-analyzerに入っているexampleらしいhttps://github.com/rust-lang/rust-analyzer/tree/master/lib/lsp-server
mun-lang
Rust製の言語で、LSP内蔵
https://github.com/mun-lang/mun/blob/main/crates/mun_language_server/Cargo.toml
lsp-server crateを使っている
となるとlsp-serverとtower-lspの2択かなあ。
tower-lsp
denoが使っている https://github.com/denoland/deno/blob/af72a9c6576cab16128a89d3c9cd5f57cd0d2504/cli/lsp/README.md
lsp-server
munが使っている
エントリポイント https://github.com/mun-lang/mun/blob/main/crates/mun_language_server/src/lib.rs#L148
denoのソースは長すぎるけど、tower-lspを使っているプロジェクトでもう少し小さいのがあった。これを参考にしてみようかな。
https://github.com/dalance/veryl/blob/master/crates/languageserver/src/main.rs
ところで
これでLSPサーバができたとして、それをvscodeから使うにはどうしたらいいんだろう
vscodeの拡張機能を書かないといけない気がする。
Munの場合 https://github.com/mun-lang/vscode-extension
へー、F5(Run→Debug)で「その拡張が入った状態のWindow」が起動するという感じなんだ。
console.logはもとのWindowのDebug Consoleに出る
ただし設定値 名前.server.traceをverboseにする必要がある。Debug中のWindowだとこの設定値があった。 https://code.visualstudio.com/api/language-extensions/language-server-extension-guide#logging-support-for-language-server
verylを参考にLSPサーバを実装する
https://github.com/dalance/veryl/blob/master/crates/languageserver/src/main.rs
tower-lspの規約で、impl LanguageServer for Backendする必要がある
backend.rsはメッセージをフォワードするだけで、本体はserver.rsにある
自分に必要な項目を抜き出す処理だけbackend.rsにあるわけね。綺麗な設計ですねyhara.icon
Backend::initializeはServerCapabilitiesを返す
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#serverCapabilities
機能
completionProvider: 補完
hoverProvider: ホバー
signatureHelpProvider
declarationProvider: 宣言に飛ぶ
definitionProvider: 定義に飛ぶ
typeDefinitionProvider: 型定義に飛ぶ
implementationProvider: 実装に飛ぶ
referencesProvider: すべての参照を表示
documentHighlightProvider:
documentSymbolProvider:
codeActionProvider:
codeLensProvider:
documentLinkProvider:
colorProvider: 「色」を表現するもの(cssのbackground-colorとか)に使う
documentFormattingProvider: オートフォーマット
documentRangeFormattingProvider: 特定範囲のオートフォーマット
documentOnTypeFormattingProvider: リアルタイムオートフォーマット
renameProvider: 変数名とかのリネーム
foldingRangeProvider: 畳み込み
executeCommandProvider: コマンド実行
selectionRangeProvider: 選択範囲をいい感じに拡張するもの?
linkedEditingRangeProvider:
callHierarchyProvider: 呼び出し階層
semanticTokensProvider: リッチなトークン情報、ここは型引数だよとか
どこが型かわかってないと「型定義に飛ぶ」が出せないもんな。yhara.icon
monikerProvider:
typeHierarchyProvider: 型階層
inlineValueProvider: この行を評価した結果はこれです、みたいなやつ?yhara.icon
inlayHintProvider:
diagnosticProvider:
workspaceSymbolProvider:
それ以外
positionEncoding:
textDocumentSync:didOpen, didChange, didCloseという3つのイベントをフックする
notebookDocumentSync:
workspace:
ワークスペースという概念があるか
Shiikaの場合は、ある(ワークスペースルートでshiika buildしたいので必要)
ファイルの作成、リネーム、削除をトラッキングできる