Skip to content

Commit

Permalink
Поддержка аннотаций в лямбда выражении
Browse files Browse the repository at this point in the history
  • Loading branch information
sfaqer committed Jan 3, 2024
1 parent 3d89d28 commit 03c6348
Show file tree
Hide file tree
Showing 4 changed files with 290 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
Если ЭтоЛямбдаВыражение = Неопределено Тогда

ЭтоЛямбдаВыражение = Новый РегулярноеВыражение(
"\(?\s*([^)]*)\s*\)?\s*->\s*\{?([^\}]+)\}?"
"(.*)->\s*\{?([^\}]+)\}?"
);

КонецЕсли;
Expand Down
157 changes: 157 additions & 0 deletions src/internal/Модули/Парсер.os
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
Перем Цифры;

Функция РазобратьСтрокуПараметров(СтрокаПараметров) Экспорт

Результат = Новый Структура(
"Аннотации, Параметры",
Новый Массив,
Новый Массив
);

Этап = "";
МетаЭтап = "АннотацииМетода";

РазбираемыеАннотации = Новый Массив;

Для Индекс = 1 По СтрДлина(СтрокаПараметров) Цикл

Токен = Сред(СтрокаПараметров, Индекс, 1);

Если Этап = "" Тогда

Если Токен = "&" Тогда
Этап = "Аннотация";
Аннотация = Новый Структура("Имя, Параметры", "", Новый Массив);
Продолжить;
КонецЕсли;

Если Токен = "(" И МетаЭтап = "АннотацииМетода" Тогда
Этап = "";
МетаЭтап = "ПараметрыМетода";
Результат.Аннотации = РазбираемыеАннотации;
РазбираемыеАннотации = Новый Массив;
Продолжить;
КонецЕсли;

Если Не ПустаяСтрока(Токен) Тогда

Этап = "ПараметрМетода";
МетаЭтап = "ПараметрыМетода";

ПараметрМетода = Новый Структура("Имя, Аннотации", "");
ПараметрМетода.Аннотации = РазбираемыеАннотации;
РазбираемыеАннотации = Новый Массив;

КонецЕсли;

КонецЕсли;

Если Этап = "Аннотация" Тогда

Если Токен = "(" Тогда
Этап = "ПараметрАннотации";
ЭтапПараметрАннотации = "Имя";
ПараметрАннотации = Новый Структура("Имя, Значение", "", "");
Продолжить;
КонецЕсли;

Если Токен = " " Тогда
Этап = "";
РазбираемыеАннотации.Добавить(Аннотация);
Продолжить;
КонецЕсли;

Аннотация.Имя = Аннотация.Имя + Токен;

КонецЕсли;

Если Этап = "ПараметрАннотации" Тогда

Если Токен = ")" Тогда
Этап = "Аннотация";
ДобавитьПараметрАннотации(Аннотация.Параметры, ПараметрАннотации);
Продолжить;
КонецЕсли;

Если Токен = "," Тогда
ДобавитьПараметрАннотации(Аннотация.Параметры, ПараметрАннотации);
ЭтапПараметрАннотации = "Имя";
ПараметрАннотации = Новый Структура("Имя, Значение", "", "");
Продолжить;
КонецЕсли;

Если Токен = """"
Или Токен = "'"
Или ЭтоЦифра(Токен) Тогда
ЭтапПараметрАннотации = "ЗначениеНачало";
КонецЕсли;

Если Токен = "=" Тогда
ЭтапПараметрАннотации = "Значение";
Продолжить;
КонецЕсли;

Если ЭтапПараметрАннотации = "Имя" Тогда

Если ПустаяСтрока(Токен) Тогда
Продолжить;
КонецЕсли;

ПараметрАннотации.Имя = ПараметрАннотации.Имя + Токен;
ИначеЕсли ЭтапПараметрАннотации = "ЗначениеНачало" Тогда
ПараметрАннотации.Значение = ПараметрАннотации.Значение + Токен;
КонецЕсли;

КонецЕсли;

Если Этап = "ПараметрМетода" Тогда

Если Токен = ")" Или Токен = "," Или Индекс = СтрДлина(СтрокаПараметров) Тогда
Этап = "";
Результат.Параметры.Добавить(ПараметрМетода);
ПараметрМетода = Новый Структура("Имя, Аннотации", "");
Продолжить;
КонецЕсли;

ПараметрМетода.Имя = ПараметрМетода.Имя + Токен;

КонецЕсли;

КонецЦикла;

Возврат Результат;

КонецФункции

Функция ЭтоЦифра(Символ)
Возврат Цифры.Найти(Символ) <> Неопределено;
КонецФункции

Процедура ДобавитьПараметрАннотации(Параметры, ПараметрАннотации)

ПараметрАннотации.Значение = СтрЗаменить(ПараметрАннотации.Значение, """", "");

Если ЭтоЦифра(Лев(ПараметрАннотации.Значение, 1)) Тогда
ПараметрАннотации.Значение = Число(ПараметрАннотации.Значение);
ИначеЕсли СтрНачинаетсяС(ПараметрАннотации.Значение, "'") Тогда
ПараметрАннотации.Значение = Дата(ПараметрАннотации.Значение);
ИначеЕсли ПараметрАннотации.Значение = "Ложь" Или ПараметрАннотации.Значение = "False"
Или ПараметрАннотации.Значение = "Истина" Или ПараметрАннотации.Значение = "True" Тогда
ПараметрАннотации.Значение = Булево(ПараметрАннотации.Значение);
КонецЕсли;

Параметры.Добавить(ПараметрАннотации);

КонецПроцедуры

Цифры = Новый Массив;
Цифры.Добавить("0");
Цифры.Добавить("1");
Цифры.Добавить("2");
Цифры.Добавить("3");
Цифры.Добавить("4");
Цифры.Добавить("5");
Цифры.Добавить("6");
Цифры.Добавить("7");
Цифры.Добавить("8");
Цифры.Добавить("9");
43 changes: 35 additions & 8 deletions src/Классы/ЛямбдаВыражение.os
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,36 @@
Метод.ЭтоПроцедура();
КонецЕсли;

Для каждого ИмяПараметра Из РазобранноеВыражение.Параметры Цикл
Метод.Параметр(Новый ПараметрМетода(ИмяПараметра));
Для Каждого Аннотация Из РазобранноеВыражение.Аннотации Цикл

АннотацияМетода = Новый Аннотация(Аннотация.Имя);

Для Каждого ПараметрАннотации Из Аннотация.Параметры Цикл
АннотацияМетода.Параметр(ПараметрАннотации.Значение, ПараметрАннотации.Имя);
КонецЦикла;

Метод.Аннотация(АннотацияМетода);

КонецЦикла;

Для каждого Параметр Из РазобранноеВыражение.Параметры Цикл

ПараметрМетода = Новый ПараметрМетода(Параметр.Имя);

Для Каждого Аннотация Из Параметр.Аннотации Цикл

АннотацияПараметра = Новый Аннотация(Аннотация.Имя);

Для Каждого ПараметрАннотации Из Аннотация.Параметры Цикл
АннотацияПараметра.Параметр(ПараметрАннотации.Значение, ПараметрАннотации.Имя);
КонецЦикла;

ПараметрМетода.Аннотация(АннотацияПараметра);

КонецЦикла;

Метод.Параметр(ПараметрМетода);

КонецЦикла;

Построитель = Новый ПостроительДекоратора(мОбъект)
Expand Down Expand Up @@ -190,11 +218,10 @@

Совпадения = ЭтоЛямбдаВыражение.НайтиСовпадения(Выражение);

РазобранноеВыражение.Параметры = СтрРазделить(
Совпадения[0].Группы[1].Значение,
",",
Ложь
);
РезультатРазбора = Парсер.РазобратьСтрокуПараметров(Совпадения[0].Группы[1].Значение);

РазобранноеВыражение.Параметры = РезультатРазбора.Параметры;
РазобранноеВыражение.Аннотации = РезультатРазбора.Аннотации;

РазобранноеВыражение.Тело = Совпадения[0].Группы[2].Значение;

Expand Down Expand Up @@ -252,7 +279,7 @@
Процедура ПриСозданииОбъекта(Выражение)

РазобранноеВыражение = Новый Структура(
"Параметры, Тело"
"Аннотации, Параметры, Тело"
);

мВыражение = Выражение;
Expand Down
98 changes: 97 additions & 1 deletion tests/ЛямбдаВыражение.os
Original file line number Diff line number Diff line change
Expand Up @@ -441,8 +441,104 @@

КонецПроцедуры

&Тест
Процедура АннотированныеПараметры() Экспорт

// Дано
ЛямбдаВыражение = Новый ЛямбдаВыражение(
"&АннотацияБезПараметра &Аннотация(""с одним параметром"") &Аннотация(Значение = ""С двумя"", Параметра = ""ми"") " +
"(&АннотацияБезПараметра x, &Аннотация(Значение = ""С двумя"", Параметра = ""ми"") y, " +
"&АннотацияБезПараметра &Аннотация(""с одним параметром"") " +
"&Аннотация(Значение = ""С двумя"", Параметра = ""ми"") z) " +
"-> a = x+y+z"
);

// Когда
Объект = ЛямбдаВыражение.Отладка().ВОбъект();

// Тогда

Методы = Рефлектор.ПолучитьТаблицуМетодов(Объект);

Метод = Методы.Найти("Принять", "Имя");

Ожидаем.Что(Метод).Существует();

Ожидаем.Что(Метод.КоличествоПараметров).Равно(3);
Ожидаем.Что(Метод.Аннотации.Количество()).Равно(3);

Аннотация = Метод.Аннотации[0];

Ожидаем.Что(Аннотация.Имя).Равно("АннотацияБезПараметра");
Ожидаем.Что(Аннотация.Параметры.Количество()).Равно(0);

Аннотация = Метод.Аннотации[1];

Ожидаем.Что(Аннотация.Имя).Равно("Аннотация");
Ожидаем.Что(Аннотация.Параметры.Количество()).Равно(1);
Ожидаем.Что(Аннотация.Параметры[0].Имя).ЭтоНеопределено();
Ожидаем.Что(Аннотация.Параметры[0].Значение).Равно("с одним параметром");

Аннотация = Метод.Аннотации[2];

Ожидаем.Что(Аннотация.Имя).Равно("Аннотация");
Ожидаем.Что(Аннотация.Параметры.Количество()).Равно(2);
Ожидаем.Что(Аннотация.Параметры[0].Имя).Равно("Значение");
Ожидаем.Что(Аннотация.Параметры[0].Значение).Равно("С двумя");
Ожидаем.Что(Аннотация.Параметры[1].Имя).Равно("Параметра");
Ожидаем.Что(Аннотация.Параметры[1].Значение).Равно("ми");

Параметр = Метод.Параметры[0];

Ожидаем.Что(Параметр.Имя).Равно("x");

Аннотация = Параметр.Аннотации[0];

Ожидаем.Что(Аннотация.Имя).Равно("АннотацияБезПараметра");
Ожидаем.Что(Аннотация.Параметры.Количество()).Равно(0);

Параметр = Метод.Параметры[1];

Ожидаем.Что(Параметр.Имя).Равно("y");

Аннотация = Параметр.Аннотации[0];

Ожидаем.Что(Аннотация.Имя).Равно("Аннотация");
Ожидаем.Что(Аннотация.Параметры.Количество()).Равно(2);
Ожидаем.Что(Аннотация.Параметры[0].Имя).Равно("Значение");
Ожидаем.Что(Аннотация.Параметры[0].Значение).Равно("С двумя");
Ожидаем.Что(Аннотация.Параметры[1].Имя).Равно("Параметра");
Ожидаем.Что(Аннотация.Параметры[1].Значение).Равно("ми");

Параметр = Метод.Параметры[2];

Ожидаем.Что(Параметр.Имя).Равно("z");

Аннотация = Параметр.Аннотации[0];

Ожидаем.Что(Аннотация.Имя).Равно("АннотацияБезПараметра");
Ожидаем.Что(Аннотация.Параметры.Количество()).Равно(0);

Аннотация = Параметр.Аннотации[1];

Ожидаем.Что(Аннотация.Имя).Равно("Аннотация");
Ожидаем.Что(Аннотация.Параметры.Количество()).Равно(1);
Ожидаем.Что(Аннотация.Параметры[0].Имя).ЭтоНеопределено();
Ожидаем.Что(Аннотация.Параметры[0].Значение).Равно("с одним параметром");

Аннотация = Параметр.Аннотации[2];

Ожидаем.Что(Аннотация.Имя).Равно("Аннотация");
Ожидаем.Что(Аннотация.Параметры.Количество()).Равно(2);
Ожидаем.Что(Аннотация.Параметры[0].Имя).Равно("Значение");
Ожидаем.Что(Аннотация.Параметры[0].Значение).Равно("С двумя");
Ожидаем.Что(Аннотация.Параметры[1].Имя).Равно("Параметра");
Ожидаем.Что(Аннотация.Параметры[1].Значение).Равно("ми");

КонецПроцедуры

Функция ЗахватываемыйОбъект()

Возврат Новый ПостроительДекоратора()
.Метод(
Новый Метод("Тест")
Expand Down

0 comments on commit 03c6348

Please sign in to comment.