UNPKG

coc.nvim

Version:

LSP based intellisense engine for neovim & vim8.

1,139 lines 103 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ /*tslint:disable*/ const path_1 = tslib_1.__importDefault(require("path")); const vscode_languageserver_protocol_1 = require("vscode-languageserver-protocol"); const vscode_uri_1 = require("vscode-uri"); const commands_1 = tslib_1.__importDefault(require("../commands")); const languages_1 = tslib_1.__importDefault(require("../languages")); const fs_1 = require("../util/fs"); const Is = tslib_1.__importStar(require("../util/is")); const workspace_1 = tslib_1.__importDefault(require("../workspace")); const async_1 = require("./utils/async"); const cv = tslib_1.__importStar(require("./utils/converter")); const UUID = tslib_1.__importStar(require("./utils/uuid")); const logger = require('../util/logger')('language-client-client'); class ConsoleLogger { error(message) { logger.error(message); } warn(message) { logger.warn(message); } info(message) { logger.info(message); } log(message) { logger.log(message); } } function createConnection(input, output, errorHandler, closeHandler) { let logger = new ConsoleLogger(); let connection = vscode_languageserver_protocol_1.createProtocolConnection(input, output, logger); connection.onError(data => { errorHandler(data[0], data[1], data[2]); }); connection.onClose(closeHandler); let result = { listen: () => connection.listen(), sendRequest: (type, ...params) => connection.sendRequest(Is.string(type) ? type : type.method, ...params), onRequest: (type, handler) => connection.onRequest(Is.string(type) ? type : type.method, handler), sendNotification: (type, params) => connection.sendNotification(Is.string(type) ? type : type.method, params), onNotification: (type, handler) => connection.onNotification(Is.string(type) ? type : type.method, handler), trace: (value, tracer, sendNotificationOrTraceOptions) => { const defaultTraceOptions = { sendNotification: false, traceFormat: vscode_languageserver_protocol_1.TraceFormat.Text }; if (sendNotificationOrTraceOptions === void 0) { connection.trace(value, tracer, defaultTraceOptions); } else if (Is.boolean(sendNotificationOrTraceOptions)) { connection.trace(value, tracer, sendNotificationOrTraceOptions); } else { connection.trace(value, tracer, sendNotificationOrTraceOptions); } }, initialize: (params) => connection.sendRequest(vscode_languageserver_protocol_1.InitializeRequest.type, params), shutdown: () => connection.sendRequest(vscode_languageserver_protocol_1.ShutdownRequest.type, undefined), exit: () => connection.sendNotification(vscode_languageserver_protocol_1.ExitNotification.type), onLogMessage: (handler) => connection.onNotification(vscode_languageserver_protocol_1.LogMessageNotification.type, handler), onShowMessage: (handler) => connection.onNotification(vscode_languageserver_protocol_1.ShowMessageNotification.type, handler), onTelemetry: (handler) => connection.onNotification(vscode_languageserver_protocol_1.TelemetryEventNotification.type, handler), didChangeConfiguration: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidChangeConfigurationNotification.type, params), didChangeWatchedFiles: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidChangeWatchedFilesNotification.type, params), didOpenTextDocument: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidOpenTextDocumentNotification.type, params), didChangeTextDocument: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type, params), didCloseTextDocument: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidCloseTextDocumentNotification.type, params), didSaveTextDocument: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidSaveTextDocumentNotification.type, params), onDiagnostics: (handler) => connection.onNotification(vscode_languageserver_protocol_1.PublishDiagnosticsNotification.type, handler), dispose: () => connection.dispose() }; return result; } /** * An action to be performed when the connection is producing errors. */ var ErrorAction; (function (ErrorAction) { /** * Continue running the server. */ ErrorAction[ErrorAction["Continue"] = 1] = "Continue"; /** * Shutdown the server. */ ErrorAction[ErrorAction["Shutdown"] = 2] = "Shutdown"; })(ErrorAction = exports.ErrorAction || (exports.ErrorAction = {})); /** * An action to be performed when the connection to a server got closed. */ var CloseAction; (function (CloseAction) { /** * Don't restart the server. The connection stays closed. */ CloseAction[CloseAction["DoNotRestart"] = 1] = "DoNotRestart"; /** * Restart the server. */ CloseAction[CloseAction["Restart"] = 2] = "Restart"; })(CloseAction = exports.CloseAction || (exports.CloseAction = {})); class DefaultErrorHandler { constructor(name) { this.name = name; this.restarts = []; } error(_error, _message, count) { if (count && count <= 3) { return ErrorAction.Continue; } return ErrorAction.Shutdown; } closed() { this.restarts.push(Date.now()); if (this.restarts.length < 5) { return CloseAction.Restart; } else { let diff = this.restarts[this.restarts.length - 1] - this.restarts[0]; if (diff <= 3 * 60 * 1000) { logger.error(`The ${this.name} server crashed 5 times in the last 3 minutes. The server will not be restarted.`); return CloseAction.DoNotRestart; } else { this.restarts.shift(); return CloseAction.Restart; } } } } var RevealOutputChannelOn; (function (RevealOutputChannelOn) { RevealOutputChannelOn[RevealOutputChannelOn["Info"] = 1] = "Info"; RevealOutputChannelOn[RevealOutputChannelOn["Warn"] = 2] = "Warn"; RevealOutputChannelOn[RevealOutputChannelOn["Error"] = 3] = "Error"; RevealOutputChannelOn[RevealOutputChannelOn["Never"] = 4] = "Never"; })(RevealOutputChannelOn = exports.RevealOutputChannelOn || (exports.RevealOutputChannelOn = {})); var State; (function (State) { State[State["Stopped"] = 1] = "Stopped"; State[State["Running"] = 2] = "Running"; State[State["Starting"] = 3] = "Starting"; })(State = exports.State || (exports.State = {})); var ClientState; (function (ClientState) { ClientState[ClientState["Initial"] = 0] = "Initial"; ClientState[ClientState["Starting"] = 1] = "Starting"; ClientState[ClientState["StartFailed"] = 2] = "StartFailed"; ClientState[ClientState["Running"] = 3] = "Running"; ClientState[ClientState["Stopping"] = 4] = "Stopping"; ClientState[ClientState["Stopped"] = 5] = "Stopped"; })(ClientState = exports.ClientState || (exports.ClientState = {})); const SupporedSymbolKinds = [ vscode_languageserver_protocol_1.SymbolKind.File, vscode_languageserver_protocol_1.SymbolKind.Module, vscode_languageserver_protocol_1.SymbolKind.Namespace, vscode_languageserver_protocol_1.SymbolKind.Package, vscode_languageserver_protocol_1.SymbolKind.Class, vscode_languageserver_protocol_1.SymbolKind.Method, vscode_languageserver_protocol_1.SymbolKind.Property, vscode_languageserver_protocol_1.SymbolKind.Field, vscode_languageserver_protocol_1.SymbolKind.Constructor, vscode_languageserver_protocol_1.SymbolKind.Enum, vscode_languageserver_protocol_1.SymbolKind.Interface, vscode_languageserver_protocol_1.SymbolKind.Function, vscode_languageserver_protocol_1.SymbolKind.Variable, vscode_languageserver_protocol_1.SymbolKind.Constant, vscode_languageserver_protocol_1.SymbolKind.String, vscode_languageserver_protocol_1.SymbolKind.Number, vscode_languageserver_protocol_1.SymbolKind.Boolean, vscode_languageserver_protocol_1.SymbolKind.Array, vscode_languageserver_protocol_1.SymbolKind.Object, vscode_languageserver_protocol_1.SymbolKind.Key, vscode_languageserver_protocol_1.SymbolKind.Null, vscode_languageserver_protocol_1.SymbolKind.EnumMember, vscode_languageserver_protocol_1.SymbolKind.Struct, vscode_languageserver_protocol_1.SymbolKind.Event, vscode_languageserver_protocol_1.SymbolKind.Operator, vscode_languageserver_protocol_1.SymbolKind.TypeParameter ]; const SupportedCompletionItemKinds = [ vscode_languageserver_protocol_1.CompletionItemKind.Text, vscode_languageserver_protocol_1.CompletionItemKind.Method, vscode_languageserver_protocol_1.CompletionItemKind.Function, vscode_languageserver_protocol_1.CompletionItemKind.Constructor, vscode_languageserver_protocol_1.CompletionItemKind.Field, vscode_languageserver_protocol_1.CompletionItemKind.Variable, vscode_languageserver_protocol_1.CompletionItemKind.Class, vscode_languageserver_protocol_1.CompletionItemKind.Interface, vscode_languageserver_protocol_1.CompletionItemKind.Module, vscode_languageserver_protocol_1.CompletionItemKind.Property, vscode_languageserver_protocol_1.CompletionItemKind.Unit, vscode_languageserver_protocol_1.CompletionItemKind.Value, vscode_languageserver_protocol_1.CompletionItemKind.Enum, vscode_languageserver_protocol_1.CompletionItemKind.Keyword, vscode_languageserver_protocol_1.CompletionItemKind.Snippet, vscode_languageserver_protocol_1.CompletionItemKind.Color, vscode_languageserver_protocol_1.CompletionItemKind.File, vscode_languageserver_protocol_1.CompletionItemKind.Reference, vscode_languageserver_protocol_1.CompletionItemKind.Folder, vscode_languageserver_protocol_1.CompletionItemKind.EnumMember, vscode_languageserver_protocol_1.CompletionItemKind.Constant, vscode_languageserver_protocol_1.CompletionItemKind.Struct, vscode_languageserver_protocol_1.CompletionItemKind.Event, vscode_languageserver_protocol_1.CompletionItemKind.Operator, vscode_languageserver_protocol_1.CompletionItemKind.TypeParameter ]; function ensure(target, key) { if (target[key] == null) { target[key] = {}; } return target[key]; } var DynamicFeature; (function (DynamicFeature) { function is(value) { let candidate = value; return (candidate && Is.func(candidate.register) && Is.func(candidate.unregister) && Is.func(candidate.dispose) && candidate.messages != null); } DynamicFeature.is = is; })(DynamicFeature || (DynamicFeature = {})); class OnReady { constructor(_resolve, _reject) { this._resolve = _resolve; this._reject = _reject; this._used = false; } get isUsed() { return this._used; } resolve() { this._used = true; this._resolve(); } reject(error) { this._used = true; this._reject(error); } } class DocumentNotifiactions { constructor(_client, _event, _type, _middleware, _createParams, _selectorFilter) { this._client = _client; this._event = _event; this._type = _type; this._middleware = _middleware; this._createParams = _createParams; this._selectorFilter = _selectorFilter; this._selectors = new Map(); } static textDocumentFilter(selectors, textDocument) { for (const selector of selectors) { if (workspace_1.default.match(selector, textDocument) > 0) { return true; } } return false; } register(_message, data) { if (!data.registerOptions.documentSelector) { return; } if (!this._listener) { this._listener = this._event(this.callback, this); } this._selectors.set(data.id, data.registerOptions.documentSelector); } callback(data) { if (!this._selectorFilter || this._selectorFilter(this._selectors.values(), data)) { if (this._middleware) { this._middleware(data, data => this._client.sendNotification(this._type, this._createParams(data))); } else { this._client.sendNotification(this._type, this._createParams(data)); } this.notificationSent(data); } } notificationSent(_data) { } unregister(id) { this._selectors.delete(id); if (this._selectors.size === 0 && this._listener) { this._listener.dispose(); this._listener = undefined; } } dispose() { this._selectors.clear(); if (this._listener) { this._listener.dispose(); this._listener = undefined; } } } class DidOpenTextDocumentFeature extends DocumentNotifiactions { constructor(client, _syncedDocuments) { super(client, workspace_1.default.onDidOpenTextDocument, vscode_languageserver_protocol_1.DidOpenTextDocumentNotification.type, client.clientOptions.middleware.didOpen, (textDocument) => { return { textDocument: cv.convertToTextDocumentItem(textDocument) }; }, DocumentNotifiactions.textDocumentFilter); this._syncedDocuments = _syncedDocuments; } get messages() { return vscode_languageserver_protocol_1.DidOpenTextDocumentNotification.type; } fillClientCapabilities(capabilities) { ensure(ensure(capabilities, 'textDocument'), 'synchronization').dynamicRegistration = true; } initialize(capabilities, documentSelector) { let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync; if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.openClose) { this.register(this.messages, { id: UUID.generateUuid(), registerOptions: { documentSelector: documentSelector } }); } } register(message, data) { super.register(message, data); if (!data.registerOptions.documentSelector) { return; } let documentSelector = data.registerOptions.documentSelector; workspace_1.default.textDocuments.forEach(textDocument => { let uri = textDocument.uri.toString(); if (this._syncedDocuments.has(uri)) { return; } if (workspace_1.default.match(documentSelector, textDocument) > 0) { let middleware = this._client.clientOptions.middleware; let didOpen = (textDocument) => { this._client.sendNotification(this._type, this._createParams(textDocument)); }; if (middleware.didOpen) { middleware.didOpen(textDocument, didOpen); } else { didOpen(textDocument); } this._syncedDocuments.set(uri, textDocument); } }); } notificationSent(textDocument) { super.notificationSent(textDocument); this._syncedDocuments.set(textDocument.uri.toString(), textDocument); } } class DidCloseTextDocumentFeature extends DocumentNotifiactions { constructor(client, _syncedDocuments) { super(client, workspace_1.default.onDidCloseTextDocument, vscode_languageserver_protocol_1.DidCloseTextDocumentNotification.type, client.clientOptions.middleware.didClose, (textDocument) => cv.asCloseTextDocumentParams(textDocument), DocumentNotifiactions.textDocumentFilter); this._syncedDocuments = _syncedDocuments; } get messages() { return vscode_languageserver_protocol_1.DidCloseTextDocumentNotification.type; } fillClientCapabilities(capabilities) { ensure(ensure(capabilities, 'textDocument'), 'synchronization').dynamicRegistration = true; } initialize(capabilities, documentSelector) { let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync; if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.openClose) { this.register(this.messages, { id: UUID.generateUuid(), registerOptions: { documentSelector: documentSelector } }); } } notificationSent(textDocument) { super.notificationSent(textDocument); this._syncedDocuments.delete(textDocument.uri.toString()); } unregister(id) { let selector = this._selectors.get(id); // The super call removed the selector from the map // of selectors. super.unregister(id); let selectors = this._selectors.values(); this._syncedDocuments.forEach(textDocument => { if (workspace_1.default.match(selector, textDocument) > 0 && !this._selectorFilter(selectors, textDocument)) { let middleware = this._client.clientOptions.middleware; let didClose = (textDocument) => { this._client.sendNotification(this._type, this._createParams(textDocument)); }; this._syncedDocuments.delete(textDocument.uri.toString()); if (middleware.didClose) { middleware.didClose(textDocument, didClose); } else { didClose(textDocument); } } }); } } class DidChangeTextDocumentFeature { constructor(_client) { this._client = _client; this._changeData = new Map(); } get messages() { return vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type; } fillClientCapabilities(capabilities) { ensure(ensure(capabilities, 'textDocument'), 'synchronization').dynamicRegistration = true; } initialize(capabilities, documentSelector) { let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync; if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.change != null && textDocumentSyncOptions.change !== vscode_languageserver_protocol_1.TextDocumentSyncKind.None) { this.register(this.messages, { id: UUID.generateUuid(), registerOptions: Object.assign({}, { documentSelector: documentSelector }, { syncKind: textDocumentSyncOptions.change }) }); } } register(_message, data) { if (!data.registerOptions.documentSelector) { return; } if (!this._listener) { this._listener = workspace_1.default.onDidChangeTextDocument(this.callback, this); } this._changeData.set(data.id, { documentSelector: data.registerOptions.documentSelector, syncKind: data.registerOptions.syncKind }); } callback(event) { // Text document changes are send for dirty changes as well. We don't // have dirty / undirty events in the LSP so we ignore content changes // with length zero. if (event.contentChanges.length === 0) { return; } let doc = workspace_1.default.getDocument(event.textDocument.uri); if (!doc) return; let { textDocument } = doc; for (const changeData of this._changeData.values()) { if (workspace_1.default.match(changeData.documentSelector, textDocument) > 0) { let middleware = this._client.clientOptions.middleware; if (changeData.syncKind === vscode_languageserver_protocol_1.TextDocumentSyncKind.Incremental) { if (middleware.didChange) { middleware.didChange(event, () => this._client.sendNotification(vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type, event)); } else { this._client.sendNotification(vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type, event); } } else if (changeData.syncKind === vscode_languageserver_protocol_1.TextDocumentSyncKind.Full) { let didChange = event => { let { textDocument } = workspace_1.default.getDocument(event.textDocument.uri); this._client.sendNotification(vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type, cv.asChangeTextDocumentParams(textDocument)); }; if (middleware.didChange) { middleware.didChange(event, didChange); } else { didChange(event); } } } } } unregister(id) { this._changeData.delete(id); if (this._changeData.size === 0 && this._listener) { this._listener.dispose(); this._listener = undefined; } } dispose() { this._changeData.clear(); if (this._listener) { this._listener.dispose(); this._listener = undefined; } } } class WillSaveFeature extends DocumentNotifiactions { constructor(client) { super(client, workspace_1.default.onWillSaveTextDocument, vscode_languageserver_protocol_1.WillSaveTextDocumentNotification.type, client.clientOptions.middleware.willSave, willSaveEvent => cv.asWillSaveTextDocumentParams(willSaveEvent), (selectors, willSaveEvent) => DocumentNotifiactions.textDocumentFilter(selectors, willSaveEvent.document)); } get messages() { return vscode_languageserver_protocol_1.WillSaveTextDocumentNotification.type; } fillClientCapabilities(capabilities) { let value = ensure(ensure(capabilities, 'textDocument'), 'synchronization'); value.willSave = true; } initialize(capabilities, documentSelector) { let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync; if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.willSave) { this.register(this.messages, { id: UUID.generateUuid(), registerOptions: { documentSelector: documentSelector } }); } } } class WillSaveWaitUntilFeature { constructor(_client) { this._client = _client; this._selectors = new Map(); } get messages() { return vscode_languageserver_protocol_1.WillSaveTextDocumentWaitUntilRequest.type; } fillClientCapabilities(capabilities) { let value = ensure(ensure(capabilities, 'textDocument'), 'synchronization'); value.willSaveWaitUntil = true; } initialize(capabilities, documentSelector) { let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync; if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.willSaveWaitUntil) { this.register(this.messages, { id: UUID.generateUuid(), registerOptions: { documentSelector: documentSelector } }); } } register(_message, data) { if (!data.registerOptions.documentSelector) { return; } if (!this._listener) { this._listener = workspace_1.default.onWillSaveUntil(this.callback, this, this._client.id); } this._selectors.set(data.id, data.registerOptions.documentSelector); } callback(event) { if (DocumentNotifiactions.textDocumentFilter(this._selectors.values(), event.document)) { let middleware = this._client.clientOptions.middleware; let willSaveWaitUntil = (event) => { return this._client .sendRequest(vscode_languageserver_protocol_1.WillSaveTextDocumentWaitUntilRequest.type, cv.asWillSaveTextDocumentParams(event)) .then(edits => { return edits ? edits : []; }, e => { workspace_1.default.showMessage(`Error on willSaveWaitUntil: ${e}`, 'error'); logger.error(e); return []; }); }; event.waitUntil(middleware.willSaveWaitUntil ? middleware.willSaveWaitUntil(event, willSaveWaitUntil) : willSaveWaitUntil(event)); } } unregister(id) { this._selectors.delete(id); if (this._selectors.size === 0 && this._listener) { this._listener.dispose(); this._listener = undefined; } } dispose() { this._selectors.clear(); if (this._listener) { this._listener.dispose(); this._listener = undefined; } } } class DidSaveTextDocumentFeature extends DocumentNotifiactions { constructor(client) { super(client, workspace_1.default.onDidSaveTextDocument, vscode_languageserver_protocol_1.DidSaveTextDocumentNotification.type, client.clientOptions.middleware.didSave, textDocument => cv.asSaveTextDocumentParams(textDocument, this._includeText), DocumentNotifiactions.textDocumentFilter); } get messages() { return vscode_languageserver_protocol_1.DidSaveTextDocumentNotification.type; } fillClientCapabilities(capabilities) { ensure(ensure(capabilities, 'textDocument'), 'synchronization').didSave = true; } initialize(capabilities, documentSelector) { let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync; if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.save) { this.register(this.messages, { id: UUID.generateUuid(), registerOptions: Object.assign({}, { documentSelector: documentSelector }, { includeText: !!textDocumentSyncOptions.save.includeText }) }); } } register(method, data) { this._includeText = !!data.registerOptions.includeText; super.register(method, data); } } class FileSystemWatcherFeature { constructor(_client, _notifyFileEvent) { this._notifyFileEvent = _notifyFileEvent; this._watchers = new Map(); } get messages() { return vscode_languageserver_protocol_1.DidChangeWatchedFilesNotification.type; } fillClientCapabilities(capabilities) { ensure(ensure(capabilities, 'workspace'), 'didChangeWatchedFiles').dynamicRegistration = true; } initialize(_capabilities, _documentSelector) { } register(_method, data) { if (!Array.isArray(data.registerOptions.watchers)) { return; } let disposables = []; for (let watcher of data.registerOptions.watchers) { if (!Is.string(watcher.globPattern)) { continue; } let watchCreate = true, watchChange = true, watchDelete = true; if (watcher.kind != null) { watchCreate = (watcher.kind & vscode_languageserver_protocol_1.WatchKind.Create) !== 0; watchChange = (watcher.kind & vscode_languageserver_protocol_1.WatchKind.Change) != 0; watchDelete = (watcher.kind & vscode_languageserver_protocol_1.WatchKind.Delete) != 0; } let fileSystemWatcher = workspace_1.default.createFileSystemWatcher(watcher.globPattern, !watchCreate, !watchChange, !watchDelete); this.hookListeners(fileSystemWatcher, watchCreate, watchChange, watchDelete, disposables); disposables.push(fileSystemWatcher); } this._watchers.set(data.id, disposables); } registerRaw(id, fileSystemWatchers) { let disposables = []; for (let fileSystemWatcher of fileSystemWatchers) { disposables.push(fileSystemWatcher); this.hookListeners(fileSystemWatcher, true, true, true, disposables); } this._watchers.set(id, disposables); } hookListeners(fileSystemWatcher, watchCreate, watchChange, watchDelete, listeners) { if (watchCreate) { fileSystemWatcher.onDidCreate(resource => this._notifyFileEvent({ uri: cv.asUri(resource), type: vscode_languageserver_protocol_1.FileChangeType.Created }), null, listeners); } if (watchChange) { fileSystemWatcher.onDidChange(resource => this._notifyFileEvent({ uri: cv.asUri(resource), type: vscode_languageserver_protocol_1.FileChangeType.Changed }), null, listeners); } if (watchDelete) { fileSystemWatcher.onDidDelete(resource => this._notifyFileEvent({ uri: cv.asUri(resource), type: vscode_languageserver_protocol_1.FileChangeType.Deleted }), null, listeners); } } unregister(id) { let disposables = this._watchers.get(id); if (disposables) { for (let disposable of disposables) { disposable.dispose(); } } } dispose() { this._watchers.forEach(disposables => { for (let disposable of disposables) { disposable.dispose(); } }); this._watchers.clear(); } } class TextDocumentFeature { constructor(_client, _message) { this._client = _client; this._message = _message; this._providers = new Map(); } get messages() { return this._message; } register(message, data) { if (message.method !== this.messages.method) { throw new Error(`Register called on wrong feature. Requested ${message.method} but reached feature ${this.messages.method}`); } if (!data.registerOptions.documentSelector) { return; } let provider = this.registerLanguageProvider(data.registerOptions); if (provider) { this._providers.set(data.id, provider); } } unregister(id) { let provider = this._providers.get(id); if (provider) { provider.dispose(); } } dispose() { this._providers.forEach(value => { value.dispose(); }); this._providers.clear(); } } exports.TextDocumentFeature = TextDocumentFeature; class WorkspaceFeature { constructor(_client, _message) { this._client = _client; this._message = _message; this._providers = new Map(); } get messages() { return this._message; } register(message, data) { if (message.method !== this.messages.method) { throw new Error(`Register called on wrong feature. Requested ${message.method} but reached feature ${this.messages.method}`); } let provider = this.registerLanguageProvider(data.registerOptions); if (provider) { this._providers.set(data.id, provider); } } unregister(id) { let provider = this._providers.get(id); if (provider) { provider.dispose(); } } dispose() { this._providers.forEach(value => { value.dispose(); }); this._providers.clear(); } } class CompletionItemFeature extends TextDocumentFeature { constructor(client) { super(client, vscode_languageserver_protocol_1.CompletionRequest.type); } fillClientCapabilities(capabilites) { let completion = ensure(ensure(capabilites, 'textDocument'), 'completion'); completion.dynamicRegistration = true; completion.contextSupport = true; completion.completionItem = { snippetSupport: true, commitCharactersSupport: true, documentationFormat: [vscode_languageserver_protocol_1.MarkupKind.Markdown, vscode_languageserver_protocol_1.MarkupKind.PlainText], deprecatedSupport: true, preselectSupport: true }; completion.completionItemKind = { valueSet: SupportedCompletionItemKinds }; } initialize(capabilities, documentSelector) { if (!capabilities.completionProvider || !documentSelector) { return; } this.register(this.messages, { id: UUID.generateUuid(), registerOptions: Object.assign({}, { documentSelector: documentSelector }, capabilities.completionProvider) }); } registerLanguageProvider(options) { let triggerCharacters = options.triggerCharacters || []; let client = this._client; let provideCompletionItems = (document, position, context, token) => { return client .sendRequest(vscode_languageserver_protocol_1.CompletionRequest.type, cv.asCompletionParams(document, position, context), token) .then(result => { // logger.debug('result', result) return result; }, error => { client.logFailedRequest(vscode_languageserver_protocol_1.CompletionRequest.type, error); return Promise.resolve([]); }); }; let resolveCompletionItem = (item, token) => { return client .sendRequest(vscode_languageserver_protocol_1.CompletionResolveRequest.type, item, token) .then(res => res, error => { client.logFailedRequest(vscode_languageserver_protocol_1.CompletionResolveRequest.type, error); return Promise.resolve(item); }); }; let middleware = this._client.clientOptions.middleware; let languageIds = cv.asLanguageIds(options.documentSelector); return languages_1.default.registerCompletionItemProvider(this._client.id, 'LS', languageIds, { provideCompletionItems: (document, position, token, context) => { return middleware.provideCompletionItem ? middleware.provideCompletionItem(document, position, context, token, provideCompletionItems) : provideCompletionItems(document, position, context, token); }, resolveCompletionItem: options.resolveProvider ? (item, token) => { return middleware.resolveCompletionItem ? middleware.resolveCompletionItem(item, token, resolveCompletionItem) : resolveCompletionItem(item, token); } : undefined }, triggerCharacters); } } class HoverFeature extends TextDocumentFeature { constructor(client) { super(client, vscode_languageserver_protocol_1.HoverRequest.type); } fillClientCapabilities(capabilites) { const hoverCapability = ensure(ensure(capabilites, 'textDocument'), 'hover'); hoverCapability.dynamicRegistration = true; hoverCapability.contentFormat = [vscode_languageserver_protocol_1.MarkupKind.Markdown, vscode_languageserver_protocol_1.MarkupKind.PlainText]; } initialize(capabilities, documentSelector) { if (!capabilities.hoverProvider || !documentSelector) { return; } this.register(this.messages, { id: UUID.generateUuid(), registerOptions: Object.assign({}, { documentSelector: documentSelector }) }); } registerLanguageProvider(options) { let client = this._client; let provideHover = (document, position, token) => { return client .sendRequest(vscode_languageserver_protocol_1.HoverRequest.type, cv.asTextDocumentPositionParams(document, position), token) .then(res => res, error => { client.logFailedRequest(vscode_languageserver_protocol_1.HoverRequest.type, error); return Promise.resolve(null); }); }; let middleware = client.clientOptions.middleware; return languages_1.default.registerHoverProvider(options.documentSelector, { provideHover: (document, position, token) => { return middleware.provideHover ? middleware.provideHover(document, position, token, provideHover) : provideHover(document, position, token); } }); } } class SignatureHelpFeature extends TextDocumentFeature { constructor(client) { super(client, vscode_languageserver_protocol_1.SignatureHelpRequest.type); } fillClientCapabilities(capabilites) { let config = ensure(ensure(capabilites, 'textDocument'), 'signatureHelp'); config.dynamicRegistration = true; config.signatureInformation = { documentationFormat: [vscode_languageserver_protocol_1.MarkupKind.Markdown, vscode_languageserver_protocol_1.MarkupKind.PlainText], parameterInformation: { labelOffsetSupport: true } }; } initialize(capabilities, documentSelector) { if (!capabilities.signatureHelpProvider || !documentSelector) { return; } this.register(this.messages, { id: UUID.generateUuid(), registerOptions: Object.assign({}, { documentSelector: documentSelector }, capabilities.signatureHelpProvider) }); } registerLanguageProvider(options) { let client = this._client; let providerSignatureHelp = (document, position, token) => { return client .sendRequest(vscode_languageserver_protocol_1.SignatureHelpRequest.type, cv.asTextDocumentPositionParams(document, position), token) .then(res => res, error => { client.logFailedRequest(vscode_languageserver_protocol_1.SignatureHelpRequest.type, error); return Promise.resolve(null); }); }; let middleware = client.clientOptions.middleware; let triggerCharacters = options.triggerCharacters || []; return languages_1.default.registerSignatureHelpProvider(options.documentSelector, { provideSignatureHelp: (document, position, token) => { return middleware.provideSignatureHelp ? middleware.provideSignatureHelp(document, position, token, providerSignatureHelp) : providerSignatureHelp(document, position, token); } }, triggerCharacters); } } class DefinitionFeature extends TextDocumentFeature { constructor(client) { super(client, vscode_languageserver_protocol_1.DefinitionRequest.type); } fillClientCapabilities(capabilites) { let definitionSupport = ensure(ensure(capabilites, 'textDocument'), 'definition'); definitionSupport.dynamicRegistration = true; // definitionSupport.linkSupport = true } initialize(capabilities, documentSelector) { if (!capabilities.definitionProvider || !documentSelector) { return; } this.register(this.messages, { id: UUID.generateUuid(), registerOptions: Object.assign({}, { documentSelector: documentSelector }) }); } registerLanguageProvider(options) { let client = this._client; let provideDefinition = (document, position, token) => { return client .sendRequest(vscode_languageserver_protocol_1.DefinitionRequest.type, cv.asTextDocumentPositionParams(document, position), token) .then(res => res, error => { client.logFailedRequest(vscode_languageserver_protocol_1.DefinitionRequest.type, error); return Promise.resolve(null); }); }; let middleware = client.clientOptions.middleware; return languages_1.default.registerDefinitionProvider(options.documentSelector, { provideDefinition: (document, position, token) => { return middleware.provideDefinition ? middleware.provideDefinition(document, position, token, provideDefinition) : provideDefinition(document, position, token); } }); } } class ReferencesFeature extends TextDocumentFeature { constructor(client) { super(client, vscode_languageserver_protocol_1.ReferencesRequest.type); } fillClientCapabilities(capabilites) { ensure(ensure(capabilites, 'textDocument'), 'references').dynamicRegistration = true; } initialize(capabilities, documentSelector) { if (!capabilities.referencesProvider || !documentSelector) { return; } this.register(this.messages, { id: UUID.generateUuid(), registerOptions: Object.assign({}, { documentSelector: documentSelector }) }); } registerLanguageProvider(options) { let client = this._client; let providerReferences = (document, position, options, token) => { return client .sendRequest(vscode_languageserver_protocol_1.ReferencesRequest.type, cv.asReferenceParams(document, position, options), token) .then(res => res, error => { client.logFailedRequest(vscode_languageserver_protocol_1.ReferencesRequest.type, error); return Promise.resolve([]); }); }; let middleware = client.clientOptions.middleware; return languages_1.default.registerReferencesProvider(options.documentSelector, { provideReferences: (document, position, options, token) => { return middleware.provideReferences ? middleware.provideReferences(document, position, options, token, providerReferences) : providerReferences(document, position, options, token); } }); } } class DocumentHighlightFeature extends TextDocumentFeature { constructor(client) { super(client, vscode_languageserver_protocol_1.DocumentHighlightRequest.type); } fillClientCapabilities(capabilites) { ensure(ensure(capabilites, 'textDocument'), 'documentHighlight').dynamicRegistration = true; } initialize(capabilities, documentSelector) { if (!capabilities.documentHighlightProvider || !documentSelector) { return; } this.register(this.messages, { id: UUID.generateUuid(), registerOptions: Object.assign({}, { documentSelector: documentSelector }) }); } registerLanguageProvider(options) { let client = this._client; let provideDocumentHighlights = (document, position, token) => { return client .sendRequest(vscode_languageserver_protocol_1.DocumentHighlightRequest.type, cv.asTextDocumentPositionParams(document, position), token) .then(res => res, error => { client.logFailedRequest(vscode_languageserver_protocol_1.DocumentHighlightRequest.type, error); return Promise.resolve([]); }); }; let middleware = client.clientOptions.middleware; return languages_1.default.registerDocumentHighlightProvider(options.documentSelector, { provideDocumentHighlights: (document, position, token) => { return middleware.provideDocumentHighlights ? middleware.provideDocumentHighlights(document, position, token, provideDocumentHighlights) : provideDocumentHighlights(document, position, token); } }); } } class DocumentSymbolFeature extends TextDocumentFeature { constructor(client) { super(client, vscode_languageserver_protocol_1.DocumentSymbolRequest.type); } fillClientCapabilities(capabilites) { let symbolCapabilities = ensure(ensure(capabilites, 'textDocument'), 'documentSymbol'); symbolCapabilities.dynamicRegistration = true; symbolCapabilities.symbolKind = { valueSet: SupporedSymbolKinds }; } initialize(capabilities, documentSelector) { if (!capabilities.documentSymbolProvider || !documentSelector) { return; } this.register(this.messages, { id: UUID.generateUuid(), registerOptions: Object.assign({}, { documentSelector: documentSelector }) }); } registerLanguageProvider(options) { let client = this._client; let provideDocumentSymbols = (document, token) => { return client .sendRequest(vscode_languageserver_protocol_1.DocumentSymbolRequest.type, cv.asDocumentSymbolParams(document), token) .then(res => res, error => { client.logFailedRequest(vscode_languageserver_protocol_1.DocumentSymbolRequest.type, error); return Promise.resolve([]); }); }; let middleware = client.clientOptions.middleware; return languages_1.default.registerDocumentSymbolProvider(options.documentSelector, { provideDocumentSymbols: (document, token) => { return middleware.provideDocumentSymbols ? middleware.provideDocumentSymbols(document, token, provideDocumentSymbols) : provideDocumentSymbols(document, token); } }); } } class WorkspaceSymbolFeature extends WorkspaceFeature { constructor(client) { super(client, vscode_languageserver_protocol_1.WorkspaceSymbolRequest.type); } fillClientCapabilities(capabilites) { let symbolCapabilities = ensure(ensure(capabilites, 'workspace'), 'symbol'); symbolCapabilities.dynamicRegistration = true; symbolCapabilities.symbolKind = { valueSet: SupporedSymbolKinds }; } initialize(capabilities, documentSelector) { if (!capabilities.workspaceSymbolProvider) { return; } this.register(this.messages, { id: UUID.generateUuid(), registerOptions: Object.assign({}, { documentSelector: documentSelector }) }); } registerLanguageProvider(options) { let client = this._client; let provideWorkspaceSymbols = (query, token) => { return client .sendRequest(vscode_languageserver_protocol_1.WorkspaceSymbolRequest.type, { query }, token) .then(res => res, error => { client.logFailedRequest(vscode_languageserver_protocol_1.WorkspaceSymbolRequest.type, error); return Promise.resolve([]); }); }; let middleware = client.clientOptions.middleware; return languages_1.default.registerWorkspaceSymbolProvider(options.documentSelector, { provideWorkspaceSymbols: (query, token) => { return middleware.provideWorkspaceSymbols ? middleware.provideWorkspaceSymbols(query, token, provideWorkspaceSymbols) : provideWorkspaceSymbols(query, token); } }); } } class CodeActionFeature extends TextDocumentFeature { constructor(client) { super(client, vscode_languageserver_protocol_1.CodeActionRequest.type); } fillClientCapabilities(capabilites) { const cap = ensure(ensure(capabilites, 'textDocument'), 'codeAction'); cap.dynamicRegistration = true; cap.codeActionLiteralSupport = { codeActionKind: { valueSet: [ '', vscode_languageserver_protocol_1.CodeActionKind.QuickFix, vscode_languageserver_protocol_1.CodeActionKind.Refactor, vscode_languageserver_protocol_1.CodeActionKind.RefactorExtract, vscode_languageserver_protocol_1.CodeActionKind.RefactorInline, vscode_languageserver_protocol_1.CodeActionKind.RefactorRewrite, vscode_languageserver_protocol_1.CodeActionKind.Source, vscode_languageserver_protocol_1.CodeActionKind.SourceOrganizeImports ] } }; } initialize(capabilities, documentSelector) { if (!capabilities.codeActionProvider || !documentSelector) { return; } let codeActionKinds; if (!Is.boolean(capabilities.codeActionProvider)) { codeActionKinds = capabilities.codeActionProvider.codeActionKinds; } this.register(this.messages, { id: UUID.generateUuid(), registerOptions: Object.assign({}, { documentSelector: documentSelector, codeActionKinds }) }); } registerLanguageProvider(options) { let client = this._client; let provideCodeActions = (document, range, context, token) => { let params = { textDocument: { uri: document.uri }, range, context, }; return