VSCodeでLSP(クライアント側のサンプルを読む編)
https://code.visualstudio.com/docs/extensions/example-language-server
のクライアント側のコードを読んで理解してみる。
クライアント側は vscode-extension-samples/lsp-sample/client 配下のファイル。
client/package.json
まずは activationEvents。
"activationEvents": [ "onLanguage:plaintext" ]
activationEvents は onLanguage に記載されたファイルが開かれる度に、拡張機能(LSPのクライアント)が実行される。
"configuration": { "type": "object", "title": "Example configuration", "properties": { "lspSample.maxNumberOfProblems": { "scope": "resource", "type": "number", "default": 100, "description": "Controls the maximum number of problems produced by the server." } } }
「この設定は起動時や、設定が変更されるたびに言語サーバーに送信される」とのこと。
"dependencies": { "vscode": "^1.1.18", "vscode-languageclient": "^4.1.4" }
vscode extension host API と vscode-languageclient library のバージョン。
client/src/extension.ts
クライアント側のコードのエントリポイント。
synchronize のあたりがイマイチ理解できていない。
import * as path from 'path'; import { workspace, ExtensionContext } from 'vscode'; import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient'; export function activate(context: ExtensionContext) { // サーバー側の起動設定 // ...本サンプルではサーバー側が TypeScript で実装されているので // ...TypeScript からコンパイルした JS のソース位置を指定している模様 let serverModule = context.asAbsolutePath(path.join('server', 'server.js')); // ...デバッグ時のオプション指定 // ......--inspect はなんだろ let debugOptions = { execArgv: ["--nolazy", "--inspect=6009"] }; // ...デバッグモードの時は debug, それ以外は run let serverOptions: ServerOptions = { run : { module: serverModule, transport: TransportKind.ipc }, debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions } } // クライアント側のオプション let clientOptions: LanguageClientOptions = { // ...テキストファイルを対象とする documentSelector: [{scheme: 'file', language: 'plaintext'}], synchronize: { // ...以下の package.json の configuration.properties の // ...lspSample をサーバーと同期する。 // ...(lspSample.maxNumberOfProblems の値の変更がサーバーにも反映される?) // ......"configuration": { // ...... "properties": { // ...... "lspSample.maxNumberOfProblems": configurationSection: 'lspSample', // ... ワークスペース内の .clientrc ファイルのの変更をサーバーに通知する fileEvents: workspace.createFileSystemWatcher('**/.clientrc') } } // クライアント側の開始 let disposable = new LanguageClient('lspSample', 'Language Server Example', serverOptions, clientOptions).start(); // クライアントが拡張機能停止時に非アクティブ化できるようにする context.subscriptions.push(disposable); }
サーバー側の実装が TypeScript 以外の場合の設定方法
Launguage Server Protocol のサーバー側の実装はどんな言語でもよいとなっている。
サンプルでは TypeScript でサーバーが実装されているが、それ以外の言語で実装した場合は、
クライアント側はどう記述すればよいのか調べてみた。
TypeScript
まずは、サンプルのTypeScript。
以下の部分がポイントのよう。
let serverModule = context.asAbsolutePath(path.join('server', 'server.js')); let serverOptions: ServerOptions = { run : { module: serverModule, transport: TransportKind.ipc }, debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions } }
C#
- dll
OmniSharp から拝借
https://github.com/OmniSharp/csharp-language-server-protocol/blob/master/vscode-testextension/src/extension.ts
サーバーを dll で作成して 'dotnet' コマンドで起動する模様。
ServerOptions.run(debug).module の代わりに command を使う
let serverExe = 'dotnet'; let serverOptions: ServerOptions = { run: { command: serverExe, args: ['D:\\Development\\Omnisharp\\csharp-language-server-protocol\\sample\\SampleServer\\bin\\Debug\\netcoreapp2.0\\win7-x64\\SampleServer.dll', '-lsp'] }, debug: { command: serverExe, args: ['D:\\Development\\Omnisharp\\csharp-language-server-protocol\\sample\\SampleServer\\bin\\Debug\\netcoreapp2.0\\win7-x64\\SampleServer.dll', '-lsp'] } }
- exe
https://github.com/matarillo/vscode-languageserver-csharp-example/blob/master/client/src/extension.ts
から拝借。
こちらは exe を起動している。
let serverCommand = context.asAbsolutePath(path.join('server', 'SampleServer.exe')); let commandOptions: ExecutableOptions = { stdio: 'pipe', detached: false }; let serverOptions: ServerOptions = (os.platform() === 'win32') ? { run : <Executable>{ command: serverCommand, options: commandOptions }, debug: <Executable>{ command: serverCommand, options: commandOptions } } : { run : <Executable>{ command: 'mono', args: [serverCommand], options: commandOptions }, debug: <Executable>{ command: 'mono', args: [serverCommand], options: commandOptions } };
Java
qiitaの記事LSP4JでLanguage Server Protocol入門から拝借
command に java のパス、args に -jar と jar の場所を指定している。
const serverOptions: Executable = { command: "C:/PROGRA~1/Zulu/zulu-10/bin/java", args: ["-jar", "F:/work/TeachYourselfLsp4j/server/build/libs/TeachYourselfLsp4j-1.0-SNAPSHOT.jar"] }