This repo is an attempt at building the developer tooling I wished existed when I first started working on Esbonio.
This is a monorepo containing a number of sub-projects.
lib/lsp-devtools - A grab bag of development utilities
A collection of cli utilities aimed at aiding the development of language servers and/or clients.
agent: Used to wrap an lsp server allowing messages sent between it and the client to be intercepted and inspected by other tools.record: Connects to an agent and record traffic to file, sqlite db or console. Supports filtering and formatting the outputinspect: A browser devtools inspired TUI to visualise and inspecting LSP traffic. Powered by textualclient: Experimental A TUI language client with built ininspectpanel. Powered by textual
lib/pytest-lsp - End-to-end testing of language servers with pytest
pytest-lsp is a pytest plugin for writing end-to-end tests for language servers.
It works by running the language server in a subprocess and communicating with it over stdio, just like a real language client.
This also means pytest-lsp can be used to test language servers written in any language - not just Python.
pytest-lsp relies on the pygls library for its language server protocol implementation.
import sys import pytest import pytest_lsp from lsprotocol import types from pytest_lsp import ( ClientServerConfig, LanguageClient, client_capabilities, ) @pytest_lsp.fixture( scope="module", config=ClientServerConfig( server_command=[sys.executable, "-m", "esbonio"], ), ) async def client(lsp_client: LanguageClient): # Setup response = await lsp_client.initialize_session( types.InitializeParams( capabilities=client_capabilities("visual-studio-code"), workspace_folders=[ types.WorkspaceFolder( uri="file:///path/to/test/project/root/", name="project" ), ], ) ) yield # Teardown await lsp_client.shutdown_session() @pytest.mark.asyncio(loop_scope="module") async def test_completion(client: LanguageClient): result = await client.text_document_completion_async( params=types.CompletionParams( position=types.Position(line=5, character=23), text_document=types.TextDocumentIdentifier( uri="file:///path/to/test/project/root/test_file.rst" ), ) ) assert len(result.items) > 0
