2673 lines
122 KiB
JavaScript
2673 lines
122 KiB
JavaScript
"use strict";
|
|
/* --------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
* ------------------------------------------------------------------------------------------ */
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.BaseLanguageClient = exports.MessageTransports = exports.TextDocumentFeature = exports.State = exports.RevealOutputChannelOn = exports.CloseAction = exports.ErrorAction = void 0;
|
|
const vscode_1 = require("vscode");
|
|
const vscode_languageserver_protocol_1 = require("vscode-languageserver-protocol");
|
|
const configuration_1 = require("./configuration");
|
|
const c2p = require("./codeConverter");
|
|
const p2c = require("./protocolConverter");
|
|
const Is = require("./utils/is");
|
|
const async_1 = require("./utils/async");
|
|
const UUID = require("./utils/uuid");
|
|
const progressPart_1 = require("./progressPart");
|
|
class ConsoleLogger {
|
|
error(message) {
|
|
vscode_languageserver_protocol_1.RAL().console.error(message);
|
|
}
|
|
warn(message) {
|
|
vscode_languageserver_protocol_1.RAL().console.warn(message);
|
|
}
|
|
info(message) {
|
|
vscode_languageserver_protocol_1.RAL().console.info(message);
|
|
}
|
|
log(message) {
|
|
vscode_languageserver_protocol_1.RAL().console.log(message);
|
|
}
|
|
}
|
|
function createConnection(input, output, errorHandler, closeHandler, options) {
|
|
let logger = new ConsoleLogger();
|
|
let connection = vscode_languageserver_protocol_1.createProtocolConnection(input, output, logger, options);
|
|
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),
|
|
onProgress: connection.onProgress,
|
|
sendProgress: connection.sendProgress,
|
|
trace: (value, tracer, sendNotificationOrTraceOptions) => {
|
|
const defaultTraceOptions = {
|
|
sendNotification: false,
|
|
traceFormat: vscode_languageserver_protocol_1.TraceFormat.Text
|
|
};
|
|
if (sendNotificationOrTraceOptions === undefined) {
|
|
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),
|
|
end: () => connection.end(),
|
|
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, maxRestartCount) {
|
|
this.name = name;
|
|
this.maxRestartCount = maxRestartCount;
|
|
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 <= this.maxRestartCount) {
|
|
return CloseAction.Restart;
|
|
}
|
|
else {
|
|
let diff = this.restarts[this.restarts.length - 1] - this.restarts[0];
|
|
if (diff <= 3 * 60 * 1000) {
|
|
vscode_1.window.showErrorMessage(`The ${this.name} server crashed ${this.maxRestartCount + 1} 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["Starting"] = 3] = "Starting";
|
|
State[State["Running"] = 2] = "Running";
|
|
})(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 || (ClientState = {}));
|
|
const SupportedSymbolKinds = [
|
|
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
|
|
];
|
|
const SupportedSymbolTags = [
|
|
vscode_languageserver_protocol_1.SymbolTag.Deprecated
|
|
];
|
|
function ensure(target, key) {
|
|
if (target[key] === undefined) {
|
|
target[key] = {};
|
|
}
|
|
return target[key];
|
|
}
|
|
var FileFormattingOptions;
|
|
(function (FileFormattingOptions) {
|
|
function fromConfiguration(document) {
|
|
const filesConfig = vscode_1.workspace.getConfiguration('files', document);
|
|
return {
|
|
trimTrailingWhitespace: filesConfig.get('trimTrailingWhitespace'),
|
|
trimFinalNewlines: filesConfig.get('trimFinalNewlines'),
|
|
insertFinalNewline: filesConfig.get('insertFinalNewline'),
|
|
};
|
|
}
|
|
FileFormattingOptions.fromConfiguration = fromConfiguration;
|
|
})(FileFormattingOptions || (FileFormattingOptions = {}));
|
|
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.registrationType !== undefined;
|
|
}
|
|
DynamicFeature.is = is;
|
|
})(DynamicFeature || (DynamicFeature = {}));
|
|
class DocumentNotifications {
|
|
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 (vscode_1.languages.match(selector, textDocument)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
register(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;
|
|
}
|
|
}
|
|
getProvider(document) {
|
|
for (const selector of this._selectors.values()) {
|
|
if (vscode_1.languages.match(selector, document)) {
|
|
return {
|
|
send: (data) => {
|
|
this.callback(data);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
}
|
|
class DidOpenTextDocumentFeature extends DocumentNotifications {
|
|
constructor(client, _syncedDocuments) {
|
|
super(client, vscode_1.workspace.onDidOpenTextDocument, vscode_languageserver_protocol_1.DidOpenTextDocumentNotification.type, client.clientOptions.middleware.didOpen, (textDocument) => client.code2ProtocolConverter.asOpenTextDocumentParams(textDocument), DocumentNotifications.textDocumentFilter);
|
|
this._syncedDocuments = _syncedDocuments;
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'textDocument'), 'synchronization').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync;
|
|
if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.openClose) {
|
|
this.register({ id: UUID.generateUuid(), registerOptions: { documentSelector: documentSelector } });
|
|
}
|
|
}
|
|
get registrationType() {
|
|
return vscode_languageserver_protocol_1.DidOpenTextDocumentNotification.type;
|
|
}
|
|
register(data) {
|
|
super.register(data);
|
|
if (!data.registerOptions.documentSelector) {
|
|
return;
|
|
}
|
|
let documentSelector = data.registerOptions.documentSelector;
|
|
vscode_1.workspace.textDocuments.forEach((textDocument) => {
|
|
let uri = textDocument.uri.toString();
|
|
if (this._syncedDocuments.has(uri)) {
|
|
return;
|
|
}
|
|
if (vscode_1.languages.match(documentSelector, textDocument)) {
|
|
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 DocumentNotifications {
|
|
constructor(client, _syncedDocuments) {
|
|
super(client, vscode_1.workspace.onDidCloseTextDocument, vscode_languageserver_protocol_1.DidCloseTextDocumentNotification.type, client.clientOptions.middleware.didClose, (textDocument) => client.code2ProtocolConverter.asCloseTextDocumentParams(textDocument), DocumentNotifications.textDocumentFilter);
|
|
this._syncedDocuments = _syncedDocuments;
|
|
}
|
|
get registrationType() {
|
|
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({ 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 (vscode_1.languages.match(selector, textDocument) && !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();
|
|
this._forcingDelivery = false;
|
|
}
|
|
get registrationType() {
|
|
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 !== undefined && textDocumentSyncOptions.change !== vscode_languageserver_protocol_1.TextDocumentSyncKind.None) {
|
|
this.register({
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector }, { syncKind: textDocumentSyncOptions.change })
|
|
});
|
|
}
|
|
}
|
|
register(data) {
|
|
if (!data.registerOptions.documentSelector) {
|
|
return;
|
|
}
|
|
if (!this._listener) {
|
|
this._listener = vscode_1.workspace.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 / un-dirty events in the LSP so we ignore content changes
|
|
// with length zero.
|
|
if (event.contentChanges.length === 0) {
|
|
return;
|
|
}
|
|
for (const changeData of this._changeData.values()) {
|
|
if (vscode_1.languages.match(changeData.documentSelector, event.document)) {
|
|
let middleware = this._client.clientOptions.middleware;
|
|
if (changeData.syncKind === vscode_languageserver_protocol_1.TextDocumentSyncKind.Incremental) {
|
|
let params = this._client.code2ProtocolConverter.asChangeTextDocumentParams(event);
|
|
if (middleware.didChange) {
|
|
middleware.didChange(event, () => this._client.sendNotification(vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type, params));
|
|
}
|
|
else {
|
|
this._client.sendNotification(vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type, params);
|
|
}
|
|
}
|
|
else if (changeData.syncKind === vscode_languageserver_protocol_1.TextDocumentSyncKind.Full) {
|
|
let didChange = (event) => {
|
|
if (this._changeDelayer) {
|
|
if (this._changeDelayer.uri !== event.document.uri.toString()) {
|
|
// Use this force delivery to track boolean state. Otherwise we might call two times.
|
|
this.forceDelivery();
|
|
this._changeDelayer.uri = event.document.uri.toString();
|
|
}
|
|
this._changeDelayer.delayer.trigger(() => {
|
|
this._client.sendNotification(vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type, this._client.code2ProtocolConverter.asChangeTextDocumentParams(event.document));
|
|
});
|
|
}
|
|
else {
|
|
this._changeDelayer = {
|
|
uri: event.document.uri.toString(),
|
|
delayer: new async_1.Delayer(200)
|
|
};
|
|
this._changeDelayer.delayer.trigger(() => {
|
|
this._client.sendNotification(vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type, this._client.code2ProtocolConverter.asChangeTextDocumentParams(event.document));
|
|
}, -1);
|
|
}
|
|
};
|
|
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._changeDelayer = undefined;
|
|
this._forcingDelivery = false;
|
|
this._changeData.clear();
|
|
if (this._listener) {
|
|
this._listener.dispose();
|
|
this._listener = undefined;
|
|
}
|
|
}
|
|
forceDelivery() {
|
|
if (this._forcingDelivery || !this._changeDelayer) {
|
|
return;
|
|
}
|
|
try {
|
|
this._forcingDelivery = true;
|
|
this._changeDelayer.delayer.forceDelivery();
|
|
}
|
|
finally {
|
|
this._forcingDelivery = false;
|
|
}
|
|
}
|
|
getProvider(document) {
|
|
for (const changeData of this._changeData.values()) {
|
|
if (vscode_1.languages.match(changeData.documentSelector, document)) {
|
|
return {
|
|
send: (event) => {
|
|
this.callback(event);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
}
|
|
class WillSaveFeature extends DocumentNotifications {
|
|
constructor(client) {
|
|
super(client, vscode_1.workspace.onWillSaveTextDocument, vscode_languageserver_protocol_1.WillSaveTextDocumentNotification.type, client.clientOptions.middleware.willSave, (willSaveEvent) => client.code2ProtocolConverter.asWillSaveTextDocumentParams(willSaveEvent), (selectors, willSaveEvent) => DocumentNotifications.textDocumentFilter(selectors, willSaveEvent.document));
|
|
}
|
|
get registrationType() {
|
|
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({
|
|
id: UUID.generateUuid(),
|
|
registerOptions: { documentSelector: documentSelector }
|
|
});
|
|
}
|
|
}
|
|
}
|
|
class WillSaveWaitUntilFeature {
|
|
constructor(_client) {
|
|
this._client = _client;
|
|
this._selectors = new Map();
|
|
}
|
|
get registrationType() {
|
|
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({
|
|
id: UUID.generateUuid(),
|
|
registerOptions: { documentSelector: documentSelector }
|
|
});
|
|
}
|
|
}
|
|
register(data) {
|
|
if (!data.registerOptions.documentSelector) {
|
|
return;
|
|
}
|
|
if (!this._listener) {
|
|
this._listener = vscode_1.workspace.onWillSaveTextDocument(this.callback, this);
|
|
}
|
|
this._selectors.set(data.id, data.registerOptions.documentSelector);
|
|
}
|
|
callback(event) {
|
|
if (DocumentNotifications.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, this._client.code2ProtocolConverter.asWillSaveTextDocumentParams(event)).then((edits) => {
|
|
let vEdits = this._client.protocol2CodeConverter.asTextEdits(edits);
|
|
return vEdits === undefined ? [] : vEdits;
|
|
});
|
|
};
|
|
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 DocumentNotifications {
|
|
constructor(client) {
|
|
super(client, vscode_1.workspace.onDidSaveTextDocument, vscode_languageserver_protocol_1.DidSaveTextDocumentNotification.type, client.clientOptions.middleware.didSave, (textDocument) => client.code2ProtocolConverter.asSaveTextDocumentParams(textDocument, this._includeText), DocumentNotifications.textDocumentFilter);
|
|
this._includeText = false;
|
|
}
|
|
get registrationType() {
|
|
return vscode_languageserver_protocol_1.DidSaveTextDocumentNotification.type;
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'textDocument'), 'synchronization').didSave = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
const textDocumentSyncOptions = capabilities.resolvedTextDocumentSync;
|
|
if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.save) {
|
|
const saveOptions = typeof textDocumentSyncOptions.save === 'boolean'
|
|
? { includeText: false }
|
|
: { includeText: !!textDocumentSyncOptions.save.includeText };
|
|
this.register({
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, { documentSelector: documentSelector }, saveOptions)
|
|
});
|
|
}
|
|
}
|
|
register(data) {
|
|
this._includeText = !!data.registerOptions.includeText;
|
|
super.register(data);
|
|
}
|
|
}
|
|
class FileSystemWatcherFeature {
|
|
constructor(_client, _notifyFileEvent) {
|
|
this._client = _client;
|
|
this._notifyFileEvent = _notifyFileEvent;
|
|
this._watchers = new Map();
|
|
}
|
|
get registrationType() {
|
|
return vscode_languageserver_protocol_1.DidChangeWatchedFilesNotification.type;
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'workspace'), 'didChangeWatchedFiles').dynamicRegistration = true;
|
|
}
|
|
initialize(_capabilities, _documentSelector) {
|
|
}
|
|
register(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 !== undefined && 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 = vscode_1.workspace.createFileSystemWatcher(watcher.globPattern, !watchCreate, !watchChange, !watchDelete);
|
|
this.hookListeners(fileSystemWatcher, watchCreate, watchChange, watchDelete);
|
|
disposables.push(fileSystemWatcher);
|
|
}
|
|
this._watchers.set(data.id, disposables);
|
|
}
|
|
registerRaw(id, fileSystemWatchers) {
|
|
let disposables = [];
|
|
for (let fileSystemWatcher of fileSystemWatchers) {
|
|
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: this._client.code2ProtocolConverter.asUri(resource),
|
|
type: vscode_languageserver_protocol_1.FileChangeType.Created
|
|
}), null, listeners);
|
|
}
|
|
if (watchChange) {
|
|
fileSystemWatcher.onDidChange((resource) => this._notifyFileEvent({
|
|
uri: this._client.code2ProtocolConverter.asUri(resource),
|
|
type: vscode_languageserver_protocol_1.FileChangeType.Changed
|
|
}), null, listeners);
|
|
}
|
|
if (watchDelete) {
|
|
fileSystemWatcher.onDidDelete((resource) => this._notifyFileEvent({
|
|
uri: this._client.code2ProtocolConverter.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, _registrationType) {
|
|
this._client = _client;
|
|
this._registrationType = _registrationType;
|
|
this._registrations = new Map();
|
|
}
|
|
get registrationType() {
|
|
return this._registrationType;
|
|
}
|
|
register(data) {
|
|
if (!data.registerOptions.documentSelector) {
|
|
return;
|
|
}
|
|
let registration = this.registerLanguageProvider(data.registerOptions);
|
|
this._registrations.set(data.id, { disposable: registration[0], data, provider: registration[1] });
|
|
}
|
|
unregister(id) {
|
|
let registration = this._registrations.get(id);
|
|
if (registration !== undefined) {
|
|
registration.disposable.dispose();
|
|
}
|
|
}
|
|
dispose() {
|
|
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];
|
|
}
|
|
let 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()) {
|
|
let selector = registration.data.registerOptions.documentSelector;
|
|
if (selector !== null && vscode_1.languages.match(selector, textDocument)) {
|
|
return registration.provider;
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
getAllProviders() {
|
|
const result = [];
|
|
for (const item of this._registrations.values()) {
|
|
result.push(item.provider);
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
exports.TextDocumentFeature = TextDocumentFeature;
|
|
class WorkspaceFeature {
|
|
constructor(_client, _registrationType) {
|
|
this._client = _client;
|
|
this._registrationType = _registrationType;
|
|
this._registrations = new Map();
|
|
}
|
|
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) {
|
|
let registration = this._registrations.get(id);
|
|
if (registration !== undefined) {
|
|
registration.disposable.dispose();
|
|
}
|
|
}
|
|
dispose() {
|
|
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;
|
|
}
|
|
}
|
|
class CompletionItemFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.CompletionRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
let completion = ensure(ensure(capabilities, '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,
|
|
tagSupport: { valueSet: [vscode_languageserver_protocol_1.CompletionItemTag.Deprecated] },
|
|
insertReplaceSupport: true,
|
|
resolveSupport: {
|
|
properties: ['documentation', 'detail', 'additionalTextEdits']
|
|
},
|
|
insertTextModeSupport: { valueSet: [vscode_languageserver_protocol_1.InsertTextMode.asIs, vscode_languageserver_protocol_1.InsertTextMode.adjustIndentation] }
|
|
};
|
|
completion.completionItemKind = { valueSet: SupportedCompletionItemKinds };
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
const options = this.getRegistrationOptions(documentSelector, capabilities.completionProvider);
|
|
if (!options) {
|
|
return;
|
|
}
|
|
this.register({
|
|
id: UUID.generateUuid(),
|
|
registerOptions: options
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
const triggerCharacters = options.triggerCharacters || [];
|
|
const provider = {
|
|
provideCompletionItems: (document, position, token, context) => {
|
|
const client = this._client;
|
|
const middleware = this._client.clientOptions.middleware;
|
|
const provideCompletionItems = (document, position, context, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.CompletionRequest.type, client.code2ProtocolConverter.asCompletionParams(document, position, context), token).then(client.protocol2CodeConverter.asCompletionResult, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.CompletionRequest.type, error, null);
|
|
});
|
|
};
|
|
return middleware.provideCompletionItem
|
|
? middleware.provideCompletionItem(document, position, context, token, provideCompletionItems)
|
|
: provideCompletionItems(document, position, context, token);
|
|
},
|
|
resolveCompletionItem: options.resolveProvider
|
|
? (item, token) => {
|
|
const client = this._client;
|
|
const middleware = this._client.clientOptions.middleware;
|
|
const resolveCompletionItem = (item, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.CompletionResolveRequest.type, client.code2ProtocolConverter.asCompletionItem(item), token).then(client.protocol2CodeConverter.asCompletionItem, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.CompletionResolveRequest.type, error, item);
|
|
});
|
|
};
|
|
return middleware.resolveCompletionItem
|
|
? middleware.resolveCompletionItem(item, token, resolveCompletionItem)
|
|
: resolveCompletionItem(item, token);
|
|
}
|
|
: undefined
|
|
};
|
|
return [vscode_1.languages.registerCompletionItemProvider(options.documentSelector, provider, ...triggerCharacters), provider];
|
|
}
|
|
}
|
|
class HoverFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.HoverRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
const hoverCapability = (ensure(ensure(capabilities, 'textDocument'), 'hover'));
|
|
hoverCapability.dynamicRegistration = true;
|
|
hoverCapability.contentFormat = [vscode_languageserver_protocol_1.MarkupKind.Markdown, vscode_languageserver_protocol_1.MarkupKind.PlainText];
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
const options = this.getRegistrationOptions(documentSelector, capabilities.hoverProvider);
|
|
if (!options) {
|
|
return;
|
|
}
|
|
this.register({
|
|
id: UUID.generateUuid(),
|
|
registerOptions: options
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
const provider = {
|
|
provideHover: (document, position, token) => {
|
|
const client = this._client;
|
|
const provideHover = (document, position, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.HoverRequest.type, client.code2ProtocolConverter.asTextDocumentPositionParams(document, position), token).then(client.protocol2CodeConverter.asHover, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.HoverRequest.type, error, null);
|
|
});
|
|
};
|
|
const middleware = client.clientOptions.middleware;
|
|
return middleware.provideHover
|
|
? middleware.provideHover(document, position, token, provideHover)
|
|
: provideHover(document, position, token);
|
|
}
|
|
};
|
|
return [vscode_1.languages.registerHoverProvider(options.documentSelector, provider), provider];
|
|
}
|
|
}
|
|
class SignatureHelpFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.SignatureHelpRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
let config = ensure(ensure(capabilities, 'textDocument'), 'signatureHelp');
|
|
config.dynamicRegistration = true;
|
|
config.signatureInformation = { documentationFormat: [vscode_languageserver_protocol_1.MarkupKind.Markdown, vscode_languageserver_protocol_1.MarkupKind.PlainText] };
|
|
config.signatureInformation.parameterInformation = { labelOffsetSupport: true };
|
|
config.signatureInformation.activeParameterSupport = true;
|
|
config.contextSupport = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
const options = this.getRegistrationOptions(documentSelector, capabilities.signatureHelpProvider);
|
|
if (!options) {
|
|
return;
|
|
}
|
|
this.register({
|
|
id: UUID.generateUuid(),
|
|
registerOptions: options
|
|
});
|
|
}
|
|
registerLanguageProvider(options) {
|
|
const provider = {
|
|
provideSignatureHelp: (document, position, token, context) => {
|
|
const client = this._client;
|
|
const providerSignatureHelp = (document, position, context, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.SignatureHelpRequest.type, client.code2ProtocolConverter.asSignatureHelpParams(document, position, context), token).then(client.protocol2CodeConverter.asSignatureHelp, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.SignatureHelpRequest.type, error, null);
|
|
});
|
|
};
|
|
const middleware = client.clientOptions.middleware;
|
|
return middleware.provideSignatureHelp
|
|
? middleware.provideSignatureHelp(document, position, context, token, providerSignatureHelp)
|
|
: providerSignatureHelp(document, position, context, token);
|
|
}
|
|
};
|
|
let disposable;
|
|
if (options.retriggerCharacters === undefined) {
|
|
const triggerCharacters = options.triggerCharacters || [];
|
|
disposable = vscode_1.languages.registerSignatureHelpProvider(options.documentSelector, provider, ...triggerCharacters);
|
|
}
|
|
else {
|
|
const metaData = {
|
|
triggerCharacters: options.triggerCharacters || [],
|
|
retriggerCharacters: options.retriggerCharacters || []
|
|
};
|
|
disposable = vscode_1.languages.registerSignatureHelpProvider(options.documentSelector, provider, metaData);
|
|
}
|
|
return [disposable, provider];
|
|
}
|
|
}
|
|
class DefinitionFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.DefinitionRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
let definitionSupport = ensure(ensure(capabilities, 'textDocument'), 'definition');
|
|
definitionSupport.dynamicRegistration = true;
|
|
definitionSupport.linkSupport = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
const options = this.getRegistrationOptions(documentSelector, capabilities.definitionProvider);
|
|
if (!options) {
|
|
return;
|
|
}
|
|
this.register({ id: UUID.generateUuid(), registerOptions: options });
|
|
}
|
|
registerLanguageProvider(options) {
|
|
const provider = {
|
|
provideDefinition: (document, position, token) => {
|
|
const client = this._client;
|
|
const provideDefinition = (document, position, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.DefinitionRequest.type, client.code2ProtocolConverter.asTextDocumentPositionParams(document, position), token).then(client.protocol2CodeConverter.asDefinitionResult, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.DefinitionRequest.type, error, null);
|
|
});
|
|
};
|
|
const middleware = client.clientOptions.middleware;
|
|
return middleware.provideDefinition
|
|
? middleware.provideDefinition(document, position, token, provideDefinition)
|
|
: provideDefinition(document, position, token);
|
|
}
|
|
};
|
|
return [vscode_1.languages.registerDefinitionProvider(options.documentSelector, provider), provider];
|
|
}
|
|
}
|
|
class ReferencesFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.ReferencesRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'textDocument'), 'references').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
const options = this.getRegistrationOptions(documentSelector, capabilities.referencesProvider);
|
|
if (!options) {
|
|
return;
|
|
}
|
|
this.register({ id: UUID.generateUuid(), registerOptions: options });
|
|
}
|
|
registerLanguageProvider(options) {
|
|
const provider = {
|
|
provideReferences: (document, position, options, token) => {
|
|
const client = this._client;
|
|
const _providerReferences = (document, position, options, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.ReferencesRequest.type, client.code2ProtocolConverter.asReferenceParams(document, position, options), token).then(client.protocol2CodeConverter.asReferences, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.ReferencesRequest.type, error, null);
|
|
});
|
|
};
|
|
const middleware = client.clientOptions.middleware;
|
|
return middleware.provideReferences
|
|
? middleware.provideReferences(document, position, options, token, _providerReferences)
|
|
: _providerReferences(document, position, options, token);
|
|
}
|
|
};
|
|
return [vscode_1.languages.registerReferenceProvider(options.documentSelector, provider), provider];
|
|
}
|
|
}
|
|
class DocumentHighlightFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.DocumentHighlightRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'textDocument'), 'documentHighlight').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
const options = this.getRegistrationOptions(documentSelector, capabilities.documentHighlightProvider);
|
|
if (!options) {
|
|
return;
|
|
}
|
|
this.register({ id: UUID.generateUuid(), registerOptions: options });
|
|
}
|
|
registerLanguageProvider(options) {
|
|
const provider = {
|
|
provideDocumentHighlights: (document, position, token) => {
|
|
const client = this._client;
|
|
const _provideDocumentHighlights = (document, position, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.DocumentHighlightRequest.type, client.code2ProtocolConverter.asTextDocumentPositionParams(document, position), token).then(client.protocol2CodeConverter.asDocumentHighlights, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.DocumentHighlightRequest.type, error, null);
|
|
});
|
|
};
|
|
const middleware = client.clientOptions.middleware;
|
|
return middleware.provideDocumentHighlights
|
|
? middleware.provideDocumentHighlights(document, position, token, _provideDocumentHighlights)
|
|
: _provideDocumentHighlights(document, position, token);
|
|
}
|
|
};
|
|
return [vscode_1.languages.registerDocumentHighlightProvider(options.documentSelector, provider), provider];
|
|
}
|
|
}
|
|
class DocumentSymbolFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.DocumentSymbolRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
let symbolCapabilities = ensure(ensure(capabilities, 'textDocument'), 'documentSymbol');
|
|
symbolCapabilities.dynamicRegistration = true;
|
|
symbolCapabilities.symbolKind = {
|
|
valueSet: SupportedSymbolKinds
|
|
};
|
|
symbolCapabilities.hierarchicalDocumentSymbolSupport = true;
|
|
symbolCapabilities.tagSupport = {
|
|
valueSet: SupportedSymbolTags
|
|
};
|
|
symbolCapabilities.labelSupport = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
const options = this.getRegistrationOptions(documentSelector, capabilities.documentSymbolProvider);
|
|
if (!options) {
|
|
return;
|
|
}
|
|
this.register({ id: UUID.generateUuid(), registerOptions: options });
|
|
}
|
|
registerLanguageProvider(options) {
|
|
const provider = {
|
|
provideDocumentSymbols: (document, token) => {
|
|
const client = this._client;
|
|
const _provideDocumentSymbols = (document, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.DocumentSymbolRequest.type, client.code2ProtocolConverter.asDocumentSymbolParams(document), token).then((data) => {
|
|
if (data === null) {
|
|
return undefined;
|
|
}
|
|
if (data.length === 0) {
|
|
return [];
|
|
}
|
|
else {
|
|
let element = data[0];
|
|
if (vscode_languageserver_protocol_1.DocumentSymbol.is(element)) {
|
|
return client.protocol2CodeConverter.asDocumentSymbols(data);
|
|
}
|
|
else {
|
|
return client.protocol2CodeConverter.asSymbolInformations(data);
|
|
}
|
|
}
|
|
}, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.DocumentSymbolRequest.type, error, null);
|
|
});
|
|
};
|
|
const middleware = client.clientOptions.middleware;
|
|
return middleware.provideDocumentSymbols
|
|
? middleware.provideDocumentSymbols(document, token, _provideDocumentSymbols)
|
|
: _provideDocumentSymbols(document, token);
|
|
}
|
|
};
|
|
const metaData = options.label !== undefined ? { label: options.label } : undefined;
|
|
return [vscode_1.languages.registerDocumentSymbolProvider(options.documentSelector, provider, metaData), provider];
|
|
}
|
|
}
|
|
class WorkspaceSymbolFeature extends WorkspaceFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.WorkspaceSymbolRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
let symbolCapabilities = ensure(ensure(capabilities, 'workspace'), 'symbol');
|
|
symbolCapabilities.dynamicRegistration = true;
|
|
symbolCapabilities.symbolKind = {
|
|
valueSet: SupportedSymbolKinds
|
|
};
|
|
symbolCapabilities.tagSupport = {
|
|
valueSet: SupportedSymbolTags
|
|
};
|
|
}
|
|
initialize(capabilities) {
|
|
if (!capabilities.workspaceSymbolProvider) {
|
|
return;
|
|
}
|
|
this.register({
|
|
id: UUID.generateUuid(),
|
|
registerOptions: capabilities.workspaceSymbolProvider === true ? { workDoneProgress: false } : capabilities.workspaceSymbolProvider
|
|
});
|
|
}
|
|
registerLanguageProvider(_options) {
|
|
const provider = {
|
|
provideWorkspaceSymbols: (query, token) => {
|
|
const client = this._client;
|
|
const provideWorkspaceSymbols = (query, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.WorkspaceSymbolRequest.type, { query }, token).then(client.protocol2CodeConverter.asSymbolInformations, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.WorkspaceSymbolRequest.type, error, null);
|
|
});
|
|
};
|
|
const middleware = client.clientOptions.middleware;
|
|
return middleware.provideWorkspaceSymbols
|
|
? middleware.provideWorkspaceSymbols(query, token, provideWorkspaceSymbols)
|
|
: provideWorkspaceSymbols(query, token);
|
|
}
|
|
};
|
|
return [vscode_1.languages.registerWorkspaceSymbolProvider(provider), provider];
|
|
}
|
|
}
|
|
class CodeActionFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.CodeActionRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
const cap = ensure(ensure(capabilities, 'textDocument'), 'codeAction');
|
|
cap.dynamicRegistration = true;
|
|
cap.isPreferredSupport = true;
|
|
cap.disabledSupport = true;
|
|
cap.dataSupport = true;
|
|
// We can only resolve the edit property.
|
|
cap.resolveSupport = {
|
|
properties: ['edit']
|
|
};
|
|
cap.codeActionLiteralSupport = {
|
|
codeActionKind: {
|
|
valueSet: [
|
|
vscode_languageserver_protocol_1.CodeActionKind.Empty,
|
|
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
|
|
]
|
|
}
|
|
};
|
|
cap.honorsChangeAnnotations = false;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
const options = this.getRegistrationOptions(documentSelector, capabilities.codeActionProvider);
|
|
if (!options) {
|
|
return;
|
|
}
|
|
this.register({ id: UUID.generateUuid(), registerOptions: options });
|
|
}
|
|
registerLanguageProvider(options) {
|
|
const provider = {
|
|
provideCodeActions: (document, range, context, token) => {
|
|
const client = this._client;
|
|
const _provideCodeActions = (document, range, context, token) => {
|
|
const params = {
|
|
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
|
|
range: client.code2ProtocolConverter.asRange(range),
|
|
context: client.code2ProtocolConverter.asCodeActionContext(context)
|
|
};
|
|
return client.sendRequest(vscode_languageserver_protocol_1.CodeActionRequest.type, params, token).then((values) => {
|
|
if (values === null) {
|
|
return undefined;
|
|
}
|
|
const result = [];
|
|
for (let item of values) {
|
|
if (vscode_languageserver_protocol_1.Command.is(item)) {
|
|
result.push(client.protocol2CodeConverter.asCommand(item));
|
|
}
|
|
else {
|
|
result.push(client.protocol2CodeConverter.asCodeAction(item));
|
|
}
|
|
}
|
|
return result;
|
|
}, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.CodeActionRequest.type, error, null);
|
|
});
|
|
};
|
|
const middleware = client.clientOptions.middleware;
|
|
return middleware.provideCodeActions
|
|
? middleware.provideCodeActions(document, range, context, token, _provideCodeActions)
|
|
: _provideCodeActions(document, range, context, token);
|
|
},
|
|
resolveCodeAction: options.resolveProvider
|
|
? (item, token) => {
|
|
const client = this._client;
|
|
const middleware = this._client.clientOptions.middleware;
|
|
const resolveCodeAction = (item, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.CodeActionResolveRequest.type, client.code2ProtocolConverter.asCodeAction(item), token).then(client.protocol2CodeConverter.asCodeAction, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.CodeActionResolveRequest.type, error, item);
|
|
});
|
|
};
|
|
return middleware.resolveCodeAction
|
|
? middleware.resolveCodeAction(item, token, resolveCodeAction)
|
|
: resolveCodeAction(item, token);
|
|
}
|
|
: undefined
|
|
};
|
|
return [vscode_1.languages.registerCodeActionsProvider(options.documentSelector, provider, (options.codeActionKinds
|
|
? { providedCodeActionKinds: this._client.protocol2CodeConverter.asCodeActionKinds(options.codeActionKinds) }
|
|
: undefined)), provider];
|
|
}
|
|
}
|
|
class CodeLensFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.CodeLensRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'textDocument'), 'codeLens').dynamicRegistration = true;
|
|
ensure(ensure(capabilities, 'workspace'), 'codeLens').refreshSupport = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
const client = this._client;
|
|
client.onRequest(vscode_languageserver_protocol_1.CodeLensRefreshRequest.type, async () => {
|
|
for (const provider of this.getAllProviders()) {
|
|
provider.onDidChangeCodeLensEmitter.fire();
|
|
}
|
|
});
|
|
const options = this.getRegistrationOptions(documentSelector, capabilities.codeLensProvider);
|
|
if (!options) {
|
|
return;
|
|
}
|
|
this.register({ id: UUID.generateUuid(), registerOptions: options });
|
|
}
|
|
registerLanguageProvider(options) {
|
|
const eventEmitter = new vscode_1.EventEmitter();
|
|
const provider = {
|
|
onDidChangeCodeLenses: eventEmitter.event,
|
|
provideCodeLenses: (document, token) => {
|
|
const client = this._client;
|
|
const provideCodeLenses = (document, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.CodeLensRequest.type, client.code2ProtocolConverter.asCodeLensParams(document), token).then(client.protocol2CodeConverter.asCodeLenses, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.CodeLensRequest.type, error, null);
|
|
});
|
|
};
|
|
const middleware = client.clientOptions.middleware;
|
|
return middleware.provideCodeLenses
|
|
? middleware.provideCodeLenses(document, token, provideCodeLenses)
|
|
: provideCodeLenses(document, token);
|
|
},
|
|
resolveCodeLens: (options.resolveProvider)
|
|
? (codeLens, token) => {
|
|
const client = this._client;
|
|
const resolveCodeLens = (codeLens, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.CodeLensResolveRequest.type, client.code2ProtocolConverter.asCodeLens(codeLens), token).then(client.protocol2CodeConverter.asCodeLens, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.CodeLensResolveRequest.type, error, codeLens);
|
|
});
|
|
};
|
|
const middleware = client.clientOptions.middleware;
|
|
return middleware.resolveCodeLens
|
|
? middleware.resolveCodeLens(codeLens, token, resolveCodeLens)
|
|
: resolveCodeLens(codeLens, token);
|
|
}
|
|
: undefined
|
|
};
|
|
return [vscode_1.languages.registerCodeLensProvider(options.documentSelector, provider), { provider, onDidChangeCodeLensEmitter: eventEmitter }];
|
|
}
|
|
}
|
|
class DocumentFormattingFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.DocumentFormattingRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'textDocument'), 'formatting').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
const options = this.getRegistrationOptions(documentSelector, capabilities.documentFormattingProvider);
|
|
if (!options) {
|
|
return;
|
|
}
|
|
this.register({ id: UUID.generateUuid(), registerOptions: options });
|
|
}
|
|
registerLanguageProvider(options) {
|
|
const provider = {
|
|
provideDocumentFormattingEdits: (document, options, token) => {
|
|
const client = this._client;
|
|
const provideDocumentFormattingEdits = (document, options, token) => {
|
|
const params = {
|
|
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
|
|
options: client.code2ProtocolConverter.asFormattingOptions(options, FileFormattingOptions.fromConfiguration(document))
|
|
};
|
|
return client.sendRequest(vscode_languageserver_protocol_1.DocumentFormattingRequest.type, params, token).then(client.protocol2CodeConverter.asTextEdits, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.DocumentFormattingRequest.type, error, null);
|
|
});
|
|
};
|
|
const middleware = client.clientOptions.middleware;
|
|
return middleware.provideDocumentFormattingEdits
|
|
? middleware.provideDocumentFormattingEdits(document, options, token, provideDocumentFormattingEdits)
|
|
: provideDocumentFormattingEdits(document, options, token);
|
|
}
|
|
};
|
|
return [vscode_1.languages.registerDocumentFormattingEditProvider(options.documentSelector, provider), provider];
|
|
}
|
|
}
|
|
class DocumentRangeFormattingFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.DocumentRangeFormattingRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'textDocument'), 'rangeFormatting').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
const options = this.getRegistrationOptions(documentSelector, capabilities.documentRangeFormattingProvider);
|
|
if (!options) {
|
|
return;
|
|
}
|
|
this.register({ id: UUID.generateUuid(), registerOptions: options });
|
|
}
|
|
registerLanguageProvider(options) {
|
|
const provider = {
|
|
provideDocumentRangeFormattingEdits: (document, range, options, token) => {
|
|
const client = this._client;
|
|
const provideDocumentRangeFormattingEdits = (document, range, options, token) => {
|
|
const params = {
|
|
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
|
|
range: client.code2ProtocolConverter.asRange(range),
|
|
options: client.code2ProtocolConverter.asFormattingOptions(options, FileFormattingOptions.fromConfiguration(document))
|
|
};
|
|
return client.sendRequest(vscode_languageserver_protocol_1.DocumentRangeFormattingRequest.type, params, token).then(client.protocol2CodeConverter.asTextEdits, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.DocumentRangeFormattingRequest.type, error, null);
|
|
});
|
|
};
|
|
const middleware = client.clientOptions.middleware;
|
|
return middleware.provideDocumentRangeFormattingEdits
|
|
? middleware.provideDocumentRangeFormattingEdits(document, range, options, token, provideDocumentRangeFormattingEdits)
|
|
: provideDocumentRangeFormattingEdits(document, range, options, token);
|
|
}
|
|
};
|
|
return [vscode_1.languages.registerDocumentRangeFormattingEditProvider(options.documentSelector, provider), provider];
|
|
}
|
|
}
|
|
class DocumentOnTypeFormattingFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.DocumentOnTypeFormattingRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'textDocument'), 'onTypeFormatting').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
const options = this.getRegistrationOptions(documentSelector, capabilities.documentOnTypeFormattingProvider);
|
|
if (!options) {
|
|
return;
|
|
}
|
|
this.register({ id: UUID.generateUuid(), registerOptions: options });
|
|
}
|
|
registerLanguageProvider(options) {
|
|
const provider = {
|
|
provideOnTypeFormattingEdits: (document, position, ch, options, token) => {
|
|
const client = this._client;
|
|
const provideOnTypeFormattingEdits = (document, position, ch, options, token) => {
|
|
let params = {
|
|
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
|
|
position: client.code2ProtocolConverter.asPosition(position),
|
|
ch: ch,
|
|
options: client.code2ProtocolConverter.asFormattingOptions(options, FileFormattingOptions.fromConfiguration(document))
|
|
};
|
|
return client.sendRequest(vscode_languageserver_protocol_1.DocumentOnTypeFormattingRequest.type, params, token).then(client.protocol2CodeConverter.asTextEdits, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.DocumentOnTypeFormattingRequest.type, error, null);
|
|
});
|
|
};
|
|
const middleware = client.clientOptions.middleware;
|
|
return middleware.provideOnTypeFormattingEdits
|
|
? middleware.provideOnTypeFormattingEdits(document, position, ch, options, token, provideOnTypeFormattingEdits)
|
|
: provideOnTypeFormattingEdits(document, position, ch, options, token);
|
|
}
|
|
};
|
|
const moreTriggerCharacter = options.moreTriggerCharacter || [];
|
|
return [vscode_1.languages.registerOnTypeFormattingEditProvider(options.documentSelector, provider, options.firstTriggerCharacter, ...moreTriggerCharacter), provider];
|
|
}
|
|
}
|
|
class RenameFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.RenameRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
let rename = ensure(ensure(capabilities, 'textDocument'), 'rename');
|
|
rename.dynamicRegistration = true;
|
|
rename.prepareSupport = true;
|
|
rename.prepareSupportDefaultBehavior = vscode_languageserver_protocol_1.PrepareSupportDefaultBehavior.Identifier;
|
|
rename.honorsChangeAnnotations = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
const options = this.getRegistrationOptions(documentSelector, capabilities.renameProvider);
|
|
if (!options) {
|
|
return;
|
|
}
|
|
if (Is.boolean(capabilities.renameProvider)) {
|
|
options.prepareProvider = false;
|
|
}
|
|
this.register({ id: UUID.generateUuid(), registerOptions: options });
|
|
}
|
|
registerLanguageProvider(options) {
|
|
const provider = {
|
|
provideRenameEdits: (document, position, newName, token) => {
|
|
const client = this._client;
|
|
const provideRenameEdits = (document, position, newName, token) => {
|
|
let params = {
|
|
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
|
|
position: client.code2ProtocolConverter.asPosition(position),
|
|
newName: newName
|
|
};
|
|
return client.sendRequest(vscode_languageserver_protocol_1.RenameRequest.type, params, token).then(client.protocol2CodeConverter.asWorkspaceEdit, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.RenameRequest.type, error, null);
|
|
});
|
|
};
|
|
const middleware = client.clientOptions.middleware;
|
|
return middleware.provideRenameEdits
|
|
? middleware.provideRenameEdits(document, position, newName, token, provideRenameEdits)
|
|
: provideRenameEdits(document, position, newName, token);
|
|
},
|
|
prepareRename: options.prepareProvider
|
|
? (document, position, token) => {
|
|
const client = this._client;
|
|
const prepareRename = (document, position, token) => {
|
|
let params = {
|
|
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
|
|
position: client.code2ProtocolConverter.asPosition(position),
|
|
};
|
|
return client.sendRequest(vscode_languageserver_protocol_1.PrepareRenameRequest.type, params, token).then((result) => {
|
|
if (vscode_languageserver_protocol_1.Range.is(result)) {
|
|
return client.protocol2CodeConverter.asRange(result);
|
|
}
|
|
else if (this.isDefaultBehavior(result)) {
|
|
return result.defaultBehavior === true
|
|
? null
|
|
: Promise.reject(new Error(`The element can't be renamed.`));
|
|
}
|
|
else if (result && vscode_languageserver_protocol_1.Range.is(result.range)) {
|
|
return {
|
|
range: client.protocol2CodeConverter.asRange(result.range),
|
|
placeholder: result.placeholder
|
|
};
|
|
}
|
|
// To cancel the rename vscode API expects a rejected promise.
|
|
return Promise.reject(new Error(`The element can't be renamed.`));
|
|
}, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.PrepareRenameRequest.type, error, undefined);
|
|
});
|
|
};
|
|
const middleware = client.clientOptions.middleware;
|
|
return middleware.prepareRename
|
|
? middleware.prepareRename(document, position, token, prepareRename)
|
|
: prepareRename(document, position, token);
|
|
}
|
|
: undefined
|
|
};
|
|
return [vscode_1.languages.registerRenameProvider(options.documentSelector, provider), provider];
|
|
}
|
|
isDefaultBehavior(value) {
|
|
const candidate = value;
|
|
return candidate && Is.boolean(candidate.defaultBehavior);
|
|
}
|
|
}
|
|
class DocumentLinkFeature extends TextDocumentFeature {
|
|
constructor(client) {
|
|
super(client, vscode_languageserver_protocol_1.DocumentLinkRequest.type);
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
const documentLinkCapabilities = ensure(ensure(capabilities, 'textDocument'), 'documentLink');
|
|
documentLinkCapabilities.dynamicRegistration = true;
|
|
documentLinkCapabilities.tooltipSupport = true;
|
|
}
|
|
initialize(capabilities, documentSelector) {
|
|
const options = this.getRegistrationOptions(documentSelector, capabilities.documentLinkProvider);
|
|
if (!options) {
|
|
return;
|
|
}
|
|
this.register({ id: UUID.generateUuid(), registerOptions: options });
|
|
}
|
|
registerLanguageProvider(options) {
|
|
const provider = {
|
|
provideDocumentLinks: (document, token) => {
|
|
const client = this._client;
|
|
const provideDocumentLinks = (document, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.DocumentLinkRequest.type, client.code2ProtocolConverter.asDocumentLinkParams(document), token).then(client.protocol2CodeConverter.asDocumentLinks, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.DocumentLinkRequest.type, error, null);
|
|
});
|
|
};
|
|
const middleware = client.clientOptions.middleware;
|
|
return middleware.provideDocumentLinks
|
|
? middleware.provideDocumentLinks(document, token, provideDocumentLinks)
|
|
: provideDocumentLinks(document, token);
|
|
},
|
|
resolveDocumentLink: options.resolveProvider
|
|
? (link, token) => {
|
|
const client = this._client;
|
|
let resolveDocumentLink = (link, token) => {
|
|
return client.sendRequest(vscode_languageserver_protocol_1.DocumentLinkResolveRequest.type, client.code2ProtocolConverter.asDocumentLink(link), token).then(client.protocol2CodeConverter.asDocumentLink, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.DocumentLinkResolveRequest.type, error, link);
|
|
});
|
|
};
|
|
const middleware = client.clientOptions.middleware;
|
|
return middleware.resolveDocumentLink
|
|
? middleware.resolveDocumentLink(link, token, resolveDocumentLink)
|
|
: resolveDocumentLink(link, token);
|
|
}
|
|
: undefined
|
|
};
|
|
return [vscode_1.languages.registerDocumentLinkProvider(options.documentSelector, provider), provider];
|
|
}
|
|
}
|
|
class ConfigurationFeature {
|
|
constructor(_client) {
|
|
this._client = _client;
|
|
this._listeners = new Map();
|
|
}
|
|
get registrationType() {
|
|
return vscode_languageserver_protocol_1.DidChangeConfigurationNotification.type;
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'workspace'), 'didChangeConfiguration').dynamicRegistration = true;
|
|
}
|
|
initialize() {
|
|
let section = this._client.clientOptions.synchronize.configurationSection;
|
|
if (section !== undefined) {
|
|
this.register({
|
|
id: UUID.generateUuid(),
|
|
registerOptions: {
|
|
section: section
|
|
}
|
|
});
|
|
}
|
|
}
|
|
register(data) {
|
|
let disposable = vscode_1.workspace.onDidChangeConfiguration((event) => {
|
|
this.onDidChangeConfiguration(data.registerOptions.section, event);
|
|
});
|
|
this._listeners.set(data.id, disposable);
|
|
if (data.registerOptions.section !== undefined) {
|
|
this.onDidChangeConfiguration(data.registerOptions.section, undefined);
|
|
}
|
|
}
|
|
unregister(id) {
|
|
let disposable = this._listeners.get(id);
|
|
if (disposable) {
|
|
this._listeners.delete(id);
|
|
disposable.dispose();
|
|
}
|
|
}
|
|
dispose() {
|
|
for (let disposable of this._listeners.values()) {
|
|
disposable.dispose();
|
|
}
|
|
this._listeners.clear();
|
|
}
|
|
onDidChangeConfiguration(configurationSection, event) {
|
|
let sections;
|
|
if (Is.string(configurationSection)) {
|
|
sections = [configurationSection];
|
|
}
|
|
else {
|
|
sections = configurationSection;
|
|
}
|
|
if (sections !== undefined && event !== undefined) {
|
|
let affected = sections.some((section) => event.affectsConfiguration(section));
|
|
if (!affected) {
|
|
return;
|
|
}
|
|
}
|
|
let didChangeConfiguration = (sections) => {
|
|
if (sections === undefined) {
|
|
this._client.sendNotification(vscode_languageserver_protocol_1.DidChangeConfigurationNotification.type, { settings: null });
|
|
return;
|
|
}
|
|
this._client.sendNotification(vscode_languageserver_protocol_1.DidChangeConfigurationNotification.type, { settings: this.extractSettingsInformation(sections) });
|
|
};
|
|
let middleware = this.getMiddleware();
|
|
middleware
|
|
? middleware(sections, didChangeConfiguration)
|
|
: didChangeConfiguration(sections);
|
|
}
|
|
extractSettingsInformation(keys) {
|
|
function ensurePath(config, path) {
|
|
let current = config;
|
|
for (let i = 0; i < path.length - 1; i++) {
|
|
let obj = current[path[i]];
|
|
if (!obj) {
|
|
obj = Object.create(null);
|
|
current[path[i]] = obj;
|
|
}
|
|
current = obj;
|
|
}
|
|
return current;
|
|
}
|
|
let resource = this._client.clientOptions.workspaceFolder
|
|
? this._client.clientOptions.workspaceFolder.uri
|
|
: undefined;
|
|
let result = Object.create(null);
|
|
for (let i = 0; i < keys.length; i++) {
|
|
let key = keys[i];
|
|
let index = key.indexOf('.');
|
|
let config = null;
|
|
if (index >= 0) {
|
|
config = vscode_1.workspace.getConfiguration(key.substr(0, index), resource).get(key.substr(index + 1));
|
|
}
|
|
else {
|
|
config = vscode_1.workspace.getConfiguration(undefined, resource).get(key);
|
|
}
|
|
if (config) {
|
|
let path = keys[i].split('.');
|
|
ensurePath(result, path)[path[path.length - 1]] = configuration_1.toJSONObject(config);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
getMiddleware() {
|
|
let middleware = this._client.clientOptions.middleware;
|
|
if (middleware.workspace && middleware.workspace.didChangeConfiguration) {
|
|
return middleware.workspace.didChangeConfiguration;
|
|
}
|
|
else {
|
|
return undefined;
|
|
}
|
|
}
|
|
}
|
|
class ExecuteCommandFeature {
|
|
constructor(_client) {
|
|
this._client = _client;
|
|
this._commands = new Map();
|
|
}
|
|
get registrationType() {
|
|
return vscode_languageserver_protocol_1.ExecuteCommandRequest.type;
|
|
}
|
|
fillClientCapabilities(capabilities) {
|
|
ensure(ensure(capabilities, 'workspace'), 'executeCommand').dynamicRegistration = true;
|
|
}
|
|
initialize(capabilities) {
|
|
if (!capabilities.executeCommandProvider) {
|
|
return;
|
|
}
|
|
this.register({
|
|
id: UUID.generateUuid(),
|
|
registerOptions: Object.assign({}, capabilities.executeCommandProvider)
|
|
});
|
|
}
|
|
register(data) {
|
|
const client = this._client;
|
|
const middleware = client.clientOptions.middleware;
|
|
const executeCommand = (command, args) => {
|
|
let params = {
|
|
command,
|
|
arguments: args
|
|
};
|
|
return client.sendRequest(vscode_languageserver_protocol_1.ExecuteCommandRequest.type, params).then(undefined, (error) => {
|
|
return client.handleFailedRequest(vscode_languageserver_protocol_1.ExecuteCommandRequest.type, error, undefined);
|
|
});
|
|
};
|
|
if (data.registerOptions.commands) {
|
|
const disposables = [];
|
|
for (const command of data.registerOptions.commands) {
|
|
disposables.push(vscode_1.commands.registerCommand(command, (...args) => {
|
|
return middleware.executeCommand
|
|
? middleware.executeCommand(command, args, executeCommand)
|
|
: executeCommand(command, args);
|
|
}));
|
|
}
|
|
this._commands.set(data.id, disposables);
|
|
}
|
|
}
|
|
unregister(id) {
|
|
let disposables = this._commands.get(id);
|
|
if (disposables) {
|
|
disposables.forEach(disposable => disposable.dispose());
|
|
}
|
|
}
|
|
dispose() {
|
|
this._commands.forEach((value) => {
|
|
value.forEach(disposable => disposable.dispose());
|
|
});
|
|
this._commands.clear();
|
|
}
|
|
}
|
|
var MessageTransports;
|
|
(function (MessageTransports) {
|
|
function is(value) {
|
|
let candidate = value;
|
|
return candidate && vscode_languageserver_protocol_1.MessageReader.is(value.reader) && vscode_languageserver_protocol_1.MessageWriter.is(value.writer);
|
|
}
|
|
MessageTransports.is = is;
|
|
})(MessageTransports = exports.MessageTransports || (exports.MessageTransports = {}));
|
|
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 BaseLanguageClient {
|
|
constructor(id, name, clientOptions) {
|
|
var _a;
|
|
this._traceFormat = vscode_languageserver_protocol_1.TraceFormat.Text;
|
|
this._features = [];
|
|
this._dynamicFeatures = new Map();
|
|
this._id = id;
|
|
this._name = name;
|
|
clientOptions = clientOptions || {};
|
|
const markdown = { isTrusted: false };
|
|
if (clientOptions.markdown !== undefined && clientOptions.markdown.isTrusted === true) {
|
|
markdown.isTrusted = true;
|
|
}
|
|
this._clientOptions = {
|
|
documentSelector: clientOptions.documentSelector || [],
|
|
synchronize: clientOptions.synchronize || {},
|
|
diagnosticCollectionName: clientOptions.diagnosticCollectionName,
|
|
outputChannelName: clientOptions.outputChannelName || this._name,
|
|
revealOutputChannelOn: clientOptions.revealOutputChannelOn || RevealOutputChannelOn.Error,
|
|
stdioEncoding: clientOptions.stdioEncoding || 'utf8',
|
|
initializationOptions: clientOptions.initializationOptions,
|
|
initializationFailedHandler: clientOptions.initializationFailedHandler,
|
|
progressOnInitialization: !!clientOptions.progressOnInitialization,
|
|
errorHandler: clientOptions.errorHandler || this.createDefaultErrorHandler((_a = clientOptions.connectionOptions) === null || _a === void 0 ? void 0 : _a.maxRestartCount),
|
|
middleware: clientOptions.middleware || {},
|
|
uriConverters: clientOptions.uriConverters,
|
|
workspaceFolder: clientOptions.workspaceFolder,
|
|
connectionOptions: clientOptions.connectionOptions,
|
|
markdown
|
|
};
|
|
this._clientOptions.synchronize = this._clientOptions.synchronize || {};
|
|
this._state = ClientState.Initial;
|
|
this._connectionPromise = undefined;
|
|
this._resolvedConnection = undefined;
|
|
this._initializeResult = undefined;
|
|
if (clientOptions.outputChannel) {
|
|
this._outputChannel = clientOptions.outputChannel;
|
|
this._disposeOutputChannel = false;
|
|
}
|
|
else {
|
|
this._outputChannel = undefined;
|
|
this._disposeOutputChannel = true;
|
|
}
|
|
this._traceOutputChannel = clientOptions.traceOutputChannel;
|
|
this._listeners = undefined;
|
|
this._providers = undefined;
|
|
this._diagnostics = undefined;
|
|
this._fileEvents = [];
|
|
this._fileEventDelayer = new async_1.Delayer(250);
|
|
this._onReady = new Promise((resolve, reject) => {
|
|
this._onReadyCallbacks = new OnReady(resolve, reject);
|
|
});
|
|
this._onStop = undefined;
|
|
this._telemetryEmitter = new vscode_languageserver_protocol_1.Emitter();
|
|
this._stateChangeEmitter = new vscode_languageserver_protocol_1.Emitter();
|
|
this._trace = vscode_languageserver_protocol_1.Trace.Off;
|
|
this._tracer = {
|
|
log: (messageOrDataObject, data) => {
|
|
if (Is.string(messageOrDataObject)) {
|
|
this.logTrace(messageOrDataObject, data);
|
|
}
|
|
else {
|
|
this.logObjectTrace(messageOrDataObject);
|
|
}
|
|
},
|
|
};
|
|
this._c2p = c2p.createConverter(clientOptions.uriConverters ? clientOptions.uriConverters.code2Protocol : undefined);
|
|
this._p2c = p2c.createConverter(clientOptions.uriConverters ? clientOptions.uriConverters.protocol2Code : undefined, this._clientOptions.markdown.isTrusted);
|
|
this._syncedDocuments = new Map();
|
|
this.registerBuiltinFeatures();
|
|
}
|
|
get state() {
|
|
return this._state;
|
|
}
|
|
set state(value) {
|
|
let oldState = this.getPublicState();
|
|
this._state = value;
|
|
let newState = this.getPublicState();
|
|
if (newState !== oldState) {
|
|
this._stateChangeEmitter.fire({ oldState, newState });
|
|
}
|
|
}
|
|
getPublicState() {
|
|
if (this.state === ClientState.Running) {
|
|
return State.Running;
|
|
}
|
|
else if (this.state === ClientState.Starting) {
|
|
return State.Starting;
|
|
}
|
|
else {
|
|
return State.Stopped;
|
|
}
|
|
}
|
|
get initializeResult() {
|
|
return this._initializeResult;
|
|
}
|
|
sendRequest(type, ...params) {
|
|
if (!this.isConnectionActive()) {
|
|
throw new Error('Language client is not ready yet');
|
|
}
|
|
this.forceDocumentSync();
|
|
try {
|
|
return this._resolvedConnection.sendRequest(type, ...params);
|
|
}
|
|
catch (error) {
|
|
this.error(`Sending request ${Is.string(type) ? type : type.method} failed.`, error);
|
|
throw error;
|
|
}
|
|
}
|
|
onRequest(type, handler) {
|
|
if (!this.isConnectionActive()) {
|
|
throw new Error('Language client is not ready yet');
|
|
}
|
|
try {
|
|
return this._resolvedConnection.onRequest(type, handler);
|
|
}
|
|
catch (error) {
|
|
this.error(`Registering request handler ${Is.string(type) ? type : type.method} failed.`, error);
|
|
throw error;
|
|
}
|
|
}
|
|
sendNotification(type, params) {
|
|
if (!this.isConnectionActive()) {
|
|
throw new Error('Language client is not ready yet');
|
|
}
|
|
this.forceDocumentSync();
|
|
try {
|
|
this._resolvedConnection.sendNotification(type, params);
|
|
}
|
|
catch (error) {
|
|
this.error(`Sending notification ${Is.string(type) ? type : type.method} failed.`, error);
|
|
throw error;
|
|
}
|
|
}
|
|
onNotification(type, handler) {
|
|
if (!this.isConnectionActive()) {
|
|
throw new Error('Language client is not ready yet');
|
|
}
|
|
try {
|
|
return this._resolvedConnection.onNotification(type, handler);
|
|
}
|
|
catch (error) {
|
|
this.error(`Registering notification handler ${Is.string(type) ? type : type.method} failed.`, error);
|
|
throw error;
|
|
}
|
|
}
|
|
onProgress(type, token, handler) {
|
|
if (!this.isConnectionActive()) {
|
|
throw new Error('Language client is not ready yet');
|
|
}
|
|
try {
|
|
if (vscode_languageserver_protocol_1.WorkDoneProgress.is(type)) {
|
|
const handleWorkDoneProgress = this._clientOptions.middleware.handleWorkDoneProgress;
|
|
if (handleWorkDoneProgress !== undefined) {
|
|
return this._resolvedConnection.onProgress(type, token, (params) => {
|
|
handleWorkDoneProgress(token, params, () => handler(params));
|
|
});
|
|
}
|
|
}
|
|
return this._resolvedConnection.onProgress(type, token, handler);
|
|
}
|
|
catch (error) {
|
|
this.error(`Registering progress handler for token ${token} failed.`, error);
|
|
throw error;
|
|
}
|
|
}
|
|
sendProgress(type, token, value) {
|
|
if (!this.isConnectionActive()) {
|
|
throw new Error('Language client is not ready yet');
|
|
}
|
|
this.forceDocumentSync();
|
|
try {
|
|
this._resolvedConnection.sendProgress(type, token, value);
|
|
}
|
|
catch (error) {
|
|
this.error(`Sending progress for token ${token} failed.`, error);
|
|
throw error;
|
|
}
|
|
}
|
|
get clientOptions() {
|
|
return this._clientOptions;
|
|
}
|
|
get protocol2CodeConverter() {
|
|
return this._p2c;
|
|
}
|
|
get code2ProtocolConverter() {
|
|
return this._c2p;
|
|
}
|
|
get onTelemetry() {
|
|
return this._telemetryEmitter.event;
|
|
}
|
|
get onDidChangeState() {
|
|
return this._stateChangeEmitter.event;
|
|
}
|
|
get outputChannel() {
|
|
if (!this._outputChannel) {
|
|
this._outputChannel = vscode_1.window.createOutputChannel(this._clientOptions.outputChannelName ? this._clientOptions.outputChannelName : this._name);
|
|
}
|
|
return this._outputChannel;
|
|
}
|
|
get traceOutputChannel() {
|
|
if (this._traceOutputChannel) {
|
|
return this._traceOutputChannel;
|
|
}
|
|
return this.outputChannel;
|
|
}
|
|
get diagnostics() {
|
|
return this._diagnostics;
|
|
}
|
|
createDefaultErrorHandler(maxRestartCount) {
|
|
if (maxRestartCount !== undefined && maxRestartCount < 0) {
|
|
throw new Error(`Invalid maxRestartCount: ${maxRestartCount}`);
|
|
}
|
|
return new DefaultErrorHandler(this._name, maxRestartCount !== null && maxRestartCount !== void 0 ? maxRestartCount : 4);
|
|
}
|
|
set trace(value) {
|
|
this._trace = value;
|
|
this.onReady().then(() => {
|
|
this.resolveConnection().then((connection) => {
|
|
connection.trace(this._trace, this._tracer, {
|
|
sendNotification: false,
|
|
traceFormat: this._traceFormat
|
|
});
|
|
});
|
|
}, () => {
|
|
});
|
|
}
|
|
data2String(data) {
|
|
if (data instanceof vscode_languageserver_protocol_1.ResponseError) {
|
|
const responseError = data;
|
|
return ` Message: ${responseError.message}\n Code: ${responseError.code} ${responseError.data ? '\n' + responseError.data.toString() : ''}`;
|
|
}
|
|
if (data instanceof Error) {
|
|
if (Is.string(data.stack)) {
|
|
return data.stack;
|
|
}
|
|
return data.message;
|
|
}
|
|
if (Is.string(data)) {
|
|
return data;
|
|
}
|
|
return data.toString();
|
|
}
|
|
info(message, data, showNotification = true) {
|
|
this.outputChannel.appendLine(`[Info - ${(new Date().toLocaleTimeString())}] ${message}`);
|
|
if (data) {
|
|
this.outputChannel.appendLine(this.data2String(data));
|
|
}
|
|
if (showNotification && this._clientOptions.revealOutputChannelOn <= RevealOutputChannelOn.Info) {
|
|
this.showNotificationMessage();
|
|
}
|
|
}
|
|
warn(message, data, showNotification = true) {
|
|
this.outputChannel.appendLine(`[Warn - ${(new Date().toLocaleTimeString())}] ${message}`);
|
|
if (data) {
|
|
this.outputChannel.appendLine(this.data2String(data));
|
|
}
|
|
if (showNotification && this._clientOptions.revealOutputChannelOn <= RevealOutputChannelOn.Warn) {
|
|
this.showNotificationMessage();
|
|
}
|
|
}
|
|
error(message, data, showNotification = true) {
|
|
this.outputChannel.appendLine(`[Error - ${(new Date().toLocaleTimeString())}] ${message}`);
|
|
if (data) {
|
|
this.outputChannel.appendLine(this.data2String(data));
|
|
}
|
|
if (showNotification && this._clientOptions.revealOutputChannelOn <= RevealOutputChannelOn.Error) {
|
|
this.showNotificationMessage();
|
|
}
|
|
}
|
|
showNotificationMessage() {
|
|
vscode_1.window.showInformationMessage('A request has failed. See the output for more information.', 'Go to output').then(() => {
|
|
this.outputChannel.show(true);
|
|
});
|
|
}
|
|
logTrace(message, data) {
|
|
this.traceOutputChannel.appendLine(`[Trace - ${(new Date().toLocaleTimeString())}] ${message}`);
|
|
if (data) {
|
|
this.traceOutputChannel.appendLine(this.data2String(data));
|
|
}
|
|
}
|
|
logObjectTrace(data) {
|
|
if (data.isLSPMessage && data.type) {
|
|
this.traceOutputChannel.append(`[LSP - ${(new Date().toLocaleTimeString())}] `);
|
|
}
|
|
else {
|
|
this.traceOutputChannel.append(`[Trace - ${(new Date().toLocaleTimeString())}] `);
|
|
}
|
|
if (data) {
|
|
this.traceOutputChannel.appendLine(`${JSON.stringify(data)}`);
|
|
}
|
|
}
|
|
needsStart() {
|
|
return this.state === ClientState.Initial || this.state === ClientState.Stopping || this.state === ClientState.Stopped;
|
|
}
|
|
needsStop() {
|
|
return this.state === ClientState.Starting || this.state === ClientState.Running;
|
|
}
|
|
onReady() {
|
|
return this._onReady;
|
|
}
|
|
isConnectionActive() {
|
|
return this.state === ClientState.Running && !!this._resolvedConnection;
|
|
}
|
|
start() {
|
|
if (this._onReadyCallbacks.isUsed) {
|
|
this._onReady = new Promise((resolve, reject) => {
|
|
this._onReadyCallbacks = new OnReady(resolve, reject);
|
|
});
|
|
}
|
|
this._listeners = [];
|
|
this._providers = [];
|
|
// If we restart then the diagnostics collection is reused.
|
|
if (!this._diagnostics) {
|
|
this._diagnostics = this._clientOptions.diagnosticCollectionName
|
|
? vscode_1.languages.createDiagnosticCollection(this._clientOptions.diagnosticCollectionName)
|
|
: vscode_1.languages.createDiagnosticCollection();
|
|
}
|
|
this.state = ClientState.Starting;
|
|
this.resolveConnection().then((connection) => {
|
|
connection.onLogMessage((message) => {
|
|
switch (message.type) {
|
|
case vscode_languageserver_protocol_1.MessageType.Error:
|
|
this.error(message.message, undefined, false);
|
|
break;
|
|
case vscode_languageserver_protocol_1.MessageType.Warning:
|
|
this.warn(message.message, undefined, false);
|
|
break;
|
|
case vscode_languageserver_protocol_1.MessageType.Info:
|
|
this.info(message.message, undefined, false);
|
|
break;
|
|
default:
|
|
this.outputChannel.appendLine(message.message);
|
|
}
|
|
});
|
|
connection.onShowMessage((message) => {
|
|
switch (message.type) {
|
|
case vscode_languageserver_protocol_1.MessageType.Error:
|
|
vscode_1.window.showErrorMessage(message.message);
|
|
break;
|
|
case vscode_languageserver_protocol_1.MessageType.Warning:
|
|
vscode_1.window.showWarningMessage(message.message);
|
|
break;
|
|
case vscode_languageserver_protocol_1.MessageType.Info:
|
|
vscode_1.window.showInformationMessage(message.message);
|
|
break;
|
|
default:
|
|
vscode_1.window.showInformationMessage(message.message);
|
|
}
|
|
});
|
|
connection.onRequest(vscode_languageserver_protocol_1.ShowMessageRequest.type, (params) => {
|
|
let messageFunc;
|
|
switch (params.type) {
|
|
case vscode_languageserver_protocol_1.MessageType.Error:
|
|
messageFunc = vscode_1.window.showErrorMessage;
|
|
break;
|
|
case vscode_languageserver_protocol_1.MessageType.Warning:
|
|
messageFunc = vscode_1.window.showWarningMessage;
|
|
break;
|
|
case vscode_languageserver_protocol_1.MessageType.Info:
|
|
messageFunc = vscode_1.window.showInformationMessage;
|
|
break;
|
|
default:
|
|
messageFunc = vscode_1.window.showInformationMessage;
|
|
}
|
|
let actions = params.actions || [];
|
|
return messageFunc(params.message, ...actions);
|
|
});
|
|
connection.onTelemetry((data) => {
|
|
this._telemetryEmitter.fire(data);
|
|
});
|
|
connection.onRequest(vscode_languageserver_protocol_1.ShowDocumentRequest.type, async (params) => {
|
|
var _a;
|
|
const showDocument = async (params) => {
|
|
const uri = this.protocol2CodeConverter.asUri(params.uri);
|
|
try {
|
|
if (params.external === true) {
|
|
const success = await vscode_1.env.openExternal(uri);
|
|
return { success };
|
|
}
|
|
else {
|
|
const options = {};
|
|
if (params.selection !== undefined) {
|
|
options.selection = this.protocol2CodeConverter.asRange(params.selection);
|
|
}
|
|
if (params.takeFocus === undefined || params.takeFocus === false) {
|
|
options.preserveFocus = true;
|
|
}
|
|
else if (params.takeFocus === true) {
|
|
options.preserveFocus = false;
|
|
}
|
|
await vscode_1.window.showTextDocument(uri, options);
|
|
return { success: true };
|
|
}
|
|
}
|
|
catch (error) {
|
|
return { success: true };
|
|
}
|
|
};
|
|
const middleware = (_a = this._clientOptions.middleware.window) === null || _a === void 0 ? void 0 : _a.showDocument;
|
|
if (middleware !== undefined) {
|
|
return middleware(params, showDocument);
|
|
}
|
|
else {
|
|
return showDocument(params);
|
|
}
|
|
});
|
|
connection.listen();
|
|
// Error is handled in the initialize call.
|
|
return this.initialize(connection);
|
|
}).then(undefined, (error) => {
|
|
this.state = ClientState.StartFailed;
|
|
this._onReadyCallbacks.reject(error);
|
|
this.error('Starting client failed', error);
|
|
vscode_1.window.showErrorMessage(`Couldn't start client ${this._name}`);
|
|
});
|
|
return new vscode_1.Disposable(() => {
|
|
if (this.needsStop()) {
|
|
this.stop();
|
|
}
|
|
});
|
|
}
|
|
resolveConnection() {
|
|
if (!this._connectionPromise) {
|
|
this._connectionPromise = this.createConnection();
|
|
}
|
|
return this._connectionPromise;
|
|
}
|
|
initialize(connection) {
|
|
this.refreshTrace(connection, false);
|
|
let initOption = this._clientOptions.initializationOptions;
|
|
let rootPath = this._clientOptions.workspaceFolder
|
|
? this._clientOptions.workspaceFolder.uri.fsPath
|
|
: this._clientGetRootPath();
|
|
let initParams = {
|
|
processId: null,
|
|
clientInfo: {
|
|
name: vscode_1.env.appName,
|
|
version: vscode_1.version
|
|
},
|
|
locale: this.getLocale(),
|
|
rootPath: rootPath ? rootPath : null,
|
|
rootUri: rootPath ? this._c2p.asUri(vscode_1.Uri.file(rootPath)) : null,
|
|
capabilities: this.computeClientCapabilities(),
|
|
initializationOptions: Is.func(initOption) ? initOption() : initOption,
|
|
trace: vscode_languageserver_protocol_1.Trace.toString(this._trace),
|
|
workspaceFolders: null
|
|
};
|
|
this.fillInitializeParams(initParams);
|
|
if (this._clientOptions.progressOnInitialization) {
|
|
const token = UUID.generateUuid();
|
|
const part = new progressPart_1.ProgressPart(connection, token);
|
|
initParams.workDoneToken = token;
|
|
return this.doInitialize(connection, initParams).then((result) => {
|
|
part.done();
|
|
return result;
|
|
}, (error) => {
|
|
part.cancel();
|
|
throw error;
|
|
});
|
|
}
|
|
else {
|
|
return this.doInitialize(connection, initParams);
|
|
}
|
|
}
|
|
doInitialize(connection, initParams) {
|
|
return connection.initialize(initParams).then((result) => {
|
|
this._resolvedConnection = connection;
|
|
this._initializeResult = result;
|
|
this.state = ClientState.Running;
|
|
let textDocumentSyncOptions = undefined;
|
|
if (Is.number(result.capabilities.textDocumentSync)) {
|
|
if (result.capabilities.textDocumentSync === vscode_languageserver_protocol_1.TextDocumentSyncKind.None) {
|
|
textDocumentSyncOptions = {
|
|
openClose: false,
|
|
change: vscode_languageserver_protocol_1.TextDocumentSyncKind.None,
|
|
save: undefined
|
|
};
|
|
}
|
|
else {
|
|
textDocumentSyncOptions = {
|
|
openClose: true,
|
|
change: result.capabilities.textDocumentSync,
|
|
save: {
|
|
includeText: false
|
|
}
|
|
};
|
|
}
|
|
}
|
|
else if (result.capabilities.textDocumentSync !== undefined && result.capabilities.textDocumentSync !== null) {
|
|
textDocumentSyncOptions = result.capabilities.textDocumentSync;
|
|
}
|
|
this._capabilities = Object.assign({}, result.capabilities, { resolvedTextDocumentSync: textDocumentSyncOptions });
|
|
connection.onDiagnostics(params => this.handleDiagnostics(params));
|
|
connection.onRequest(vscode_languageserver_protocol_1.RegistrationRequest.type, params => this.handleRegistrationRequest(params));
|
|
// See https://github.com/Microsoft/vscode-languageserver-node/issues/199
|
|
connection.onRequest('client/registerFeature', params => this.handleRegistrationRequest(params));
|
|
connection.onRequest(vscode_languageserver_protocol_1.UnregistrationRequest.type, params => this.handleUnregistrationRequest(params));
|
|
// See https://github.com/Microsoft/vscode-languageserver-node/issues/199
|
|
connection.onRequest('client/unregisterFeature', params => this.handleUnregistrationRequest(params));
|
|
connection.onRequest(vscode_languageserver_protocol_1.ApplyWorkspaceEditRequest.type, params => this.handleApplyWorkspaceEdit(params));
|
|
connection.sendNotification(vscode_languageserver_protocol_1.InitializedNotification.type, {});
|
|
this.hookFileEvents(connection);
|
|
this.hookConfigurationChanged(connection);
|
|
this.initializeFeatures(connection);
|
|
this._onReadyCallbacks.resolve();
|
|
return result;
|
|
}).then(undefined, (error) => {
|
|
if (this._clientOptions.initializationFailedHandler) {
|
|
if (this._clientOptions.initializationFailedHandler(error)) {
|
|
this.initialize(connection);
|
|
}
|
|
else {
|
|
this.stop();
|
|
this._onReadyCallbacks.reject(error);
|
|
}
|
|
}
|
|
else if (error instanceof vscode_languageserver_protocol_1.ResponseError && error.data && error.data.retry) {
|
|
vscode_1.window.showErrorMessage(error.message, { title: 'Retry', id: 'retry' }).then(item => {
|
|
if (item && item.id === 'retry') {
|
|
this.initialize(connection);
|
|
}
|
|
else {
|
|
this.stop();
|
|
this._onReadyCallbacks.reject(error);
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
if (error && error.message) {
|
|
vscode_1.window.showErrorMessage(error.message);
|
|
}
|
|
this.error('Server initialization failed.', error);
|
|
this.stop();
|
|
this._onReadyCallbacks.reject(error);
|
|
}
|
|
throw error;
|
|
});
|
|
}
|
|
_clientGetRootPath() {
|
|
let folders = vscode_1.workspace.workspaceFolders;
|
|
if (!folders || folders.length === 0) {
|
|
return undefined;
|
|
}
|
|
let folder = folders[0];
|
|
if (folder.uri.scheme === 'file') {
|
|
return folder.uri.fsPath;
|
|
}
|
|
return undefined;
|
|
}
|
|
stop() {
|
|
this._initializeResult = undefined;
|
|
if (!this._connectionPromise) {
|
|
this.state = ClientState.Stopped;
|
|
return Promise.resolve();
|
|
}
|
|
if (this.state === ClientState.Stopping && this._onStop) {
|
|
return this._onStop;
|
|
}
|
|
this.state = ClientState.Stopping;
|
|
this.cleanUp(false);
|
|
// unhook listeners
|
|
return this._onStop = this.resolveConnection().then(connection => {
|
|
return connection.shutdown().then(() => {
|
|
connection.exit();
|
|
connection.end();
|
|
connection.dispose();
|
|
this.state = ClientState.Stopped;
|
|
this.cleanUpChannel();
|
|
this._onStop = undefined;
|
|
this._connectionPromise = undefined;
|
|
this._resolvedConnection = undefined;
|
|
});
|
|
});
|
|
}
|
|
cleanUp(channel = true, diagnostics = true) {
|
|
if (this._listeners) {
|
|
this._listeners.forEach(listener => listener.dispose());
|
|
this._listeners = undefined;
|
|
}
|
|
if (this._providers) {
|
|
this._providers.forEach(provider => provider.dispose());
|
|
this._providers = undefined;
|
|
}
|
|
if (this._syncedDocuments) {
|
|
this._syncedDocuments.clear();
|
|
}
|
|
for (const feature of this._features.values()) {
|
|
feature.dispose();
|
|
}
|
|
if (channel) {
|
|
this.cleanUpChannel();
|
|
}
|
|
if (diagnostics && this._diagnostics) {
|
|
this._diagnostics.dispose();
|
|
this._diagnostics = undefined;
|
|
}
|
|
}
|
|
cleanUpChannel() {
|
|
if (this._outputChannel && this._disposeOutputChannel) {
|
|
this._outputChannel.dispose();
|
|
this._outputChannel = undefined;
|
|
}
|
|
}
|
|
notifyFileEvent(event) {
|
|
var _a;
|
|
const client = this;
|
|
function didChangeWatchedFile(event) {
|
|
client._fileEvents.push(event);
|
|
client._fileEventDelayer.trigger(() => {
|
|
client.onReady().then(() => {
|
|
client.resolveConnection().then(connection => {
|
|
if (client.isConnectionActive()) {
|
|
client.forceDocumentSync();
|
|
connection.didChangeWatchedFiles({ changes: client._fileEvents });
|
|
}
|
|
client._fileEvents = [];
|
|
});
|
|
}, (error) => {
|
|
client.error(`Notify file events failed.`, error);
|
|
});
|
|
});
|
|
}
|
|
const workSpaceMiddleware = (_a = this.clientOptions.middleware) === null || _a === void 0 ? void 0 : _a.workspace;
|
|
(workSpaceMiddleware === null || workSpaceMiddleware === void 0 ? void 0 : workSpaceMiddleware.didChangeWatchedFile) ? workSpaceMiddleware.didChangeWatchedFile(event, didChangeWatchedFile) : didChangeWatchedFile(event);
|
|
}
|
|
forceDocumentSync() {
|
|
if (this._didChangeTextDocumentFeature === undefined) {
|
|
this._didChangeTextDocumentFeature = this._dynamicFeatures.get(vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type.method);
|
|
}
|
|
this._didChangeTextDocumentFeature.forceDelivery();
|
|
}
|
|
handleDiagnostics(params) {
|
|
if (!this._diagnostics) {
|
|
return;
|
|
}
|
|
let uri = this._p2c.asUri(params.uri);
|
|
let diagnostics = this._p2c.asDiagnostics(params.diagnostics);
|
|
let middleware = this.clientOptions.middleware;
|
|
if (middleware.handleDiagnostics) {
|
|
middleware.handleDiagnostics(uri, diagnostics, (uri, diagnostics) => this.setDiagnostics(uri, diagnostics));
|
|
}
|
|
else {
|
|
this.setDiagnostics(uri, diagnostics);
|
|
}
|
|
}
|
|
setDiagnostics(uri, diagnostics) {
|
|
if (!this._diagnostics) {
|
|
return;
|
|
}
|
|
this._diagnostics.set(uri, diagnostics);
|
|
}
|
|
createConnection() {
|
|
let errorHandler = (error, message, count) => {
|
|
this.handleConnectionError(error, message, count);
|
|
};
|
|
let closeHandler = () => {
|
|
this.handleConnectionClosed();
|
|
};
|
|
return this.createMessageTransports(this._clientOptions.stdioEncoding || 'utf8').then((transports) => {
|
|
return createConnection(transports.reader, transports.writer, errorHandler, closeHandler, this._clientOptions.connectionOptions);
|
|
});
|
|
}
|
|
handleConnectionClosed() {
|
|
// Check whether this is a normal shutdown in progress or the client stopped normally.
|
|
if (this.state === ClientState.Stopping || this.state === ClientState.Stopped) {
|
|
return;
|
|
}
|
|
try {
|
|
if (this._resolvedConnection) {
|
|
this._resolvedConnection.dispose();
|
|
}
|
|
}
|
|
catch (error) {
|
|
// Disposing a connection could fail if error cases.
|
|
}
|
|
let action = CloseAction.DoNotRestart;
|
|
try {
|
|
action = this._clientOptions.errorHandler.closed();
|
|
}
|
|
catch (error) {
|
|
// Ignore errors coming from the error handler.
|
|
}
|
|
this._connectionPromise = undefined;
|
|
this._resolvedConnection = undefined;
|
|
if (action === CloseAction.DoNotRestart) {
|
|
this.error('Connection to server got closed. Server will not be restarted.');
|
|
if (this.state === ClientState.Starting) {
|
|
this._onReadyCallbacks.reject(new Error(`Connection to server got closed. Server will not be restarted.`));
|
|
this.state = ClientState.StartFailed;
|
|
}
|
|
else {
|
|
this.state = ClientState.Stopped;
|
|
}
|
|
this.cleanUp(false, true);
|
|
}
|
|
else if (action === CloseAction.Restart) {
|
|
this.info('Connection to server got closed. Server will restart.');
|
|
this.cleanUp(false, false);
|
|
this.state = ClientState.Initial;
|
|
this.start();
|
|
}
|
|
}
|
|
handleConnectionError(error, message, count) {
|
|
let action = this._clientOptions.errorHandler.error(error, message, count);
|
|
if (action === ErrorAction.Shutdown) {
|
|
this.error('Connection to server is erroring. Shutting down server.');
|
|
this.stop();
|
|
}
|
|
}
|
|
hookConfigurationChanged(connection) {
|
|
vscode_1.workspace.onDidChangeConfiguration(() => {
|
|
this.refreshTrace(connection, true);
|
|
});
|
|
}
|
|
refreshTrace(connection, sendNotification = false) {
|
|
let config = vscode_1.workspace.getConfiguration(this._id);
|
|
let trace = vscode_languageserver_protocol_1.Trace.Off;
|
|
let traceFormat = vscode_languageserver_protocol_1.TraceFormat.Text;
|
|
if (config) {
|
|
const traceConfig = config.get('trace.server', 'off');
|
|
if (typeof traceConfig === 'string') {
|
|
trace = vscode_languageserver_protocol_1.Trace.fromString(traceConfig);
|
|
}
|
|
else {
|
|
trace = vscode_languageserver_protocol_1.Trace.fromString(config.get('trace.server.verbosity', 'off'));
|
|
traceFormat = vscode_languageserver_protocol_1.TraceFormat.fromString(config.get('trace.server.format', 'text'));
|
|
}
|
|
}
|
|
this._trace = trace;
|
|
this._traceFormat = traceFormat;
|
|
connection.trace(this._trace, this._tracer, {
|
|
sendNotification,
|
|
traceFormat: this._traceFormat
|
|
});
|
|
}
|
|
hookFileEvents(_connection) {
|
|
let fileEvents = this._clientOptions.synchronize.fileEvents;
|
|
if (!fileEvents) {
|
|
return;
|
|
}
|
|
let watchers;
|
|
if (Is.array(fileEvents)) {
|
|
watchers = fileEvents;
|
|
}
|
|
else {
|
|
watchers = [fileEvents];
|
|
}
|
|
if (!watchers) {
|
|
return;
|
|
}
|
|
this._dynamicFeatures.get(vscode_languageserver_protocol_1.DidChangeWatchedFilesNotification.type.method).registerRaw(UUID.generateUuid(), watchers);
|
|
}
|
|
registerFeatures(features) {
|
|
for (let feature of features) {
|
|
this.registerFeature(feature);
|
|
}
|
|
}
|
|
registerFeature(feature) {
|
|
this._features.push(feature);
|
|
if (DynamicFeature.is(feature)) {
|
|
const registrationType = feature.registrationType;
|
|
this._dynamicFeatures.set(registrationType.method, feature);
|
|
}
|
|
}
|
|
getFeature(request) {
|
|
return this._dynamicFeatures.get(request);
|
|
}
|
|
registerBuiltinFeatures() {
|
|
this.registerFeature(new ConfigurationFeature(this));
|
|
this.registerFeature(new DidOpenTextDocumentFeature(this, this._syncedDocuments));
|
|
this.registerFeature(new DidChangeTextDocumentFeature(this));
|
|
this.registerFeature(new WillSaveFeature(this));
|
|
this.registerFeature(new WillSaveWaitUntilFeature(this));
|
|
this.registerFeature(new DidSaveTextDocumentFeature(this));
|
|
this.registerFeature(new DidCloseTextDocumentFeature(this, this._syncedDocuments));
|
|
this.registerFeature(new FileSystemWatcherFeature(this, (event) => this.notifyFileEvent(event)));
|
|
this.registerFeature(new CompletionItemFeature(this));
|
|
this.registerFeature(new HoverFeature(this));
|
|
this.registerFeature(new SignatureHelpFeature(this));
|
|
this.registerFeature(new DefinitionFeature(this));
|
|
this.registerFeature(new ReferencesFeature(this));
|
|
this.registerFeature(new DocumentHighlightFeature(this));
|
|
this.registerFeature(new DocumentSymbolFeature(this));
|
|
this.registerFeature(new WorkspaceSymbolFeature(this));
|
|
this.registerFeature(new CodeActionFeature(this));
|
|
this.registerFeature(new CodeLensFeature(this));
|
|
this.registerFeature(new DocumentFormattingFeature(this));
|
|
this.registerFeature(new DocumentRangeFormattingFeature(this));
|
|
this.registerFeature(new DocumentOnTypeFormattingFeature(this));
|
|
this.registerFeature(new RenameFeature(this));
|
|
this.registerFeature(new DocumentLinkFeature(this));
|
|
this.registerFeature(new ExecuteCommandFeature(this));
|
|
}
|
|
fillInitializeParams(params) {
|
|
for (let feature of this._features) {
|
|
if (Is.func(feature.fillInitializeParams)) {
|
|
feature.fillInitializeParams(params);
|
|
}
|
|
}
|
|
}
|
|
computeClientCapabilities() {
|
|
const result = {};
|
|
ensure(result, 'workspace').applyEdit = true;
|
|
const workspaceEdit = ensure(ensure(result, 'workspace'), 'workspaceEdit');
|
|
workspaceEdit.documentChanges = true;
|
|
workspaceEdit.resourceOperations = [vscode_languageserver_protocol_1.ResourceOperationKind.Create, vscode_languageserver_protocol_1.ResourceOperationKind.Rename, vscode_languageserver_protocol_1.ResourceOperationKind.Delete];
|
|
workspaceEdit.failureHandling = vscode_languageserver_protocol_1.FailureHandlingKind.TextOnlyTransactional;
|
|
workspaceEdit.normalizesLineEndings = true;
|
|
workspaceEdit.changeAnnotationSupport = {
|
|
groupsOnLabel: true
|
|
};
|
|
const diagnostics = ensure(ensure(result, 'textDocument'), 'publishDiagnostics');
|
|
diagnostics.relatedInformation = true;
|
|
diagnostics.versionSupport = false;
|
|
diagnostics.tagSupport = { valueSet: [vscode_languageserver_protocol_1.DiagnosticTag.Unnecessary, vscode_languageserver_protocol_1.DiagnosticTag.Deprecated] };
|
|
diagnostics.codeDescriptionSupport = true;
|
|
diagnostics.dataSupport = true;
|
|
const windowCapabilities = ensure(result, 'window');
|
|
const showMessage = ensure(windowCapabilities, 'showMessage');
|
|
showMessage.messageActionItem = { additionalPropertiesSupport: true };
|
|
const showDocument = ensure(windowCapabilities, 'showDocument');
|
|
showDocument.support = true;
|
|
const generalCapabilities = ensure(result, 'general');
|
|
generalCapabilities.regularExpressions = { engine: 'ECMAScript', version: 'ES2020' };
|
|
generalCapabilities.markdown = { parser: 'marked', version: '1.1.0' };
|
|
for (let feature of this._features) {
|
|
feature.fillClientCapabilities(result);
|
|
}
|
|
return result;
|
|
}
|
|
initializeFeatures(_connection) {
|
|
let documentSelector = this._clientOptions.documentSelector;
|
|
for (let feature of this._features) {
|
|
feature.initialize(this._capabilities, documentSelector);
|
|
}
|
|
}
|
|
handleRegistrationRequest(params) {
|
|
return new Promise((resolve, reject) => {
|
|
for (const registration of params.registrations) {
|
|
const feature = this._dynamicFeatures.get(registration.method);
|
|
if (feature === undefined) {
|
|
reject(new Error(`No feature implementation for ${registration.method} found. Registration failed.`));
|
|
return;
|
|
}
|
|
const options = registration.registerOptions || {};
|
|
options.documentSelector = options.documentSelector || this._clientOptions.documentSelector;
|
|
const data = {
|
|
id: registration.id,
|
|
registerOptions: options
|
|
};
|
|
try {
|
|
feature.register(data);
|
|
}
|
|
catch (err) {
|
|
reject(err);
|
|
return;
|
|
}
|
|
}
|
|
resolve();
|
|
});
|
|
}
|
|
handleUnregistrationRequest(params) {
|
|
return new Promise((resolve, reject) => {
|
|
for (let unregistration of params.unregisterations) {
|
|
const feature = this._dynamicFeatures.get(unregistration.method);
|
|
if (!feature) {
|
|
reject(new Error(`No feature implementation for ${unregistration.method} found. Unregistration failed.`));
|
|
return;
|
|
}
|
|
feature.unregister(unregistration.id);
|
|
}
|
|
resolve();
|
|
});
|
|
}
|
|
handleApplyWorkspaceEdit(params) {
|
|
// This is some sort of workaround since the version check should be done by VS Code in the Workspace.applyEdit.
|
|
// However doing it here adds some safety since the server can lag more behind then an extension.
|
|
let workspaceEdit = params.edit;
|
|
let openTextDocuments = new Map();
|
|
vscode_1.workspace.textDocuments.forEach((document) => openTextDocuments.set(document.uri.toString(), document));
|
|
let versionMismatch = false;
|
|
if (workspaceEdit.documentChanges) {
|
|
for (const change of workspaceEdit.documentChanges) {
|
|
if (vscode_languageserver_protocol_1.TextDocumentEdit.is(change) && change.textDocument.version && change.textDocument.version >= 0) {
|
|
let textDocument = openTextDocuments.get(change.textDocument.uri);
|
|
if (textDocument && textDocument.version !== change.textDocument.version) {
|
|
versionMismatch = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (versionMismatch) {
|
|
return Promise.resolve({ applied: false });
|
|
}
|
|
return Is.asPromise(vscode_1.workspace.applyEdit(this._p2c.asWorkspaceEdit(params.edit)).then((value) => { return { applied: value }; }));
|
|
}
|
|
handleFailedRequest(type, error, defaultValue) {
|
|
// If we get a request cancel or a content modified don't log anything.
|
|
if (error instanceof vscode_languageserver_protocol_1.ResponseError) {
|
|
if (error.code === vscode_languageserver_protocol_1.LSPErrorCodes.RequestCancelled) {
|
|
throw this.makeCancelError();
|
|
}
|
|
else if (error.code === vscode_languageserver_protocol_1.LSPErrorCodes.ContentModified) {
|
|
return defaultValue;
|
|
}
|
|
}
|
|
this.error(`Request ${type.method} failed.`, error);
|
|
throw error;
|
|
}
|
|
makeCancelError() {
|
|
const result = new Error(BaseLanguageClient.Canceled);
|
|
result.name = BaseLanguageClient.Canceled;
|
|
return result;
|
|
}
|
|
}
|
|
exports.BaseLanguageClient = BaseLanguageClient;
|
|
BaseLanguageClient.Canceled = 'Canceled';
|
|
//# sourceMappingURL=client.js.map
|