VSCode Language Server Protocol client implementation for extension integration with language servers
—
Core client classes and lifecycle management for establishing and maintaining language server connections.
Abstract base class providing core functionality for all language clients.
/**
* Abstract base class for all language clients providing core LSP functionality
*/
abstract class BaseLanguageClient {
/** Client name identifier */
readonly name: string;
/** Current client state */
readonly state: State;
/** Initialization result from the language server */
readonly initializeResult: InitializeResult | undefined;
/** Client configuration options */
readonly clientOptions: LanguageClientOptions;
/** Middleware configuration for feature customization */
readonly middleware: Middleware;
/** Output channel for client messages */
readonly outputChannel: OutputChannel;
/** Output channel for trace messages */
readonly traceOutputChannel: OutputChannel;
/** Diagnostic collection for server diagnostics */
readonly diagnostics: DiagnosticCollection | undefined;
/** Protocol to code converter instance */
readonly protocol2CodeConverter: Protocol2CodeConverter;
/** Code to protocol converter instance */
readonly code2ProtocolConverter: Code2ProtocolConverter;
/** Event emitted when client state changes */
readonly onDidChangeState: Event<StateChangeEvent>;
/** Event emitted for telemetry data from server */
readonly onTelemetry: Event<any>;
/** Start the language client and establish connection to server */
start(): Promise<void>;
/** Stop the language client with optional timeout */
stop(timeout?: number): Promise<void>;
/** Dispose the client and cleanup resources */
dispose(timeout?: number): Promise<void>;
/** Send a request to the language server */
sendRequest<R, PR, E>(type: ProtocolRequestType<PR, R, E, any>, params: PR, token?: CancellationToken): Promise<R>;
sendRequest<R, E>(type: RequestType0<R, E>, token?: CancellationToken): Promise<R>;
sendRequest<R, P, E>(type: RequestType<P, R, E>, params: P, token?: CancellationToken): Promise<R>;
/** Send a notification to the language server */
sendNotification<RO>(type: ProtocolNotificationType<RO, any>, params?: RO): Promise<void>;
sendNotification<P>(type: NotificationType<P>, params?: P): Promise<void>;
sendNotification(type: NotificationType0): Promise<void>;
/** Register a request handler for server requests */
onRequest<R, PR, E>(type: ProtocolRequestType<PR, R, E, any>, handler: RequestHandler<PR, R, E>): Disposable;
onRequest<R, E>(type: RequestType0<R, E>, handler: RequestHandler0<R, E>): Disposable;
onRequest<R, P, E>(type: RequestType<P, R, E>, handler: RequestHandler<P, R, E>): Disposable;
onRequest(method: string, handler: GenericRequestHandler): Disposable;
/** Register a notification handler for server notifications */
onNotification<RO>(type: ProtocolNotificationType<RO, any>, handler: NotificationHandler<RO>): Disposable;
onNotification<P>(type: NotificationType<P>, handler: NotificationHandler<P>): Disposable;
onNotification(type: NotificationType0, handler: NotificationHandler0): Disposable;
onNotification(method: string, handler: GenericNotificationHandler): Disposable;
/** Send progress notification */
sendProgress<P>(type: ProgressType<P>, token: ProgressToken, value: P): Promise<void>;
/** Register progress handler */
onProgress<P>(type: ProgressType<P>, token: ProgressToken, handler: NotificationHandler<P>): Disposable;
/** Set trace level for debugging */
setTrace(value: Trace): Promise<void>;
/** Register a feature with the client */
registerFeature(feature: StaticFeature | DynamicFeature<any>): void;
/** Get a registered feature by request method */
getFeature(request: string): DynamicFeature<any> | undefined;
/** Create message transports for communication (implemented by subclasses) */
protected abstract createMessageTransports(encoding: string): Promise<MessageTransports>;
/** Handle connection errors */
protected handleConnectionError(error: Error, message: Message | undefined, count: number | undefined): void;
/** Handle connection closed */
protected handleConnectionClosed(): void;
}Usage Examples:
Basic client lifecycle:
import { LanguageClient } from "vscode-languageclient/node";
const client = new LanguageClient(
'my-language-client',
'My Language Client',
serverOptions,
clientOptions
);
// Start the client
await client.start();
console.log(`Client state: ${client.state}`); // State.Running
// Send a custom request
const result = await client.sendRequest('custom/method', { param: 'value' });
// Stop the client
await client.stop();Request/notification handling:
// Handle server requests
client.onRequest('workspace/configuration', (params) => {
return [{ setting: 'value' }];
});
// Handle server notifications
client.onNotification('window/logMessage', (params) => {
console.log(`Server: ${params.message}`);
});
// Send custom notification
await client.sendNotification('custom/notification', { data: 'value' });Node.js implementation of the language client supporting various transport mechanisms.
/**
* Node.js implementation of LanguageClient supporting stdio, IPC, pipe, and socket transports
*/
class LanguageClient extends BaseLanguageClient {
/** Whether the client is running in debug mode */
readonly isInDebugMode: boolean;
/**
* Create a language client for Node.js environment
* @param name - Client name (also used as ID)
* @param serverOptions - Server configuration options
* @param clientOptions - Client configuration options
* @param forceDebug - Force debug mode regardless of environment
*/
constructor(name: string, serverOptions: ServerOptions, clientOptions: LanguageClientOptions, forceDebug?: boolean);
/**
* Create a language client with explicit ID and name
* @param id - Client identifier
* @param name - Display name for the client
* @param serverOptions - Server configuration options
* @param clientOptions - Client configuration options
* @param forceDebug - Force debug mode regardless of environment
*/
constructor(id: string, name: string, serverOptions: ServerOptions, clientOptions: LanguageClientOptions, forceDebug?: boolean);
/** Create message transports based on server options */
protected createMessageTransports(encoding: string): Promise<MessageTransports>;
}Browser implementation of the language client using Web Workers for communication.
/**
* Browser implementation of LanguageClient using Web Worker communication
*/
class LanguageClient extends BaseLanguageClient {
/** The Web Worker running the language server */
private readonly worker: Worker;
/**
* Create a language client for browser environment
* @param id - Client identifier
* @param name - Display name for the client
* @param clientOptions - Client configuration options
* @param worker - Web Worker instance running the language server
*/
constructor(id: string, name: string, clientOptions: LanguageClientOptions, worker: Worker);
/** Create message transports using browser message readers/writers */
protected createMessageTransports(encoding: string): Promise<MessageTransports>;
}Usage Examples:
Node.js client with stdio transport:
import { LanguageClient, ServerOptions, TransportKind } from "vscode-languageclient/node";
const serverOptions: ServerOptions = {
run: { command: 'language-server', transport: TransportKind.stdio },
debug: { command: 'language-server', args: ['--debug'], transport: TransportKind.stdio }
};
const client = new LanguageClient(
'example-client',
'Example Language Client',
serverOptions,
clientOptions
);Browser client with Web Worker:
import { LanguageClient } from "vscode-languageclient/browser";
const worker = new Worker('./language-server-worker.js');
const client = new LanguageClient(
'example-browser-client',
'Example Browser Client',
clientOptions,
worker
);enum State {
/** Client is stopped */
Stopped = 1,
/** Client is starting up */
Starting = 3,
/** Client is running and connected */
Running = 2
}
interface StateChangeEvent {
/** Previous client state */
oldState: State;
/** New client state */
newState: State;
}interface MessageTransports {
/** Message reader for receiving from server */
reader: MessageReader;
/** Message writer for sending to server */
writer: MessageWriter;
/** Whether the transport is detached from the client lifecycle */
detached?: boolean;
}Install with Tessl CLI
npx tessl i tessl/npm-vscode-languageclient