/
githubmirror
/
brackets
Обзор
Документация
Войти
/
githubmirror
/
brackets
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/extensions/default/JavaScriptCodeHints/ParameterHintsProvider.js
229 строк
8 KB
Subhash Jha
Language Server Protocol Support for Brackets (#14606)
02 апр 2019, 12:35
02 апр 2019, 12:35
df7aea4
Код
Авторство
О чём код?
/* * Copyright (c) 2013 - present Adobe Systems Incorporated. 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. * */ define(function (require, exports, module) { "use strict"; var ScopeManager = brackets.getModule("JSUtils/ScopeManager"), OVERWRITE_EXISTING_HINT = false; function JSParameterHintsProvider() { this.hintState = {}; this.hintStack = []; this.preserveHintStack = null; // close a function hint without clearing stack this.session = null; // current editor session, updated by main } /** * Update the current session for use by the Function Hint Manager. * * @param {Session} value - current session. */ JSParameterHintsProvider.prototype.setSession = function (value) { this.session = value; }; /** * Test if a function hint is being displayed. * * @return {boolean} - true if a function hint is being displayed, false * otherwise. */ JSParameterHintsProvider.prototype.isHintDisplayed = function () { return this.hintState.visible === true; }; /** * Save the state of the current hint. Called when popping up a parameter hint * for a parameter, when the parameter already part of an existing parameter * hint. */ JSParameterHintsProvider.prototype.pushHintOnStack = function () { this.hintStack.push(this.hintState); }; /** * Restore the state of the previous function hint. * * @return {boolean} - true the a parameter hint has been popped, false otherwise. */ JSParameterHintsProvider.prototype.popHintFromStack = function () { if (this.hintStack.length > 0) { this.hintState = this.hintStack.pop(); this.hintState.visible = false; return true; } return false; }; /** * Reset the function hint stack. */ JSParameterHintsProvider.prototype.clearFunctionHintStack = function () { this.hintStack = []; }; /** * Test if the function call at the cursor is different from the currently displayed * function hint. * * @param {{line:number, ch:number}} functionCallPos - the offset of the function call. * @return {boolean} */ JSParameterHintsProvider.prototype.hasFunctionCallPosChanged = function (functionCallPos) { var oldFunctionCallPos = this.hintState.functionCallPos; return (oldFunctionCallPos === undefined || oldFunctionCallPos.line !== functionCallPos.line || oldFunctionCallPos.ch !== functionCallPos.ch); }; /** * Dismiss the function hint. * */ JSParameterHintsProvider.prototype.cleanHintState = function () { if (this.hintState.visible) { if (!this.preserveHintStack) { this.clearFunctionHintStack(); } } }; /** * Pop up a function hint on the line above the caret position. * * @param {boolean=} pushExistingHint - if true, push the existing hint on the stack. Default is false, not * to push the hint. * @param {string=} hint - function hint string from tern. * @param {{inFunctionCall: boolean, functionCallPos: * {line: number, ch: number}}=} functionInfo - * if the functionInfo is already known, it can be passed in to avoid * figuring it out again. * @return {jQuery.Promise} - The promise will not complete until the * hint has completed. Returns null, if the function hint is already * displayed or there is no function hint at the cursor. * */ JSParameterHintsProvider.prototype._getParameterHint = function (pushExistingHint, hint, functionInfo) { var result = $.Deferred(); functionInfo = functionInfo || this.session.getFunctionInfo(); if (!functionInfo.inFunctionCall) { this.cleanHintState(); return result.reject(null); } if (this.hasFunctionCallPosChanged(functionInfo.functionCallPos)) { var pushHint = pushExistingHint && this.isHintDisplayed(); if (pushHint) { this.pushHintOnStack(); this.preserveHintStack = true; } this.cleanHintState(); this.preserveHintStack = false; } else if (this.isHintDisplayed()) { return result.reject(null); } this.hintState.functionCallPos = functionInfo.functionCallPos; var request = null; if (!hint) { request = ScopeManager.requestParameterHint(this.session, functionInfo.functionCallPos); } else { this.session.setFnType(hint); request = $.Deferred(); request.resolveWith(null, [hint]); } var self = this; request.done(function (fnType) { var hints = self.session.getParameterHint(functionInfo.functionCallPos); hints.functionCallPos = functionInfo.functionCallPos; result.resolve(hints); }).fail(function () { self.hintState = {}; result.reject(null); }); return result; }; JSParameterHintsProvider.prototype.hasParameterHints = function () { var functionInfo = this.session.getFunctionInfo(); return functionInfo.inFunctionCall; }; JSParameterHintsProvider.prototype.getParameterHints = function (explicit, onCursorActivity) { var functionInfo = this.session.getFunctionInfo(), result = null; if (!onCursorActivity) { if (functionInfo.inFunctionCall) { var token = this.session.getToken(); if ((token && token.string === "(") || explicit) { return this._getParameterHint(); } } else { this.cleanHintState(); } return $.Deferred().reject(null); } if (!functionInfo.inFunctionCall) { this.cleanHintState(); return $.Deferred().reject(null); } // If in a different function hint, then dismiss the old one and // display the new one if there is one on the stack if (this.hasFunctionCallPosChanged(functionInfo.functionCallPos)) { if (this.popHintFromStack()) { var poppedFunctionCallPos = this.hintState.functionCallPos, currentFunctionCallPos = this.functionInfo.functionCallPos; if (poppedFunctionCallPos.line === currentFunctionCallPos.line && poppedFunctionCallPos.ch === currentFunctionCallPos.ch) { this.preserveHintStack = true; result = this._getParameterHint(OVERWRITE_EXISTING_HINT, this.hintState.fnType, functionInfo); this.preserveHintStack = false; return result; } } else { this.cleanHintState(); } } var hints = this.session.getParameterHint(functionInfo.functionCallPos); hints.functionCallPos = functionInfo.functionCallPos; return $.Deferred().resolve(hints); }; exports.JSParameterHintsProvider = JSParameterHintsProvider; });