/* -------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ 'use strict'; import { createConnection, TextDocuments, TextDocument, Diagnostic, DiagnosticSeverity, ProposedFeatures, InitializeParams } from 'vscode-languageserver'; // Create a connection for the server. The connection uses Node's IPC as a transport let connection = createConnection(ProposedFeatures.all); // Create a simple text document manager. The text document manager // supports full document sync only let documents: TextDocuments = new TextDocuments(); let hasConfigurationCapability = false; connection.onInitialize((params: InitializeParams) => { function hasClientCapability(...keys: string[]) { let c = params.capabilities; for (let i = 0; c && i < keys.length; i++) { c = c[keys[i]]; } return !!c; } // Does the client support the `workspace/configuration` request? // If not, we will fall back using global settings hasConfigurationCapability = hasClientCapability('workspace', 'configuration'); return { capabilities: { textDocumentSync: documents.syncKind } } }); // The example settings interface MultiRootExampleSettings { maxNumberOfProblems: number; } // The global settings, used when the `workspace/configuration` request is not supported by the client. // Please note that this is not the case when using this server with the client provided in this example // but could happen with other clients. const defaultSettings: MultiRootExampleSettings = { maxNumberOfProblems: 1000 }; let globalSettings: MultiRootExampleSettings = defaultSettings; // Cache the settings of all open documents let documentSettings: Map> = new Map(); connection.onDidChangeConfiguration(change => { if (hasConfigurationCapability) { // Reset all cached document settings documentSettings.clear(); } else { globalSettings = (change.settings.lspMultiRootSample || defaultSettings); } // Revalidate all open text documents documents.all().forEach(validateTextDocument); }); function getDocumentSettings(resource: string): Thenable { if (!hasConfigurationCapability) { return Promise.resolve(globalSettings); } let result = documentSettings.get(resource); if (!result) { result = connection.workspace.getConfiguration({ scopeUri: resource }); documentSettings.set(resource, result); } return result; } // Only keep settings for open documents documents.onDidClose(e => { documentSettings.delete(e.document.uri); }); // 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) => { validateTextDocument(change.document); }); async function validateTextDocument(textDocument: TextDocument): Promise { // In this simple example we get the settings for every validate run. let settings = await getDocumentSettings(textDocument.uri); // The validator creates diagnostics for all uppercase words length 2 and more let text = textDocument.getText(); let pattern = /\b[A-Z]{2,}\b/g; let m: RegExpExecArray; let problems = 0; let diagnostics: Diagnostic[] = []; while ((m = pattern.exec(text)) && problems < settings.maxNumberOfProblems) { problems++; diagnostics.push({ severity: DiagnosticSeverity.Warning, range: { start: textDocument.positionAt(m.index), end: textDocument.positionAt(m.index + m[0].length) }, message: `${m[0].length} is all uppercase.`, source: 'ex' }); } // Send the computed diagnostics to VSCode. connection.sendDiagnostics({ uri: textDocument.uri, diagnostics }); } // 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();