Wiki
Clone wikiextDiff-snegopat / extSyntaxCheck
Альтернативный вывод информации об ошибка при синтаксической проверки.
Введение
У меня стоит автоматическая проверка синтаксиса для сервера/внешнего соединения/клиента и в случаии ошибки или опечатки при проверке синтаксиса появляется сразу 3 сообщения с одной и тоей же ошибкой, что очень неудобно.
Попытаемся исправить. Для этого необходимо перехватить сообщение об ошибки и вывести в свою форму, где уже сгрупируем так как нам удобно.
- Идем на сайт снегопата и благодарим Артура Аюханова за описание событий . Как можно посмотреть, есть событие onMessage к которому можно попробовать присоединиться, с одним едениственным параметром.
-
В первый попавшийся скрипт подключаем событие и ставим точку останова. Как видим перехват сообщения есть, так что можно приступать к созданию своего скрипта по показу ошибок и нашей формы со своими плюшками.
-
Приступим к созданию скрипта. Назовем его extSyntaxCheck.
Подключим необходимые скрипты. Стоит обратить внимание на ScriptForm.js, замечательная библиотека упрощающая работу с формой и настройками для скирпта. Без TextWindow.js не обойдется ни один скрипт, желающий работать с текстовым окном. Ну и log4js.js для удобного логгирования, применяю в основном когда хочеться без отладки понять что выполняет скрипт.#!javascript $engine JScript $uname extSyntaxCheck $dname Расширенние сообщений об ошибках . $addin stdlib $addin stdcommands // (c) Сосна Евгений <shenja@sosna.zp.ua> stdlib.require('TextWindow.js', SelfScript); stdlib.require('ScriptForm.js', SelfScript); stdlib.require('log4js.js', SelfScript);
#!javascript var logger = Log4js.getLogger(SelfScript.uniqueName); var appender = new Log4js.BrowserConsoleAppender(); appender.setLayout(new Log4js.PatternLayout(Log4js.PatternLayout.TTCC_CONVERSION_PATTERN)); logger.addAppender(appender); logger.setLevel(Log4js.Level.ERROR);
Напомним себе задачи и цели данного скрипта
Скрипт перехватывает сообщения о синтаксической проверки и выводит само сообщение только один раз, а вид проверки толи на сервере или же для внешнего соединения будет выводить отдельным списком. Скрипт должен иметь настройку, пока вижу только булевый флаг перехватывать/не перехватывать и возможность указания данной настройки. Для таких простых настроек можно обойдить простым MessageBox с варинатами ответов, но нам интересно ведь нарисовать совю форму. В статье Александра Кунташова подробно описано создание формы и подключение обработчиков событий для элементов форм и примеры сохранения и восстановления настроек, но мы пойдем еще более простым путем - будем использовать уже готовые библиотеки и одна из них это ScriptForm.js . На базе ScriptForm создадим объект, для которого определим необходимые параметры для сохранения/восстановеления настроек.
#!javascript ExtSyntaxCheck = ScriptForm.extend({ settingsRootPath : SelfScript.uniqueName, settings : { pflSnegopat : { 'cathSyntaxCheck': false // Перехватывать комманду синтаксической проверки. } }, construct : function () { this._super(SelfScript.fullPath.replace(/.js$/, '.ssf')); //Загрузим форму с настройками, форма должна называться так же как и скрипт, только с расширением ssf this.loadSettings(); //Загрузим сохраненные настройки. ExtSyntaxCheck._instance = this; }, loadSettings: function(){ this._super(); }, Ok_Click:function(Button){ this.saveSettings(); this.loadSettings(); this.form.Close(); }, Close_Click:function(Button){ this.form.Close(); } }) function GetExtSyntaxCheck() { if (!ExtSyntaxCheck._instance) new ExtSyntaxCheck(); return ExtSyntaxCheck._instance; } GetExtSyntaxCheck();
ExtSyntaxCheck = ScriptForm.extend({})
settingsRootPath : SelfScript.uniqueName,
settings : { pflSnegopat : { 'cathSyntaxCheck': false // Перехватывать комманду синтаксической проверки. } },
this._super(SelfScript.fullPath.replace(/.js$/, '.ssf')); //Загрузим форму с настройками, форма должна называться так же как и скрипт, только с расширением ssf this.loadSettings(); //Загрузим сохраненные настройки. ExtSyntaxCheck._instance = this; },
Интересны строки кода, для переопределения обработчиков событий, если открыть сам файл формы, то можно увидеть, что никаких обработчиков событий я не подключал к кнопкам Ok и закрыть.
#!javascript Ok_Click:function(Button){ this.saveSettings(); this.loadSettings(); this.form.Close(); }, Close_Click:function(Button){ this.form.Close(); }
Итак полностью скрипт будет выглядить так.
#!javascript $engine JScript $uname extSyntaxCheck $dname Расширенние сообщений об ошибках . $addin stdlib $addin stdcommands // (c) Сосна Евгений <shenja@sosna.zp.ua> stdlib.require('TextWindow.js', SelfScript); stdlib.require('ScriptForm.js', SelfScript); stdlib.require('log4js.js', SelfScript); var logger = Log4js.getLogger(SelfScript.uniqueName); var appender = new Log4js.BrowserConsoleAppender(); appender.setLayout(new Log4js.PatternLayout(Log4js.PatternLayout.TTCC_CONVERSION_PATTERN)); logger.addAppender(appender); logger.setLevel(Log4js.Level.ERROR); SelfScript.self['macrosНастройка'] = function() { extSyntaxCheck = GetExtSyntaxCheck(); extSyntaxCheck.show(); } ExtSyntaxCheck = ScriptForm.extend({ settingsRootPath : SelfScript.uniqueName, settings : { pflSnegopat : { 'cathSyntaxCheck': false // Перехватывать комманду синтаксической проверки. } }, construct : function () { this._super(SelfScript.fullPath.replace(/.js$/, '.ssf')); //Загрузим форму с настройками, форма должна называться так же как и скрипт, только с расширением ssf this.loadSettings(); //Загрузим сохраненные настройки. ExtSyntaxCheck._instance = this; }, loadSettings: function(){ this._super(); }, Ok_Click:function(Button){ this.saveSettings(); this.loadSettings(); this.form.Close(); }, Close_Click:function(Button){ this.form.Close(); } }) function GetExtSyntaxCheck() { if (!ExtSyntaxCheck._instance) new ExtSyntaxCheck(); return ExtSyntaxCheck._instance; } GetExtSyntaxCheck();
Мы определили макрос для вызова настроек, форма открываетса, настройка сохраняется.
Приступим к самому интиресному. Перехват сообщения. Для этого необходимо подключиться к событию onMessage. Добавим в onMessage и подключение к событию в loadSettings. Для того что бы событие onMessage не отрабатывало все подряд сообщения, будем подключаться только тогда когда пользователь вызовет проверку синтаксиса. В простом условии определяем установленна ли настройка перехвата сообщений, если установленна тогда подклчюаемся к событию проверки. Примеры работы с событиями вызова команд 1С можно посмотреть в traymessage.js.
#!javascript loadSettings: function(){ this._super(); if (this.form.cathSyntaxCheck) { //Подключаемся к команде проверки текста logger.debug('loadSettings addHandler') stdcommands.Frntend.SyntaxCheck.addHandler(this, "onSyntaxCheck"); } else { logger.debug('loadSettings delHandler') try { stdcommands.Frntend.SyntaxCheck.delHandler(this, "onSyntaxCheck"); } catch(e) { logger.debug(e.description); } } },
#!javascript logger.debug('onSyntaxCheck connect') events.connect(Designer, "onMessage", this);
#!javascript if(!cmd.isBefore) { logger.debug('onSyntaxCheck disconnect') this.errors = {}; try { events.disconnect(Designer, "onMessage", this); } catch (e) { } }
#!javascript onSyntaxCheck : function (cmd){ logger.debug('onSyntaxCheck ') if(!cmd.isBefore) { logger.debug('onSyntaxCheck disconnect') this.errors = {}; try { events.disconnect(Designer, "onMessage", this); } catch (e) { } } else { logger.debug('onSyntaxCheck connect') events.connect(Designer, "onMessage", this); } logger.debug('onSyntaxCheck end') },
Проверка об ошибках
Для начала определим саму функцию onMessage и будем просто дублировать сообщения.
#!javascript onMessage:function(param){ text = param.text; if (!text.length) return Message(''+text)
#!javascript onMessage:function(param){ text = param.text; if (!text.length) return this.RE = new RegExp("^(\\{.{1,}\\}\:.{1,}\)$", "mig"); if ((Matches = this.RE.exec(text)) != null){ param.cancel = true; str = Matches[1]; if (!this.errors[str]){ this.errors[str] = text; } else { this.RE_ERROR_TEXT = new RegExp("\\s\\((Проверка\\:\\s.{1,})\\)$", "gim"); param.cancel = true; if ((Matches_error = this.RE_ERROR_TEXT.exec(text)) != null){ str_error = Matches_error[0]; this.errors[str] = this.errors[str]+' '+str_error; } } } },
Как видно, по первому регулярном выражению фильтруем заголовок, проверяем если уже существует такое сообщение, тогда в стек для вывода не добавляем, а пытаемся найти какая проверка сработала с помощью другого регулярного выражения. Например для строки
{ВнешняяОбработка.ВыгрузкаЗагрузкаДанныхXML.МодульОбъекта(16,1)}: Объявления переменных должны быть расположены в начале модуля, процедуры или функции <<?>>Перем ИспользующиеИтоги; (Проверка: Сервер)
{ВнешняяОбработка.ВыгрузкаЗагрузкаДанныхXML.МодульОбъекта(16,1)}: Объявления переменных должны быть расположены в начале модуля, процедуры или функции
(Проверка: Сервер)
В результате, будем к тексту просто добавлять режимы проверки, и итоговая строка для вывода пользователю получиться:
{ВнешняяОбработка.ВыгрузкаЗагрузкаДанныхXML.МодульОбъекта(16,1)}: Объявления переменных должны быть расположены в начале модуля, процедуры или функции <<?>>Перем ИспользующиеИтоги; (Проверка: Сервер) (Проверка: Внешнее соединение) (Проверка: Толстый клиент (обычное приложение))
Осталось дело за малым вывести эти ошибки пользователю. Для этого в функцию onSyntaxCheck добавим вывод сообщений уже после того как отключимся от события onMessage. В простейшем случаи достаточно проверить есть ли у нас в стеке записи с ошибками и вывести их как сообщения.
#!javascript for (var k in this.errors){ hasErrors = true; text = this.errors[k]; Message(''+text); }
Updated