mirror of
https://github.com/salexdv/bsl_console.git
synced 2024-11-28 08:48:48 +02:00
Поддержка пользовательских функций.
Функционал для загрузки пользовательских сниппетов и функций. Исправление ситуации, когда в автокомплит не попадали функции, в названии которых есть цифры.
This commit is contained in:
parent
cccc52c554
commit
7f1c39262f
@ -33127,6 +33127,7 @@ define([], function () {
|
||||
},
|
||||
"Прочее": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"customFunctions": {}
|
||||
}
|
||||
});
|
@ -136,7 +136,7 @@ class bslHelper {
|
||||
let index = expArray.length - 1;
|
||||
|
||||
while (!exp && 0 <= index) {
|
||||
if (/^[^\(\)\[\]=\+\*/%<>"\.\,;:][a-zA-Z\u0410-\u044F_\.]*$/.test(expArray[index]))
|
||||
if (/^[^\(\)\[\]=\+\*/%<>"\.\,;:][a-zA-Z0-9\u0410-\u044F_\.]*$/.test(expArray[index]))
|
||||
exp = expArray[index]
|
||||
else {
|
||||
if (expArray[index].trim() !== '' && !this.lastOperator)
|
||||
@ -188,7 +188,7 @@ class bslHelper {
|
||||
let index = expArray.length - 1;
|
||||
|
||||
while (!exp && 0 <= index) {
|
||||
if (/^(?!новый |new )[^\(\)\[\]=\+\*/%<>"][a-zA-Z\u0410-\u044F_\.]*$/.test(expArray[index])) {
|
||||
if (/^(?!новый |new )[^\(\)\[\]=\+\*/%<>"][a-zA-Z0-9\u0410-\u044F_\.]*$/.test(expArray[index])) {
|
||||
exp = expArray[index]
|
||||
}
|
||||
index--;
|
||||
@ -265,8 +265,11 @@ class bslHelper {
|
||||
postfix = '()';
|
||||
}
|
||||
|
||||
values.push({ name: value.name, detail: value.description, description: value.hasOwnProperty('returns') ? value.returns : '', postfix: postfix });
|
||||
values.push({ name: value.name_en, detail: value.description, description: value.hasOwnProperty('returns') ? value.returns : '', postfix: postfix });
|
||||
let template = value.hasOwnProperty('template') ? value.template : '';
|
||||
|
||||
values.push({ name: value.name, detail: value.description, description: value.hasOwnProperty('returns') ? value.returns : '', postfix: postfix, template: template });
|
||||
if (value.hasOwnProperty('name_en'))
|
||||
values.push({ name: value.name_en, detail: value.description, description: value.hasOwnProperty('returns') ? value.returns : '', postfix: postfix, template: template });
|
||||
|
||||
}
|
||||
else {
|
||||
@ -275,7 +278,7 @@ class bslHelper {
|
||||
let postfix = '';
|
||||
if (invalue.hasOwnProperty('postfix'))
|
||||
postfix = invalue.postfix;
|
||||
values.push({ name: inkey, detail: '', description: '', postfix: postfix });
|
||||
values.push({ name: inkey, detail: '', description: '', postfix: postfix, template: '' });
|
||||
}
|
||||
|
||||
}
|
||||
@ -285,7 +288,7 @@ class bslHelper {
|
||||
suggestions.push({
|
||||
label: value.name,
|
||||
kind: kind,
|
||||
insertText: value.name + value.postfix,
|
||||
insertText: value.template ? value.template : value.name + value.postfix,
|
||||
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
||||
detail: value.detail,
|
||||
documentation: value.description
|
||||
@ -483,9 +486,13 @@ class bslHelper {
|
||||
let itemExists = false;
|
||||
|
||||
let exp = this.getLastRawExpression();
|
||||
|
||||
if (exp) {
|
||||
|
||||
let fullText = this.getFullTextBeforePosition();
|
||||
let regex = new RegExp(exp + '\\s?=\\s?(.*)\\(.*\\);', 'gi');
|
||||
regex = regex.exec(fullText);
|
||||
|
||||
if (regex && 1 < regex.length) {
|
||||
|
||||
regex = /(.+?)(?:\.(.*?))?\.?(?:\.(.*?))?\(?$/.exec(regex[1]);
|
||||
@ -561,6 +568,8 @@ class bslHelper {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return itemExists;
|
||||
|
||||
}
|
||||
@ -743,6 +752,7 @@ class bslHelper {
|
||||
this.getCommonCompletition(suggestions, bslGlobals.globalfunctions, monaco.languages.CompletionItemKind.Function, true);
|
||||
this.getCommonCompletition(suggestions, bslGlobals.globalvariables, monaco.languages.CompletionItemKind.Class, false);
|
||||
this.getCommonCompletition(suggestions, bslGlobals.systemEnum, monaco.languages.CompletionItemKind.Enum, false);
|
||||
this.getCommonCompletition(suggestions, bslGlobals.customFunctions, monaco.languages.CompletionItemKind.Function, true);
|
||||
}
|
||||
|
||||
this.getSnippets(suggestions, snippets);
|
||||
@ -917,6 +927,9 @@ class bslHelper {
|
||||
let helper = null;
|
||||
|
||||
let exp = this.getLastNExpression(4);
|
||||
|
||||
if (exp) {
|
||||
|
||||
let fullText = this.getFullTextBeforePosition();
|
||||
let regex = new RegExp(exp + '\\s?=\\s?(.*)\\(.*\\);', 'gi');
|
||||
regex = regex.exec(fullText);
|
||||
@ -978,6 +991,8 @@ class bslHelper {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return helper;
|
||||
|
||||
}
|
||||
@ -1122,6 +1137,9 @@ class bslHelper {
|
||||
if (!helper)
|
||||
helper = this.getCommonSigHelp(bslGlobals.globalfunctions);
|
||||
|
||||
if (!helper)
|
||||
helper = this.getCommonSigHelp(bslGlobals.customFunctions);
|
||||
|
||||
if (helper)
|
||||
return new SignatureHelpResult(helper);
|
||||
|
||||
@ -1155,6 +1173,84 @@ class bslHelper {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes special character in json-string
|
||||
* before parsing
|
||||
*
|
||||
* @param {string} jsonString string to parsing
|
||||
*
|
||||
* @returns {string} escaped string
|
||||
*/
|
||||
static escapeJSON(jsonString) {
|
||||
|
||||
return jsonString.replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates snippets from JSON-string which
|
||||
* was received from 1C
|
||||
*
|
||||
* @param {string} data JSON-string with snippets info
|
||||
* @param {boolean} replace whether or not to replace native snippents
|
||||
*
|
||||
* @returns {true|object} true - snippets was updated, {errorDescription} - not
|
||||
*/
|
||||
static updateSnippets(data, replace) {
|
||||
|
||||
try {
|
||||
let snippetsObj = JSON.parse(this.escapeJSON(data));
|
||||
if (snippetsObj.hasOwnProperty('snippets')) {
|
||||
if (replace) {
|
||||
snippets = snippetsObj.snippets;
|
||||
}
|
||||
else {
|
||||
for (const [key, value] of Object.entries(snippetsObj.snippets)) {
|
||||
snippets[key] = value;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
throw new TypeError("Wrong structure of snippets");
|
||||
}
|
||||
|
||||
}
|
||||
catch (e) {
|
||||
return { errorDescription: e.message };
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates custom functions JSON-string which
|
||||
* was received from 1C
|
||||
*
|
||||
* @param {string} snips JSON-string with function's definition
|
||||
*
|
||||
* @returns {true|object} true - functions was updated, {errorDescription} - not
|
||||
*/
|
||||
static updateCustomFunctions(data) {
|
||||
|
||||
try {
|
||||
let funcObj = JSON.parse(data);
|
||||
if (funcObj.hasOwnProperty('customFunctions')) {
|
||||
bslGlobals.customFunctions = funcObj.customFunctions;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
throw new TypeError("Wrong structure of custom functions");
|
||||
}
|
||||
|
||||
}
|
||||
catch (e) {
|
||||
return { errorDescription: e.message };
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,6 +58,18 @@ define(['bslGlobals', 'bslMetadata', 'snippets', 'bsl_language', 'vs/editor/edit
|
||||
|
||||
}
|
||||
|
||||
updateSnippets = function (snips, replace = false) {
|
||||
|
||||
return bslHelper.updateSnippets(snips, replace);
|
||||
|
||||
}
|
||||
|
||||
updateCustomFunctions = function (data) {
|
||||
|
||||
return bslHelper.updateCustomFunctions(data);
|
||||
|
||||
}
|
||||
|
||||
setTheme = function (theme) {
|
||||
|
||||
monaco.editor.setTheme(theme);
|
||||
|
59
src/test.js
59
src/test.js
@ -26,6 +26,21 @@ describe("Проверка автокомлита и подсказок реда
|
||||
return new bslHelper(model, position);
|
||||
}
|
||||
|
||||
function helperToConsole(helper) {
|
||||
|
||||
console.log('line number:', helper.column);
|
||||
console.log('column:', helper.lineNumber);
|
||||
console.log('word:', helper.word);
|
||||
console.log('last operator:', helper.lastOperator);
|
||||
console.log('whitespace:', helper.hasWhitespace);
|
||||
console.log('last expr:', helper.lastExpression);
|
||||
console.log('expr array:', helper.getExpressioArray());
|
||||
console.log('last raw expr:', helper.lastRawExpression);
|
||||
console.log('raw array:', helper.getRawExpressioArray());
|
||||
console.log('text before:', helper.textBeforePosition);
|
||||
|
||||
}
|
||||
|
||||
let bsl = helper('');
|
||||
let bslLoaded = (bslGlobals != undefined);
|
||||
|
||||
@ -247,6 +262,30 @@ describe("Проверка автокомлита и подсказок реда
|
||||
bslMetadata = JSON.parse(JSON.stringify(mCopy));
|
||||
});
|
||||
|
||||
it("проверка обновления сниппетов", function () {
|
||||
let sCopy = JSON.parse(JSON.stringify(snippets));
|
||||
assert.notEqual(updateSnippets(123), true);
|
||||
let strJSON = '{"snippets": { "ЕслиЧто": { "prefix": "Если", "body": "Если ${1:Условие} Тогда\n\t$0\nКонецЕсли;", "description": "ЕслиЧто"}}}';
|
||||
assert.equal(updateSnippets(strJSON), true);
|
||||
bsl = helper('ЕслиЧто');
|
||||
let suggestions = [];
|
||||
bsl.getSnippets(suggestions, snippets);
|
||||
expect(suggestions).to.be.an('array').that.not.is.empty;
|
||||
assert.equal(suggestions.some(suggest => suggest.detail === "ЕслиЧто"), true);
|
||||
snippets = JSON.parse(JSON.stringify(sCopy));
|
||||
});
|
||||
|
||||
it("проверка замены сниппетов", function () {
|
||||
let sCopy = JSON.parse(JSON.stringify(snippets));
|
||||
let strJSON = '{"snippets": { "ЕслиЧто": { "prefix": "Если", "body": "Если ${1:Условие} Тогда\n\t$0\nКонецЕсли;", "description": "ЕслиЧто"}}}';
|
||||
assert.equal(updateSnippets(strJSON, true), true);
|
||||
bsl = helper('Если');
|
||||
let suggestions = [];
|
||||
bsl.getSnippets(suggestions, snippets);
|
||||
assert.equal(suggestions.length, 1);
|
||||
snippets = JSON.parse(JSON.stringify(sCopy));
|
||||
});
|
||||
|
||||
it("проверка всплывающей подсказки", function () {
|
||||
let model = getModel("Найти(");
|
||||
let position = new monaco.Position(1, 2);
|
||||
@ -269,6 +308,26 @@ describe("Проверка автокомлита и подсказок реда
|
||||
assert.equal(getFormatString(), null);
|
||||
});
|
||||
|
||||
it("проверка загрузки пользовательских функций", function () {
|
||||
let strJSON = '{ "customFunctions":{ "МояФункция1":{ "name":"МояФункция1", "name_en":"MyFuntion1", "description":"Получает из строки закодированной по алгоритму base64 двоичные данные.", "returns":"Тип: ДвоичныеДанные. ", "signature":{ "default":{ "СтрокаПараметров":"(Строка: Строка): ДвоичныеДанные", "Параметры":{ "Строка":"Строка, закодированная по алгоритму base64." } } } }, "МояФункция2":{ "name":"МояФункция2", "name_en":"MyFuntion2", "description":"Выполняет сериализацию значения в формат XML.", "template":"МояФункция2(ВызовЗависимойФункции(${1:ПервыйЗависимыйПараметр}, ${2:ВторойЗависимыйПараметр}), ${0:ПараметрМоейФункции}))", "signature":{ "ЗаписатьБезИмени":{ "СтрокаПараметров":"(ЗаписьXML: ЗаписьXML, Значение: Произвольный, НазначениеТипа?: НазначениеТипаXML)", "Параметры":{ "ЗаписьXML":"Объект, через который осуществляется запись XML, полученный через зависимою функцию", "Значение":"Записываемое в поток XML значение. Тип параметра определяется совокупностью типов, для которых определена XML-сериализация." } }, "ЗаписатьСПолнымИменем":{ "СтрокаПараметров":"(ЗаписьXML: ЗаписьXML, Значение: Произвольный, ПолноеИмя: Строка, НазначениеТипа?: НазначениеТипаXML)", "Параметры":{ "ЗаписьXML":"Объект, через который осуществляется запись XML.", "Значение":"Записываемое в поток XML значение. Тип параметра определяется совокупностью типов, для которых определена XML-сериализация.", "ПолноеИмя":"Полное имя элемента XML, в который будет записано значение.", "НазначениеТипа":"Определяет необходимость назначения типа элементу XML. Значение по умолчанию: Неявное." } }, "ЗаписатьСЛокальнымИменемИПространствомИмен":{ "СтрокаПараметров":"(ЗаписьXML: ЗаписьXML, Значение: Произвольный, ЛокальноеИмя: Строка, URIПространстваИмен: Строка, НазначениеТипа?: НазначениеТипаXML)", "Параметры":{ "ЗаписьXML":"Объект, через который осуществляется запись XML.", "Значение":"Записываемое в поток XML значение. Тип параметра определяется совокупностью типов, для которых определена XML-сериализация.", "ЛокальноеИмя":"Локальное имя элемента XML, в который будет записано значение.", "URIПространстваИмен":"URI пространства имен, к которому принадлежит указанное ЛокальноеИмя.", "НазначениеТипа":"Определяет необходимость назначения типа элементу XML. Значение по умолчанию: Неявное." } } } } } }';
|
||||
assert.notEqual(updateCustomFunctions(123), true);
|
||||
assert.equal(updateCustomFunctions(strJSON), true);
|
||||
});
|
||||
|
||||
it("проверка автокомплита для пользовательской функции МояФункция2", function () {
|
||||
bsl = helper('мояфу');
|
||||
let suggestions = [];
|
||||
bsl.getCommonCompletition(suggestions, bslGlobals.customFunctions, monaco.languages.CompletionItemKind.Function)
|
||||
expect(suggestions).to.be.an('array').that.not.is.empty;
|
||||
});
|
||||
|
||||
it("проверка подсказки параметров для пользовательской функции МояФункция2", function () {
|
||||
bsl = helper('МояФункция2');
|
||||
let suggestions = [];
|
||||
let help = bsl.getCommonSigHelp(bslGlobals.customFunctions);
|
||||
expect(help).to.have.property('activeParameter');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
mocha.run();
|
||||
|
Loading…
Reference in New Issue
Block a user