言語サーバー プロトコルLanguage Server Protocol

言語サーバー プロトコルとは何ですか。What is the Language Server Protocol?

サポートの豊富な編集機能などのソース コード自動補完機能または定義へ移動エディターまたは IDE でのプログラミング言語は従来から非常に困難で時間がかかります。Supporting rich editing features like source code auto-completions or Go to Definition for a programming language in an editor or IDE is traditionally very challenging and time consuming. 通常、エディターや IDE のプログラミング言語で (スキャナー、パーサー、型チェック、ビルダーなど) は、ドメイン モデルの作成が必要です。Usually it requires writing a domain model (a scanner, a parser, a type checker, a builder and more) in the programming language of the editor or IDE. たとえば、Eclipse IDE で C/C++ 用のサポートを提供する CDT の Eclipse プラグインは Java で記述された Eclipse IDE 自体は Java で記述するため。For example, the Eclipse CDT plugin, which provides support for C/C++ in the Eclipse IDE is written in Java since the Eclipse IDE itself is written in Java. この方法は、次の for Visual Studio で c# for Visual Studio Code では、TypeScript での C/C++ ドメイン モデルとは別のドメイン モデルを実装することは意味します。Following this approach, it would mean implementing a C/C++ domain model in TypeScript for Visual Studio Code, and a separate domain model in C# for Visual Studio.

言語固有のドメイン モデルの作成も、ずっと楽、開発ツールでは、既存の言語固有のライブラリを再利用できます。Creating language-specific domain models are also a lot easier if a development tool can reuse existing language-specific libraries. ただし、これらのライブラリは通常、プログラミング言語そのもの (たとえば、正常な C/C++ ドメイン C および C++ でモデルを実装) で実装します。However, these libraries are usually implemented in the programming language itself (for example, good C/C++ domain models are implemented in C/C++). TypeScript で記述された、エディターに C と C++ のライブラリを統合する技術的には可能ですが難しい。Integrating a C/C++ library into an editor written in TypeScript is technically possible but hard to do.

言語のサーバーLanguage servers

別の方法を独自のプロセスで、ライブラリを実行し、プロセス間通信を使用して、通信が行わします。Another approach is to run the library in its own process and use inter-process communication to talk to it. メッセージの送受信は、プロトコルを形成します。The messages sent back and forth form a protocol. 言語サーバー プロトコル (LSP) は、製品の開発ツールと言語のサーバー プロセスの間で交換されるメッセージを標準化することです。The language server protocol (LSP) is the product of standardizing the messages exchanged between a development tool and a language server process. 言語のサーバーまたはデーモンの使用は、新規または斬新な考え方ではありません。Using language servers or demons is not a new or novel idea. Vim および Emacs 行っていたこのしばらくセマンティック オート コンプリートをサポートするようにエディター。Editors like Vim and Emacs have been doing this for some time to provide semantic auto-completion support. お客様の LSP の目的は、この種の統合を簡素化し、さまざまなツールへの言語機能を公開するための便利なフレームワークを提供することでした。The goal of the LSP was to simplify these sorts of integrations and provide a useful framework for exposing language features to a variety of tools.

一般的なプロトコルのプログラミング言語の機能を言語のドメイン モデルの既存の実装を再利用して最小限の労力で、開発ツールに統合できます。Having a common protocol allows the integration of programming language features into a development tool with minimal fuss by reusing an existing implementation of the language's domain model. 言語サーバー バックエンドは、PHP、Python、または Java で記述できることし、さまざまなツールに簡単に統合することにより、お客様の LSP です。A language server back-end could be written in PHP, Python, or Java and the LSP lets it be easily integrated into a variety of tools. プロトコルは、ツールは、基になるドメイン モデルに固有の微妙な差異を完全に理解することがなく豊富な言語サービスを提供できますように抽象化の一般的なレベルで動作します。The protocol works at a common level of abstraction so that a tool can offer rich language services without needing to fully understand the nuances specific to the underlying domain model.

開始 LSP で機能するしくみHow work on the LSP started

LSP は、時間の経過と共に進化してきた現在 Version 3.0 には.The LSP has evolved over time and today it is at Version 3.0. 言語サーバーの概念によって取得された OmniSharp (C#) または高度な編集機能を提供するときに開始します。It started when the concept of a language server was picked up by OmniSharp to provide rich editing features for C#. 最初に、OmniSharp は、JSON ペイロードで HTTP プロトコルを使用しなどいくつかのエディターに統合されましたVisual Studio Codeします。Initially, OmniSharp used the HTTP protocol with a JSON payload and has been integrated into several editors including Visual Studio Code.

同時期は、Microsoft は、Sublime Text、Emacs などのエディターで TypeScript をサポートするというアイデア、TypeScript 言語のサーバーの作業を開始します。Around the same time, Microsoft started to work on a TypeScript language server, with the idea of supporting TypeScript in editors like Emacs and Sublime Text. この実装では、エディターは、stdin と stdout TypeScript サーバー プロセスを経由して通信し、要求と応答、V8 デバッガー プロトコルに触発された JSON ペイロードを使用します。In this implementation, an editor communicates through stdin/stdout with the TypeScript server process and uses a JSON payload inspired by the V8 debugger protocol for requests and responses. TypeScript サーバーは、TypeScript の豊富な編集の TypeScript Sublime プラグイン、VS Code に統合されています。The TypeScript server has been integrated into the TypeScript Sublime plugin and VS Code for rich TypeScript editing.

別の言語の 2 つのサーバーを統合すると後、は、VS Code チームがエディターや Ide の一般的な言語サーバー プロトコルの詳細を開始しました。After having integrated two different language servers, the VS Code team started to explore a common language server protocol for editors and IDEs. 一般的なプロトコルにより、別の Ide で使用できる 1 つの言語のサーバーを作成する言語プロバイダー。A common protocol enables a language provider to create a single language server that can be consumed by different IDEs. 言語サーバーのコンシューマーは、1 回クライアント側のプロトコルを実装するためにのみがあります。A language server consumer only has to implement the client side of the protocol once. これにより、確実な状況での言語プロバイダーと言語のコンシューマーの両方。This results in a win-win situation for both the language provider and the language consumer.

言語サーバー プロトコルは、VS Code language API に触発された詳細の言語機能と展開、TypeScript サーバーによって使用されるプロトコルを開始します。The language server protocol started with the protocol used by the TypeScript server, expanding it with more language features inspired by the VS Code language API. プロトコルは、わかりやすくするために、既存のライブラリにより、リモート起動するための JSON RPC でサポートされます。The protocol is backed with JSON-RPC for remote invocation due to its simplicity and existing libraries.

VS コードの lint (スキャン) をいくつかのリンター言語サーバーに応答を実装することで、プロトコルが要求チームのプロトタイプをファイルと、検出された警告とエラーのセットを返します。The VS Code team prototyped the protocol by implementing several linter language servers which respond to requests to lint (scan) a file and return a set of detected warnings and errors. 目標でした lint 対象ファイルがある多数の lint 処理要求エディター セッション中には、ドキュメント内のユーザーによるコンテンツの編集。The goal was to lint a file as the user edits in a document, which means that there will be many linting requests during an editor session. 理サーバーを新しい lint 処理プロセスでしたを各ユーザーの編集を開始する必要がないようにを稼働し、続けるにします。It made sense to keep a server up and running so that a new linting process did not need to be started for each user edit. VS Code のなど、いくつかのリンター サーバーが実装された ESLint および TSLint の拡張機能。Several linter servers were implemented, including VS Code's ESLint and TSLint extensions. これら 2 つのリンター サーバーし、TypeScript と JavaScript で実装の両方で Node.js を実行します。These two linter servers are both implemented in TypeScript/JavaScript and run on Node.js. プロトコルのクライアントとサーバーの一部を実装するライブラリを共有します。They share a library that implements the client and server part of the protocol.

お客様の LSP のしくみHow the LSP works

言語サーバーが、独自のプロセスで実行され、Visual Studio または VS Code などのツールと言語のプロトコルを使用して JSON RPC 経由でサーバーの通信。A language server runs in its own process, and tools like Visual Studio or VS Code communicate with the server using the language protocol over JSON-RPC. 専用のプロセスで動作している言語のサーバーのもう 1 つの利点は、1 つのプロセス モデルに関連するパフォーマンスの問題が回避されます。Another advantage of the language server operating in a dedicated process is that performance issues related to a single process model are avoided. 実際のトランスポート チャネルには stdio、ソケット、名前付きパイプ、またはノード ipc かを指定できます、クライアントとサーバーの両方が Node.js で記述された場合。The actual transport channel can either be stdio, sockets, named pipes, or node ipc if both the client and server are written in Node.js.

ルーチンの中に、ツールと言語のサーバーが通信する方法の例は以下がセッションを編集します。Below is an example for how a tool and a language server communicate during a routine editing session:

lsp フロー図

  • ユーザーがツールで (ドキュメントと呼ばれる) ファイルを開く:ツールは、ドキュメントが開かれている言語のサーバーに通知します (' textDocument/didOpen ')。The user opens a file (referred to as a document) in the tool: The tool notifies the language server that a document is open ('textDocument/didOpen'). ドキュメントの内容に関する事実では、ファイル システムにされていませんが、ツールによってメモリに保持されます。From now on, the truth about the contents of the document is no longer on the file system but kept by the tool in memory.

  • ユーザーが編集を行った:ドキュメントの変更 (' textDocument/didChange ') について、サーバーに通知し、言語のサーバーによって、プログラムのセマンティック情報が更新します。The user makes edits: The tool notifies the server about the document change ('textDocument/didChange') and the semantic information of the program is updated by the language server. このとき、言語のサーバーはこの情報を分析し、検出されたエラーと警告 (' textDocument/publishDiagnostics ') を使用して、ツールを通知します。As this happens, the language server analyzes this information and notifies the tool with the detected errors and warnings ('textDocument/publishDiagnostics').

  • ユーザーが"定義へ移動 を実行し、エディター内のシンボル:ツールは、2 つのパラメーター 'textDocument/定義' の要求を送信します。(1)、ドキュメントの URI と (2) サーバーに定義の要求への移動が開始位置からテキストの位置。The user executes "Go to Definition" on a symbol in the editor: The tool sends a 'textDocument/definition' request with two parameters: (1) the document URI and (2) the text position from where the Go to Definition request was initiated to the server. サーバーは、ドキュメントの URI とシンボルの定義、文書内の位置を返します。The server responds with the document URI and the position of the symbol's definition inside the document.

  • ユーザーがドキュメント (ファイル) を閉じる:'TextDocument/didClose' 通知を送信、ツール、ドキュメントが不要になったのメモリに現在の内容は今すぐファイル システムに最新の状態を言語のサーバーに通知します。The user closes the document (file): A 'textDocument/didClose' notification is sent from the tool, informing the language server that the document is now no longer in memory and that the current contents is now up to date on the file system.

この例では、プロトコルが「定義へ移動」、「すべての参照の検索」のようなエディター機能のレベルで言語のサーバーと通信する方法を示しています。This example illustrates how the protocol communicates with the language server at the level of editor features like "Go to Definition", "Find all References". プロトコルで使用されるデータ型とは、エディターまたは IDE、現在開いているテキスト ドキュメントと、カーソルの位置のようなデータ型です。The data types used by the protocol are editor or IDE 'data types' like the currently open text document and the position of the cursor. データ型は、抽象構文ツリー、およびコンパイラのシンボル (解決された型を名前空間など) を提供することは通常、プログラミング言語のドメイン モデルのレベルでないです。これにより、プロトコルが大幅に合理化されます。The data types are not at the level of a programming language domain model which would usually provide abstract syntax trees and compiler symbols (for example, resolved types, namespaces, ...). This simplifies the protocol significantly.

今すぐ 'textDocument/定義' の要求について詳しく見てみましょう。Now let's look at the 'textDocument/definition' request in more detail. クライアント ツールと C++ のドキュメントで「定義へ移動」要求の言語のサーバー間で移動するペイロードを以下に示します。Below are the payloads that go between the client tool and the language server for the "Go to Definition" request in a C++ document.

これが、要求。This is the request:

{
    "jsonrpc": "2.0",
    "id" : 1,
    "method": "textDocument/definition",
    "params": {
        "textDocument": {
            "uri": "file:///p%3A/mseng/VSCode/Playgrounds/cpp/use.cpp"
        },
        "position": {
            "line": 3,
            "character": 12
        }
    }
}

これは、応答を示します。This is the response:

{
    "jsonrpc": "2.0",
    "id": "1",
    "result": {
        "uri": "file:///p%3A/mseng/VSCode/Playgrounds/cpp/provide.cpp",
        "range": {
            "start": {
                "line": 0,
                "character": 4
            },
            "end": {
                "line": 0,
                "character": 11
            }
        }
    }
}

今にして思えば、プログラミング言語モデルのレベルではなく、エディターのレベルでのデータ型を記述するは、言語サーバー プロトコルの成功の理由の 1 つ。In retrospect, describing the data types at the level of the editor rather than at the level of the programming language model is one of the reasons for the success of the language server protocol. テキスト ドキュメント URI を標準化するよりもシンプルまたはカーソル位置をさまざまなプログラミング言語、抽象構文ツリーとコンパイラのシンボルを標準化することと比較します。It is much simpler to standardize a text document URI or a cursor position compared with standardizing an abstract syntax tree and compiler symbols across different programming languages.

ユーザーは、異なる言語で動作しているときに VS Code は通常各プログラミング言語の言語のサーバーを起動します。When a user is working with different languages, VS Code typically starts a language server for each programming language. 次の例は、ユーザーが Java と SASS ファイルには機能、セッションを示しています。The example below shows a session where the user works on Java and SASS files.

java と sass

機能Capabilities

すべての言語のサーバーには、プロトコルで定義されているすべての機能をサポートできます。Not every language server can support all features defined by the protocol. そのため、クライアントとサーバーは、'capabilities' をサポートされている機能セットを発表します。Therefore, the client and server announces their supported feature set through 'capabilities'. 例として、サーバーは、' textDocument/定義 'の要求を処理できますが、' ワークスペース/シンボル' 要求を処理する可能性がありますはないことを発表します。As an example, a server announces that it can handle the 'textDocument/definition' request, but it might not handle the 'workspace/symbol' request. 同様に、クライアントが ' 'の保存に提供されることを発表することができます、文書を保存するため、サーバーが編集されたドキュメントを自動的に書式設定するテキストの編集を計算する前に通知します。Similarly, clients can announce that they are able to provide 'about to save' notifications before a document is saved, so that a server can compute textual edits to automatically format the edited document.

言語サーバーの統合Integrating a language server

言語サーバーの特定のツールへの実際の統合は言語サーバー プロトコルで定義されていないと、ツールの実装にします。The actual integration of a language server into a particular tool is not defined by the language server protocol and is left to the tool implementors. いくつかのツールは、拡張機能を開始でき、任意の種類の言語のサーバーと通信することで一般的に言語のサーバーを統合します。Some tools integrate language servers generically by having an extension that can start and talk to any kind of language server. 、他のユーザー、VS コードのようにカスタム拡張機能を作成、サーバーの言語ごと拡張機能が、一部のカスタム言語機能を提供することができるようにします。Others, like VS Code, create a custom extension per language server, so that an extension is still able to provide some custom language features.

言語のサーバーとクライアントの実装を簡略化するにはライブラリまたは Sdk のクライアントとサーバーの部分です。To simplify the implementation of language servers and clients, there are libraries or SDKs for the client and server parts. これらのライブラリは、さまざまな言語で提供されます。These libraries are provided for different languages. などがありますが、言語クライアントの npm モジュールに VS Code 拡張機能と言語のサーバーの統合を容易に言語 server の npm モジュール言語を Node.js を使用してサーバーを記述します。For example, there is a language client npm module to ease the integration of a language server into a VS Code extension and another language server npm module to write a language server using Node.js. これは、現在一覧サポート ライブラリの。This is the current list of support libraries.

Visual Studio での言語サーバー プロトコルの使用Using the Language Server Protocol in Visual Studio