Maciek905_dreamstime_50188994
Code Maciek905 Dreamstime L 50188994

Examining the Language Server Protocol and Its Implementation

May 6, 2022
The Language Server Protocol (LSP) lets you transcend IDEs. Here’s what you need to know.

What you’ll learn:

  • Details behind the Language Server Protocol.            
  • Why it is necessary.
  •  Where to begin.

More than likely, you’ve already been using a software-development tool that takes advantage of the Language Server Protocol (LSP), but didn’t even realize it. LSP is designed to facilitate support of different language, which is one reason why your favorite tool may be supporting more languages than in the past.

LSP is defined as an open set of rules that describes how language clients and language servers should communicate (Fig. 1). All services are handled by the server and exposed to the client via the protocol. The client is either a standard text editor or the integrated development environments (IDEs) used by a developer, while the server is the process containing all of the smarts about a given language.

Microsoft developed the protocol in 2015 to help separate language tools and editors, allowing programming language support to be implemented and distributed independently of any given editor or IDE. As with some programming environments, the LSP grew out of necessity rather than innovation. Before LSP, most work needed to be repeated for each development tool, as each tool provided different application programming interfaces (APIs) to implement the same features.

Supporting those features, such as source code auto-completion or “Go to Definition” for a programming language in an editor or IDE, is usually a challenging and time-consuming process. It requires writing a domain model (scanner, parser, type checker, builder, etc.) in the programming language of the editor or IDE.

For example, the Eclipse CDT plugin, which supports C/C++ in the Eclipse IDE, is written in Java since the IDE itself also is written in Java. Following this approach would mean implementing a C/C++ domain model in the TypeScript language for Visual Studio Code and a separate domain model in C# for Microsoft Visual Studio.

How the LSP Functions

Clients and servers can be thought of as code editors and language tools communicating in simple text messages. These messages have HTTP-like headers and JSON-RPC content, and they can originate from the client or server. The JSON-RPC protocol defines requests, responses, and notifications and a few basic rules around them (Fig. 2). One of the key features is that it's designed to work asynchronously, so that clients/servers can deal with messages out of order and with a level of parallelism.

The Language Server Protocol is all about reducing effort, and nobody likes relentless repetition when it comes to coding. That’s why LSP was developed—the JSON-RPC protocol allows the editor/IDE to talk to a language server and thus remove that effort and repetition.

Another advantage of the language server operating in a dedicated process is that it mitigates performance issues related to a single process model. 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.

The following is an example of how the LSP process works:

  1. A user opens a file (i.e., a document) in the tool, notifying the language server that a document is open (“textDocument/didOpen”). At this point, the truth about the document's contents is no longer on the file system; rather, it’s kept by the tool in memory and remains there for the entire process.
  2. As 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. The language server analyzes this information during the process and notifies the tool of the detected errors and warnings (“textDocument/publishDiagnostics”).
  3. Once completed, the user executes “Go to Definition” on a symbol in the editor: The tool sends a 'textDocument/definition' request with two parameters: the document URI, and the text position from where the Go to Definition request was initiated to the server. The server then responds with the document URI and the position of the symbol’s definition inside the document.
  4. When the process is finished, the user closes the document (file), and a “textDocument/didClose” notification is sent from the tool. It informs the language server that the document is now no longer in memory and the current contents are now up-to-date on the file system.

The example highlights how the protocol communicates with the server at the document reference and position level. The data types are programming-language-neutral, meaning they apply to all programming languages.

It's important to note that the data types aren’t at the level of a programming-language domain model, which would usually provide abstract syntax trees and compiler symbols, such as resolved-types, namespaces, and others. Because the data types are simple and the programming language is neutral, it simplifies the protocol substantially.

The LSP isn't a Universal Solution

While the Language Server Protocol is immensely beneficial, it's not an all-encompassing solution and has a few drawbacks. Some developers found that some servers behaved differently to specific requests or responded differently than expected. Other server developers might rely on one client implementation to develop their server, leading to discrepancies between expected and actual results. Even protocol extensions, such as CodeAction, can be server-specific, making it difficult for clients to write generic code for expected responses.

In addition, not every server will be configured in the same way, and not every language server can support all features defined by the protocol, which further negates the one-stop solution. Instead, the LSP provides capabilities that group a set of language features.

A development tool and the language server announce their supported features using capabilities. For example, a server announces that it can handle the “textDocument/definition” request, but it might not handle the “workspace/symbol” request.

To that end, myriad supported languages continue to benefit from LSP. Among them are new languages such as Rust, which can take advantage of the protocol to support modern IDEs and text editors. This is just a simple overview of the Language Server Protocol and what it can accomplish. More in-depth information, including specifications and implementations, can be found on Microsoft's GitHub page.

Sponsored Recommendations

Near- and Far-Field Measurements

April 16, 2024
In this comprehensive application note, we delve into the methods of measuring the transmission (or reception) pattern, a key determinant of antenna gain, using a vector network...

DigiKey Factory Tomorrow Season 3: Sustainable Manufacturing

April 16, 2024
Industry 4.0 is helping manufacturers develop and integrate technologies such as AI, edge computing and connectivity for the factories of tomorrow. Learn more at DigiKey today...

Connectivity – The Backbone of Sustainable Automation

April 16, 2024
Advanced interfaces for signals, data, and electrical power are essential. They help save resources and costs when networking production equipment.

Empowered by Cutting-Edge Automation Technology: The Sustainable Journey

April 16, 2024
Advanced automation is key to efficient production and is a powerful tool for optimizing infrastructure and processes in terms of sustainability.

Comments

To join the conversation, and become an exclusive member of Electronic Design, create an account today!