cIhuV>XwiZ5H8f{cDUkz$dSW4kZ=cDekK>
zACzgXDy+?piQru|lzpcP-bJ#nIby()OKB>7E><>A2i
z(eobBQxUZY$fX1JO7`)JIaszt{yUqQ!SsTX&aW*_9Gai**zLQEFFJ2!{n?$*--W5%
zaEh9DDc{RKBQfi43M&Hb8=-@DIKl@V<6{48g=-0nT~LvIU`t)2a6G*tDJ7RQ>-rEF
z_0{*wchK$Guj;}$tEL#lBHPBoFm7BiFY`N7TV#04mF=%{ex9oNDjQ=}Zh
zvbIl*tN4V}oc(~>nH}#*pR?+2xHRNLsv3Oj5rx8>FOuB#PJRs
zTUgE(4q;b4=2JAE=HXQ|pV9au=z{C~Z*K1@nn-i$GMWf?{0WpaSPdghpmAM!2V602
zgokc*5^m+nM=Gkh8wM$;rD!6JvO3cWa^?LMasmw(Wpj=(Z%pnCNF;10k@)pFS5El#
zN<5G8+n+e7YwX)4g+jx7=5qzmittp`WZrvxFWm
zwQyWTL?wrUL>S!DUCAvHr;!d8_|bzWQh&LV7kZ~J-2eap
literal 0
HcmV?d00001
diff --git a/packagedef b/packagedef
new file mode 100644
index 0000000..729e246
--- /dev/null
+++ b/packagedef
@@ -0,0 +1,19 @@
+ПутКПараметрам = ОбъединитьПути(ТекущийСценарий().Каталог, "src", "Модули", "ПараметрыПриложения.os");
+Параметры = ЗагрузитьСценарий(ПутКПараметрам);
+
+Описание.Имя(Параметры.ИмяПриложения())
+ .Версия(Параметры.Версия())
+ .Автор("")
+ .АдресАвтора("")
+ .Описание("Отправка замечаний edt в отчет для сонара")
+ .ВерсияСреды("1.7.0")
+ .ВключитьФайл("src")
+ .ВключитьФайл("doc")
+ .ВключитьФайл("tasks")
+ .ВключитьФайл("custom-rules.json")
+ .ЗависитОт("logos")
+ .ЗависитОт("cli")
+ .ЗависитОт("fs")
+ .ЗависитОт("v8metadata-reader")
+ .ИсполняемыйФайл("src/main.os")
+ ;
diff --git a/src/main.os b/src/main.os
new file mode 100644
index 0000000..99f49e0
--- /dev/null
+++ b/src/main.os
@@ -0,0 +1,61 @@
+#Использовать "."
+#Использовать cli
+
+Перем Лог;
+
+Процедура ВыполнитьПриложение()
+
+ Приложение = Новый КонсольноеПриложение(ПараметрыПриложения.ИмяПриложения(),
+ "Приложение для работы с файлами ошибок статических анализаторов",
+ ЭтотОбъект);
+
+ Приложение.Версия("version", ПараметрыПриложения.Версия());
+
+ Приложение.Опция("v verbose", Ложь, "Вывод отладочной информация в процессе выполнения")
+ .Флаговый();
+
+ Приложение.Опция("f file", "", "Путь к внешнему файлу-коллектору замечаний")
+ .ТСтрока();
+
+ Приложение.ДобавитьКоманду("parse", "Создание отчета",
+ Новый КомандаПарсерОтчетаЕДТ);
+
+ Приложение.ДобавитьКоманду("publish", "Удаление из выбранного файла правил служебных блоков,
+ | результирующий файл готов для загрузки в сонар",
+ Новый КомандаПубликацияПравил);
+
+ Приложение.Запустить(АргументыКоманднойСтроки);
+
+КонецПроцедуры
+
+Процедура ПередВыполнениемКоманды(Знач Команда) Экспорт
+
+ ОтладкаВключена = Команда.ЗначениеОпции("verbose");
+
+ ПараметрыПриложения.УстановитьРежимОтладки(ОтладкаВключена);
+
+ ВнешнийФайлОписаний = Команда.ЗначениеОпции("file");
+
+ Если ЗначениеЗаполнено(ВнешнийФайлОписаний) Тогда
+ Файл = Новый Файл(ВнешнийФайлОписаний);
+ Если НЕ (Файл.Существует() И Файл.ЭтоФайл()) Тогда
+ Лог.КритичнаяОшибка("Файл %1 недоступен", ВнешнийФайлОписаний);
+ КонецЕсли;
+ КонецЕсли;
+
+ ПараметрыПриложения.УстановитьКонтекстСохранения(ВнешнийФайлОписаний);
+
+КонецПроцедуры
+
+Лог = ПараметрыПриложения.Лог();
+
+Попытка
+
+ ВыполнитьПриложение();
+
+Исключение
+
+ Лог.КритичнаяОшибка(ОписаниеОшибки());
+ ЗавершитьРаботу(1);
+
+КонецПопытки;
diff --git "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\223\320\265\320\275\320\265\321\200\320\260\321\202\320\276\321\200\320\236\321\202\321\207\320\265\321\202\320\276\320\262BSL.os" "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\223\320\265\320\275\320\265\321\200\320\260\321\202\320\276\321\200\320\236\321\202\321\207\320\265\321\202\320\276\320\262BSL.os"
new file mode 100644
index 0000000..a624388
--- /dev/null
+++ "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\223\320\265\320\275\320\265\321\200\320\260\321\202\320\276\321\200\320\236\321\202\321\207\320\265\321\202\320\276\320\262BSL.os"
@@ -0,0 +1,136 @@
+#Использовать fs
+
+#Область ОписаниеПеременных
+
+// Содержит формируемый отчет в формате BSL LS
+Перем Отчет;
+
+// Переменная для логирования
+Перем Лог;
+
+#КонецОбласти
+
+#Область ПрограммныйИнтерфейс
+
+// Создает новое пустое замечание для файла и пополняет коллекци замечаний.
+//
+// Параметры:
+// Путь - Строка - Путь к bsl файлу для регистрации нового замечания
+//
+// Возвращаемое значение:
+// Структура - Все поля описаны в файле diagnostic.json
+//
+Функция НовыйЗамечаниеДляОбъекта(Путь) Экспорт
+
+ // СырыеДанныеСтрокой() - промежуточный слой для хранения замечаний. Ключ для регистрации - имя файла.
+ РазделЗамечанияДляФайла = Отчет[СырыеДанныеСтрокой()].Получить(Путь);
+
+ Если РазделЗамечанияДляФайла = Неопределено Тогда
+
+ Отчет[СырыеДанныеСтрокой()].Вставить(Путь, Новый Структура("diagnostics", Новый Массив));
+
+ КонецЕсли;
+
+ Замечание = Замечание();
+
+ Отчет[СырыеДанныеСтрокой()][Путь].diagnostics.Добавить(Замечание);
+
+ Возврат Замечание;
+
+КонецФункции
+
+// Записывает отчет в файл, если путь не передан, отчет запишется в текущий каталог запуска
+//
+// Параметры:
+// Путь - Строка - Путь к файлу, куда будет записан отчет в формате BSL LS
+//
+Процедура ЗаписатьОтчет(Путь = Неопределено) Экспорт
+
+ Если Путь = Неопределено Тогда
+ Путь = ОбъединитьПути(ТекущийКаталог(), "edt-bsl-report.json");
+ КонецЕсли;
+
+ ЗаписьJSON = Новый ЗаписьJSON;
+ ЗаписьJSON.ОткрытьФайл(Путь, "UTF-8", , Новый ПараметрыЗаписиJSON(, Символы.Таб));
+
+ ИзменитьСтруктуруОтчета();
+
+ ЗаписатьJSON(ЗаписьJSON, Отчет);
+ ЗаписьJSON.Закрыть();
+
+ Лог.Информация("Записан файл %1", Путь);
+
+КонецПроцедуры
+
+#КонецОбласти
+
+#Область СлужебныеПроцедурыИФункции
+
+Процедура ИзменитьСтруктуруОтчета()
+
+ Для Каждого ОбъектЗамечаний Из Отчет[СырыеДанныеСтрокой()] Цикл
+
+ Замечание = Новый Соответствие;
+ Замечание.Вставить("path", ОбъектЗамечаний.Ключ);
+ Замечание.Вставить("diagnostics", ОбъектЗамечаний.Значение.diagnostics);
+ Отчет["fileinfos"].Добавить(Замечание);
+
+ КонецЦикла;
+
+ Отчет.Удалить(СырыеДанныеСтрокой());
+
+КонецПроцедуры
+
+Функция СырыеДанныеСтрокой()
+
+ Возврат "fileinfos_dirty";
+
+КонецФункции
+
+Функция ПрочитатьОбъект(ПутьКФайлу, ВСоответствие = Истина)
+
+ ЧтениеJSON = Новый ЧтениеJSON;
+ ЧтениеJSON.ОткрытьФайл(ПутьКФайлу, "UTF-8");
+
+ Объект = ПрочитатьJSON(ЧтениеJSON, ВСоответствие);
+ ЧтениеJSON.Закрыть();
+
+ Возврат Объект;
+
+КонецФункции
+
+Функция ШаблонОтчет()
+
+ Возврат ОбъединитьПути(ТекущийСценарий().Каталог, "..", Ресурсы(), "report.json");
+
+КонецФункции
+
+Функция ШаблонЗамечания()
+
+ Возврат ОбъединитьПути(ТекущийСценарий().Каталог, "..", Ресурсы(), "diagnostic.json");
+
+КонецФункции
+
+Функция Ресурсы()
+
+ Возврат "Ресурсы";
+
+КонецФункции
+
+Функция Замечание()
+
+ Возврат ПрочитатьОбъект(ШаблонЗамечания(), Ложь);
+
+КонецФункции
+
+Процедура ПриСозданииОбъекта()
+
+ Отчет = ПрочитатьОбъект(ШаблонОтчет());
+
+ Отчет["date"] = Формат(ТекущаяУниверсальнаяДата(), "ДФ='yyyy-MM-dd HH:mm:ss'");
+
+КонецПроцедуры
+
+#КонецОбласти
+
+Лог = ПараметрыПриложения.Лог();
diff --git "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\232\320\276\320\274\320\260\320\275\320\264\320\260\320\237\320\260\321\200\321\201\320\265\321\200\320\236\321\202\321\207\320\265\321\202\320\260\320\225\320\224\320\242.os" "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\232\320\276\320\274\320\260\320\275\320\264\320\260\320\237\320\260\321\200\321\201\320\265\321\200\320\236\321\202\321\207\320\265\321\202\320\260\320\225\320\224\320\242.os"
new file mode 100644
index 0000000..4cffc64
--- /dev/null
+++ "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\232\320\276\320\274\320\260\320\275\320\264\320\260\320\237\320\260\321\200\321\201\320\265\321\200\320\236\321\202\321\207\320\265\321\202\320\260\320\225\320\224\320\242.os"
@@ -0,0 +1,69 @@
+Процедура ОписаниеКоманды(Команда) Экспорт
+
+ Команда.Аргумент("PATH", "", "Файл с отчетом")
+ .ТСтрока();
+
+ Команда.Аргумент("WORKDIR", "", "Корень репозитория или проектной области")
+ .ТСтрока();
+
+ Команда.Аргумент("PROJECTS", Новый Массив, "Список проектов, которые были переданы в ЕДТ для анализа")
+ .ТМассивСтрок();
+
+ Команда.Аргумент("OUT", "", "Путь к файлу отчета в формате BSL LS")
+ .ТСтрока();
+
+ Команда.Опция("nixPath", Истина, "Использовать пути как в линукс системах")
+ .ТБулево();
+
+КонецПроцедуры
+
+Процедура ПередВыполнениемКоманды(Знач Команда) Экспорт
+
+ Лог = ПараметрыПриложения.Лог();
+
+ БылиОшибки = Ложь;
+
+ ФайлДляОбработки = Новый Файл(Команда.ЗначениеАргумента("PATH"));
+
+ Если НЕ (ФайлДляОбработки.Существует() И ФайлДляОбработки.ЭтоФайл()) Тогда
+ Лог.Ошибка("Не найден файл %1", Команда.ЗначениеАргумента("PATH"));
+ БылиОшибки = Истина;
+ КонецЕсли;
+
+ Репозиторий = Новый Файл(Команда.ЗначениеАргумента("WORKDIR"));
+
+ Если НЕ (Репозиторий.Существует() И Репозиторий.ЭтоКаталог()) Тогда
+ Лог.Ошибка("Не найден корневой каталог проектов %1", Команда.ЗначениеАргумента("WORKDIR"));
+ БылиОшибки = Истина;
+ КонецЕсли;
+
+ Проекты = Команда.ЗначениеАргумента("PROJECTS");
+
+ Для Каждого Проект Из Проекты Цикл
+
+ ДиректорияПроекта = Новый Файл(ОбъединитьПути(Команда.ЗначениеАргумента("WORKDIR"), Проект));
+
+ Если НЕ (ДиректорияПроекта.Существует() И ДиректорияПроекта.ЭтоКаталог()) Тогда
+ Лог.Ошибка("Не найден корневой каталог проекта %1 в %2", Проект, Команда.ЗначениеАргумента("WORKDIR"));
+ БылиОшибки = Истина;
+ КонецЕсли;
+
+ КонецЦикла;
+
+ Если БылиОшибки Тогда
+ ВызватьИсключение "Продолжение работы невозможно";
+ КонецЕсли;
+
+КонецПроцедуры
+
+Процедура ВыполнитьКоманду(Знач Команда) Экспорт
+
+ ФайлДляОбработки = Команда.ЗначениеАргумента("PATH");
+ Репозиторий = Команда.ЗначениеАргумента("WORKDIR");
+ Проекты = Команда.ЗначениеАргумента("PROJECTS");
+ ФайлРезультата = Команда.ЗначениеАргумента("OUT");
+ ПутиКакВЛинукс = Команда.ЗначениеОпции("nixPath");
+
+ ПарсерОшибок.Прочитать(ФайлДляОбработки, Репозиторий, Проекты, ФайлРезультата, ПутиКакВЛинукс);
+
+КонецПроцедуры
diff --git "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\232\320\276\320\274\320\260\320\275\320\264\320\260\320\237\321\203\320\261\320\273\320\270\320\272\320\260\321\206\320\270\321\217\320\237\321\200\320\260\320\262\320\270\320\273.os" "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\232\320\276\320\274\320\260\320\275\320\264\320\260\320\237\321\203\320\261\320\273\320\270\320\272\320\260\321\206\320\270\321\217\320\237\321\200\320\260\320\262\320\270\320\273.os"
new file mode 100644
index 0000000..b0109f4
--- /dev/null
+++ "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\232\320\276\320\274\320\260\320\275\320\264\320\260\320\237\321\203\320\261\320\273\320\270\320\272\320\260\321\206\320\270\321\217\320\237\321\200\320\260\320\262\320\270\320\273.os"
@@ -0,0 +1,14 @@
+Процедура ОписаниеКоманды(Команда) Экспорт
+
+ Команда.Аргумент("OUT", "", "Путь к файлу отчета в формате BSL LS")
+ .ТСтрока();
+
+КонецПроцедуры
+
+Процедура ВыполнитьКоманду(Знач Команда) Экспорт
+
+ ФайлРезультата = Команда.ЗначениеАргумента("OUT");
+ ХранилищеПравил = Новый ХранилищеПравил;
+ ХранилищеПравил.Опубликовать(ФайлРезультата);
+
+КонецПроцедуры
diff --git "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\245\321\200\320\260\320\275\320\270\320\273\320\270\321\211\320\265\320\237\321\200\320\260\320\262\320\270\320\273.os" "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\245\321\200\320\260\320\275\320\270\320\273\320\270\321\211\320\265\320\237\321\200\320\260\320\262\320\270\320\273.os"
new file mode 100644
index 0000000..456af81
--- /dev/null
+++ "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\245\321\200\320\260\320\275\320\270\320\273\320\270\321\211\320\265\320\237\321\200\320\260\320\262\320\270\320\273.os"
@@ -0,0 +1,145 @@
+#Область ОписаниеПеременных
+
+// Хранилище правилы
+Перем Правила;
+#КонецОбласти
+
+#Область ПрограммныйИнтерфейс
+
+// Ищет в коллекции правил элемент по имени правила
+//
+// Параметры:
+// Код - Строка - Код правила - нормализованная строка пригодная быть в качестве кода либо сам код из ЕДТ
+//
+// Возвращаемое значение:
+// Структура - Структура с описанием правила (подробнее см НовыйПравило)
+//
+Функция НайтиПоКоду (Код) Экспорт
+
+ Возврат Правила.ПоКоду.Получить(Код);
+
+КонецФункции
+
+// Считает количество добавленных правил
+//
+// Возвращаемое значение:
+// Число - количество правил, сохраненных в файле с описанием правил
+//
+Функция Количество() Экспорт
+
+ Возврат Правила.ПоКоду.Количество();
+
+КонецФункции
+
+// Добавляет новые правила в хранилище правил
+//
+// Параметры:
+// МассивДобавлений - <Массив> - Массив с новыми правилами, которые будут записаны в итоговый файл
+//
+Процедура Дополнить(МассивДобавлений) Экспорт
+
+ Объект = ПравилаКакОбъект();
+
+ Для Каждого Добавление Из МассивДобавлений Цикл
+
+ Объект.Rules.Добавить(Добавление.Значение);
+
+ КонецЦикла;
+
+ ЗаписатьОбъект(ПараметрыПриложения.ПолучитьКонтекст(), Объект);
+
+КонецПроцедуры
+
+// Обрабатывает хранилище правил во внутреннем формате и создает файл, пригодный для экспорта в SQ
+//
+// Параметры:
+// Путь - Строка - Путь к файлу результата.
+//
+Процедура Опубликовать(Путь) Экспорт
+
+ Объект = ПравилаКакОбъект();
+
+ МаксимальнаяДлиннаИмениПравила = 198;
+ Для Каждого Правило Из Объект.Rules Цикл
+ // InternalCode используется для внутреннего сопоставления и для SQ будет являться лишним атрибутом
+ Правило.Удалить("InternalCode");
+
+ Если СтрДлина(Правило.Name) >= 198 Тогда
+
+ Правило.Description = Правило.Name;
+ Правило.Name = Лев(Правило.Name, 198);
+
+ КонецЕсли;
+
+ КонецЦикла;
+
+ ЗаписатьОбъект(Путь, Объект);
+
+КонецПроцедуры
+
+// Создает базовое описание нового правила по замечанию, которое нашло ЕДТ.
+//
+// Параметры:
+// ВнутреннийКод - Строка - Код из ЕДТ или нормализованное имя правила
+// Имя - Строка - Имя правила
+// Тип - ТипыЗамечаний - Тип замечания (см ТипыЗамечаний)
+// Критичность - КритичностьЗамечаний- Критичность замечания (см КритичностьЗамечаний)
+//
+// Возвращаемое значение:
+// Структура- Описание нового правила
+//
+Функция НовыйПравило(ВнутреннийКод, Имя, Тип, Критичность) Экспорт
+
+ Правило = Новый Структура;
+ Правило.Вставить("Code", "");
+ Правило.Вставить("InternalCode", ВнутреннийКод);
+ Правило.Вставить("Name", Имя);
+ Правило.Вставить("Description", "Отсутствует");
+ Правило.Вставить("Type", Тип);
+ Правило.Вставить("Severity", Критичность);
+ Правило.Вставить("Active", true);
+ Правило.Вставить("EffortMinutes", 3);
+
+ Возврат Правило;
+
+КонецФункции
+
+#КонецОбласти
+
+Процедура ЗаписатьОбъект(ПутьКФайлу, ОбъектЗаписи)
+
+ ЗаписьJSON = Новый ЗаписьJSON;
+ ЗаписьJSON.ОткрытьФайл(ПутьКФайлу, "UTF-8", , Новый ПараметрыЗаписиJSON(, Символы.Таб));
+ ЗаписатьJSON(ЗаписьJSON, ОбъектЗаписи);
+ ЗаписьJSON.Закрыть();
+
+КонецПроцедуры
+
+Функция ПрочитатьОбъект(ИмяФайла)
+
+ ЧтениеJSON = Новый ЧтениеJSON;
+ ЧтениеJSON.ОткрытьФайл(ИмяФайла, "UTF-8");
+ Объект = ПрочитатьJSON(ЧтениеJSON, Ложь);
+ ЧтениеJSON.Закрыть();
+ Возврат Объект;
+
+КонецФункции
+
+Функция ПравилаКакОбъект()
+
+ Возврат ПрочитатьОбъект(ПараметрыПриложения.ПолучитьКонтекст());
+
+КонецФункции
+
+Процедура ПриСозданииОбъекта()
+
+ Объект = ПравилаКакОбъект();
+ ПоКоду = Новый Соответствие();
+
+ Для Каждого Правило Из Объект.Rules Цикл
+ ПоКоду.Вставить(Правило.InternalCode, Правило);
+ КонецЦикла;
+
+ Правила = Новый Структура("ПоКоду", ПоКоду);
+
+КонецПроцедуры
diff --git "a/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\232\320\276\320\275\321\204\320\270\320\263\321\203\321\200\320\260\321\206\320\270\321\217.os" "b/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\232\320\276\320\275\321\204\320\270\320\263\321\203\321\200\320\260\321\206\320\270\321\217.os"
new file mode 100644
index 0000000..04e0c8f
--- /dev/null
+++ "b/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\232\320\276\320\275\321\204\320\270\320\263\321\203\321\200\320\260\321\206\320\270\321\217.os"
@@ -0,0 +1,155 @@
+#Использовать v8metadata-reader
+#Использовать fs
+
+#Область ОписаниеПеременных
+
+#КонецОбласти
+
+#Область ПрограммныйИнтерфейс
+
+// Нормализует пути, заменяя раздетилель пути на тот, который используется на SQ
+//
+// Параметры:
+// Путь - Строка - любой путь на ФС
+// КакВЛинукс - Булево - Использовать разделитель пути как в линукс
+//
+// Возвращаемое значение:
+// Строка - Нормализованный путь
+//
+Функция НормализованыйПуть(Путь, КакВЛинукс = Истина) Экспорт
+
+ КонечныйПуть = "";
+
+ Если КакВЛинукс Тогда
+ КонечныйПуть = СтрЗаменить(Путь, "\", "/");
+ Иначе
+ КонечныйПуть = СтрЗаменить(Путь, "/", "\");
+ КонецЕсли;
+
+ Возврат КонечныйПуть;
+
+КонецФункции
+
+// Нормализует пути, заменяя раздетилель пути на тот, который используется на SQ
+//
+// Параметры:
+// Файл - Файл - Объект типа
+// КакВЛинукс - Булево - Использовать разделитель пути как в линукс
+//
+// Возвращаемое значение:
+// Строка - Нормализованный путь
+//
+Функция НормализованныйПутьФайла(Файл, КакВЛинукс = Истина) Экспорт
+
+ Возврат НормализованыйПуть(Файл.ПолноеИмя, КакВЛинукс);
+
+КонецФункции
+
+// Определяет путь на ФС по которому находится объект метаданных
+//
+// Параметры:
+// Генератор - v8metadata-reader.Путь1СПоМетаданным - Объект класса для поиска пути
+// ОбъектМетаданных - Строка - Представление объекта метаданных
+//
+// Возвращаемое значение:
+// Строка - Путь к объекту конфигурации на ФС
+//
+Функция ПутьКОбъектуКонфигурации(Генератор, ОбъектМетаданных) Экспорт
+
+ Возврат Генератор.Путь(ОбъектМетаданных);
+
+КонецФункции
+
+// Возвращает нормализованный путь на ФС к объекту конфигурации
+//
+// Параметры:
+// Генератор - v8metadata-reader.Путь1СПоМетаданным - Объект класса для поиска пути
+// Объект - Строка - Представление объекта метаданных
+// КакВЛинукс - Булево - Использовать пути как в линукс
+//
+// Возвращаемое значение:
+// Строка - Нормализованный путь к объекту конфигурации на ФС
+//
+Функция НормализованныйПутьКОбъектуКонфигурации(Генератор, Объект, КакВЛинукс = Истина) Экспорт
+
+ Возврат НормализованыйПуть(ПутьКОбъектуКонфигурации(Генератор, Объект), КакВЛинукс);
+
+КонецФункции
+
+// Проверяет существует ли путь на ФС к модулю объекта конфигурации, если путь не существует
+// ищет верхнеуровневые модули.
+//
+// Параметры:
+// Генератор - v8metadata-reader.Путь1СПоМетаданным - Объект класса для поиска пути
+// Объект - Строка - Представление объекта метаданных
+//
+// Возвращаемое значение:
+// Строка - Путь к модулю объекта конфигурации либо к модулю переопределенного объекта
+//
+Функция ПодобратьМодуль(Генератор, Знач Объект) Экспорт
+
+ Переопределение = "";
+ Шаблон = "%1.%2";
+ ТипыМодулей = Новый Массив;
+ ТипыМодулей.Добавить(СтрШаблон(Шаблон, Объект, "Модуль"));
+ ТипыМодулей.Добавить(СтрШаблон(Шаблон, Объект, "МодульОбъекта"));
+ ТипыМодулей.Добавить(СтрШаблон(Шаблон, Объект, "МодульМенеджера"));
+ ТипыМодулей.Добавить(СтрШаблон(Шаблон, Объект, "МодульНабораЗаписей"));
+ ТипыМодулей.Добавить(СтрШаблон(Шаблон, Объект, "МодульКоманды"));
+ ТипыМодулей.Добавить(СтрШаблон(Шаблон, Объект, "МодульМенеджераЗначения"));
+ ТипыМодулей.Добавить(МодульПриложенияСтрокой());
+ ТипыМодулей.Добавить(МодульОбычногоПриложенияСтрокой());
+ ТипыМодулей.Добавить(МодульСеансаСтрокой());
+
+ Для Каждого ТипМодуля Из ТипыМодулей Цикл
+
+ Если МожноИспользоватьВЗамечаниях(Генератор, ТипМодуля) Тогда
+ Переопределение = ТипМодуля;
+ Прервать;
+ КонецЕсли;
+
+ КонецЦикла;
+
+ Возврат Переопределение;
+
+КонецФункции
+
+#КонецОбласти
+
+#Область СлужебныеПроцедурыИФункции
+
+Функция МодульПриложенияСтрокой()
+
+ Возврат "Конфигурация.МодульУправляемогоПриложения";
+
+КонецФункции
+
+Функция МодульОбычногоПриложенияСтрокой()
+
+ Возврат "Конфигурация.МодульОбычногоПриложения";
+
+КонецФункции
+
+Функция МодульСеансаСтрокой()
+
+ Возврат "Конфигурация.МодульСеанса";
+
+КонецФункции
+
+Функция МожноИспользоватьВЗамечаниях(Знач Генератор, Знач Объект)
+
+ Результат = Истина;
+
+ Путь = НормализованныйПутьКОбъектуКонфигурации(Генератор, Объект);
+
+ Если НЕ ЗначениеЗаполнено(Путь) ИЛИ НЕ ФС.ФайлСуществует(Путь) Тогда
+ Результат = Ложь;
+ КонецЕсли;
+
+ Возврат Результат;
+
+КонецФункции
+
+#КонецОбласти
+
+Лог = ПараметрыПриложения.Лог();
diff --git "a/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\232\321\200\320\270\321\202\320\270\321\207\320\275\320\276\321\201\321\202\321\214\320\227\320\260\320\274\320\265\321\207\320\260\320\275\320\270\320\271.os" "b/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\232\321\200\320\270\321\202\320\270\321\207\320\275\320\276\321\201\321\202\321\214\320\227\320\260\320\274\320\265\321\207\320\260\320\275\320\270\320\271.os"
new file mode 100644
index 0000000..6b08f62
--- /dev/null
+++ "b/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\232\321\200\320\270\321\202\320\270\321\207\320\275\320\276\321\201\321\202\321\214\320\227\320\260\320\274\320\265\321\207\320\260\320\275\320\270\320\271.os"
@@ -0,0 +1,55 @@
+#Область ОписаниеПеременных
+
+Перем Информационное Экспорт;
+Перем Незначительное Экспорт;
+Перем Важное Экспорт;
+Перем Критическое Экспорт;
+Перем Блокирующее Экспорт;
+
+#КонецОбласти
+
+///////////////////////////////////////////////////////////////////////////////
+
+// Сопоставляет уровень критичности из отчета ЕДТ и уровень критичности правила для сонара
+//
+// Параметры:
+// Критичность - Строка - Уровень критичности замечания из ЕДТ
+//
+// Возвращаемое значение:
+// Строка - Уровень критичности для правила в BSL LS
+//
+Функция Определить(Критичность) Экспорт
+
+ Если Критичность = "Тривиальная" Тогда
+
+ Возврат Информационное;
+
+ ИначеЕсли Критичность = "Незначительная" Тогда
+
+ Возврат Незначительное;
+
+ ИначеЕсли Критичность = "Значительная" Тогда
+
+ Возврат Важное;
+
+ ИначеЕсли Критичность = "Критическая" Тогда
+
+ Возврат Критическое;
+
+ ИначеЕсли Критичность = "Ошибка конфигурации" Тогда
+
+ Возврат Важное;
+
+ Иначе
+
+ Возврат Незначительное;
+
+ КонецЕсли;
+
+КонецФункции
+
+Информационное = "INFO";
+Незначительное = "MINOR";
+Важное = "MAJOR";
+Критическое = "CRITICAL";
+Блокирующее = "BLOCKER";
diff --git "a/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\237\320\260\321\200\320\260\320\274\320\265\321\202\321\200\321\213\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\321\217.os" "b/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\237\320\260\321\200\320\260\320\274\320\265\321\202\321\200\321\213\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\321\217.os"
new file mode 100644
index 0000000..e5ac8da
--- /dev/null
+++ "b/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\237\320\260\321\200\320\260\320\274\320\265\321\202\321\200\321\213\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\321\217.os"
@@ -0,0 +1,119 @@
+#Использовать logos
+
+#Область ОписаниеПеременных
+
+Перем Лог;
+
+Перем Контекст;
+
+#КонецОбласти
+
+#Область ПрограммныйИнтерфейс
+
+// Возвращает объект лог для фиксации сообщений
+//
+// Возвращаемое значение:
+// logos.Лог - объект типа
+//
+Функция Лог() Экспорт
+
+ Если Лог = Неопределено Тогда
+ Лог = Логирование.ПолучитьЛог(ИмяЛогаПриложения());
+ КонецЕсли;
+
+ Возврат Лог;
+
+КонецФункции
+
+// Устанавливает место, откуда будут читаться старые замечания и записываться новые.
+//
+// Параметры:
+// ПутьКФайлу - Строка - Путь к внешнему файлу правил
+//
+Процедура УстановитьКонтекстСохранения(Знач ПутьКФайлу) Экспорт
+
+ Если ЗначениеЗаполнено(ПутьКФайлу) Тогда
+ Контекст = ПутьКФайлу;
+
+ Иначе
+ Контекст = ЛокальныйКонтекст();
+ КонецЕсли;
+
+ Лог().Информация("Установлен контекст сохранения замечаний %1", Контекст);
+
+КонецПроцедуры
+
+// Устанавливает способ сохранения замечаний и возвращает выбранный контекст
+//
+// Возвращаемое значение:
+// Строка - контекст для работы с сохранением правил
+//
+Функция ПолучитьКонтекст() Экспорт
+
+ Если Контекст = Неопределено Тогда
+ УстановитьКонтекстСохранения(Неопределено);
+ КонецЕсли;
+
+ Возврат Контекст;
+
+КонецФункции
+
+// Путь к локальному файлу с сохраненными правилами
+//
+// Возвращаемое значение:
+// Строка - Путь к файлу
+//
+Функция ЛокальныйКонтекст() Экспорт
+
+ Возврат ОбъединитьПути(ТекущийСценарий().Каталог, "../..", "custom-rules.json");
+
+КонецФункции
+
+// Возвращает имя лога приложения
+//
+// Возвращаемое значение:
+// Строка - Имя лога
+//
+Функция ИмяЛогаПриложения() Экспорт
+ Возврат "oscript.app." + ИмяПриложения();
+КонецФункции
+
+// Возвращает имя приложения
+//
+// Возвращаемое значение:
+// Строка - Имя приложения
+//
+Функция ИмяПриложения() Экспорт
+
+ Возврат "edt-ripper";
+
+КонецФункции
+
+// Версия приложения
+//
+// Возвращаемое значение:
+// Строка - Строка с версией приложения
+//
+Функция Версия() Экспорт
+
+ Возврат "0.7";
+
+КонецФункции
+
+// Устанавливает режим отладки для логирования приложения
+//
+// Параметры:
+// РежимОтладки - Булево - Если Истина отладка включается, если ложь - выключается
+//
+Процедура УстановитьРежимОтладки(Знач РежимОтладки) Экспорт
+
+ Если РежимОтладки Тогда
+
+ Лог().УстановитьУровень(УровниЛога.Отладка);
+ Лог.Отладка("Установлен уровень логов ОТЛАДКА");
+
+ КонецЕсли;
+
+КонецПроцедуры
+
+#КонецОбласти
diff --git "a/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\237\320\260\321\200\321\201\320\265\321\200\320\236\321\210\320\270\320\261\320\276\320\272.os" "b/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\237\320\260\321\200\321\201\320\265\321\200\320\236\321\210\320\270\320\261\320\276\320\272.os"
new file mode 100644
index 0000000..6d02dfc
--- /dev/null
+++ "b/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\237\320\260\321\200\321\201\320\265\321\200\320\236\321\210\320\270\320\261\320\276\320\272.os"
@@ -0,0 +1,245 @@
+#Область ОписаниеПеременных
+
+Перем КешПрочитанныхФайлов;
+Перем Лог;
+
+#КонецОбласти
+
+#Область ПрограммныйИнтерфейс
+
+// Разбирает отчет из ЕДТ и формирует отчет в формате bsl ls
+//
+// Параметры:
+// Файл - Строка - Путь к файлу, результату работы ЕДТ
+// ПутьКРепозиторию - Строка - Путь к репозиторию с проектами
+// СписокПроектов - Массив - Список проектов в репозитории
+// ФайлРезультата - Строка - Файл, куда будет записан отчет
+// ПутиКакВЛинукс - Строка - Использовать пути как в линукс в отчете
+//
+Процедура Прочитать(Файл, ПутьКРепозиторию, СписокПроектов, ФайлРезультата, ПутиКакВЛинукс) Экспорт
+
+ Чтение = Новый ЧтениеТекста;
+ Чтение.Открыть(Файл, "UTF-8", , , Ложь);
+
+ Строка = Чтение.ПрочитатьСтроку();
+ Отчет = Новый ГенераторОтчетовBSL();
+
+ ВыражениеУбратьКавычки = Новый РегулярноеВыражение("(\s*[:\[][\S\s]+)");
+ ВыражениеУбратьКавычки2 = Новый РегулярноеВыражение("(\s\([\S\s]+?\))");
+ ВыражениеУбратьКавычки3 = Новый РегулярноеВыражение("(\s*(?>""'|[""'])[\S\s]*?(?>'""|['""]))");
+
+ МассивДобавлений = Новый Соответствие;
+ ХранилищеПравил = Новый ХранилищеПравил;
+
+ // проверка EDT могла быть запущена по мультипроектам с одним файлом результата(напр. конфа + расширения)
+ ГенераторыПутей = ИнициализироватьГенераторы(ПутьКРепозиторию, СписокПроектов);
+
+ Пока Строка <> Неопределено Цикл
+
+ СыроеЗамечание = РазобратьЗамечаниеВСтруктуру(Строка);
+
+ Если СтрНачинаетсяС(СыроеЗамечание.Сообщение, "[BSL LS]") Тогда
+ Строка = Чтение.ПрочитатьСтроку();
+ Продолжить;
+ КонецЕсли;
+
+ ГенераторПутей = ГенераторыПутей.Получить(СыроеЗамечание.Проект);
+
+ Если ГенераторПутей = Неопределено Тогда
+ //Выкинуть в лог?
+ ВызватьИсключение "Неизвестный проект " + СыроеЗамечание.Проект + "Невозможно подобрать путь";
+ КонецЕсли;
+
+ Позиция = НайтиПозициюВСтрокеЗамечания(СыроеЗамечание.Позиция);
+
+ МетаданныеЗамечания = "";
+ ЗамечаниеПеренесено = Ложь;
+
+ Если Позиция = Неопределено Тогда // это не модуль
+
+ МетаданныеЗамечания = Конфигурация.ПодобратьМодуль(ГенераторПутей, СыроеЗамечание.Объект);
+ ЗамечаниеПеренесено = Истина;
+
+ Иначе
+ МетаданныеЗамечания = СыроеЗамечание.Объект;
+ КонецЕсли;
+
+ ОбъектЗамечания = Конфигурация.НормализованныйПутьКОбъектуКонфигурации(ГенераторПутей, МетаданныеЗамечания, ПутиКакВЛинукс);
+
+ Если ЗамечаниеПеренесено Тогда
+ Позиция = ПолучитьЗначимуюСтроку(ОбъектЗамечания);
+ КонецЕсли;
+
+ Замечание = Отчет.НовыйЗамечаниеДляОбъекта(ОбъектЗамечания);
+
+ //Описание замечания берется из выхлопа EDT
+ Замечание.message = ?(ЗамечаниеПеренесено, СыроеЗамечание.РасширенноеСообщение, СыроеЗамечание.Сообщение);
+
+ // Диапазон срабатывания - позиция вычисленная ранее
+ Замечание.range.start.line = Позиция - 1;
+ Замечание.range.start.character = 0;
+ Замечание.range.end.line = Позиция - 1;
+ Замечание.range.end.character = 1;
+
+ // Определение кода события. Изначально если присутствует берется из EDT.
+ // Отсутствующий код берется из файла правил сонар.
+ КодПравила = СыроеЗамечание.Код;
+
+ Имя = ВыражениеУбратьКавычки.Заменить(СыроеЗамечание.Сообщение, "");
+ Имя = ВыражениеУбратьКавычки3.Заменить(Имя, "");
+ Имя = СокрЛП(ВыражениеУбратьКавычки2.Заменить(Имя, ""));;
+
+ Код = НайтиСоздатьПравило(ХранилищеПравил, КодПравила, Имя,СыроеЗамечание.Тип, СыроеЗамечание, МассивДобавлений);
+
+ Замечание.code = Код;
+
+ Строка = Чтение.ПрочитатьСтроку();
+ КонецЦикла;
+ Чтение.Закрыть();
+
+ Добавлено = МассивДобавлений.Количество();
+ Если Добавлено Тогда
+ ХранилищеПравил.Дополнить(МассивДобавлений);
+ КонецЕсли;
+
+ Отчет.ЗаписатьОтчет(ФайлРезультата);
+
+КонецПроцедуры
+
+#КонецОбласти
+
+#Область СлужебныеПроцедурыИФункции
+
+Функция НайтиСоздатьПравило(ХранилищеПравил, КодПравила, Имя, Тип, Важность, МассивДобавлений)
+
+ СтрокаПоиска = "";
+ Если ЗначениеЗаполнено(КодПравила) Тогда
+ СтрокаПоиска = КодПравила;
+ Иначе
+ СтрокаПоиска = Имя;
+ КонецЕсли;
+
+ Правило = ХранилищеПравил.НайтиПоКоду(СтрокаПоиска);
+
+ ПравилоОтсутствуетВХранилище = Правило = Неопределено;
+ НовоеПравило = МассивДобавлений.Получить(СтрокаПоиска);
+
+ Если НовоеПравило <> Неопределено Тогда
+
+ Возврат НовоеПравило.Code;
+
+ ИначеЕсли ПравилоОтсутствуетВХранилище Тогда
+
+ НовоеПравило = ХранилищеПравил.НовыйПравило(СтрокаПоиска, Имя, ТипыЗамечаний.Определить(Тип), КритичностьЗамечаний.Определить(Важность));
+ НовоеПравило.Code = "EDT" + "-" + (ХранилищеПравил.Количество() + МассивДобавлений.Количество() + 1);
+ МассивДобавлений.Вставить(СтрокаПоиска, НовоеПравило);
+
+ Возврат НовоеПравило.Code;
+
+ Иначе
+ Возврат Правило.Code;
+ КонецЕсли;
+
+КонецФункции
+
+Функция ИнициализироватьГенераторы(Репо, Проекты)
+
+ Генераторы = Новый Соответствие();
+
+ Для Каждого Проект Из Проекты Цикл
+
+ Путь = ОбъединитьПути(Репо, Проект, "src");
+ ПараметрыПриложения.Лог().Отладка("Использован путь проекта %1", Путь);
+ Генераторы.Вставить(Проект, Новый Путь1СПоМетаданным(Путь));
+ КонецЦикла;
+
+ Возврат Генераторы;
+
+КонецФункции
+
+Функция НайтиПозициюВСтрокеЗамечания(Позиция)
+
+ НайденаяПозиция = Неопределено;
+
+ Если ЗначениеЗаполнено(Позиция) Тогда
+
+ Попытка
+ НайденаяПозиция = Число(СтрЗаменить(Позиция, "строка ", ""));
+ Исключение
+ Попытка
+ НайденаяПозиция = Число(СтрЗаменить(Позиция, "line ", ""));
+ Исключение
+ НайденаяПозиция = Неопределено;
+ КонецПопытки;
+ КонецПопытки;
+ КонецЕсли;
+
+ Возврат НайденаяПозиция;
+
+КонецФункции
+
+Функция ПолучитьЗначимуюСтроку(ПутьКФайлу)
+
+ Если КешПрочитанныхФайлов.Получить(ПутьКФайлу) = Неопределено Тогда
+ ЗначимаяСтрока = ЗначимаяСтрокаФайла(ПутьКФайлу);
+ КешПрочитанныхФайлов.Вставить(ПутьКФайлу, ЗначимаяСтрока);
+ Возврат ЗначимаяСтрока;
+ Иначе;
+ Возврат КешПрочитанныхФайлов.Получить(ПутьКФайлу)
+ КонецЕсли;
+
+КонецФункции
+
+Функция ЗначимаяСтрокаФайла(ПутьКФайлу)
+ ЗначимаяСтрока = 0;
+ Текст = Новый ЧтениеТекста();
+
+ Попытка
+
+ Текст.Открыть(ПутьКФайлу);
+ Строка = Текст.ПрочитатьСтроку();
+
+ Пока Строка <> Неопределено Цикл
+
+ Если НЕ ПустаяСтрока(Строка) Тогда
+ Прервать;
+ КонецЕсли;
+
+ ЗначимаяСтрока = ЗначимаяСтрока + 1;
+ Строка = Текст.ПрочитатьСтроку();
+ КонецЦикла;
+
+ Исключение
+ Текст.Закрыть();
+ КонецПопытки;
+
+ Текст.Закрыть();
+
+ ЗначимаяСтрока = ЗначимаяСтрока + 1;
+
+ Возврат ЗначимаяСтрока;
+
+КонецФункции
+
+Функция РазобратьЗамечаниеВСтруктуру(Строка)
+
+ ОписаниеЗамечания = СтрРазделить(Строка, Символы.Таб, Истина);
+ Замечание = Новый Структура;
+ Замечание.Вставить("Дата", ОписаниеЗамечания[0]);
+ Замечание.Вставить("Важность", ОписаниеЗамечания[1]);
+ Замечание.Вставить("Тип", ОписаниеЗамечания[2]);
+ Замечание.Вставить("Проект", ОписаниеЗамечания[3]);
+ Замечание.Вставить("Код", ОписаниеЗамечания[4]);
+ Замечание.Вставить("Объект", ОписаниеЗамечания[5]);
+ Замечание.Вставить("Позиция", ОписаниеЗамечания[6]);
+ Замечание.Вставить("Сообщение", ОписаниеЗамечания[7]);
+ Замечание.Вставить("РасширенноеСообщение", ОписаниеЗамечания[5] + "->" + ОписаниеЗамечания[7]);
+
+ Возврат Замечание;
+
+КонецФункции;
+
+#КонецОбласти
+
+КешПрочитанныхФайлов = Новый Соответствие();
+Лог = ПараметрыПриложения.Лог();
diff --git "a/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\242\320\270\320\277\321\213\320\227\320\260\320\274\320\265\321\207\320\260\320\275\320\270\320\271.os" "b/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\242\320\270\320\277\321\213\320\227\320\260\320\274\320\265\321\207\320\260\320\275\320\270\320\271.os"
new file mode 100644
index 0000000..d61e4ab
--- /dev/null
+++ "b/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\242\320\270\320\277\321\213\320\227\320\260\320\274\320\265\321\207\320\260\320\275\320\270\320\271.os"
@@ -0,0 +1,55 @@
+Перем Ошибка Экспорт;
+Перем ДефектКода Экспорт;
+Перем Уязвимость Экспорт;
+
+///////////////////////////////////////////////////////////////////////////////
+
+// Сопоставляет тип замечания из отчета ЕДТ и тип замечания для правила сонара
+//
+// Параметры:
+// ТипЗамечания - Строка - Тип замечания из ЕДТ
+//
+// Возвращаемое значение:
+// Строка - Подобраный тип замечания для правила в BSL LS
+//
+Функция Определить(ТипЗамечания) Экспорт
+
+ Если ТипЗамечания = "Производительность" Тогда
+
+ Возврат Ошибка;
+
+ ИначеЕсли ТипЗамечания = "Переносимость" Тогда
+
+ Возврат ДефектКода;
+
+ ИначеЕсли ТипЗамечания = "Предупреждение" Тогда
+
+ Возврат ДефектКода;
+
+ ИначеЕсли ТипЗамечания = "Ошибка конфигурации" Тогда
+
+ Возврат Ошибка;
+
+ ИначеЕсли ТипЗамечания = "Стандарты кодирования" Тогда
+
+ Возврат ДефектКода;
+
+ ИначеЕсли ТипЗамечания = "Безопасность" Тогда
+
+ Возврат Уязвимость;
+
+ ИначеЕсли ТипЗамечания = "Стандарты разработки интерфейсов" Тогда
+
+ Возврат Ошибка;
+
+ Иначе
+
+ Возврат ДефектКода;
+
+ КонецЕсли;
+
+КонецФункции
+
+Ошибка = "BUG";
+ДефектКода = "CODE_SMELL";
+Уязвимость = "VULNERABILITY";
diff --git "a/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\244\320\260\320\271\320\273\320\276\320\262\321\213\320\265\320\236\320\277\320\265\321\200\320\260\321\206\320\270\320\270.os" "b/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\244\320\260\320\271\320\273\320\276\320\262\321\213\320\265\320\236\320\277\320\265\321\200\320\260\321\206\320\270\320\270.os"
new file mode 100644
index 0000000..9ba95ef
--- /dev/null
+++ "b/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\244\320\260\320\271\320\273\320\276\320\262\321\213\320\265\320\236\320\277\320\265\321\200\320\260\321\206\320\270\320\270.os"
@@ -0,0 +1,106 @@
+#Область ПрограммныйИнтерфейс
+
+// Читает json файл и преобразует его в объект
+//
+// Параметры:
+// ПутьКФайлу - Строка - Путь к файлу, который будет прочитан
+// ВСоответствие - Булево - От значения параметра зависит в какой тип будет происходить чтение
+//
+// Возвращаемое значение:
+// Соответствие,Структура - Объект из json файла
+//
+Функция ПрочитатьОбъект(ПутьКФайлу, ВСоответствие = Истина) Экспорт
+ ЧтениеJSON = Новый ЧтениеJSON;
+ ЧтениеJSON.ОткрытьФайл(ПутьКФайлу, "UTF-8");
+ Объект = ПрочитатьJSON(ЧтениеJSON, ВСоответствие);
+ ЧтениеJSON.Закрыть();
+ Возврат Объект;
+КонецФункции
+
+// Записывает произвольный объект в json файл
+//
+// Параметры:
+// ПутьКФайлу - Строка - Путь json файлу
+// ОбъектЗаписи - Объект - Объект для серриализации
+//
+Процедура ЗаписатьОбъект(ПутьКФайлу, ОбъектЗаписи) Экспорт
+ ЗаписьJSON = Новый ЗаписьJSON;
+ ЗаписьJSON.ОткрытьФайл(ПутьКФайлу, "UTF-8", , Новый ПараметрыЗаписиJSON(, Символы.Таб));
+ ЗаписатьJSON(ЗаписьJSON, ОбъектЗаписи);
+ ЗаписьJSON.Закрыть();
+
+КонецПроцедуры
+
+// Находит шаблон для отчета
+//
+// Возвращаемое значение:
+// Строка - путь к файлу с шаблоном отчета
+//
+Функция РесурсОтчет() Экспорт
+
+ Возврат ОбъединитьПути(Ресурсы(), "report.json");
+
+КонецФункции
+
+// Находит шаблон замечания
+//
+// Возвращаемое значение:
+// Строка - Путь к шаблону замечания
+//
+Функция РесурсЗамечание() Экспорт
+
+ Возврат ОбъединитьПути(Ресурсы(), "diagnostic.json");
+
+КонецФункции
+
+#КонецОбласти
+
+#Область СлужебныйПрограммныйИнтерфейс
+
+// Находит путь к каталогу с ресурсами
+//
+// Возвращаемое значение:
+// Строка - путь к каталогу с ресурсами
+//
+Функция Ресурсы() Экспорт
+
+ Возврат ОбъединитьПути(КаталогИсходников(), ДиректорияРесурсов());
+
+КонецФункции
+
+// Находит путь к каталогу исходных файлов программы
+//
+// Возвращаемое значение:
+// Строка - Каталог исходных файлов программы
+//
+Функция КаталогИсходников() Экспорт
+ Возврат ОбъединитьПути(ТекущийСценарий().Каталог, "..");
+КонецФункции
+
+// Находит путь к корневому каталогу программы
+//
+// Возвращаемое значение:
+// Строка - Путь к корневому каталогу программы
+//
+Функция КаталогПрограммы() Экспорт
+ Возврат ОбъединитьПути(КаталогИсходников(), "..");
+КонецФункции
+
+// Находит внутренний файл правил
+//
+// Возвращаемое значение:
+// Строка - Путь к внутреннему файлу правил
+//
+Функция ФайлПравилПрограммы() Экспорт
+ Возврат ОбъединитьПути(КаталогПрограммы(), "custom-rules.json");
+КонецФункции
+
+#КонецОбласти
+
+#Область СлужебныеПроцедурыИФункции
+
+Функция ДиректорияРесурсов()
+ Возврат "Ресурсы";
+КонецФункции
+
+#КонецОбласти
diff --git "a/src/\320\240\320\265\321\201\321\203\321\200\321\201\321\213/diagnostic.json" "b/src/\320\240\320\265\321\201\321\203\321\200\321\201\321\213/diagnostic.json"
new file mode 100644
index 0000000..c32b6ab
--- /dev/null
+++ "b/src/\320\240\320\265\321\201\321\203\321\200\321\201\321\213/diagnostic.json"
@@ -0,0 +1,17 @@
+{
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 0
+ },
+ "end": {
+ "line": 0,
+ "character": 0
+ }
+ },
+ "severity": "Information",
+ "code": "",
+ "source": "edt-rules",
+ "message": "",
+ "relatedInformation": null
+}
\ No newline at end of file
diff --git "a/src/\320\240\320\265\321\201\321\203\321\200\321\201\321\213/fileinfo.json" "b/src/\320\240\320\265\321\201\321\203\321\200\321\201\321\213/fileinfo.json"
new file mode 100644
index 0000000..0a9e7b1
--- /dev/null
+++ "b/src/\320\240\320\265\321\201\321\203\321\200\321\201\321\213/fileinfo.json"
@@ -0,0 +1,4 @@
+{
+ "diagnostics": [
+ ]
+}
\ No newline at end of file
diff --git "a/src/\320\240\320\265\321\201\321\203\321\200\321\201\321\213/report.json" "b/src/\320\240\320\265\321\201\321\203\321\200\321\201\321\213/report.json"
new file mode 100644
index 0000000..34964a1
--- /dev/null
+++ "b/src/\320\240\320\265\321\201\321\203\321\200\321\201\321\213/report.json"
@@ -0,0 +1,8 @@
+{
+ "date": "",
+ "fileinfos": [
+ ],
+ "fileinfos_dirty": {
+
+ }
+}
\ No newline at end of file
diff --git a/tasks/test.os b/tasks/test.os
new file mode 100644
index 0000000..10059c3
--- /dev/null
+++ b/tasks/test.os
@@ -0,0 +1,82 @@
+#Использовать 1bdd
+#Использовать 1testrunner
+#Использовать fs
+
+Функция ПрогнатьТесты()
+
+ Тестер = Новый Тестер;
+ Тестер.УстановитьФорматЛогФайла(Тестер.ФорматыЛогФайла().GenericExec);
+
+ ПутьКТестам = "tests";
+ ПутьКОтчетуJUnit = "out";
+
+ ФС.ОбеспечитьПустойКаталог(ПутьКОтчетуJUnit);
+
+ РезультатТестирования = Тестер.ТестироватьКаталог(
+ Новый Файл(ПутьКТестам),
+ Новый Файл(ПутьКОтчетуJUnit)
+ );
+
+ Успешно = РезультатТестирования = 0;
+
+ Возврат Успешно;
+КонецФункции // ПрогнатьТесты()
+
+Функция ПрогнатьФичи()
+
+ ПутьОтчетаJUnit = ОбъединитьПути(ТекущийКаталог(), "out", "bdd-log.xml");
+
+ КаталогФич = ОбъединитьПути(".", "features");
+
+ Файл_КаталогФич = Новый Файл(КаталогФич);
+
+ ИсполнительБДД = Новый ИсполнительБДД;
+ РезультатыВыполнения = ИсполнительБДД.ВыполнитьФичу(Файл_КаталогФич, Файл_КаталогФич);
+ ИтоговыйРезультатВыполнения = ИсполнительБДД.ПолучитьИтоговыйСтатусВыполнения(РезультатыВыполнения);
+
+ СтатусВыполнения = ИсполнительБДД.ВозможныеСтатусыВыполнения().НеВыполнялся;
+ Если РезультатыВыполнения.Строки.Количество() > 0 Тогда
+
+ СтатусВыполнения = ИсполнительБДД.ПолучитьИтоговыйСтатусВыполнения(РезультатыВыполнения);
+
+ КонецЕсли;
+
+ ГенераторОтчетаJUnit = Новый ГенераторОтчетаJUnit;
+ ГенераторОтчетаJUnit.Сформировать(РезультатыВыполнения, СтатусВыполнения, ПутьОтчетаJUnit);
+
+ Сообщить(СтрШаблон("Результат прогона фич <%1>
+ |", ИтоговыйРезультатВыполнения));
+
+ Возврат ИтоговыйРезультатВыполнения <> ИсполнительБДД.ВозможныеСтатусыВыполнения().Сломался;
+КонецФункции // ПрогнатьФичи()
+
+// основной код
+
+ТекКаталог = ТекущийКаталог();
+
+Попытка
+ ТестыПрошли = ПрогнатьТесты();
+Исключение
+ ТестыПрошли = Ложь;
+ Сообщить(СтрШаблон("Тесты через 1testrunner выполнены неудачно
+ |%1", ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())));
+КонецПопытки;
+
+УстановитьТекущийКаталог(ТекКаталог);
+
+Попытка
+ ФичиПрошли = ПрогнатьФичи();
+Исключение
+ ФичиПрошли = Ложь;
+ Сообщить(СтрШаблон("Тесты поведения через 1bdd выполнены неудачно
+ |%1", ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())));
+КонецПопытки;
+
+Если Не ТестыПрошли Или Не ФичиПрошли Тогда
+ ВызватьИсключение "Тестирование завершилось неудачно!";
+Иначе
+ Сообщить(СтрШаблон("Результат прогона тестов <%1>
+ |", ТестыПрошли));
+ Сообщить(СтрШаблон("Результат прогона основных фич <%1>
+ |", ФичиПрошли));
+КонецЕсли;
diff --git "a/tests/\320\223\320\265\320\275\320\265\321\200\320\260\321\202\320\276\321\200\320\236\321\202\321\207\320\265\321\202\320\276\320\262.os" "b/tests/\320\223\320\265\320\275\320\265\321\200\320\260\321\202\320\276\321\200\320\236\321\202\321\207\320\265\321\202\320\276\320\262.os"
new file mode 100644
index 0000000..dc542b9
--- /dev/null
+++ "b/tests/\320\223\320\265\320\275\320\265\321\200\320\260\321\202\320\276\321\200\320\236\321\202\321\207\320\265\321\202\320\276\320\262.os"
@@ -0,0 +1,57 @@
+#Использовать asserts
+#Использовать logos
+#Использовать tempfiles
+#Использовать "../src"
+
+Перем юТест;
+Перем Лог;
+Перем МенеджерВременныхФайлов;
+
+// Основная точка входа
+Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт
+
+ ПередЗапускомТестов();
+
+ юТест = ЮнитТестирование;
+
+ ВсеТесты = Новый Массив;
+
+ ВсеТесты.Добавить("Тест_ГенераторОтчетов");
+
+ Возврат ВсеТесты;
+
+КонецФункции
+
+Процедура ПередЗапускомТестов()
+
+ Попытка
+ ВремТестер = Новый Тестер;
+ Лог = Логирование.ПолучитьЛог(ВремТестер.ИмяЛога());
+ Исключение
+ Лог = Логирование.ПолучитьЛог("Test");
+ КонецПопытки;
+
+КонецПроцедуры
+
+Процедура ПередЗапускомТеста() Экспорт
+
+ ПараметрыПриложения.УстановитьРежимОтладки();
+
+ МенеджерВременныхФайлов = Новый МенеджерВременныхФайлов;
+
+КонецПроцедуры
+
+
+Процедура ПослеЗапускаТеста() Экспорт
+
+ МенеджерВременныхФайлов.Удалить();
+ МенеджерВременныхФайлов = Неопределено;
+
+КонецПроцедуры
+
+Процедура Тест_ГенераторОтчетов() Экспорт
+
+ Отчет = Новый ГенераторОтчетовBSL();
+
+ Ожидаем.Что(ЗначениеЗаполнено(Отчет.Получить("date"))).ЭтоИстина();
+КонецПроцедуры
diff --git "a/tests/\320\237\320\260\321\200\321\201\320\265\321\200\320\236\321\210\320\270\320\261\320\276\320\272.os" "b/tests/\320\237\320\260\321\200\321\201\320\265\321\200\320\236\321\210\320\270\320\261\320\276\320\272.os"
new file mode 100644
index 0000000..e69de29
diff --git "a/tests/\320\244\320\260\320\271\320\273\320\276\320\262\321\213\320\265\320\236\320\277\320\265\321\200\320\260\321\206\320\270\320\270.os" "b/tests/\320\244\320\260\320\271\320\273\320\276\320\262\321\213\320\265\320\236\320\277\320\265\321\200\320\260\321\206\320\270\320\270.os"
new file mode 100644
index 0000000..cd61648
--- /dev/null
+++ "b/tests/\320\244\320\260\320\271\320\273\320\276\320\262\321\213\320\265\320\236\320\277\320\265\321\200\320\260\321\206\320\270\320\270.os"
@@ -0,0 +1,72 @@
+#Использовать asserts
+#Использовать logos
+#Использовать tempfiles
+#Использовать fs
+#Использовать "../src"
+
+Перем юТест;
+Перем Лог;
+Перем МенеджерВременныхФайлов;
+
+// Основная точка входа
+Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт
+
+ ПередЗапускомТестов();
+
+ юТест = ЮнитТестирование;
+
+ ВсеТесты = Новый Массив;
+
+ ВсеТесты.Добавить("Тест_ПолучениеРесурсов");
+ ВсеТесты.Добавить("Тест_СериализацияИДесериализация");
+
+ Возврат ВсеТесты;
+
+КонецФункции
+
+Процедура ПередЗапускомТестов()
+
+ Попытка
+ ВремТестер = Новый Тестер;
+ Лог = Логирование.ПолучитьЛог(ВремТестер.ИмяЛога());
+ Исключение
+ Лог = Логирование.ПолучитьЛог("Test");
+ КонецПопытки;
+
+КонецПроцедуры
+
+Процедура ПередЗапускомТеста() Экспорт
+
+ ПараметрыПриложения.УстановитьРежимОтладки();
+
+ МенеджерВременныхФайлов = Новый МенеджерВременныхФайлов;
+
+КонецПроцедуры
+
+Процедура ПослеЗапускаТеста() Экспорт
+
+ МенеджерВременныхФайлов.Удалить();
+ МенеджерВременныхФайлов = Неопределено;
+
+КонецПроцедуры
+
+Процедура Тест_ПолучениеРесурсов() Экспорт
+
+ Файл = Новый Файл(ФайловыеОперации.Ресурсы());
+
+ Ожидаем.Что(Файл.Существует(), "Директории не существует").ЭтоИстина();
+ Ожидаем.Что(Файл.ЭтоКаталог(), "Не является директорией").ЭтоИстина();
+ Ожидаем.Что(НайтиФайлы(ФайловыеОперации.Ресурсы(), "*.json").Количество(), "Изменилось количество ресурсов").Равно(4);
+
+КонецПроцедуры
+
+Процедура Тест_СериализацияИДесериализация() Экспорт
+
+ ПутьКФайлу = МенеджерВременныхФайлов.СоздатьФайл("test.json");
+
+ Объект = ФайловыеОперации.ПрочитатьОбъект(ФайловыеОперации.РесурсОтчет(), Истина);
+ Ожидаем.Что(ТипЗнч(Объект), "Типы не совпали").Равно(Тип("Соответствие"));
+
+ ФайловыеОперации.ЗаписатьОбъект(ПутьКФайлу, Объект);
+
+КонецПроцедуры
diff --git "a/tests/\320\245\321\200\320\260\320\275\320\270\320\273\320\270\321\211\320\265\320\237\321\200\320\260\320\262\320\270\320\273.os" "b/tests/\320\245\321\200\320\260\320\275\320\270\320\273\320\270\321\211\320\265\320\237\321\200\320\260\320\262\320\270\320\273.os"
new file mode 100644
index 0000000..e69de29
diff --git a/v8config.json b/v8config.json
new file mode 100644
index 0000000..000735c
--- /dev/null
+++ b/v8config.json
@@ -0,0 +1,23 @@
+{
+ "Precommt4onecСценарии": {
+ "ИспользоватьСценарииРепозитория": false,
+ "КаталогЛокальныхСценариев": "",
+ "ГлобальныеСценарии": [
+ "ЗапретИспользованияПерейти.os",
+ "УдалениеЛишнихПустыхСтрок.os",
+ "ПроверкаДублейПроцедурИФункций.os",
+ "ДобавлениеПробеловПередКлючевымиСловами.os",
+ "ПроверкаКорректностиИнструкцийПрепроцессора.os",
+ "ПроверкаКорректностиОбластей.os",
+ "ИсправлениеНеКаноническогоНаписания.os",
+ "УдалениеЛишнихКонцевыхПробелов.os"
+ ],
+ "ОтключенныеСценарии": [],
+ "НастройкиСценариев": {
+ "СортировкаДереваМетаданных": {
+ "УчитываяПрефикс": ""
+ }
+ },
+ "Проекты": {}
+ }
+}
\ No newline at end of file