Welcome to the lsp-language-server-Protocol, bytedance’s “Bug 2”.

Author: Worm 2

Learning the lsp-language-server-protocol specification

The official document: Microsoft. Making. IO/language – se…

Vscode LSP document: docs.microsoft.com/zh-cn/visua…

Yuge is learning the implementation mechanism of WebIDE recently, and needs to realize the interactive experience of intelligent hints, grammar checking and parsing, and hovering documents similar to IDE. Since it is not possible to embed VSCode directly, I want to learn the implementation of related aspects. The goal is to implement an IDE using Monaco and LSP.

Language Server Protocol (LSP), which defines the Protocol used between the editor or IDE and the Language Server. The Language Server provides functions such as automatic completion, go to the definition, and search for all references. The goal of the language server index format is to support rich code navigation in development tools or a web user interface that does not require a local copy of the source code.

Divided into the following aspects

  • What is the LSP

  • How LSP works

  • How do the IDE and the language server interact

  • The function of the LSP

  • LSP provider and consumer library (SDK)

Summary of LSP

What is the LSP

Each development IDE has to implement language functions such as auto-complete, rotate definitions, and hover over words to provide documentation. Traditionally, each IDE has to implement these functions according to its OWN API. Even if the same function is repeated by different ides, the code is different. For example, the Eclipse CDT plug-in (which supports C/C++ in the Eclipse IDE) is written in Java because the Eclipse IDE itself is written in Java. In this way, this means implementing the C/C++ domain model in TypeScript in Visual Studio code and a separate domain model in C# in Visual Studio.

It is also much easier to create language-specific domain models if development tools can reuse existing language-specific libraries. However, these libraries are usually implemented in the programming language itself (for example, a good C/C++ domain model is implemented in C/C++). It is technically possible, but difficult, to integrate C/C++ libraries into TypeScript editors.

A language server is designed to provide intelligence for a language and communicate with development tools through protocols that support interprocess communication.

LSP is designed to standardize communication between the language server and development tools. The language service can be reused by multiple development tools to support multiple languages with minimal change. The language server back end can be written in PHP, Python, or Java, and LSP can be easily integrated into a variety of tools. The protocol provides a common level of abstraction so that tools can provide rich language services without fully understanding the nuances specific to the underlying domain model.

LSP is a win-win for both language providers and tool providers!

How LSP works

The language server runs as a separate process, while development tools communicate with the server using a JSON-RPC-based language protocol.

Here is an example of communication between a development tool and a language server during editing:

  • When the user opens a file in the IDE: the IDE notifies the language server that the file is open (textDocument/didOpen), and the contents of the document are not stored in the actual file system, but in IDE memory. Content must be synchronized between the IDE and the language server.

  • When the user edits a file: the IDE notifies the language server that the file is updated (textDocument/didChange), and the language server updates the language representation of the file. Language after the server will analyze this message and will detect the error and warning, response (textDocument/publishDiagnostics) notify the IDE.

  • When the user executes the “Goto Definition” directive: THE IDE sends a request with parameters (textDocument/ Definition), params: {documentURI, position} to the language server, which responds with the documentURI and definition’s Location.

Here is an example of c++

When the user closes the file: THE IDE notifies the language server that the file is closed (textDocument/didClose), the file is no longer in memory, and the current content is up to date in the file system.

The example above illustrates how the protocol communicates with the language server at the document reference (URI) and document location levels. These data types are language-independent and apply to all programming languages. Data types are not at the level of programming language domain models, which typically provide abstract syntax trees and compiler notations (for example, parsed types, namespaces, and so on). The fact is that the data types are simple and programming language-independent, simplifying the protocol considerably. It is much easier to standardize text document URIs or cursor positions than it is to standardize abstract syntax trees and compiler symbols across different programming languages.

How does the IDE and language server work

The IDE starts a language server for each programming language when the user is using a different language. The following example shows how the IDE can use Java and SASS files on one session.

Capability of LSP

Not every language server can support all of the capabilities defined by the protocol, so LSP provides Capabilities, which can group a set of language capabilities together. Ides and language servers use capabilities to announce the capabilities they support.

For example, the language server declares that it can handle requests for textDocument/ Definition, but may not handle requests for workspace/ Symbol. Similarly, the IDE announces an About to Save notification before saving a document so that the server can calculate that the text editor will format the edited document before saving it.

Note that the integration of the language server implementation into a particular IDE is not defined by the language server protocol, but is determined by the IDE implementer

Here’s what Visual Studio provides

MessageHas Support in Visual StudioSWIDE
initialize yes
initialized yes
shutdown yes
exit yes
$/cancelRequest yes
window/showMessage yes
window/showMessageRequest yes
window/logMessage yes
telemetry/event
client/registerCapability
client/unregisterCapability
workspace/didChangeConfiguration yes
workspace/didChangeWatchedFiles yes
workspace/symbol yes
workspace/executeCommand yes
workspace/applyEdit yes
textDocument/publishDiagnostics yes
textDocument/didOpen yes
textDocument/didChange yes
textDocument/willSave
textDocument/willSaveWaitUntil
textDocument/didSave yes
textDocument/didClose yes
textDocument/completion yes
completion/resolve yes
textDocument/hover yes
textDocument/signatureHelp yes
textDocument/references yes
textDocument/documentHighlight yes
textDocument/documentSymbol yes
textDocument/formatting yes
textDocument/rangeFormatting yes
textDocument/onTypeFormatting
textDocument/definition yes
textDocument/codeAction yes
textDocument/codeLens
codeLens/resolve
textDocument/documentLink
documentLink/resolve
textDocument/rename yes

LSP provider and consumer library (SDK)

To simplify the implementation of the language server and client, libraries or SDKS are provided:

  • IDE SDK: Each development tool typically provides a library for integrating a language server. For example, for JavaScript/TypeScript, there is the language client NPM module [1] to simplify the integration of the language server and vs extensions.

  • Language server SDK for implementing different languages: An SDK can be used to implement a language server in a specific language. For example, to implement a language server using Node.js, you can use the language server NPM module [2].

References

[1] NPM module: www.npmjs.com/package/vsc…

[2] language server NPM module: www.npmjs.com/package/vsc…

LSP – language – server – [3] language study: protocol specification mp.weixin.qq.com/s/leNgwb0fT…

The  End