Explaining Language Server Protocol Simply

GarvGarv
4 min read

Introduction

Language Server Protocol is a specification of communication between the IDE(client) and the programming language’s server. LSP was developed by Microsoft, RedChat and Codenvy. It was open-sourced in 2016 but became popular around 2020. LSP is based on JSONRPC standard for sharing requests, responses between the client and the server. In this blog I will breakdown and explain the concept of LSP along with a small project in JavaScript.

Table of Contents

Introduction
Why LSP
What is jsonrpc
How LSP works
BabyLSP - An LSP Project In JS

Why LSP

Features like autocompletion, text formatting, hovereffects, diagnostics, go to definition seem like non-negotiable in the code editors like VSCode, Neovim etc. But all these features can’t be possible without LSP. So as a developer you want all these useful, helpful, productive and necessary features in all the programming languages you use. But without LSP there is no standard for communication between the programming language and the different editors out there. So then the language maintainers would then have to make a specific code editor for their language and the editor maintainers would have to provide all the above mentioned cool features for each language; this effectively becomes a M x N complexity case. But because LSP is there is a standard to communication in place thus each language would have to provide a single Language Server and a code editor would have to give one client communication functionality with the background Language process. Now communication is possible between M languages and N editors in M + N time complexity.

So now since your interest is set about LSP, let’s get deeper into it.


What is jsonrpc

JSON RPC 2.0 is the specification for sending the response, request messages between the Client (Editor) and the Language Server. It ensures a standard format for message transfer between multiple clients and multiple language servers thus ensuring uniformity, ease of use and simplicity.

The basic syntax for JSON RPC is as follows :

client's request to server -> {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}

server's response to the client -> {"jsonrpc": "2.0", "result": 19, "id": 1}

For more understanding and examples check out the JSON RPC 2.0 Specification Guide.


How LSP Works

Till now you would have understood about “Why LSP is Needed?” and “What is the syntax/specification for sending LSP Messages?” ; let’s look at “How the LSP functions?”

LSP is communication established between the client and the server which continues till the entire editor’s session’s lifetime. The client sends first the “initialize” communication by requesting to the language’s server which then responds with the “capabilities” of the server like text formatting, auto completion, hover effects, go to definitions, diagnostics (error information) etc.

After the communication is established then the client’s sends request messages to the LSP in cases of changes would then have to make a specific code editor for their language to method send in the message along with its parameters .

The response from the Language Server contains the result property with the appropriate response data or if in case of error in the communication process error property.


BabyLSP - An LSP Project In JS

Check out my Github repo for the entire code. Here I will be explaining the overview of the project.

Dependies Used :

In this the vscode-languageserver Node.js API provides the LSP and the connection function with events like initialization, hoverEffect, autoCompletion, error handling etc. The sample response object is as follows :

const { createConnection, ProposedFeatures }= require("vscode-languageserver")
const { TextDocument }= require("vscode-languageserver-textdocument")

// 1. Establish connection between client (editor) and Server

const connection = createConnection(ProposedFeatures.all)

// 2. Initiaze handler 
connection.onInitialize(() => {
    console.log("LSP connected !");

    return {
        capabilities: {
            textDocumentSync: 1, // Basic file tracking 
            hoverProvider: true,
            completionProvider: { // Autocomplete support
                triggerCharacters: [".", " "] // Give suggestions after "." or " " is pressed
            }
        }
    }
})

The sample request object is as follows:

sendLSPMessage({
    jsonrpc: "2.0",
    id: 1,
    method: "initialize",
    params: { capabilities: {} }
});

The server.js file can be tested both in Neovim and VSCode.

And you can also see the test-input.js file for seeing more test cases.


Conclusion

In this blog you got an overview about LSP : how it works, its syntax and behind the scenes. Now do make your own pet project on LSP. And don’t forget to star my Github repo and like, share and retweet my X post.

0
Subscribe to my newsletter

Read articles from Garv directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Garv
Garv

A person trying to learn and question things.