### Old Client Start and onReady Usage Source: https://github.com/microsoft/vscode-languageserver-node/blob/main/README.md This is an example of the old way to start a LanguageClient and wait for it to be ready, which is no longer supported. ```typescript const client: LanguageClient = ...; client.start(); await client.onReady(); ``` -------------------------------- ### Print 'Hello World' in Python Source: https://github.com/microsoft/vscode-languageserver-node/blob/main/testbed/workspace/python.ipynb Demonstrates the basic print function in Python. Ensure Python is installed to run. ```python print('Hello World') ``` -------------------------------- ### Initialize and Start LanguageClient in VS Code Extension Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt This snippet shows how to activate a VS Code extension by initializing and starting a `LanguageClient`. It configures server options, client options including document selectors and synchronization, and demonstrates sending a custom request to the server. The client is added to the extension's subscriptions for proper lifecycle management. ```typescript import * as path from 'path'; import * as vscode from 'vscode'; import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, RevealOutputChannelOn } from 'vscode-languageclient/node'; let client: LanguageClient; export async function activate(context: vscode.ExtensionContext): Promise { const serverModule = context.asAbsolutePath(path.join('server', 'out', 'server.js')); const serverOptions: ServerOptions = { run: { module: serverModule, transport: TransportKind.ipc }, debug: { module: serverModule, transport: TransportKind.ipc, options: { execArgv: ['--nolazy', '--inspect=6009'] } } }; const clientOptions: LanguageClientOptions = { documentSelector: [{ scheme: 'file', language: 'typescript' }], synchronize: { fileEvents: vscode.workspace.createFileSystemWatcher('**/*.ts') }, revealOutputChannelOn: RevealOutputChannelOn.Error, middleware: { // Intercept completion items before they are shown provideCompletionItem: async (document, position, context, token, next) => { const result = await next(document, position, context, token); // post-process result... return result; } } }; client = new LanguageClient('myLanguageServer', 'My Language Server', serverOptions, clientOptions); // Start the client (spawns server, performs initialize handshake) await client.start(); // Send a custom request to the server const wordCount: number = await client.sendRequest('custom/wordCount', { uri: vscode.window.activeTextEditor?.document.uri.toString() }); vscode.window.showInformationMessage(`Word count: ${wordCount}`); context.subscriptions.push(client); } export async function deactivate(): Promise { if (client) { await client.stop(); } } ``` -------------------------------- ### Initialize TextDocuments with TextDocument Implementation (JavaScript) Source: https://github.com/microsoft/vscode-languageserver-node/blob/main/README.md Use this JavaScript example to initialize TextDocuments with the TextDocument implementation from 'vscode-languageserver-textdocument'. This is required for servers needing a standard text document implementation. ```javascript const server = require("vscode-languageserver"); const textDocument = require("vscode-languageserver-textdocument"); const documents = new server.TextDocuments(textDocument.TextDocument); ``` -------------------------------- ### Server-side JSON-RPC Connection Setup Source: https://github.com/microsoft/vscode-languageserver-node/blob/main/jsonrpc/README.md Sets up a symmetrical JSON-RPC connection on the server side, listening for notifications via stdin and writing to stdout. This mirrors the client setup for bidirectional communication. ```typescript import * as rpc from 'vscode-jsonrpc/node'; let connection = rpc.createMessageConnection( new rpc.StreamMessageReader(process.stdin), new rpc.StreamMessageWriter(process.stdout)); let notification = new rpc.NotificationType('testNotification'); connection.onNotification(notification, (param: string) => { console.log(param); // This prints Hello World }); connection.listen(); ``` -------------------------------- ### Initialize TextDocuments with TextDocument Implementation (TypeScript) Source: https://github.com/microsoft/vscode-languageserver-node/blob/main/README.md Use this TypeScript example to initialize TextDocuments with the TextDocument implementation from 'vscode-languageserver-textdocument'. This is required for servers needing a standard text document implementation. ```typescript import { TextDocuments } from 'vscode-languageserver'; import { TextDocument } from 'vscode-languageserver-textdocument'; const documents = new TextDocuments(TextDocument); ``` -------------------------------- ### Print 'Hello World 2' in Python Source: https://github.com/microsoft/vscode-languageserver-node/blob/main/testbed/workspace/python.ipynb Another example of the Python print function. This snippet is identical to the previous one except for the string content. ```python print('Hello World 2') ``` -------------------------------- ### createMessageConnection Example Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Demonstrates how to use `createMessageConnection` to set up a JSON-RPC 2.0 connection between a server and a client using TCP sockets. It shows how to define custom request and notification types, handle incoming requests and notifications, and send requests with cancellation support. ```APIDOC ## `vscode-jsonrpc` — createMessageConnection `createMessageConnection` is the low-level JSON-RPC 2.0 connection factory from `vscode-jsonrpc`. It wraps any `MessageReader`/`MessageWriter` pair into a typed bidirectional connection that can send/receive requests and notifications, handle cancellation, and report progress. The LSP packages build on top of this primitive. ```typescript import { createMessageConnection, RequestType, NotificationType, StreamMessageReader, StreamMessageWriter, NullLogger, CancellationTokenSource } from 'vscode-jsonrpc/node'; import * as net from 'net'; // Define custom request/notification types const SumRequest = new RequestType<{ a: number; b: number }, number, void>('math/sum'); const LogNotification = new NotificationType<{ message: string }>('log/message'); // --- Server side --- const server = net.createServer(socket => { const conn = createMessageConnection( new StreamMessageReader(socket), new StreamMessageWriter(socket), NullLogger ); conn.onRequest(SumRequest, (params, token) => { if (token.isCancellationRequested) return 0; return params.a + params.b; }); conn.onNotification(LogNotification, params => { console.log('[server received]', params.message); }); conn.listen(); }); server.listen(7000); // --- Client side --- const socket = net.createConnection(7000); const client = createMessageConnection( new StreamMessageReader(socket), new StreamMessageWriter(socket), NullLogger ); client.listen(); // Send request with cancellation support const cts = new CancellationTokenSource(); const result = await client.sendRequest(SumRequest, { a: 3, b: 4 }, cts.token); console.log(result); // 7 // Send one-way notification await client.sendNotification(LogNotification, { message: 'hello from client' }); // Cleanup client.dispose(); server.close(); ``` ``` -------------------------------- ### Update Client Start and Stop Methods in VS Code Language Server Source: https://github.com/microsoft/vscode-languageserver-node/blob/main/README.md The `start` and `stop` methods for the LanguageClient are now async and return promises. This is a breaking change from previous versions where `start` returned a disposable. Extensions should await the `start()` call and return the `stop` promise from their `deactivate` function. ```typescript const client: LanguageClient = ...; await client.start(); ``` -------------------------------- ### Client-side JSON-RPC Connection Setup Source: https://github.com/microsoft/vscode-languageserver-node/blob/main/jsonrpc/README.md Establishes a JSON-RPC connection from the client side using stdin and stdout for communication with a spawned child process. Ensure the child process is correctly spawned. ```typescript import * as cp from 'child_process'; import * as rpc from 'vscode-jsonrpc/node'; let childProcess = cp.spawn(...); // Use stdin and stdout for communication: let connection = rpc.createMessageConnection( new rpc.StreamMessageReader(childProcess.stdout), new rpc.StreamMessageWriter(childProcess.stdin)); let notification = new rpc.NotificationType('testNotification'); connection.listen(); connection.sendNotification(notification, 'Hello World'); ``` -------------------------------- ### Log to Console in JavaScript Source: https://github.com/microsoft/vscode-languageserver-node/blob/main/testbed/workspace/test.ipynb A basic JavaScript snippet to log output to the console. No specific setup is required beyond a JavaScript environment. ```javascript console.log() ``` -------------------------------- ### Implement Middleware for LanguageClient Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt This snippet demonstrates how to define and use middleware for `LanguageClientOptions` to intercept and modify language server communications. It shows examples of augmenting hover results, filtering completion items, and handling diagnostics. This allows for custom behavior without modifying the language server itself. ```typescript import { LanguageClientOptions, Middleware } from 'vscode-languageclient/node'; import { Hover, CompletionList } from 'vscode-languageserver-types'; const middleware: Middleware = { // Augment hover results provideHover: async (document, position, token, next) => { const hover = await next(document, position, token) as Hover | null; if (hover) { // Append extra info if (typeof hover.contents === 'object' && 'value' in hover.contents) { hover.contents.value += '\n\n*[augmented by middleware]*'; } } return hover; }, // Filter completion items provideCompletionItem: async (document, position, context, token, next) => { const result = await next(document, position, context, token); if (result && 'items' in (result as CompletionList)) { const list = result as CompletionList; list.items = list.items.filter(item => !item.label.startsWith('_')); return list; } return result; }, // Intercept diagnostics handleDiagnostics: (uri, diagnostics, next) => { const filtered = diagnostics.filter(d => d.severity !== 4 /* Hint */); next(uri, filtered); } }; const clientOptions: LanguageClientOptions = { documentSelector: [{ scheme: 'file', language: 'python' }], middleware }; ``` -------------------------------- ### Inlay Hints Implementation Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Demonstrates how to register and handle inlay hint requests. The server provides inlay hints, which are annotations in the source code, by returning an array of `InlayHint` objects. ```APIDOC ## `textDocument/inlayHint` Request Handling ### Description Handles requests for inlay hints, providing inline annotations for source code such as parameter names or inferred types. The server must register `inlayHintProvider` during initialization. ### Method `connection.languages.inlayHint.on(params => { ... });` ### Parameters - `params` (object) - Contains information about the text document for which inlay hints are requested. - `textDocument` (TextDocumentIdentifier) - The text document's identifier. ### Request Example (Server-side handling of `textDocument/inlayHint`) ### Response - `InlayHint[]` - An array of `InlayHint` objects. ### Response Example ```typescript [ { position: Position.create(5, 14), label: 'name:', kind: InlayHintKind.Parameter }, { position: Position.create(7, 18), label: [ { value: ': string', tooltip: 'Inferred type: string', location: Location.create('file:///lib/types.d.ts', Range.create(10, 0, 10, 20)) } ], kind: InlayHintKind.Type, paddingLeft: true } ] ``` ``` -------------------------------- ### Create LSP Connection and Handle Events (Node.js) Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Initializes an LSP connection, manages text documents, and sets up handlers for initialization, diagnostics, completions, and hovers. Ensure to import necessary types from `vscode-languageserver/node` and `vscode-languageserver-textdocument`. ```typescript import { createConnection, TextDocuments, ProposedFeatures, InitializeParams, InitializeResult, TextDocumentSyncKind, CompletionItem, CompletionItemKind, TextDocumentPositionParams, Diagnostic, DiagnosticSeverity, Range, PublishDiagnosticsParams } from 'vscode-languageserver/node'; import { TextDocument } from 'vscode-languageserver-textdocument'; // Create the connection (reads --stdio / --node-ipc / etc. from argv) const connection = createConnection(ProposedFeatures.all); // Manage open documents const documents = new TextDocuments(TextDocument); connection.onInitialize((params: InitializeParams): InitializeResult => { return { capabilities: { textDocumentSync: TextDocumentSyncKind.Incremental, completionProvider: { resolveProvider: true }, hoverProvider: true, diagnosticProvider: { interFileDependencies: false, workspaceDiagnostics: false } } }; }); connection.onInitialized(() => { connection.window.showInformationMessage('Server initialized!'); }); // Validate documents on change documents.onDidChangeContent(change => { const diagnostics: Diagnostic[] = []; const text = change.document.getText(); if (text.includes('TODO')) { diagnostics.push( Diagnostic.create( Range.create(0, 0, 0, 5), 'Found a TODO comment', DiagnosticSeverity.Hint, 'todo-warning', 'my-server' ) ); } connection.sendDiagnostics({ uri: change.document.uri, diagnostics }); }); // Completion connection.onCompletion((_params: TextDocumentPositionParams): CompletionItem[] => { return [ { label: 'TypeScript', kind: CompletionItemKind.Text, data: 1 }, { label: 'JavaScript', kind: CompletionItemKind.Text, data: 2 } ]; }); connection.onCompletionResolve((item: CompletionItem): CompletionItem => { if (item.data === 1) { item.detail = 'TypeScript details'; item.documentation = 'TypeScript docs'; } if (item.data === 2) { item.detail = 'JavaScript details'; item.documentation = 'JavaScript docs'; } return item; }); // Hover connection.onHover(params => { const doc = documents.get(params.textDocument.uri); if (!doc) return null; return { contents: { kind: 'markdown', value: `Hovering at line ${params.position.line}` } }; }); // Wire up document manager and start listening documents.listen(connection); connection.listen(); ``` -------------------------------- ### Log 'Hello World' in JavaScript Source: https://github.com/microsoft/vscode-languageserver-node/blob/main/testbed/workspace/test.ipynb A simple JavaScript snippet to log the string 'Hello World' to the console. This is useful for basic output verification. ```javascript console.log('Hello World') ``` -------------------------------- ### Playwright Reporter for Mocha Source: https://github.com/microsoft/vscode-languageserver-node/blob/main/jsonrpc/src/browser/test/index.html A custom Mocha reporter that intercepts test events (start, end, suite, test, pass, fail, etc.) and forwards them to a global `window.mocha_report` function. This allows integration with external reporting tools like Playwright. ```javascript function PlaywrightReporter(runner) { runner.on('start', () => window.mocha_report('start')); runner.on('end', () => window.mocha_report('end')); runner.on('suite', suite => window.mocha_report('suite', serializeSuite(suite))); runner.on('suite end', suite => window.mocha_report('suite end', serializeSuite(suite))); runner.on('test', test => window.mocha_report('test', serializeRunnable(test))); runner.on('test end', test => window.mocha_report('test end', serializeRunnable(test))); runner.on('hook', hook => window.mocha_report('hook', serializeRunnable(hook))); runner.on('hook end', hook => window.mocha_report('hook end', serializeRunnable(hook))); runner.on('pass', test => window.mocha_report('pass', serializeRunnable(test))); runner.on('fail', (test, err) => window.mocha_report('fail', serializeRunnable(test), serializeError(err))); runner.on('pending', test => window.mocha_report('pending', serializeRunnable(test))); } ``` -------------------------------- ### CompletionItem and CompletionList Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Demonstrates creating CompletionItem and CompletionList objects for providing code completion suggestions. ```APIDOC ## CompletionItem & CompletionList ### Description Creates objects for code completion suggestions, including individual items and lists. ### Methods - `CompletionItem.create(label: string): CompletionItem` - `CompletionList.create(items: CompletionItem[], isIncomplete: boolean): CompletionList` ### Example ```typescript import { CompletionItem, CompletionItemKind, CompletionList } from 'vscode-languageserver-types'; const item = CompletionItem.create('myFunction'); item.kind = CompletionItemKind.Function; item.insertText = 'myFunction($1)'; const list = CompletionList.create([item], false); ``` ``` -------------------------------- ### InlayHint Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Shows how to create InlayHint objects, used for displaying inline information like type hints. ```APIDOC ## InlayHint ### Description Creates InlayHint objects for displaying inline information within the editor. ### Methods - `InlayHint.create(position: Position, label: string | InlayHintLabelPart[], kind?: InlayHintKind): InlayHint` ### Example ```typescript import { InlayHint, InlayHintKind, Position } from 'vscode-languageserver-types'; const hint = InlayHint.create(Position.create(5, 10), ': string', InlayHintKind.Type); ``` ``` -------------------------------- ### Register and Handle Inlay Hint Requests Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Implement the `inlayHintProvider` capability to handle `textDocument/inlayHint` requests. Supports simple string labels or interactive `InlayHintLabelPart` objects with navigation and tooltips. ```typescript import { createConnection, TextDocuments, InlayHint, InlayHintKind, InlayHintLabelPart, Position, Range, Location } from 'vscode-languageserver/node'; import { TextDocument } from 'vscode-languageserver-textdocument'; const connection = createConnection(); const documents = new TextDocuments(TextDocument); connection.onInitialize(() => ({ capabilities: { inlayHintProvider: { resolveProvider: false } } })); connection.languages.inlayHint.on(params => { const doc = documents.get(params.textDocument.uri); if (!doc) return []; const hints: InlayHint[] = []; // Simple string label — parameter name hint hints.push(InlayHint.create(Position.create(5, 14), 'name:', InlayHintKind.Parameter)); // Interactive label part with navigation location and tooltip const part = InlayHintLabelPart.create(': string'); part.tooltip = 'Inferred type: string'; part.location = Location.create( 'file:///lib/types.d.ts', Range.create(10, 0, 10, 20) ); hints.push({ position: Position.create(7, 18), label: [part], kind: InlayHintKind.Type, paddingLeft: true }); return hints; }); documents.listen(connection); connection.listen(); ``` -------------------------------- ### Hover with MarkupContent Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Demonstrates creating Hover objects, which can contain documentation in Markdown or plain text format. ```APIDOC ## Hover with Markdown ### Description Creates Hover objects that display information, potentially formatted using Markdown. ### Example ```typescript import { Hover, MarkupContent, MarkupKind, Range, Position } from 'vscode-languageserver-types'; const range = Range.create(Position.create(0, 0), Position.create(1, 0)); const hover: Hover = { contents: MarkupContent.is({ kind: MarkupKind.Markdown, value: '**bold** text' }) ? { kind: MarkupKind.Markdown, value: '**bold** text' } : 'plain text', range }; ``` ``` -------------------------------- ### Position and Range Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Demonstrates how to create and check Position and Range objects using the `Position.create()` and `Range.create()` factory methods, along with the `Range.is()` type guard. ```APIDOC ## Position & Range ### Description Creates and validates Position and Range objects. ### Methods - `Position.create(line: number, character: number): Position` - `Range.create(start: Position, end: Position): Range` - `Range.is(value: any): value is Range` ### Example ```typescript import { Position, Range } from 'vscode-languageserver-types'; const start = Position.create(0, 5); const end = Position.create(0, 10); const range = Range.create(start, end); console.log(Range.is(range)); // true ``` ``` -------------------------------- ### TextDocument.create / update / applyEdits Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Demonstrates how to create a new TextDocument, update it with changes received from the client, and apply edits to produce a new document string. ```APIDOC ## TextDocument.create / update / applyEdits ### Description This section covers the core functionalities of the `TextDocument` class from `vscode-languageserver-textdocument`. It explains how to initialize a document, apply incremental or full content changes, and non-destructively apply edits to generate a new document string. ### Usage ```typescript import { TextDocument } from 'vscode-languageserver-textdocument'; // Create a new document let doc = TextDocument.create( 'file:///path/to/file.ts', // uri 'typescript', // languageId 1, // version 'const x = 1;\nconst y = 2;\n' ); console.log(doc.lineCount); // 3 console.log(doc.getText()); // full text console.log(doc.offsetAt({ line: 1, character: 6 })); // 20 console.log(doc.positionAt(20)); // { line: 1, character: 6 } console.log(doc.getText({ start: { line: 1, character: 0 }, end: { line: 1, character: 13 } })); // → 'const y = 2;' // Apply incremental change (client sends a textDocument/didChange) doc = TextDocument.update(doc, [ { range: { start: { line: 0, character: 10 }, end: { line: 0, character: 11 } }, text: '42' } ], 2); console.log(doc.getText({ start: { line: 0, character: 0 }, end: { line: 0, character: 14 } })); // → 'const x = 42;' // Apply edits to produce a new string (without mutating the document) const result = TextDocument.applyEdits(doc, [ { range: { start: { line: 1, character: 6 }, end: { line: 1, character: 7 } }, newText: 'z' } ]); console.log(result); // → 'const x = 42;\nconst z = 2;\n' ``` ### Methods * **`TextDocument.create(uri: string, languageId: string, version: number, content: string): TextDocument`** Creates a new `TextDocument` instance. * **`TextDocument.update(document: TextDocument, changes: TextDocumentContentChangeEvent[], newVersion: number): TextDocument`** Applies content changes to a `TextDocument` and returns a new `TextDocument` instance with the updated content and version. * **`TextDocument.applyEdits(document: TextDocument, edits: TextEdit[]): string`** Applies an array of `TextEdit` objects to the given `TextDocument` non-destructively and returns the resulting document content as a string. ### Types * **`TextDocumentContentChangeEvent`**: Represents a change to the document's content. It can be a full content replacement or a range-based edit. * `range` (Range): The range of the document that changed. * `text` (string): The new text for the specified range. * **`TextEdit`**: Represents a text edit operation. * `range` (Range): The range of text to be replaced. * `newText` (string): The new text to be inserted. * **`Range`**: Represents a range in a text document. * `start` (Position): The start position of the range. * `end` (Position): The end position of the range. * **`Position`**: Represents a position in a text document. * `line` (number): The line number (0-based). * `character` (number): The character offset within the line (0-based). ``` -------------------------------- ### Diagnostic with Code Description and Related Information Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Illustrates how to create and enrich `Diagnostic` objects with features like code descriptions (linking to documentation), tags for rendering hints, and related information pointing to other locations. ```APIDOC ## `Diagnostic` Object Enrichment ### Description Demonstrates the creation and enrichment of `Diagnostic` objects with advanced metadata, including severity, codes, code descriptions with URIs, tags for rendering, and related information for other code locations. ### Method `Diagnostic.create(range, message, severity, code, codeDescription)` ### Parameters - `range` (Range) - The range to which this diagnostic applies. - `message` (string) - The diagnostic message. - `severity` (DiagnosticSeverity) - The severity of the diagnostic. - `code` (string | integer | null) - The code associated with the diagnostic. - `codeDescription` (CodeDescription | null) - A link to documentation about the code. ### Request Example (Creating a diagnostic object) ### Response - `Diagnostic` - A `Diagnostic` object with enriched metadata. ### Response Example ```typescript { range: Range.create(4, 0, 4, 15), message: "Variable 'counter' is assigned but never used", severity: DiagnosticSeverity.Warning, code: 'no-unused-vars', codeDescription: { href: 'https://eslint.org/docs/rules/no-unused-vars' }, tags: [DiagnosticTag.Unnecessary], relatedInformation: [ { location: Location.create('file:///src/app.ts', Range.create(1, 6, 1, 13)), message: "'counter' is declared here" } ], data: { ruleId: 'no-unused-vars', fixable: true } // Arbitrary data } ``` ``` -------------------------------- ### Initialize and Run Mocha Tests Source: https://github.com/microsoft/vscode-languageserver-node/blob/main/jsonrpc/src/browser/test/index.html Configures Mocha with a specific UI ('tdd') and timeout, then registers the custom PlaywrightReporter and initiates test execution. This is the main entry point for running the browser tests. ```javascript mocha.setup({ ui: 'tdd', timeout: 5000 }); mocha.reporter(PlaywrightReporter); mocha.run(); ``` -------------------------------- ### Create Rich Diagnostics with vscode-languageserver-types Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Construct `Diagnostic` objects with advanced metadata including severity, string/numeric codes, code descriptions via URIs, rendering tags, and related information for pinpointing issues. ```typescript import { Diagnostic, DiagnosticSeverity, DiagnosticTag, DiagnosticRelatedInformation, Location, Range } from 'vscode-languageserver-types'; const primaryRange = Range.create(4, 0, 4, 15); const diag = Diagnostic.create( primaryRange, "Variable 'counter' is assigned but never used", DiagnosticSeverity.Warning, 'no-unused-vars', 'eslint' ); // Link to rule documentation dia.codeDescription = { href: 'https://eslint.org/docs/rules/no-unused-vars' }; // Render as faded-out (unnecessary code) diag.tags = [DiagnosticTag.Unnecessary]; // Point at the original declaration diag.relatedInformation = [ DiagnosticRelatedInformation.create( Location.create('file:///src/app.ts', Range.create(1, 6, 1, 13)), "'counter' is declared here" ) ]; // Preserve arbitrary data across codeAction/resolve diag.data = { ruleId: 'no-unused-vars', fixable: true }; console.log(Diagnostic.is(diag)); // true ``` -------------------------------- ### Semantic Tokens Provider Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Details how to implement semantic token highlighting by registering token types and modifiers and responding to `textDocument/semanticTokens/full` and `textDocument/semanticTokens/range` requests. ```APIDOC ## `connection.languages.semanticTokens` ### Description Provides functionality for servers to offer semantic token information to clients, enabling more advanced syntax highlighting. This involves registering token legends and handling requests for full document or range-based token data. ### Registration Register capabilities in `onInitialize`: ```typescript connection.onInitialize(() => ({ capabilities: { semanticTokensProvider: { legend: { tokenTypes, tokenModifiers }, full: { delta: true }, range: true } } })); ``` ### Handlers - `connection.languages.semanticTokens.on(handler)`: Handles requests for full document semantic tokens (`textDocument/semanticTokens/full`). - `connection.languages.semanticTokens.onRange(handler)`: Handles requests for semantic tokens within a specified range (`textDocument/semanticTokens/range`). ### `SemanticTokensBuilder` Used to construct the token data array. - `push(line, char, length, tokenTypeIndex, tokenModifierBitmask)`: Adds a token to the builder. - `build()`: Returns the encoded token data array. ### Parameters - `legend`: An object containing `tokenTypes` (string array) and `tokenModifiers` (string array). - `params` for handlers: - `textDocument`: The document URI. - `range`: The range for `onRange` requests. - `tokenTypes`: Predefined types like `SemanticTokenTypes.variable`, `SemanticTokenTypes.function`, etc. - `tokenModifiers`: Predefined modifiers like `SemanticTokenModifiers.declaration`, `SemanticTokenModifiers.readonly`, etc. ### Response - The handlers should return an object with a `data` property, which is an array of encoded semantic tokens. The `SemanticTokensBuilder.build()` method generates this array. ``` -------------------------------- ### Create and Validate LSP Types with vscode-languageserver-types Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Import and use factory functions like `Position.create` and type guards like `Range.is` to work with LSP data structures. Ensure all necessary types are imported. ```typescript import { Position, Range, Location, LocationLink, TextEdit, Diagnostic, DiagnosticSeverity, DiagnosticTag, CompletionItem, CompletionItemKind, CompletionList, CodeAction, CodeActionKind, WorkspaceEdit, WorkspaceChange, SymbolInformation, SymbolKind, DocumentSymbol, Hover, MarkupContent, MarkupKind, InlayHint, InlayHintKind, InlayHintLabelPart, SemanticTokenTypes, SemanticTokenModifiers } from 'vscode-languageserver-types'; // Position & Range const start = Position.create(0, 5); // { line: 0, character: 5 } const end = Position.create(0, 10); const range = Range.create(start, end); // { start, end } console.log(Range.is(range)); // true // Location & LocationLink const loc = Location.create('file:///foo.ts', range); const link = LocationLink.create('file:///bar.ts', Range.create(0, 0, 10, 0), // targetRange Range.create(2, 4, 2, 8) // targetSelectionRange ); // Diagnostic const diag = Diagnostic.create( Range.create(3, 0, 3, 10), 'Unused variable', DiagnosticSeverity.Warning, 'no-unused-vars', 'eslint' ); diag.tags = [DiagnosticTag.Unnecessary]; // CompletionItem & CompletionList const item = CompletionItem.create('myFunction'); item.kind = CompletionItemKind.Function; item.insertText = 'myFunction($1)'; const list = CompletionList.create([item], /*isIncomplete*/ false); // CodeAction with WorkspaceEdit const change = new WorkspaceChange(); const editChange = change.getTextEditChange('file:///foo.ts'); editChange.replace(Range.create(0, 4, 0, 7), 'bar'); const action = CodeAction.create( 'Rename to bar', change.edit, CodeActionKind.QuickFix ); // Hover with Markdown const hover: Hover = { contents: MarkupContent.is({ kind: MarkupKind.Markdown, value: '**bold** text' }) ? { kind: MarkupKind.Markdown, value: '**bold** text' } : 'plain text', range }; // InlayHint const hint = InlayHint.create(Position.create(5, 10), ': string', InlayHintKind.Type); ``` -------------------------------- ### Progress Reporting Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Demonstrates how to create and manage work-done progress notifications from the server to the client, including handling cancellation requests. ```APIDOC ## `connection.window.createWorkDoneProgress()` ### Description Creates a progress token that can be used to report work-done progress updates to the client. This is typically used for long-running operations. ### Method `connection.window.createWorkDoneProgress()` ### Usage ```typescript const progress = await connection.window.createWorkDoneProgress(); progress.begin('Message', 0, 'Subtle message', true); progress.report(percentage, 'Message'); progress.done(); ``` ### Parameters - `begin` method: - `title` (string): The main title of the progress notification. - `percentage` (number): The current progress percentage (0-100). - `message` (string): A more detailed message about the current progress. - `cancellable` (boolean): Whether the operation can be cancelled by the user. - `report` method: - `percentage` (number): The current progress percentage (0-100). - `message` (string): A more detailed message about the current progress. ### Response - `begin`, `report`, `done` methods do not return a value. - The `createWorkDoneProgress` method returns a `WorkDoneProgressReporter` object. ``` -------------------------------- ### Completion Context in Client Middleware Source: https://github.com/microsoft/vscode-languageserver-node/blob/main/README.md Illustrates the change in the signature for `provideCompletionItem` in the client middleware due to the introduction of completion context. The old signature lacked the `context` argument, while the new one includes it. ```typescript provideCompletionItem?: (this: void, document: TextDocument, position: VPosition, token: CancellationToken, next: ProvideCompletionItemsSignature) => ProviderResult; ``` ```typescript provideCompletionItem?: (this: void, document: TextDocument, position: VPosition, context: VCompletionContext, token: CancellationToken, next: ProvideCompletionItemsSignature) => ProviderResult; ``` -------------------------------- ### MessageReader / MessageWriter with Streams Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Illustrates using `ReadableStreamMessageReader` and `WriteableStreamMessageWriter` to create a message connection over Node.js streams, commonly used for inter-process communication like in LSP servers. It also shows how to configure progress reporting for partial messages. ```APIDOC ## `vscode-jsonrpc` — MessageReader / MessageWriter `AbstractMessageReader` and `AbstractMessageWriter` are base classes for custom transports. `ReadableStreamMessageReader` and `WriteableStreamMessageWriter` wrap Node.js `Readable`/`Writable` streams with the LSP content-length framing. For browser environments the corresponding browser variants use `MessagePort` / `Worker` postMessage channels. ```typescript import { ReadableStreamMessageReader, WriteableStreamMessageWriter, createMessageConnection, NullLogger, NotificationType } from 'vscode-jsonrpc/node'; // Use stdin/stdout as transport (typical for LSP servers launched as child processes) const reader = new ReadableStreamMessageReader(process.stdin); const writer = new WriteableStreamMessageWriter(process.stdout); const connection = createMessageConnection(reader, writer, NullLogger); const PingNotification = new NotificationType('ping'); connection.onNotification(PingNotification, () => { process.stderr.write('ping received\n'); }); connection.listen(); // Custom reader with partial-message progress reporting reader.partialMessageTimeout = 5000; // ms before partial-message warning fires reader.onPartialMessage(info => { process.stderr.write(`Partial message: got ${info.messageToken} bytes\n`); }); ``` ``` -------------------------------- ### Wait for Client Ready in TypeScript Source: https://github.com/microsoft/vscode-languageserver-node/blob/main/README.md Use the onReady() Promise to ensure the language client is ready before sending notifications or requests. This prevents errors caused by calling these methods before the client is initialized. ```typescript let client = new LanguageClient(...); client.onReady().then(() => { client.onNotification(...); client.sendRequest(...); ); ``` -------------------------------- ### CodeAction and WorkspaceEdit Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Shows how to construct CodeAction objects, which can include WorkspaceEdit for making changes to documents. ```APIDOC ## CodeAction with WorkspaceEdit ### Description Creates CodeAction objects, which can encapsulate changes to be applied to documents via WorkspaceEdit. ### Methods - `CodeAction.create(title: string, edit?: WorkspaceEdit, kind?: CodeActionKind): CodeAction` ### Example ```typescript import { CodeAction, CodeActionKind, WorkspaceChange, Range, Position } from 'vscode-languageserver-types'; const change = new WorkspaceChange(); const editChange = change.getTextEditChange('file:///foo.ts'); editChange.replace(Range.create(Position.create(0, 4), Position.create(0, 7)), 'bar'); const action = CodeAction.create( 'Rename to bar', change.edit, CodeActionKind.QuickFix ); ``` ``` -------------------------------- ### createConnection Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Creates a bidirectional LSP connection for a Node.js server. It auto-detects transport from command-line arguments or accepts explicit streams. The returned `Connection` object provides typed handlers for LSP requests and notifications, along with server-to-client methods. ```APIDOC ## `createConnection` ### Description Creates a bidirectional LSP connection for a Node.js server. It auto-detects the transport from command-line arguments (`--stdio`, `--node-ipc`, `--socket=PORT`, `--pipe=NAME`) or accepts explicit streams/readers+writers. The returned `Connection` object exposes typed handlers for every LSP request and notification, plus server-to-client methods for showing messages, registering capabilities dynamically, and reporting progress. ### Usage ```typescript import { createConnection, ProposedFeatures } from 'vscode-languageserver/node'; // Create the connection (reads --stdio / --node-ipc / etc. from argv) const connection = createConnection(ProposedFeatures.all); // ... server logic ... connection.listen(); ``` ### Handlers - `onInitialize`: Handles the `initialize` request from the client. - `onInitialized`: Called after the client has sent the `initialized` notification. - `onCompletion`: Handles completion requests. - `onCompletionResolve`: Resolves additional details for completion items. - `onHover`: Handles hover requests. ### Server-to-Client Methods - `window.showInformationMessage`: Displays an information message to the user. - `sendDiagnostics`: Sends diagnostic information for a document. - `console.log`: Logs messages to the server's console. ``` -------------------------------- ### Location and LocationLink Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Shows how to create Location and LocationLink objects, which represent a location in a resource. ```APIDOC ## Location & LocationLink ### Description Creates Location and LocationLink objects for specifying locations within a document. ### Methods - `Location.create(uri: string, range: Range): Location` - `LocationLink.create(targetUri: string, targetRange: Range, targetSelectionRange: Range): LocationLink` ### Example ```typescript import { Location, LocationLink, Range, Position } from 'vscode-languageserver-types'; const range = Range.create(Position.create(0, 0), Position.create(10, 0)); const loc = Location.create('file:///foo.ts', range); const link = LocationLink.create('file:///bar.ts', range, Range.create(Position.create(2, 4), Position.create(2, 8))); ``` ``` -------------------------------- ### WorkspaceEdit Builder Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Explains how to use the `WorkspaceChange` builder to construct a `WorkspaceEdit` object, which can include text edits, file creations, renames, and deletions. ```APIDOC ## `WorkspaceChange` ### Description A builder class for accumulating various types of edits (text, file operations) into a `WorkspaceEdit` object. The resulting edit can be returned from LSP requests or applied using `connection.workspace.applyEdit()`. ### Methods - `getTextEditChange(textDocumentIdentifier)`: Returns a `TextEditChange` object for the specified document. - `createFile(uri, options)`: Adds a file creation operation. - `renameFile(oldUri, newUri, options)`: Adds a file rename operation. - `deleteFile(uri, options)`: Adds a file deletion operation. ### `TextEditChange` Methods - `replace(range, newText, [annotation])`: Replaces text within a specified range. - `insert(position, newText, [annotation])`: Inserts text at a specified position. - `delete(range, [annotation])`: Deletes text within a specified range. ### Parameters - `textDocumentIdentifier`: An object with `uri` and `version` properties. - `range`: An object with `start` and `end` `Position` objects. - `position`: An object with `line` and `character` properties. - `annotation`: An optional `ChangeAnnotation` object for tracking edits. - `options` for file operations: `{ overwrite?: boolean, recursive?: boolean, ignoreIfNotExists?: boolean }` ### Response - The `edit` property of a `WorkspaceChange` instance returns the complete `WorkspaceEdit` object. - `getTextEditChange` returns a `TextEditChange` object. - File operation methods return void. ``` -------------------------------- ### Move Image Files Source: https://github.com/microsoft/vscode-languageserver-node/blob/main/testbed/workspace/test.txt This command moves files with .jpg, .png, or .bmp extensions from c:\source to c:\images. It utilizes the same XCOPY command with /m and /y switches for copying and attribute management. ```batch FOR %%f IN (*.jpg *.png *.bmp) DO XCOPY C:\source"%%f" c:\images /m /y REM This moves any files with a .jpg, .png, REM or .bmp extension from c:\source to c:\images;; ``` -------------------------------- ### Implement Work-Done Progress Reporting in VS Code Language Server Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Use `connection.window.createWorkDoneProgress()` to create a progress token for server-initiated progress. Report incremental updates using `progress.report()` and finalize with `progress.done()`. Handle cancellation requests by checking `token.isCancellationRequested`. ```typescript import { createConnection, WorkDoneProgressReporter } from 'vscode-languageserver/node'; import { TextDocument } from 'vscode-languageserver-textdocument'; const connection = createConnection(); connection.onRequest('workspace/executeCommand', async (params, token) => { if (params.command !== 'myExtension.longTask') return; // Create server-initiated progress const progress = await connection.window.createWorkDoneProgress(); progress.begin('Indexing files', 0, 'Starting…', true /* cancellable */); const files = ['a.ts', 'b.ts', 'c.ts', 'd.ts', 'e.ts']; for (let i = 0; i < files.length; i++) { if (token.isCancellationRequested) { progress.done(); return { cancelled: true }; } // simulate work await new Promise(r => setTimeout(r, 200)); progress.report( Math.round(((i + 1) / files.length) * 100), `Processing ${files[i]}` ); } progress.done(); return { indexed: files.length }; }); connection.listen(); ``` -------------------------------- ### TextDocuments Manager for LSP Server (Node.js) Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Manages text documents in an LSP server, subscribing to document events like open, change, and close. Use `documents.listen(connection)` to attach and `documents.get(uri)` to access document content. ```typescript import { createConnection, TextDocuments, TextDocumentSyncKind } from 'vscode-languageserver/node'; import { TextDocument } from 'vscode-languageserver-textdocument'; const connection = createConnection(); const documents = new TextDocuments(TextDocument); // Fired when a document is opened documents.onDidOpen(event => { connection.console.log(`Opened: ${event.document.uri} (lang: ${event.document.languageId})`); }); // Fired on every content change (incremental or full) documents.onDidChangeContent(event => { const doc = event.document; connection.console.log(`Changed: ${doc.uri} v${doc.version}, ${doc.lineCount} lines`); // re-validate... }); // Fired when the client closes a document documents.onDidClose(event => { // Clear diagnostics for closed file connection.sendDiagnostics({ uri: event.document.uri, diagnostics: [] }); }); // Fired before save — can provide pre-save text edits documents.onWillSaveWaitUntil(event => { // Example: strip trailing whitespace before save const edits = []; // ... compute edits ... return edits; }); // Access current document snapshot connection.onRequest('custom/wordCount', params => { const doc = documents.get(params.uri); if (!doc) return 0; return doc.getText().split(/\s+/).length; }); documents.listen(connection); connection.listen(); ``` -------------------------------- ### Implement Custom Message Reader/Writer with Streams Source: https://context7.com/microsoft/vscode-languageserver-node/llms.txt Use `ReadableStreamMessageReader` and `WriteableStreamMessageWriter` to wrap Node.js streams for LSP communication. Configure `partialMessageTimeout` for progress reporting on incomplete messages. ```typescript import { ReadableStreamMessageReader, WriteableStreamMessageWriter, createMessageConnection, NullLogger, NotificationType } from 'vscode-jsonrpc/node'; // Use stdin/stdout as transport (typical for LSP servers launched as child processes) const reader = new ReadableStreamMessageReader(process.stdin); const writer = new WriteableStreamMessageWriter(process.stdout); const connection = createMessageConnection(reader, writer, NullLogger); const PingNotification = new NotificationType('ping'); connection.onNotification(PingNotification, () => { process.stderr.write('ping received\n'); }); connection.listen(); // Custom reader with partial-message progress reporting reader.partialMessageTimeout = 5000; // ms before partial-message warning fires reader.onPartialMessage(info => { process.stderr.write(`Partial message: got ${info.messageToken} bytes\n`); }); ``` -------------------------------- ### File Sorting and Copying with Batch Script Source: https://github.com/microsoft/vscode-languageserver-node/blob/main/testbed/workspace/test.ipynb This Batch script sorts and copies files based on their extensions. It uses XCOPY with the /m and /y flags for copying and mirroring attributes. Ensure the source and destination directories exist before execution. ```batch REM @ECHO OFF cd c:\source REM This is the location of the files that you want to sort FOR %%f IN (*.doc *.txt) DO XCOPY c:\source"%%f" c:\text /m /y REM This moves any files with a .doc or REM .txt extension from . c:\source to c:\textkkk REM %%f is a variable FOR %%f IN (*.jpg *.png *.bmp) DO XCOPY C:\source"%%f" c:\images /m /y REM This moves any files with a .jpg, .png, REM or .bmp extension from c:\source to c:\images;; ```