UNPKG

lsp-ws-connection

Version:
568 lines 24.6 kB
var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; import * as events from 'events'; import 'setimmediate'; import { ConsoleLogger, listen } from 'vscode-ws-jsonrpc'; import { registerServerCapability, unregisterServerCapability } from './server-capability-registration'; import { CompletionTriggerKind } from './types'; /** * Changes as compared to upstream: * - markdown is preferred over plaintext * - informative members are public and others are protected, not private * - onServerInitialized() was extracted; it also emits a message once connected * - initializeParams() was extracted, and can be modified by subclasses * - typescript 3.7 was adopted to clean up deep references */ var LspWsConnection = /** @class */ (function (_super) { __extends(LspWsConnection, _super); function LspWsConnection(options) { var _this = _super.call(this) || this; _this.isConnected = false; _this.isInitialized = false; _this.openedUris = new Map(); _this.rootUri = options.rootUri; return _this; } Object.defineProperty(LspWsConnection.prototype, "isReady", { get: function () { return this.isConnected && this.isInitialized; }, enumerable: false, configurable: true }); /** * Initialize a connection over a web socket that speaks the LSP protocol */ LspWsConnection.prototype.connect = function (socket) { var _this = this; this.socket = socket; listen({ webSocket: this.socket, logger: new ConsoleLogger(), onConnection: function (connection) { connection.listen(); _this.isConnected = true; _this.connection = connection; _this.sendInitialize(); _this.connection.onNotification('textDocument/publishDiagnostics', function (params) { _this.emit('diagnostic', params); }); _this.connection.onNotification('window/showMessage', function (params) { _this.emit('logging', params); }); _this.connection.onRequest('client/registerCapability', function (params) { params.registrations.forEach(function (capabilityRegistration) { try { _this.serverCapabilities = registerServerCapability(_this.serverCapabilities, capabilityRegistration); } catch (err) { console.error(err); } }); _this.emit('logging', params); }); _this.connection.onRequest('client/unregisterCapability', function (params) { params.unregisterations.forEach(function (capabilityUnregistration) { _this.serverCapabilities = unregisterServerCapability(_this.serverCapabilities, capabilityUnregistration); }); _this.emit('logging', params); }); _this.connection.onRequest('window/showMessageRequest', function (params) { _this.emit('logging', params); }); _this.connection.onError(function (e) { _this.emit('error', e); }); _this.connection.onClose(function () { _this.isConnected = false; }); } }); return this; }; LspWsConnection.prototype.close = function () { if (this.connection) { this.connection.dispose(); } this.openedUris.clear(); this.socket.close(); }; /** * Initialization parameters to be sent to the language server. * Subclasses should override this when adding more features. */ LspWsConnection.prototype.initializeParams = function () { return { capabilities: {}, processId: null, rootUri: this.rootUri, workspaceFolders: null }; }; LspWsConnection.prototype.sendInitialize = function () { var _this = this; if (!this.isConnected) { return; } this.openedUris.clear(); var message = this.initializeParams(); this.connection .sendRequest('initialize', message) .then(function (params) { _this.onServerInitialized(params); }, function (e) { console.warn('lsp-ws-connection initialization failure', e); }); }; LspWsConnection.prototype.sendOpen = function (documentInfo) { var textDocumentMessage = { textDocument: { uri: documentInfo.uri, languageId: documentInfo.languageId, text: documentInfo.text, version: documentInfo.version } }; void this.connection.sendNotification('textDocument/didOpen', textDocumentMessage); this.openedUris.set(documentInfo.uri, true); this.sendChange(documentInfo); }; LspWsConnection.prototype.sendChange = function (documentInfo) { if (!this.isReady) { return; } if (!this.openedUris.get(documentInfo.uri)) { this.sendOpen(documentInfo); return; } var textDocumentChange = { textDocument: { uri: documentInfo.uri, version: documentInfo.version }, contentChanges: [{ text: documentInfo.text }] }; void this.connection.sendNotification('textDocument/didChange', textDocumentChange); documentInfo.version++; }; LspWsConnection.prototype.sendSaved = function (documentInfo) { if (!this.isReady) { return; } var textDocumentChange = { textDocument: { uri: documentInfo.uri, version: documentInfo.version }, text: documentInfo.text }; void this.connection.sendNotification('textDocument/didSave', textDocumentChange); }; LspWsConnection.prototype.sendConfigurationChange = function (settings) { if (!this.isReady) { return; } void this.connection.sendNotification('workspace/didChangeConfiguration', settings); }; /** * @deprecated */ LspWsConnection.prototype.getHoverTooltip = function (location, documentInfo, emit) { var _a; if (emit === void 0) { emit = true; } return __awaiter(this, void 0, void 0, function () { var params, hover; return __generator(this, function (_b) { switch (_b.label) { case 0: if (!(this.isReady && ((_a = this.serverCapabilities) === null || _a === void 0 ? void 0 : _a.hoverProvider))) { return [2 /*return*/]; } params = { textDocument: { uri: documentInfo.uri }, position: { line: location.line, character: location.ch } }; return [4 /*yield*/, this.connection.sendRequest('textDocument/hover', params)]; case 1: hover = _b.sent(); if (emit) { this.emit('hover', hover, documentInfo.uri); } return [2 /*return*/, hover]; } }); }); }; /** * @deprecated */ LspWsConnection.prototype.getCompletion = function (location, token, documentInfo, emit, triggerCharacter, triggerKind) { var _a; if (emit === void 0) { emit = true; } return __awaiter(this, void 0, void 0, function () { var params, items, itemList; return __generator(this, function (_b) { switch (_b.label) { case 0: if (!(this.isReady && ((_a = this.serverCapabilities) === null || _a === void 0 ? void 0 : _a.completionProvider))) { return [2 /*return*/]; } params = { textDocument: { uri: documentInfo.uri }, position: { line: location.line, character: location.ch }, context: { triggerKind: triggerKind || CompletionTriggerKind.Invoked, triggerCharacter: triggerCharacter } }; return [4 /*yield*/, this.connection.sendRequest('textDocument/completion', params)]; case 1: items = _b.sent(); itemList = items && 'items' in items ? items.items : items; if (emit) { this.emit('completion', itemList); } return [2 /*return*/, itemList]; } }); }); }; LspWsConnection.prototype.getDetailedCompletion = function (completionItem) { var _this = this; if (!this.isReady) { return; } void this.connection .sendRequest('completionItem/resolve', completionItem) .then(function (result) { _this.emit('completionResolved', result); }); }; /** * @deprecated */ LspWsConnection.prototype.getSignatureHelp = function (location, documentInfo, emit) { var _a, _b, _c; if (emit === void 0) { emit = true; } return __awaiter(this, void 0, void 0, function () { var code, lines, typedCharacter, triggers, params, help; return __generator(this, function (_d) { switch (_d.label) { case 0: if (!(this.isReady && ((_a = this.serverCapabilities) === null || _a === void 0 ? void 0 : _a.signatureHelpProvider))) { return [2 /*return*/]; } code = documentInfo.text; lines = code.split('\n'); typedCharacter = lines[location.line][location.ch - 1]; triggers = ((_c = (_b = this.serverCapabilities) === null || _b === void 0 ? void 0 : _b.signatureHelpProvider) === null || _c === void 0 ? void 0 : _c.triggerCharacters) || []; if (triggers.indexOf(typedCharacter) === -1) { // Not a signature character return [2 /*return*/]; } params = { textDocument: { uri: documentInfo.uri }, position: { line: location.line, character: location.ch } }; return [4 /*yield*/, this.connection.sendRequest('textDocument/signatureHelp', params)]; case 1: help = _d.sent(); if (emit) { this.emit('signature', help, documentInfo.uri); } return [2 /*return*/, help]; } }); }); }; /** * Request the locations of all matching document symbols * @deprecated */ LspWsConnection.prototype.getDocumentHighlights = function (location, documentInfo, emit) { var _a; if (emit === void 0) { emit = true; } return __awaiter(this, void 0, void 0, function () { var highlights; return __generator(this, function (_b) { switch (_b.label) { case 0: if (!this.isReady || !((_a = this.serverCapabilities) === null || _a === void 0 ? void 0 : _a.documentHighlightProvider)) { return [2 /*return*/]; } return [4 /*yield*/, this.connection.sendRequest('textDocument/documentHighlight', { textDocument: { uri: documentInfo.uri }, position: { line: location.line, character: location.ch } })]; case 1: highlights = _b.sent(); if (emit) { this.emit('highlight', highlights, documentInfo.uri); } return [2 /*return*/, highlights]; } }); }); }; /** * Request a link to the definition of the current symbol. The results will not be displayed * unless they are within the same file URI * @deprecated */ LspWsConnection.prototype.getDefinition = function (location, documentInfo, emit) { if (emit === void 0) { emit = true; } return __awaiter(this, void 0, void 0, function () { var params, targets; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!(this.isReady && this.isDefinitionSupported())) { return [2 /*return*/]; } params = { textDocument: { uri: documentInfo.uri }, position: { line: location.line, character: location.ch } }; return [4 /*yield*/, this.connection.sendRequest('textDocument/definition', params)]; case 1: targets = _a.sent(); if (emit) { this.emit('goTo', targets, documentInfo.uri); } return [2 /*return*/, targets]; } }); }); }; /** * Request a link to the type definition of the current symbol. The results will not be displayed * unless they are within the same file URI * @deprecated */ LspWsConnection.prototype.getTypeDefinition = function (location, documentInfo, emit) { if (emit === void 0) { emit = true; } return __awaiter(this, void 0, void 0, function () { var params, locations; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!this.isReady || !this.isTypeDefinitionSupported()) { return [2 /*return*/]; } params = { textDocument: { uri: documentInfo.uri }, position: { line: location.line, character: location.ch } }; return [4 /*yield*/, this.connection.sendRequest('textDocument/typeDefinition', params)]; case 1: locations = _a.sent(); if (emit) { this.emit('goTo', locations); } return [2 /*return*/, locations]; } }); }); }; /** * Request a link to the implementation of the current symbol. The results will not be displayed * unless they are within the same file URI * @deprecated */ LspWsConnection.prototype.getImplementation = function (location, documentInfo) { var _this = this; if (!this.isReady || !this.isImplementationSupported()) { return; } void this.connection .sendRequest('textDocument/implementation', { textDocument: { uri: documentInfo.uri }, position: { line: location.line, character: location.ch } }) .then(function (result) { _this.emit('goTo', result); }); }; /** * Request a link to all references to the current symbol. The results will not be displayed * unless they are within the same file URI * @deprecated */ LspWsConnection.prototype.getReferences = function (location, documentInfo, emit) { if (emit === void 0) { emit = false; } return __awaiter(this, void 0, void 0, function () { var params, locations; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!this.isReady || !this.isReferencesSupported()) { return [2 /*return*/]; } params = { context: { includeDeclaration: true }, textDocument: { uri: documentInfo.uri }, position: { line: location.line, character: location.ch } }; return [4 /*yield*/, this.connection.sendRequest('textDocument/references', params)]; case 1: locations = _a.sent(); if (emit) { this.emit('goTo', locations, documentInfo.uri); } return [2 /*return*/, locations]; } }); }); }; /** * The characters that trigger completion automatically. * @deprecated */ LspWsConnection.prototype.getLanguageCompletionCharacters = function () { var _a, _b; return ((_b = (_a = this.serverCapabilities) === null || _a === void 0 ? void 0 : _a.completionProvider) === null || _b === void 0 ? void 0 : _b.triggerCharacters) || []; }; /** * The characters that trigger signature help automatically. * @deprecated */ LspWsConnection.prototype.getLanguageSignatureCharacters = function () { var _a, _b; return (((_b = (_a = this.serverCapabilities) === null || _a === void 0 ? void 0 : _a.signatureHelpProvider) === null || _b === void 0 ? void 0 : _b.triggerCharacters) || []); }; /** * Does the server support go to definition? * @deprecated */ LspWsConnection.prototype.isDefinitionSupported = function () { var _a; return !!((_a = this.serverCapabilities) === null || _a === void 0 ? void 0 : _a.definitionProvider); }; /** * Does the server support go to type definition? * @deprecated */ LspWsConnection.prototype.isTypeDefinitionSupported = function () { var _a; return !!((_a = this.serverCapabilities) === null || _a === void 0 ? void 0 : _a.typeDefinitionProvider); }; /** * Does the server support go to implementation? * @deprecated */ LspWsConnection.prototype.isImplementationSupported = function () { var _a; return !!((_a = this.serverCapabilities) === null || _a === void 0 ? void 0 : _a.implementationProvider); }; /** * Does the server support find all references? * @deprecated */ LspWsConnection.prototype.isReferencesSupported = function () { var _a; return !!((_a = this.serverCapabilities) === null || _a === void 0 ? void 0 : _a.referencesProvider); }; LspWsConnection.prototype.onServerInitialized = function (params) { this.isInitialized = true; this.serverCapabilities = params.capabilities; void this.connection.sendNotification('initialized', {}); void this.connection.sendNotification('workspace/didChangeConfiguration', { settings: {} }); this.emit('serverInitialized', this.serverCapabilities); }; return LspWsConnection; }(events.EventEmitter)); export { LspWsConnection }; //# sourceMappingURL=ws-connection.js.map