VS Code Language Server
The `vscode-languageserver` package provides a Node.js-based implementation of the Language Server Protocol (LSP), allowing developers to build language servers that offer rich language-specific features (e.g., autocomplete, diagnostics, go-to-definition, refactoring) to various text editors and IDEs, primarily VS Code. It abstracts the complexities of the LSP specification and JSON-RPC communication, enabling a focus on core language logic. The current stable version is `9.0.1`, with `10.0.0` actively in `next` development, signaling upcoming significant updates and LSP specification alignments. This project is a core component of the official VS Code ecosystem, characterized by its robust, well-maintained, and protocol-compliant tooling, making it a de facto standard for Node.js-based LSP servers. The release cadence includes frequent `next` versions for client, server, protocol, and jsonrpc packages, reflecting continuous integration and adaptation to evolving LSP standards.
Common errors
-
Error: Cannot find module 'vscode-languageserver/node'
cause Incorrect import path or missing dependency installation for the Language Server package.fixEnsure `vscode-languageserver` is installed via `npm install vscode-languageserver` or `yarn add vscode-languageserver`. Verify the import path is `import { createConnection } from 'vscode-languageserver/node';`. -
Property 'onDidOpenTextDocument' does not exist on type 'Connection'.
cause Attempting to directly register document event handlers on the `connection` object. Document management is now abstracted by `TextDocuments`.fixUse the `TextDocuments` instance to listen for document events: `documents.listen(connection); documents.onDidChangeContent(...)`. -
Type 'null' is not assignable to type 'InitializeResult'.
cause The `onInitialize` handler must return an `InitializeResult` object describing the server's capabilities, not `null` or `undefined`.fixEnsure the `connection.onInitialize` callback returns a valid `InitializeResult` object, typically like: `return { capabilities: { textDocumentSync: TextDocumentSyncKind.Full } };`. -
There was an error activating the remote language server (or similar client-side activation errors).
cause The client-side extension (e.g., `vscode-languageclient`) failed to establish or maintain a connection with the language server. This can be due to the server crashing on startup, incorrect IPC configuration, or permission issues.fixCheck the language server's console output for errors. Ensure the `createConnection` call is correctly configured for IPC (e.g., `createConnection(ProposedFeatures.all)` for standard Node.js IPC). Verify there are no file access permission issues preventing the server from starting or writing logs. Implement robust `errorHandler` and `initializationFailedHandler` on the client side for better diagnostics.
Warnings
- breaking The upcoming `10.0.0` major release (currently in `next` state) is expected to introduce significant breaking changes. These changes will likely affect API usage, especially for `Connection` and `TextDocuments`, and will align with new LSP specifications and internal architectural improvements. Users upgrading from `9.x` should review the release notes carefully. Key areas of change include how modules use `exports` in `package.json`, compiler upgrades, and updated Node.js environment requirements (e.g., Node.js 22.13.14 and `es2022` target).
- gotcha When initializing `TextDocuments`, the constructor requires a `TextDocument` factory from `vscode-languageserver-textdocument` (e.g., `new TextDocuments(TextDocument)`). Older versions of the library allowed `new TextDocuments()`, but this was deprecated in `vscode-languageserver@6.0.0`. Failing to provide the factory will lead to runtime errors when documents are managed.
- gotcha It's crucial to specify the `/node` subpath when importing `createConnection` and `ProposedFeatures` (e.g., `import { createConnection } from 'vscode-languageserver/node';`) for Node.js environments. Omitting this subpath can lead to module resolution issues or incorrect usage of browser-specific implementations, especially in modern module systems.
- gotcha Running `vscode-languageserver` in a browser environment (e.g., a React app using Monaco Editor) can lead to errors related to Node.js built-in modules like `fs`. The core `vscode-languageserver` package is designed for Node.js, and directly importing it client-side without proper polyfills or shims for Node.js APIs will fail. Consider `vscode-languageserver-protocol` for browser-compatible type definitions or a browser-specific LSP implementation.
- gotcha An LSP server must correctly declare its `capabilities` in the `InitializeResult` to inform the client which features it supports (e.g., `completionProvider`, `hoverProvider`, `textDocumentSync`). Incorrect or missing capability declarations will result in the client not activating those features, leading to a non-functional language experience.
- deprecated Older methods for managing text document content, where the entire document content was sent on every change (full synchronization), are less efficient. While still supported, modern LSP implementations encourage incremental text document synchronization for better performance.
Install
-
npm install vscode-languageserver -
yarn add vscode-languageserver -
pnpm add vscode-languageserver
Imports
- createConnection
const createConnection = require('vscode-languageserver').createConnection;import { createConnection, ProposedFeatures } from 'vscode-languageserver/node'; - TextDocuments
import { TextDocuments } from 'vscode-languageserver'; const documents = new TextDocuments();import { TextDocuments } from 'vscode-languageserver'; import { TextDocument } from 'vscode-languageserver-textdocument'; const documents = new TextDocuments(TextDocument); - InitializeParams
import { InitializeParams } from 'vscode-languageserver';import type { InitializeParams } from 'vscode-languageserver';
Quickstart
import {
createConnection,
TextDocuments,
ProposedFeatures,
InitializeParams,
InitializeResult,
TextDocumentSyncKind,
} from 'vscode-languageserver/node';
import { TextDocument } from 'vscode-languageserver-textdocument';
// Create a connection for the server. The connection uses Node's IPC as a transport.
const connection = createConnection(ProposedFeatures.all);
// Create a simple text document manager. The text document manager
// supports full document sync only and tracks open, change, and close events.
const documents: TextDocuments<TextDocument> = new TextDocuments(TextDocument);
connection.onInitialize((params: InitializeParams) => {
const capabilities = params.capabilities;
const result: InitializeResult = {
capabilities: {
textDocumentSync: TextDocumentSyncKind.Full,
// Tell the client that the server supports code completion
completionProvider: {
resolveProvider: true, // We need to resolve additional information for a completion item
triggerCharacters: ['.']
},
hoverProvider: true,
},
};
return result;
});
connection.onInitialized(() => {
connection.console.log('Language server initialized!');
});
// The content of a text document has changed. This event is emitted
// when the text document first opened or when its content has changed.
documents.onDidChangeContent(change => {
connection.console.log(`Document changed: ${change.document.uri}`);
// In a real server, you would perform diagnostics here
// connection.sendDiagnostics({ uri: change.document.uri, diagnostics: [] });
});
connection.onCompletion(
(_textDocumentPosition, _token) => {
// This is a very basic completion provider. In a real server,
// you would analyze the document and provide context-aware suggestions.
return [
{ label: 'console', kind: 18 }, // Method
{ label: 'log', kind: 6 }, // Function
{ label: 'warn', kind: 6 },
{ label: 'error', kind: 6 }
];
}
);
// This handler resolves additional information for the selected completion item.
connection.onCompletionResolve((item) => {
if (item.label === 'log') {
item.detail = 'Logs a message to the console.';
item.documentation = 'The `console.log()` method outputs a message to the web console.';
}
return item;
});
// Make the text document manager listen on the connection
// for open, change and close text document events
documents.listen(connection);
// Listen on the connection
connection.listen();