UNPKG

vscode-languageclient

Version:
375 lines (374 loc) 14.7 kB
"use strict"; /* -------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.DefaultDiagnosticCollectionProvider = exports.DiagnosticCollectionSource = exports.WorkspaceFeature = exports.TextDocumentLanguageFeature = exports.TextDocumentEventFeature = exports.DynamicDocumentFeature = exports.DynamicFeature = exports.StaticFeature = exports.LSPCancellationError = void 0; exports.ensure = ensure; const vscode_1 = require("vscode"); const vscode_languageserver_protocol_1 = require("vscode-languageserver-protocol"); const Is = __importStar(require("./utils/is")); const UUID = __importStar(require("./utils/uuid")); class LSPCancellationError extends vscode_1.CancellationError { data; constructor(data) { super(); this.data = data; } } exports.LSPCancellationError = LSPCancellationError; function ensure(target, key) { if (target[key] === undefined) { target[key] = {}; } return target[key]; } var StaticFeature; (function (StaticFeature) { function is(value) { const candidate = value; return candidate !== undefined && candidate !== null && Is.func(candidate.fillClientCapabilities) && Is.func(candidate.initialize) && Is.func(candidate.getState) && Is.func(candidate.clear) && (candidate.fillInitializeParams === undefined || Is.func(candidate.fillInitializeParams)); } StaticFeature.is = is; })(StaticFeature || (exports.StaticFeature = StaticFeature = {})); var DynamicFeature; (function (DynamicFeature) { function is(value) { const candidate = value; return candidate !== undefined && candidate !== null && Is.func(candidate.fillClientCapabilities) && Is.func(candidate.initialize) && Is.func(candidate.getState) && Is.func(candidate.clear) && (candidate.fillInitializeParams === undefined || Is.func(candidate.fillInitializeParams)) && Is.func(candidate.register) && Is.func(candidate.unregister) && candidate.registrationType !== undefined; } DynamicFeature.is = is; })(DynamicFeature || (exports.DynamicFeature = DynamicFeature = {})); /** * An abstract dynamic feature implementation that operates on documents (e.g. text * documents or notebooks). */ class DynamicDocumentFeature { _client; constructor(client) { this._client = client; } /** * Returns the state the feature is in. */ getState() { const selectors = this.getDocumentSelectors(); let count = 0; for (const selector of selectors) { count++; for (const document of vscode_1.workspace.textDocuments) { if (vscode_1.languages.match(selector, document) > 0) { return { kind: 'document', id: this.registrationType.method, registrations: true, matches: true }; } } } const registrations = count > 0; return { kind: 'document', id: this.registrationType.method, registrations, matches: false }; } } exports.DynamicDocumentFeature = DynamicDocumentFeature; /** * An abstract base class to implement features that react to events * emitted from text documents. */ class TextDocumentEventFeature extends DynamicDocumentFeature { _event; _type; _middleware; _createParams; _textDocument; _selectorFilter; _listener; _selectors; _onAboutToSendNotification; _onNotificationSent; static textDocumentFilter(selectors, textDocument) { for (const selector of selectors) { if (vscode_1.languages.match(selector, textDocument) > 0) { return true; } } return false; } constructor(client, event, type, middleware, createParams, textDocument, selectorFilter) { super(client); this._event = event; this._type = type; this._middleware = middleware; this._createParams = createParams; this._textDocument = textDocument; this._selectorFilter = selectorFilter; this._selectors = new Map(); this._onAboutToSendNotification = new vscode_1.EventEmitter(); this._onNotificationSent = new vscode_1.EventEmitter(); } getStateInfo() { return [this._selectors.values(), false]; } getDocumentSelectors() { return this._selectors.values(); } register(data) { if (!data.registerOptions.documentSelector) { return; } if (!this._listener) { this._listener = this._event((data) => { this.callback(data).catch((error) => { this._client.error(`Sending document notification ${this._type.method} failed.`, error); }); }); } this._selectors.set(data.id, this._client.protocol2CodeConverter.asDocumentSelector(data.registerOptions.documentSelector)); } async callback(data) { const doSend = async (data) => { const textDocument = this.getTextDocument(data); const params = this._createParams(data); this.aboutToSendNotification(textDocument, this._type, params); await this._client.sendNotification(this._type, params); this.notificationSent(textDocument, this._type, params); }; if (this.matches(data)) { const middleware = this._middleware(); return middleware ? middleware(data, (data) => doSend(data)) : doSend(data); } } matches(data) { if (this._client.hasDedicatedTextSynchronizationFeature(this._textDocument(data))) { return false; } return !this._selectorFilter || this._selectorFilter(this._selectors.values(), data); } get onAboutToSendNotification() { return this._onAboutToSendNotification.event; } aboutToSendNotification(textDocument, type, params) { this._onAboutToSendNotification.fire({ textDocument, type, params }); } get onNotificationSent() { return this._onNotificationSent.event; } notificationSent(textDocument, type, params) { this._onNotificationSent.fire({ textDocument, type, params }); } unregister(id) { this._selectors.delete(id); if (this._selectors.size === 0 && this._listener) { this._listener.dispose(); this._listener = undefined; } } clear() { this._selectors.clear(); this._onNotificationSent.dispose(); this._onNotificationSent = new vscode_1.EventEmitter(); if (this._listener) { this._listener.dispose(); this._listener = undefined; } } getProvider(document) { for (const selector of this._selectors.values()) { if (vscode_1.languages.match(selector, document) > 0) { return { send: (data) => { return this.callback(data); } }; } } return undefined; } } exports.TextDocumentEventFeature = TextDocumentEventFeature; /** * A abstract feature implementation that registers language providers * for text documents using a given document selector. */ class TextDocumentLanguageFeature extends DynamicDocumentFeature { _registrationType; _registrations; constructor(client, registrationType) { super(client); this._registrationType = registrationType; this._registrations = new Map(); } *getDocumentSelectors() { for (const registration of this._registrations.values()) { const selector = registration.data.registerOptions.documentSelector; if (selector === null) { continue; } yield this._client.protocol2CodeConverter.asDocumentSelector(selector); } } get registrationType() { return this._registrationType; } register(data) { if (!data.registerOptions.documentSelector) { return; } const registration = this.registerLanguageProvider(data.registerOptions, data.id); this._registrations.set(data.id, { disposable: registration[0], data, provider: registration[1] }); } unregister(id) { const registration = this._registrations.get(id); if (registration !== undefined) { this._registrations.delete(id); registration.disposable.dispose(); } } clear() { this._registrations.forEach((value) => { value.disposable.dispose(); }); this._registrations.clear(); } getRegistration(documentSelector, capability) { if (!capability) { return [undefined, undefined]; } else if (vscode_languageserver_protocol_1.TextDocumentRegistrationOptions.is(capability)) { const id = vscode_languageserver_protocol_1.StaticRegistrationOptions.hasId(capability) ? capability.id : UUID.generateUuid(); const selector = capability.documentSelector ?? documentSelector; if (selector) { return [id, Object.assign({}, capability, { documentSelector: selector })]; } } else if (Is.boolean(capability) && capability === true || vscode_languageserver_protocol_1.WorkDoneProgressOptions.is(capability)) { if (!documentSelector) { return [undefined, undefined]; } const options = (Is.boolean(capability) && capability === true ? { documentSelector } : Object.assign({}, capability, { documentSelector })); return [UUID.generateUuid(), options]; } return [undefined, undefined]; } getRegistrationOptions(documentSelector, capability) { if (!documentSelector || !capability) { return undefined; } return (Is.boolean(capability) && capability === true ? { documentSelector } : Object.assign({}, capability, { documentSelector })); } getProvider(textDocument) { for (const registration of this._registrations.values()) { const selector = registration.data.registerOptions.documentSelector; if (selector !== null && vscode_1.languages.match(this._client.protocol2CodeConverter.asDocumentSelector(selector), textDocument) > 0) { return registration.provider; } } return undefined; } getAllProviders() { const result = []; for (const item of this._registrations.values()) { result.push(item.provider); } return result; } } exports.TextDocumentLanguageFeature = TextDocumentLanguageFeature; class WorkspaceFeature { _client; _registrationType; _registrations; constructor(client, registrationType) { this._client = client; this._registrationType = registrationType; this._registrations = new Map(); } getState() { const registrations = this._registrations.size > 0; return { kind: 'workspace', id: this._registrationType.method, registrations }; } get registrationType() { return this._registrationType; } register(data) { const registration = this.registerLanguageProvider(data.registerOptions); this._registrations.set(data.id, { disposable: registration[0], provider: registration[1] }); } unregister(id) { const registration = this._registrations.get(id); if (registration !== undefined) { this._registrations.delete(id); registration.disposable.dispose(); } } clear() { this._registrations.forEach((registration) => { registration.disposable.dispose(); }); this._registrations.clear(); } getProviders() { const result = []; for (const registration of this._registrations.values()) { result.push(registration.provider); } return result; } } exports.WorkspaceFeature = WorkspaceFeature; var DiagnosticCollectionSource; (function (DiagnosticCollectionSource) { DiagnosticCollectionSource["push"] = "push"; DiagnosticCollectionSource["pull"] = "pull"; })(DiagnosticCollectionSource || (exports.DiagnosticCollectionSource = DiagnosticCollectionSource = {})); /** * The default {@link DiagnosticCollectionProvider}. It never shares a diagnostic * collection between the push and the pull model. Every call to {@link create} * returns a new collection and {@link dispose} disposes it directly. */ class DefaultDiagnosticCollectionProvider { create(name, _source) { return name !== undefined ? vscode_1.languages.createDiagnosticCollection(name) : vscode_1.languages.createDiagnosticCollection(); } dispose(collection, _source) { collection.dispose(); } } exports.DefaultDiagnosticCollectionProvider = DefaultDiagnosticCollectionProvider;