/
githubmirror
/
brackets
Обзор
Документация
Войти
/
githubmirror
/
brackets
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/languageTools/LanguageClient/LanguageClient.js
232 строки
8 KB
Subhash Jha
Language Server Protocol Support for Brackets (#14606)
02 апр 2019, 12:35
02 апр 2019, 12:35
df7aea4
Код
Авторство
О чём код?
/* * Copyright (c) 2019 - present Adobe. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * */ /*global exports, Promise, LanguageClientInfo */ /*eslint no-console: 0*/ /*eslint strict: ["error", "global"]*/ /*eslint max-len: ["error", { "code": 200 }]*/ "use strict"; var ProtocolAdapter = require("./ProtocolAdapter"), ServerUtils = require("./ServerUtils"), Connection = require("./Connection"), NodeToBracketsInterface = require("./NodeToBracketsInterface").NodeToBracketsInterface, ToolingInfo = LanguageClientInfo.toolingInfo, MESSAGE_TYPE = { BRACKETS: "brackets", SERVER: "server" }; function validateHandler(handler) { var retval = false; if (handler && typeof handler === "function") { retval = true; } else { console.warn("Handler validation failed. Handler should be of type 'function'. Provided handler is of type :", typeof handler); } return retval; } function LanguageClient(clientName, domainManager, options) { this._clientName = clientName; this._bracketsInterface = null; this._notifyBrackets = null; this._requestBrackets = null; this._connection = null, this._startUpParams = null, //_projectRoot, capabilties, workspaceFolders etc. this._initialized = false, this._onRequestHandler = {}; this._onNotificationHandlers = {}; this._options = options || null; this._init(domainManager); } LanguageClient.prototype._createConnection = function () { if (!this._options || !this._options.serverOptions) { return Promise.reject("No valid options provided for client :", this._clientName); } var restartLanguageClient = this.start.bind(this), stopLanguageClient = this.stop.bind(this); var serverOptions = this._options.serverOptions; return ServerUtils.startServerAndGetConnectionArgs(serverOptions) .then(function (connectionArgs) { return Connection.createConnection(connectionArgs.reader, connectionArgs.writer, restartLanguageClient, stopLanguageClient); }).catch(function (err) { console.error("Couldn't establish connection", err); }); }; LanguageClient.prototype.setOptions = function (options) { if (options && typeof options === "object") { this._options = options; } else { console.error("Invalid options provided for client :", this._clientName); } }; LanguageClient.prototype.start = function (params) { var self = this; //Check to see if a connection to a language server already exists. if (self._connection) { return Promise.resolve(true); } self._connection = null; self._startUpParams = params || self._startUpParams; //We default to standard capabilties if (!self._startUpParams.capabilities) { self._startUpParams.capabilities = LanguageClientInfo.defaultBracketsCapabilities; } return self._createConnection() .then(function (connection) { connection.listen(); self._connection = connection; return ProtocolAdapter.initialize(connection, self._startUpParams); }).then(function (result) { self._initialized = result; ProtocolAdapter.attachOnNotificationHandlers(self._connection, self._notifyBrackets); ProtocolAdapter.attachOnRequestHandlers(self._connection, self._requestBrackets); ProtocolAdapter.initialized(self._connection); return result; }).catch(function (error) { console.error('Starting client failed because :', error); console.error('Couldn\'t start client :', self._clientName); return error; }); }; LanguageClient.prototype.stop = function () { var self = this; self._initialized = false; if (!self._connection) { return Promise.resolve(true); } return ProtocolAdapter.shutdown(self._connection).then(function () { ProtocolAdapter.exit(self._connection); self._connection.dispose(); self._connection = null; }); }; LanguageClient.prototype.request = function (params) { var messageParams = params.params; if (messageParams && messageParams.messageType === MESSAGE_TYPE.BRACKETS) { if (!messageParams.type) { console.log("Invalid brackets request"); return Promise.reject(); } var requestHandler = this._onRequestHandler[messageParams.type]; if(validateHandler(requestHandler)) { return requestHandler.call(null, messageParams.params); } console.log("No handler provided for brackets request type : ", messageParams.type); return Promise.reject(); } return ProtocolAdapter.processRequest(this._connection, params); }; LanguageClient.prototype.notify = function (params) { var messageParams = params.params; if (messageParams && messageParams.messageType === MESSAGE_TYPE.BRACKETS) { if (!messageParams.type) { console.log("Invalid brackets notification"); return; } var notificationHandlers = this._onNotificationHandlers[messageParams.type]; if(notificationHandlers && Array.isArray(notificationHandlers) && notificationHandlers.length) { notificationHandlers.forEach(function (handler) { if(validateHandler(handler)) { handler.call(null, messageParams.params); } }); } else { console.log("No handlers provided for brackets notification type : ", messageParams.type); } } else { ProtocolAdapter.processNotification(this._connection, params); } }; LanguageClient.prototype.addOnRequestHandler = function (type, handler) { if (validateHandler(handler)) { this._onRequestHandler[type] = handler; } }; LanguageClient.prototype.addOnNotificationHandler = function (type, handler) { if (validateHandler(handler)) { if (!this._onNotificationHandlers[type]) { this._onNotificationHandlers[type] = []; } this._onNotificationHandlers[type].push(handler); } }; LanguageClient.prototype._init = function (domainManager) { this._bracketsInterface = new NodeToBracketsInterface(domainManager, this._clientName); //Expose own methods for interfaceing. All these are async except notify. this._bracketsInterface.registerMethods([ { methodName: ToolingInfo.LANGUAGE_SERVICE.START, methodHandle: this.start.bind(this) }, { methodName: ToolingInfo.LANGUAGE_SERVICE.STOP, methodHandle: this.stop.bind(this) }, { methodName: ToolingInfo.LANGUAGE_SERVICE.REQUEST, methodHandle: this.request.bind(this) }, { methodName: ToolingInfo.LANGUAGE_SERVICE.NOTIFY, methodHandle: this.notify.bind(this) } ]); //create function interfaces for Brackets this._notifyBrackets = this._bracketsInterface.createInterface(ToolingInfo.LANGUAGE_SERVICE.NOTIFY); this._requestBrackets = this._bracketsInterface.createInterface(ToolingInfo.LANGUAGE_SERVICE.REQUEST, true); }; exports.LanguageClient = LanguageClient;