Upsilon-VsCode/Client/node_modules/vscode-languageclient/lib/client.js

2237 lines
99 KiB
JavaScript
Executable File

/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
const vscode_1 = require("vscode");
const vscode_languageserver_protocol_1 = require("vscode-languageserver-protocol");
const c2p = require("./codeConverter");
const p2c = require("./protocolConverter");
const Is = require("./utils/is");
const async_1 = require("./utils/async");
const UUID = require("./utils/uuid");
__export(require("vscode-languageserver-protocol"));
class ConsoleLogger {
error(message) {
console.error(message);
}
warn(message) {
console.warn(message);
}
info(message) {
console.info(message);
}
log(message) {
console.log(message);
}
}
function createConnection(input, output, errorHandler, closeHandler) {
let logger = new ConsoleLogger();
let connection = vscode_languageserver_protocol_1.createProtocolConnection(input, output, logger);
connection.onError((data) => { errorHandler(data[0], data[1], data[2]); });
connection.onClose(closeHandler);
let result = {
listen: () => connection.listen(),
sendRequest: (type, ...params) => connection.sendRequest(Is.string(type) ? type : type.method, ...params),
onRequest: (type, handler) => connection.onRequest(Is.string(type) ? type : type.method, handler),
sendNotification: (type, params) => connection.sendNotification(Is.string(type) ? type : type.method, params),
onNotification: (type, handler) => connection.onNotification(Is.string(type) ? type : type.method, handler),
trace: (value, tracer, sendNotification = false) => connection.trace(value, tracer, sendNotification),
initialize: (params) => connection.sendRequest(vscode_languageserver_protocol_1.InitializeRequest.type, params),
shutdown: () => connection.sendRequest(vscode_languageserver_protocol_1.ShutdownRequest.type, undefined),
exit: () => connection.sendNotification(vscode_languageserver_protocol_1.ExitNotification.type),
onLogMessage: (handler) => connection.onNotification(vscode_languageserver_protocol_1.LogMessageNotification.type, handler),
onShowMessage: (handler) => connection.onNotification(vscode_languageserver_protocol_1.ShowMessageNotification.type, handler),
onTelemetry: (handler) => connection.onNotification(vscode_languageserver_protocol_1.TelemetryEventNotification.type, handler),
didChangeConfiguration: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidChangeConfigurationNotification.type, params),
didChangeWatchedFiles: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidChangeWatchedFilesNotification.type, params),
didOpenTextDocument: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidOpenTextDocumentNotification.type, params),
didChangeTextDocument: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type, params),
didCloseTextDocument: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidCloseTextDocumentNotification.type, params),
didSaveTextDocument: (params) => connection.sendNotification(vscode_languageserver_protocol_1.DidSaveTextDocumentNotification.type, params),
onDiagnostics: (handler) => connection.onNotification(vscode_languageserver_protocol_1.PublishDiagnosticsNotification.type, handler),
dispose: () => connection.dispose()
};
return result;
}
/**
* An action to be performed when the connection is producing errors.
*/
var ErrorAction;
(function (ErrorAction) {
/**
* Continue running the server.
*/
ErrorAction[ErrorAction["Continue"] = 1] = "Continue";
/**
* Shutdown the server.
*/
ErrorAction[ErrorAction["Shutdown"] = 2] = "Shutdown";
})(ErrorAction = exports.ErrorAction || (exports.ErrorAction = {}));
/**
* An action to be performed when the connection to a server got closed.
*/
var CloseAction;
(function (CloseAction) {
/**
* Don't restart the server. The connection stays closed.
*/
CloseAction[CloseAction["DoNotRestart"] = 1] = "DoNotRestart";
/**
* Restart the server.
*/
CloseAction[CloseAction["Restart"] = 2] = "Restart";
})(CloseAction = exports.CloseAction || (exports.CloseAction = {}));
class DefaultErrorHandler {
constructor(name) {
this.name = name;
this.restarts = [];
}
error(_error, _message, count) {
if (count && count <= 3) {
return ErrorAction.Continue;
}
return ErrorAction.Shutdown;
}
closed() {
this.restarts.push(Date.now());
if (this.restarts.length < 5) {
return CloseAction.Restart;
}
else {
let diff = this.restarts[this.restarts.length - 1] - this.restarts[0];
if (diff <= 3 * 60 * 1000) {
vscode_1.window.showErrorMessage(`The ${this.name} server crashed 5 times in the last 3 minutes. The server will not be restarted.`);
return CloseAction.DoNotRestart;
}
else {
this.restarts.shift();
return CloseAction.Restart;
}
}
}
}
var RevealOutputChannelOn;
(function (RevealOutputChannelOn) {
RevealOutputChannelOn[RevealOutputChannelOn["Info"] = 1] = "Info";
RevealOutputChannelOn[RevealOutputChannelOn["Warn"] = 2] = "Warn";
RevealOutputChannelOn[RevealOutputChannelOn["Error"] = 3] = "Error";
RevealOutputChannelOn[RevealOutputChannelOn["Never"] = 4] = "Never";
})(RevealOutputChannelOn = exports.RevealOutputChannelOn || (exports.RevealOutputChannelOn = {}));
var State;
(function (State) {
State[State["Stopped"] = 1] = "Stopped";
State[State["Running"] = 2] = "Running";
})(State = 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 SupporedSymbolKinds = [
vscode_languageserver_protocol_1.SymbolKind.File,
vscode_languageserver_protocol_1.SymbolKind.Module,
vscode_languageserver_protocol_1.SymbolKind.Namespace,
vscode_languageserver_protocol_1.SymbolKind.Package,
vscode_languageserver_protocol_1.SymbolKind.Class,
vscode_languageserver_protocol_1.SymbolKind.Method,
vscode_languageserver_protocol_1.SymbolKind.Property,
vscode_languageserver_protocol_1.SymbolKind.Field,
vscode_languageserver_protocol_1.SymbolKind.Constructor,
vscode_languageserver_protocol_1.SymbolKind.Enum,
vscode_languageserver_protocol_1.SymbolKind.Interface,
vscode_languageserver_protocol_1.SymbolKind.Function,
vscode_languageserver_protocol_1.SymbolKind.Variable,
vscode_languageserver_protocol_1.SymbolKind.Constant,
vscode_languageserver_protocol_1.SymbolKind.String,
vscode_languageserver_protocol_1.SymbolKind.Number,
vscode_languageserver_protocol_1.SymbolKind.Boolean,
vscode_languageserver_protocol_1.SymbolKind.Array,
vscode_languageserver_protocol_1.SymbolKind.Object,
vscode_languageserver_protocol_1.SymbolKind.Key,
vscode_languageserver_protocol_1.SymbolKind.Null,
vscode_languageserver_protocol_1.SymbolKind.EnumMember,
vscode_languageserver_protocol_1.SymbolKind.Struct,
vscode_languageserver_protocol_1.SymbolKind.Event,
vscode_languageserver_protocol_1.SymbolKind.Operator,
vscode_languageserver_protocol_1.SymbolKind.TypeParameter
];
const SupportedCompletionItemKinds = [
vscode_languageserver_protocol_1.CompletionItemKind.Text,
vscode_languageserver_protocol_1.CompletionItemKind.Method,
vscode_languageserver_protocol_1.CompletionItemKind.Function,
vscode_languageserver_protocol_1.CompletionItemKind.Constructor,
vscode_languageserver_protocol_1.CompletionItemKind.Field,
vscode_languageserver_protocol_1.CompletionItemKind.Variable,
vscode_languageserver_protocol_1.CompletionItemKind.Class,
vscode_languageserver_protocol_1.CompletionItemKind.Interface,
vscode_languageserver_protocol_1.CompletionItemKind.Module,
vscode_languageserver_protocol_1.CompletionItemKind.Property,
vscode_languageserver_protocol_1.CompletionItemKind.Unit,
vscode_languageserver_protocol_1.CompletionItemKind.Value,
vscode_languageserver_protocol_1.CompletionItemKind.Enum,
vscode_languageserver_protocol_1.CompletionItemKind.Keyword,
vscode_languageserver_protocol_1.CompletionItemKind.Snippet,
vscode_languageserver_protocol_1.CompletionItemKind.Color,
vscode_languageserver_protocol_1.CompletionItemKind.File,
vscode_languageserver_protocol_1.CompletionItemKind.Reference,
vscode_languageserver_protocol_1.CompletionItemKind.Folder,
vscode_languageserver_protocol_1.CompletionItemKind.EnumMember,
vscode_languageserver_protocol_1.CompletionItemKind.Constant,
vscode_languageserver_protocol_1.CompletionItemKind.Struct,
vscode_languageserver_protocol_1.CompletionItemKind.Event,
vscode_languageserver_protocol_1.CompletionItemKind.Operator,
vscode_languageserver_protocol_1.CompletionItemKind.TypeParameter
];
function ensure(target, key) {
if (target[key] === void 0) {
target[key] = {};
}
return target[key];
}
var DynamicFeature;
(function (DynamicFeature) {
function is(value) {
let candidate = value;
return candidate && Is.func(candidate.register) && Is.func(candidate.unregister) && Is.func(candidate.dispose) && candidate.messages !== void 0;
}
DynamicFeature.is = is;
})(DynamicFeature || (DynamicFeature = {}));
class DocumentNotifiactions {
constructor(_client, _event, _type, _middleware, _createParams, _selectorFilter) {
this._client = _client;
this._event = _event;
this._type = _type;
this._middleware = _middleware;
this._createParams = _createParams;
this._selectorFilter = _selectorFilter;
this._selectors = new Map();
}
static textDocumentFilter(selectors, textDocument) {
for (const selector of selectors) {
if (vscode_1.languages.match(selector, textDocument)) {
return true;
}
}
return false;
}
register(_message, data) {
if (!data.registerOptions.documentSelector) {
return;
}
if (!this._listener) {
this._listener = this._event(this.callback, this);
}
this._selectors.set(data.id, data.registerOptions.documentSelector);
}
callback(data) {
if (!this._selectorFilter || this._selectorFilter(this._selectors.values(), data)) {
if (this._middleware) {
this._middleware(data, (data) => this._client.sendNotification(this._type, this._createParams(data)));
}
else {
this._client.sendNotification(this._type, this._createParams(data));
}
this.notificationSent(data);
}
}
notificationSent(_data) {
}
unregister(id) {
this._selectors.delete(id);
if (this._selectors.size === 0 && this._listener) {
this._listener.dispose();
this._listener = undefined;
}
}
dispose() {
this._selectors.clear();
if (this._listener) {
this._listener.dispose();
}
}
}
class DidOpenTextDocumentFeature extends DocumentNotifiactions {
constructor(client, _syncedDocuments) {
super(client, vscode_1.workspace.onDidOpenTextDocument, vscode_languageserver_protocol_1.DidOpenTextDocumentNotification.type, client.clientOptions.middleware.didOpen, (textDocument) => client.code2ProtocolConverter.asOpenTextDocumentParams(textDocument), DocumentNotifiactions.textDocumentFilter);
this._syncedDocuments = _syncedDocuments;
}
get messages() {
return vscode_languageserver_protocol_1.DidOpenTextDocumentNotification.type;
}
fillClientCapabilities(capabilities) {
ensure(ensure(capabilities, 'textDocument'), 'synchronization').dynamicRegistration = true;
}
initialize(capabilities, documentSelector) {
let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync;
if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.openClose) {
this.register(this.messages, { id: UUID.generateUuid(), registerOptions: { documentSelector: documentSelector } });
}
}
register(message, data) {
super.register(message, data);
if (!data.registerOptions.documentSelector) {
return;
}
let documentSelector = data.registerOptions.documentSelector;
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 DocumentNotifiactions {
constructor(client, _syncedDocuments) {
super(client, vscode_1.workspace.onDidCloseTextDocument, vscode_languageserver_protocol_1.DidCloseTextDocumentNotification.type, client.clientOptions.middleware.didClose, (textDocument) => client.code2ProtocolConverter.asCloseTextDocumentParams(textDocument), DocumentNotifiactions.textDocumentFilter);
this._syncedDocuments = _syncedDocuments;
}
get messages() {
return vscode_languageserver_protocol_1.DidCloseTextDocumentNotification.type;
}
fillClientCapabilities(capabilities) {
ensure(ensure(capabilities, 'textDocument'), 'synchronization').dynamicRegistration = true;
}
initialize(capabilities, documentSelector) {
let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync;
if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.openClose) {
this.register(this.messages, { id: UUID.generateUuid(), registerOptions: { documentSelector: documentSelector } });
}
}
notificationSent(textDocument) {
super.notificationSent(textDocument);
this._syncedDocuments.delete(textDocument.uri.toString());
}
unregister(id) {
let selector = this._selectors.get(id);
// The super call removed the selector from the map
// of selectors.
super.unregister(id);
let selectors = this._selectors.values();
this._syncedDocuments.forEach((textDocument) => {
if (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 messages() {
return vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type;
}
fillClientCapabilities(capabilities) {
ensure(ensure(capabilities, 'textDocument'), 'synchronization').dynamicRegistration = true;
}
initialize(capabilities, documentSelector) {
let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync;
if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.change !== void 0 && textDocumentSyncOptions.change !== vscode_languageserver_protocol_1.TextDocumentSyncKind.None) {
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: Object.assign({}, { documentSelector: documentSelector }, { syncKind: textDocumentSyncOptions.change })
});
}
}
register(_message, data) {
if (!data.registerOptions.documentSelector) {
return;
}
if (!this._listener) {
this._listener = 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 / undirty 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;
}
}
}
class WillSaveFeature extends DocumentNotifiactions {
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) => DocumentNotifiactions.textDocumentFilter(selectors, willSaveEvent.document));
}
get messages() {
return vscode_languageserver_protocol_1.WillSaveTextDocumentNotification.type;
}
fillClientCapabilities(capabilities) {
let value = ensure(ensure(capabilities, 'textDocument'), 'synchronization');
value.willSave = true;
}
initialize(capabilities, documentSelector) {
let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync;
if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.willSave) {
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: { documentSelector: documentSelector }
});
}
}
}
class WillSaveWaitUntilFeature {
constructor(_client) {
this._client = _client;
this._selectors = new Map();
}
get messages() {
return vscode_languageserver_protocol_1.WillSaveTextDocumentWaitUntilRequest.type;
}
fillClientCapabilities(capabilities) {
let value = ensure(ensure(capabilities, 'textDocument'), 'synchronization');
value.willSaveWaitUntil = true;
}
initialize(capabilities, documentSelector) {
let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync;
if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.willSaveWaitUntil) {
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: { documentSelector: documentSelector }
});
}
}
register(_message, data) {
if (!data.registerOptions.documentSelector) {
return;
}
if (!this._listener) {
this._listener = vscode_1.workspace.onWillSaveTextDocument(this.callback, this);
}
this._selectors.set(data.id, data.registerOptions.documentSelector);
}
callback(event) {
if (DocumentNotifiactions.textDocumentFilter(this._selectors.values(), event.document)) {
let middleware = this._client.clientOptions.middleware;
let willSaveWaitUntil = (event) => {
return this._client.sendRequest(vscode_languageserver_protocol_1.WillSaveTextDocumentWaitUntilRequest.type, this._client.code2ProtocolConverter.asWillSaveTextDocumentParams(event)).then((edits) => {
let vEdits = this._client.protocol2CodeConverter.asTextEdits(edits);
return vEdits === void 0 ? [] : 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 DocumentNotifiactions {
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), DocumentNotifiactions.textDocumentFilter);
}
get messages() {
return vscode_languageserver_protocol_1.DidSaveTextDocumentNotification.type;
}
fillClientCapabilities(capabilities) {
ensure(ensure(capabilities, 'textDocument'), 'synchronization').didSave = true;
}
initialize(capabilities, documentSelector) {
let textDocumentSyncOptions = capabilities.resolvedTextDocumentSync;
if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.save) {
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: Object.assign({}, { documentSelector: documentSelector }, { includeText: !!textDocumentSyncOptions.save.includeText })
});
}
}
register(method, data) {
this._includeText = !!data.registerOptions.includeText;
super.register(method, data);
}
}
class FileSystemWatcherFeature {
constructor(_client, _notifyFileEvent) {
this._client = _client;
this._notifyFileEvent = _notifyFileEvent;
this._watchers = new Map();
}
get messages() {
return vscode_languageserver_protocol_1.DidChangeWatchedFilesNotification.type;
}
fillClientCapabilities(capabilities) {
ensure(ensure(capabilities, 'workspace'), 'didChangeWatchedFiles').dynamicRegistration = true;
}
initialize(_capabilities, _documentSelector) {
}
register(_method, data) {
if (!Array.isArray(data.registerOptions.watchers)) {
return;
}
let disposeables = [];
for (let watcher of data.registerOptions.watchers) {
if (!Is.string(watcher.globPattern)) {
continue;
}
let watchCreate = true, watchChange = true, watchDelete = true;
if (watcher.kind !== void 0 && 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);
disposeables.push(fileSystemWatcher);
}
this._watchers.set(data.id, disposeables);
}
registerRaw(id, fileSystemWatchers) {
let disposeables = [];
for (let fileSystemWatcher of fileSystemWatchers) {
this.hookListeners(fileSystemWatcher, true, true, true, disposeables);
}
this._watchers.set(id, disposeables);
}
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 disposeables = this._watchers.get(id);
if (disposeables) {
for (let disposable of disposeables) {
disposable.dispose();
}
}
}
dispose() {
this._watchers.forEach((disposeables) => {
for (let disposable of disposeables) {
disposable.dispose();
}
});
this._watchers.clear();
}
}
class TextDocumentFeature {
constructor(_client, _message) {
this._client = _client;
this._message = _message;
this._providers = new Map();
}
get messages() {
return this._message;
}
register(message, data) {
if (message.method !== this.messages.method) {
throw new Error(`Register called on wrong feature. Requested ${message.method} but reached feature ${this.messages.method}`);
}
if (!data.registerOptions.documentSelector) {
return;
}
let provider = this.registerLanguageProvider(data.registerOptions);
if (provider) {
this._providers.set(data.id, provider);
}
}
unregister(id) {
let provider = this._providers.get(id);
if (provider) {
provider.dispose();
}
}
dispose() {
this._providers.forEach((value) => {
value.dispose();
});
this._providers.clear();
}
}
exports.TextDocumentFeature = TextDocumentFeature;
class WorkspaceFeature {
constructor(_client, _message) {
this._client = _client;
this._message = _message;
this._providers = new Map();
}
get messages() {
return this._message;
}
register(message, data) {
if (message.method !== this.messages.method) {
throw new Error(`Register called on wron feature. Requested ${message.method} but reached feature ${this.messages.method}`);
}
let provider = this.registerLanguageProvider(data.registerOptions);
if (provider) {
this._providers.set(data.id, provider);
}
}
unregister(id) {
let provider = this._providers.get(id);
if (provider) {
provider.dispose();
}
}
dispose() {
this._providers.forEach((value) => {
value.dispose();
});
this._providers.clear();
}
}
class CompletionItemFeature extends TextDocumentFeature {
constructor(client) {
super(client, vscode_languageserver_protocol_1.CompletionRequest.type);
}
fillClientCapabilities(capabilites) {
let completion = ensure(ensure(capabilites, 'textDocument'), 'completion');
completion.dynamicRegistration = true;
completion.contextSupport = true;
completion.completionItem = {
snippetSupport: true,
commitCharactersSupport: true,
documentationFormat: [vscode_languageserver_protocol_1.MarkupKind.Markdown, vscode_languageserver_protocol_1.MarkupKind.PlainText],
deprecatedSupport: true,
preselectSupport: true
};
completion.completionItemKind = { valueSet: SupportedCompletionItemKinds };
}
initialize(capabilities, documentSelector) {
if (!capabilities.completionProvider || !documentSelector) {
return;
}
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: Object.assign({}, { documentSelector: documentSelector }, capabilities.completionProvider)
});
}
registerLanguageProvider(options) {
let triggerCharacters = options.triggerCharacters || [];
let client = this._client;
let provideCompletionItems = (document, position, context, token) => {
return client.sendRequest(vscode_languageserver_protocol_1.CompletionRequest.type, client.code2ProtocolConverter.asCompletionParams(document, position, context), token).then(client.protocol2CodeConverter.asCompletionResult, (error) => {
client.logFailedRequest(vscode_languageserver_protocol_1.CompletionRequest.type, error);
return Promise.resolve([]);
});
};
let resolveCompletionItem = (item, token) => {
return client.sendRequest(vscode_languageserver_protocol_1.CompletionResolveRequest.type, client.code2ProtocolConverter.asCompletionItem(item), token).then(client.protocol2CodeConverter.asCompletionItem, (error) => {
client.logFailedRequest(vscode_languageserver_protocol_1.CompletionResolveRequest.type, error);
return Promise.resolve(item);
});
};
let middleware = this._client.clientOptions.middleware;
return vscode_1.languages.registerCompletionItemProvider(options.documentSelector, {
provideCompletionItems: (document, position, token, context) => {
return middleware.provideCompletionItem
? middleware.provideCompletionItem(document, position, context, token, provideCompletionItems)
: provideCompletionItems(document, position, context, token);
},
resolveCompletionItem: options.resolveProvider
? (item, token) => {
return middleware.resolveCompletionItem
? middleware.resolveCompletionItem(item, token, resolveCompletionItem)
: resolveCompletionItem(item, token);
}
: undefined
}, ...triggerCharacters);
}
}
class HoverFeature extends TextDocumentFeature {
constructor(client) {
super(client, vscode_languageserver_protocol_1.HoverRequest.type);
}
fillClientCapabilities(capabilites) {
const hoverCapability = (ensure(ensure(capabilites, 'textDocument'), 'hover'));
hoverCapability.dynamicRegistration = true;
hoverCapability.contentFormat = [vscode_languageserver_protocol_1.MarkupKind.Markdown, vscode_languageserver_protocol_1.MarkupKind.PlainText];
}
initialize(capabilities, documentSelector) {
if (!capabilities.hoverProvider || !documentSelector) {
return;
}
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: Object.assign({}, { documentSelector: documentSelector })
});
}
registerLanguageProvider(options) {
let client = this._client;
let provideHover = (document, position, token) => {
return client.sendRequest(vscode_languageserver_protocol_1.HoverRequest.type, client.code2ProtocolConverter.asTextDocumentPositionParams(document, position), token).then(client.protocol2CodeConverter.asHover, (error) => {
client.logFailedRequest(vscode_languageserver_protocol_1.HoverRequest.type, error);
return Promise.resolve(null);
});
};
let middleware = client.clientOptions.middleware;
return vscode_1.languages.registerHoverProvider(options.documentSelector, {
provideHover: (document, position, token) => {
return middleware.provideHover
? middleware.provideHover(document, position, token, provideHover)
: provideHover(document, position, token);
}
});
}
}
class SignatureHelpFeature extends TextDocumentFeature {
constructor(client) {
super(client, vscode_languageserver_protocol_1.SignatureHelpRequest.type);
}
fillClientCapabilities(capabilites) {
let config = ensure(ensure(capabilites, 'textDocument'), 'signatureHelp');
config.dynamicRegistration = true;
config.signatureInformation = { documentationFormat: [vscode_languageserver_protocol_1.MarkupKind.Markdown, vscode_languageserver_protocol_1.MarkupKind.PlainText] };
}
initialize(capabilities, documentSelector) {
if (!capabilities.signatureHelpProvider || !documentSelector) {
return;
}
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: Object.assign({}, { documentSelector: documentSelector }, capabilities.signatureHelpProvider)
});
}
registerLanguageProvider(options) {
let client = this._client;
let providerSignatureHelp = (document, position, token) => {
return client.sendRequest(vscode_languageserver_protocol_1.SignatureHelpRequest.type, client.code2ProtocolConverter.asTextDocumentPositionParams(document, position), token).then(client.protocol2CodeConverter.asSignatureHelp, (error) => {
client.logFailedRequest(vscode_languageserver_protocol_1.SignatureHelpRequest.type, error);
return Promise.resolve(null);
});
};
let middleware = client.clientOptions.middleware;
let triggerCharacters = options.triggerCharacters || [];
return vscode_1.languages.registerSignatureHelpProvider(options.documentSelector, {
provideSignatureHelp: (document, position, token) => {
return middleware.provideSignatureHelp
? middleware.provideSignatureHelp(document, position, token, providerSignatureHelp)
: providerSignatureHelp(document, position, token);
}
}, ...triggerCharacters);
}
}
class DefinitionFeature extends TextDocumentFeature {
constructor(client) {
super(client, vscode_languageserver_protocol_1.DefinitionRequest.type);
}
fillClientCapabilities(capabilites) {
ensure(ensure(capabilites, 'textDocument'), 'definition').dynamicRegistration = true;
}
initialize(capabilities, documentSelector) {
if (!capabilities.definitionProvider || !documentSelector) {
return;
}
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: Object.assign({}, { documentSelector: documentSelector })
});
}
registerLanguageProvider(options) {
let client = this._client;
let provideDefinition = (document, position, token) => {
return client.sendRequest(vscode_languageserver_protocol_1.DefinitionRequest.type, client.code2ProtocolConverter.asTextDocumentPositionParams(document, position), token).then(client.protocol2CodeConverter.asDefinitionResult, (error) => {
client.logFailedRequest(vscode_languageserver_protocol_1.DefinitionRequest.type, error);
return Promise.resolve(null);
});
};
let middleware = client.clientOptions.middleware;
return vscode_1.languages.registerDefinitionProvider(options.documentSelector, {
provideDefinition: (document, position, token) => {
return middleware.provideDefinition
? middleware.provideDefinition(document, position, token, provideDefinition)
: provideDefinition(document, position, token);
}
});
}
}
class ReferencesFeature extends TextDocumentFeature {
constructor(client) {
super(client, vscode_languageserver_protocol_1.ReferencesRequest.type);
}
fillClientCapabilities(capabilites) {
ensure(ensure(capabilites, 'textDocument'), 'references').dynamicRegistration = true;
}
initialize(capabilities, documentSelector) {
if (!capabilities.referencesProvider || !documentSelector) {
return;
}
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: Object.assign({}, { documentSelector: documentSelector })
});
}
registerLanguageProvider(options) {
let client = this._client;
let providerReferences = (document, position, options, token) => {
return client.sendRequest(vscode_languageserver_protocol_1.ReferencesRequest.type, client.code2ProtocolConverter.asReferenceParams(document, position, options), token).then(client.protocol2CodeConverter.asReferences, (error) => {
client.logFailedRequest(vscode_languageserver_protocol_1.ReferencesRequest.type, error);
return Promise.resolve([]);
});
};
let middleware = client.clientOptions.middleware;
return vscode_1.languages.registerReferenceProvider(options.documentSelector, {
provideReferences: (document, position, options, token) => {
return middleware.provideReferences
? middleware.provideReferences(document, position, options, token, providerReferences)
: providerReferences(document, position, options, token);
}
});
}
}
class DocumentHighlightFeature extends TextDocumentFeature {
constructor(client) {
super(client, vscode_languageserver_protocol_1.DocumentHighlightRequest.type);
}
fillClientCapabilities(capabilites) {
ensure(ensure(capabilites, 'textDocument'), 'documentHighlight').dynamicRegistration = true;
}
initialize(capabilities, documentSelector) {
if (!capabilities.documentHighlightProvider || !documentSelector) {
return;
}
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: Object.assign({}, { documentSelector: documentSelector })
});
}
registerLanguageProvider(options) {
let client = this._client;
let provideDocumentHighlights = (document, position, token) => {
return client.sendRequest(vscode_languageserver_protocol_1.DocumentHighlightRequest.type, client.code2ProtocolConverter.asTextDocumentPositionParams(document, position), token).then(client.protocol2CodeConverter.asDocumentHighlights, (error) => {
client.logFailedRequest(vscode_languageserver_protocol_1.DocumentHighlightRequest.type, error);
return Promise.resolve([]);
});
};
let middleware = client.clientOptions.middleware;
return vscode_1.languages.registerDocumentHighlightProvider(options.documentSelector, {
provideDocumentHighlights: (document, position, token) => {
return middleware.provideDocumentHighlights
? middleware.provideDocumentHighlights(document, position, token, provideDocumentHighlights)
: provideDocumentHighlights(document, position, token);
}
});
}
}
class DocumentSymbolFeature extends TextDocumentFeature {
constructor(client) {
super(client, vscode_languageserver_protocol_1.DocumentSymbolRequest.type);
}
fillClientCapabilities(capabilites) {
let symbolCapabilities = ensure(ensure(capabilites, 'textDocument'), 'documentSymbol');
symbolCapabilities.dynamicRegistration = true;
symbolCapabilities.symbolKind = {
valueSet: SupporedSymbolKinds
};
symbolCapabilities.hierarchicalDocumentSymbolSupport = true;
}
initialize(capabilities, documentSelector) {
if (!capabilities.documentSymbolProvider || !documentSelector) {
return;
}
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: Object.assign({}, { documentSelector: documentSelector })
});
}
registerLanguageProvider(options) {
let client = this._client;
let provideDocumentSymbols = (document, token) => {
return client.sendRequest(vscode_languageserver_protocol_1.DocumentSymbolRequest.type, 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) => {
client.logFailedRequest(vscode_languageserver_protocol_1.DocumentSymbolRequest.type, error);
return Promise.resolve([]);
});
};
let middleware = client.clientOptions.middleware;
return vscode_1.languages.registerDocumentSymbolProvider(options.documentSelector, {
provideDocumentSymbols: (document, token) => {
return middleware.provideDocumentSymbols
? middleware.provideDocumentSymbols(document, token, provideDocumentSymbols)
: provideDocumentSymbols(document, token);
}
});
}
}
class WorkspaceSymbolFeature extends WorkspaceFeature {
constructor(client) {
super(client, vscode_languageserver_protocol_1.WorkspaceSymbolRequest.type);
}
fillClientCapabilities(capabilites) {
let symbolCapabilities = ensure(ensure(capabilites, 'workspace'), 'symbol');
symbolCapabilities.dynamicRegistration = true;
symbolCapabilities.symbolKind = {
valueSet: SupporedSymbolKinds
};
}
initialize(capabilities) {
if (!capabilities.workspaceSymbolProvider) {
return;
}
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: undefined
});
}
registerLanguageProvider(_options) {
let client = this._client;
let provideWorkspaceSymbols = (query, token) => {
return client.sendRequest(vscode_languageserver_protocol_1.WorkspaceSymbolRequest.type, { query }, token).then(client.protocol2CodeConverter.asSymbolInformations, (error) => {
client.logFailedRequest(vscode_languageserver_protocol_1.WorkspaceSymbolRequest.type, error);
return Promise.resolve([]);
});
};
let middleware = client.clientOptions.middleware;
return vscode_1.languages.registerWorkspaceSymbolProvider({
provideWorkspaceSymbols: (query, token) => {
return middleware.provideWorkspaceSymbols
? middleware.provideWorkspaceSymbols(query, token, provideWorkspaceSymbols)
: provideWorkspaceSymbols(query, token);
}
});
}
}
class CodeActionFeature extends TextDocumentFeature {
constructor(client) {
super(client, vscode_languageserver_protocol_1.CodeActionRequest.type);
}
fillClientCapabilities(capabilites) {
const cap = ensure(ensure(capabilites, 'textDocument'), 'codeAction');
cap.dynamicRegistration = true;
cap.codeActionLiteralSupport = {
codeActionKind: {
valueSet: [
'',
vscode_languageserver_protocol_1.CodeActionKind.QuickFix,
vscode_languageserver_protocol_1.CodeActionKind.Refactor,
vscode_languageserver_protocol_1.CodeActionKind.RefactorExtract,
vscode_languageserver_protocol_1.CodeActionKind.RefactorInline,
vscode_languageserver_protocol_1.CodeActionKind.RefactorRewrite,
vscode_languageserver_protocol_1.CodeActionKind.Source,
vscode_languageserver_protocol_1.CodeActionKind.SourceOrganizeImports
]
}
};
}
initialize(capabilities, documentSelector) {
if (!capabilities.codeActionProvider || !documentSelector) {
return;
}
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: Object.assign({}, { documentSelector: documentSelector })
});
}
registerLanguageProvider(options) {
let client = this._client;
let provideCodeActions = (document, range, context, token) => {
let 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;
}
let 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) => {
client.logFailedRequest(vscode_languageserver_protocol_1.CodeActionRequest.type, error);
return Promise.resolve([]);
});
};
let middleware = client.clientOptions.middleware;
return vscode_1.languages.registerCodeActionsProvider(options.documentSelector, {
provideCodeActions: (document, range, context, token) => {
return middleware.provideCodeActions
? middleware.provideCodeActions(document, range, context, token, provideCodeActions)
: provideCodeActions(document, range, context, token);
}
});
}
}
class CodeLensFeature extends TextDocumentFeature {
constructor(client) {
super(client, vscode_languageserver_protocol_1.CodeLensRequest.type);
}
fillClientCapabilities(capabilites) {
ensure(ensure(capabilites, 'textDocument'), 'codeLens').dynamicRegistration = true;
}
initialize(capabilities, documentSelector) {
if (!capabilities.codeLensProvider || !documentSelector) {
return;
}
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: Object.assign({}, { documentSelector: documentSelector }, capabilities.codeLensProvider)
});
}
registerLanguageProvider(options) {
let client = this._client;
let provideCodeLenses = (document, token) => {
return client.sendRequest(vscode_languageserver_protocol_1.CodeLensRequest.type, client.code2ProtocolConverter.asCodeLensParams(document), token).then(client.protocol2CodeConverter.asCodeLenses, (error) => {
client.logFailedRequest(vscode_languageserver_protocol_1.CodeLensRequest.type, error);
return Promise.resolve([]);
});
};
let resolveCodeLens = (codeLens, token) => {
return client.sendRequest(vscode_languageserver_protocol_1.CodeLensResolveRequest.type, client.code2ProtocolConverter.asCodeLens(codeLens), token).then(client.protocol2CodeConverter.asCodeLens, (error) => {
client.logFailedRequest(vscode_languageserver_protocol_1.CodeLensResolveRequest.type, error);
return codeLens;
});
};
let middleware = client.clientOptions.middleware;
return vscode_1.languages.registerCodeLensProvider(options.documentSelector, {
provideCodeLenses: (document, token) => {
return middleware.provideCodeLenses
? middleware.provideCodeLenses(document, token, provideCodeLenses)
: provideCodeLenses(document, token);
},
resolveCodeLens: (options.resolveProvider)
? (codeLens, token) => {
return middleware.resolveCodeLens
? middleware.resolveCodeLens(codeLens, token, resolveCodeLens)
: resolveCodeLens(codeLens, token);
}
: undefined
});
}
}
class DocumentFormattingFeature extends TextDocumentFeature {
constructor(client) {
super(client, vscode_languageserver_protocol_1.DocumentFormattingRequest.type);
}
fillClientCapabilities(capabilites) {
ensure(ensure(capabilites, 'textDocument'), 'formatting').dynamicRegistration = true;
}
initialize(capabilities, documentSelector) {
if (!capabilities.documentFormattingProvider || !documentSelector) {
return;
}
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: Object.assign({}, { documentSelector: documentSelector })
});
}
registerLanguageProvider(options) {
let client = this._client;
let provideDocumentFormattingEdits = (document, options, token) => {
let params = {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
options: client.code2ProtocolConverter.asFormattingOptions(options)
};
return client.sendRequest(vscode_languageserver_protocol_1.DocumentFormattingRequest.type, params, token).then(client.protocol2CodeConverter.asTextEdits, (error) => {
client.logFailedRequest(vscode_languageserver_protocol_1.DocumentFormattingRequest.type, error);
return Promise.resolve([]);
});
};
let middleware = client.clientOptions.middleware;
return vscode_1.languages.registerDocumentFormattingEditProvider(options.documentSelector, {
provideDocumentFormattingEdits: (document, options, token) => {
return middleware.provideDocumentFormattingEdits
? middleware.provideDocumentFormattingEdits(document, options, token, provideDocumentFormattingEdits)
: provideDocumentFormattingEdits(document, options, token);
}
});
}
}
class DocumentRangeFormattingFeature extends TextDocumentFeature {
constructor(client) {
super(client, vscode_languageserver_protocol_1.DocumentRangeFormattingRequest.type);
}
fillClientCapabilities(capabilites) {
ensure(ensure(capabilites, 'textDocument'), 'rangeFormatting').dynamicRegistration = true;
}
initialize(capabilities, documentSelector) {
if (!capabilities.documentRangeFormattingProvider || !documentSelector) {
return;
}
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: Object.assign({}, { documentSelector: documentSelector })
});
}
registerLanguageProvider(options) {
let client = this._client;
let provideDocumentRangeFormattingEdits = (document, range, options, token) => {
let params = {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
range: client.code2ProtocolConverter.asRange(range),
options: client.code2ProtocolConverter.asFormattingOptions(options)
};
return client.sendRequest(vscode_languageserver_protocol_1.DocumentRangeFormattingRequest.type, params, token).then(client.protocol2CodeConverter.asTextEdits, (error) => {
client.logFailedRequest(vscode_languageserver_protocol_1.DocumentRangeFormattingRequest.type, error);
return Promise.resolve([]);
});
};
let middleware = client.clientOptions.middleware;
return vscode_1.languages.registerDocumentRangeFormattingEditProvider(options.documentSelector, {
provideDocumentRangeFormattingEdits: (document, range, options, token) => {
return middleware.provideDocumentRangeFormattingEdits
? middleware.provideDocumentRangeFormattingEdits(document, range, options, token, provideDocumentRangeFormattingEdits)
: provideDocumentRangeFormattingEdits(document, range, options, token);
}
});
}
}
class DocumentOnTypeFormattingFeature extends TextDocumentFeature {
constructor(client) {
super(client, vscode_languageserver_protocol_1.DocumentOnTypeFormattingRequest.type);
}
fillClientCapabilities(capabilites) {
ensure(ensure(capabilites, 'textDocument'), 'onTypeFormatting').dynamicRegistration = true;
}
initialize(capabilities, documentSelector) {
if (!capabilities.documentOnTypeFormattingProvider || !documentSelector) {
return;
}
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: Object.assign({}, { documentSelector: documentSelector }, capabilities.documentOnTypeFormattingProvider)
});
}
registerLanguageProvider(options) {
let client = this._client;
let moreTriggerCharacter = options.moreTriggerCharacter || [];
let 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)
};
return client.sendRequest(vscode_languageserver_protocol_1.DocumentOnTypeFormattingRequest.type, params, token).then(client.protocol2CodeConverter.asTextEdits, (error) => {
client.logFailedRequest(vscode_languageserver_protocol_1.DocumentOnTypeFormattingRequest.type, error);
return Promise.resolve([]);
});
};
let middleware = client.clientOptions.middleware;
return vscode_1.languages.registerOnTypeFormattingEditProvider(options.documentSelector, {
provideOnTypeFormattingEdits: (document, position, ch, options, token) => {
return middleware.provideOnTypeFormattingEdits
? middleware.provideOnTypeFormattingEdits(document, position, ch, options, token, provideOnTypeFormattingEdits)
: provideOnTypeFormattingEdits(document, position, ch, options, token);
}
}, options.firstTriggerCharacter, ...moreTriggerCharacter);
}
}
class RenameFeature extends TextDocumentFeature {
constructor(client) {
super(client, vscode_languageserver_protocol_1.RenameRequest.type);
}
fillClientCapabilities(capabilites) {
ensure(ensure(capabilites, 'textDocument'), 'rename').dynamicRegistration = true;
}
initialize(capabilities, documentSelector) {
if (!capabilities.renameProvider || !documentSelector) {
return;
}
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: Object.assign({}, { documentSelector: documentSelector })
});
}
registerLanguageProvider(options) {
let client = this._client;
let 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) => {
client.logFailedRequest(vscode_languageserver_protocol_1.RenameRequest.type, error);
return Promise.reject(new Error(error.message));
});
};
let middleware = client.clientOptions.middleware;
return vscode_1.languages.registerRenameProvider(options.documentSelector, {
provideRenameEdits: (document, position, newName, token) => {
return middleware.provideRenameEdits
? middleware.provideRenameEdits(document, position, newName, token, provideRenameEdits)
: provideRenameEdits(document, position, newName, token);
}
});
}
}
class DocumentLinkFeature extends TextDocumentFeature {
constructor(client) {
super(client, vscode_languageserver_protocol_1.DocumentLinkRequest.type);
}
fillClientCapabilities(capabilites) {
ensure(ensure(capabilites, 'textDocument'), 'documentLink').dynamicRegistration = true;
}
initialize(capabilities, documentSelector) {
if (!capabilities.documentLinkProvider || !documentSelector) {
return;
}
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: Object.assign({}, { documentSelector: documentSelector }, capabilities.documentLinkProvider)
});
}
registerLanguageProvider(options) {
let client = this._client;
let provideDocumentLinks = (document, token) => {
return client.sendRequest(vscode_languageserver_protocol_1.DocumentLinkRequest.type, client.code2ProtocolConverter.asDocumentLinkParams(document), token).then(client.protocol2CodeConverter.asDocumentLinks, (error) => {
client.logFailedRequest(vscode_languageserver_protocol_1.DocumentLinkRequest.type, error);
Promise.resolve(new Error(error.message));
});
};
let resolveDocumentLink = (link, token) => {
return client.sendRequest(vscode_languageserver_protocol_1.DocumentLinkResolveRequest.type, client.code2ProtocolConverter.asDocumentLink(link), token).then(client.protocol2CodeConverter.asDocumentLink, (error) => {
client.logFailedRequest(vscode_languageserver_protocol_1.DocumentLinkResolveRequest.type, error);
Promise.resolve(new Error(error.message));
});
};
let middleware = client.clientOptions.middleware;
return vscode_1.languages.registerDocumentLinkProvider(options.documentSelector, {
provideDocumentLinks: (document, token) => {
return middleware.provideDocumentLinks
? middleware.provideDocumentLinks(document, token, provideDocumentLinks)
: provideDocumentLinks(document, token);
},
resolveDocumentLink: options.resolveProvider
? (link, token) => {
return middleware.resolveDocumentLink
? middleware.resolveDocumentLink(link, token, resolveDocumentLink)
: resolveDocumentLink(link, token);
}
: undefined
});
}
}
class ConfigurationFeature {
constructor(_client) {
this._client = _client;
this._listeners = new Map();
}
get messages() {
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 !== void 0) {
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: {
section: section
}
});
}
}
register(_message, data) {
let disposable = vscode_1.workspace.onDidChangeConfiguration((event) => {
this.onDidChangeConfiguration(data.registerOptions.section, event);
});
this._listeners.set(data.id, disposable);
if (data.registerOptions.section !== void 0) {
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 !== void 0 && event !== void 0) {
let affected = sections.some((section) => event.affectsConfiguration(section));
if (!affected) {
return;
}
}
let didChangeConfiguration = (sections) => {
if (sections === void 0) {
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(key, resource);
}
if (config) {
let path = keys[i].split('.');
ensurePath(result, path)[path[path.length - 1]] = 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 messages() {
return vscode_languageserver_protocol_1.ExecuteCommandRequest.type;
}
fillClientCapabilities(capabilities) {
ensure(ensure(capabilities, 'workspace'), 'executeCommand').dynamicRegistration = true;
}
initialize(capabilities) {
if (!capabilities.executeCommandProvider) {
return;
}
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: Object.assign({}, capabilities.executeCommandProvider)
});
}
register(_message, data) {
let client = this._client;
if (data.registerOptions.commands) {
let disposeables = [];
for (const command of data.registerOptions.commands) {
disposeables.push(vscode_1.commands.registerCommand(command, (...args) => {
let params = {
command,
arguments: args
};
return client.sendRequest(vscode_languageserver_protocol_1.ExecuteCommandRequest.type, params).then(undefined, (error) => {
client.logFailedRequest(vscode_languageserver_protocol_1.ExecuteCommandRequest.type, error);
});
}));
}
this._commands.set(data.id, disposeables);
}
}
unregister(id) {
let disposeables = this._commands.get(id);
if (disposeables) {
disposeables.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 BaseLanguageClient {
constructor(id, name, clientOptions) {
this._features = [];
this._method2Message = new Map();
this._dynamicFeatures = new Map();
this._id = id;
this._name = name;
clientOptions = clientOptions || {};
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,
errorHandler: clientOptions.errorHandler || new DefaultErrorHandler(this._name),
middleware: clientOptions.middleware || {},
uriConverters: clientOptions.uriConverters,
workspaceFolder: clientOptions.workspaceFolder
};
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._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 = { resolve, reject };
});
this._onStop = undefined;
this._telemetryEmitter = new vscode_languageserver_protocol_1.Emitter();
this._stateChangeEmitter = new vscode_languageserver_protocol_1.Emitter();
this._tracer = {
log: (message, data) => {
this.logTrace(message, data);
}
};
this._c2p = c2p.createConverter(clientOptions.uriConverters ? clientOptions.uriConverters.code2Protocol : undefined);
this._p2c = p2c.createConverter(clientOptions.uriConverters ? clientOptions.uriConverters.protocol2Code : undefined);
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 {
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 {
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 {
this._resolvedConnection.onNotification(type, handler);
}
catch (error) {
this.error(`Registering notification handler ${Is.string(type) ? type : type.method} 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 diagnostics() {
return this._diagnostics;
}
createDefaultErrorHandler() {
return new DefaultErrorHandler(this._name);
}
set trace(value) {
this._trace = value;
this.onReady().then(() => {
this.resolveConnection().then((connection) => {
connection.trace(value, this._tracer);
});
}, () => {
});
}
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) {
this.outputChannel.appendLine(`[Info - ${(new Date().toLocaleTimeString())}] ${message}`);
if (data) {
this.outputChannel.appendLine(this.data2String(data));
}
if (this._clientOptions.revealOutputChannelOn <= RevealOutputChannelOn.Info) {
this.outputChannel.show(true);
}
}
warn(message, data) {
this.outputChannel.appendLine(`[Warn - ${(new Date().toLocaleTimeString())}] ${message}`);
if (data) {
this.outputChannel.appendLine(this.data2String(data));
}
if (this._clientOptions.revealOutputChannelOn <= RevealOutputChannelOn.Warn) {
this.outputChannel.show(true);
}
}
error(message, data) {
this.outputChannel.appendLine(`[Error - ${(new Date().toLocaleTimeString())}] ${message}`);
if (data) {
this.outputChannel.appendLine(this.data2String(data));
}
if (this._clientOptions.revealOutputChannelOn <= RevealOutputChannelOn.Error) {
this.outputChannel.show(true);
}
}
logTrace(message, data) {
this.outputChannel.appendLine(`[Trace - ${(new Date().toLocaleTimeString())}] ${message}`);
if (data) {
this.outputChannel.appendLine(this.data2String(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() {
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);
break;
case vscode_languageserver_protocol_1.MessageType.Warning:
this.warn(message.message);
break;
case vscode_languageserver_protocol_1.MessageType.Info:
this.info(message.message);
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.listen();
// Error is handled in the intialize 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: process.pid,
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);
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) && result.capabilities.textDocumentSync !== vscode_languageserver_protocol_1.TextDocumentSyncKind.None) {
textDocumentSyncOptions = {
openClose: true,
change: result.capabilities.textDocumentSync,
save: {
includeText: false
}
};
}
else if (result.capabilities.textDocumentSync !== void 0 && 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);
}
});
}
_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();
// unkook listeners
return this._onStop = this.resolveConnection().then(connection => {
return connection.shutdown().then(() => {
connection.exit();
connection.dispose();
this.state = ClientState.Stopped;
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 (let handler of this._dynamicFeatures.values()) {
handler.dispose();
}
if (channel && this._outputChannel && this._disposeOutputChannel) {
this._outputChannel.dispose();
this._outputChannel = undefined;
}
if (diagnostics && this._diagnostics) {
this._diagnostics.dispose();
this._diagnostics = undefined;
}
}
notifyFileEvent(event) {
this._fileEvents.push(event);
this._fileEventDelayer.trigger(() => {
this.onReady().then(() => {
this.resolveConnection().then(connection => {
if (this.isConnectionActive()) {
connection.didChangeWatchedFiles({ changes: this._fileEvents });
}
this._fileEvents = [];
});
}, (error) => {
this.error(`Notify file events failed.`, error);
});
});
}
forceDocumentSync() {
this._dynamicFeatures.get(vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type.method).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.handleDiagnostics;
if (middleware) {
middleware(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);
});
}
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.');
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;
if (config) {
trace = vscode_languageserver_protocol_1.Trace.fromString(config.get('trace.server', 'off'));
}
this._trace = trace;
connection.trace(this._trace, this._tracer, sendNotification);
}
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)) {
let messages = feature.messages;
if (Array.isArray(messages)) {
for (let message of messages) {
this._method2Message.set(message.method, message);
this._dynamicFeatures.set(message.method, feature);
}
}
else {
this._method2Message.set(messages.method, messages);
this._dynamicFeatures.set(messages.method, feature);
}
}
}
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() {
let result = {};
ensure(result, 'workspace').applyEdit = true;
ensure(ensure(result, 'workspace'), 'workspaceEdit').documentChanges = true;
ensure(ensure(result, 'textDocument'), 'publishDiagnostics').relatedInformation = true;
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 (let registration of params.registrations) {
const feature = this._dynamicFeatures.get(registration.method);
if (!feature) {
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
};
feature.register(this._method2Message.get(registration.method), data);
}
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 (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 vscode_1.workspace.applyEdit(this._p2c.asWorkspaceEdit(params.edit)).then((value) => { return { applied: value }; });
}
;
logFailedRequest(type, error) {
// If we get a request cancel don't log anything.
if (error instanceof vscode_languageserver_protocol_1.ResponseError && error.code === vscode_languageserver_protocol_1.ErrorCodes.RequestCancelled) {
return;
}
this.error(`Request ${type.method} failed.`, error);
}
}
exports.BaseLanguageClient = BaseLanguageClient;