Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packagedef
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
Описание.Имя("annotations")
.Версия("1.6.0")
.Версия("1.7.0")
.Автор("Nikita Fedkin")
.АдресАвтора("nixel2007@gmail.com")
.Описание("Аннотации как объекты первого класса")
.ВерсияСреды("1.9.2")
.ВерсияСреды("2.0.0")
.ВключитьФайл("src")
.ВключитьФайл("docs")
.ВключитьФайл("tasks")
Expand Down
2 changes: 1 addition & 1 deletion src/Классы/КонтейнерАннотаций.os
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
);
КонецЕсли;

ОпределениеАннотации = Новый ОпределениеАннотации(ИмяАннотации, ИмяТипаАннотации, Параметры, Аннотации);
ОпределениеАннотации = Новый ОпределениеАннотации(ИмяАннотации, ИмяТипаАннотации, Параметры, Аннотации, ЭтотОбъект);

ОпределенияАннотаций.Вставить(НРег(ИмяАннотации), ОпределениеАннотации);

Expand Down
66 changes: 60 additions & 6 deletions src/Классы/ОпределениеАннотации.os
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
// Подчиненные аннотации
Перем Аннотации;

// КонтейнерАннотаций - Контейнер определений аннотаций, которому принадлежит данное определение.
// Используется для рекурсивной материализации вложенных аннотаций-значений.
Перем КонтейнерАннотаций;

#КонецОбласти

#Область ПрограммныйИнтерфейс
Expand Down Expand Up @@ -106,13 +110,18 @@
КонецПроцедуры

// Создать объект класса аннотации по параметрам аннотации.
// Значения-параметры, являющиеся вложенными аннотациями, рекурсивно материализуются в объекты
// соответствующих аннотаций, если их определения зарегистрированы в контейнере данного определения.
//
// Параметры:
// Аннотация - СтрокаТаблицыЗначений - Данные аннотации:
// * Имя - Строка - Имя аннотации.
// * Параметры - ТаблицаЗначений - Таблица параметров аннотации:
// ** Имя - Строка - Имя параметра аннотации.
// ** Значение - Строка - Значение параметра аннотации.
// ** Значение - Строка, Число, Булево, Дата, Неопределено, Null - литеральное значение параметра;
// - СтрокаТаблицыЗначений - вложенная аннотация (см. РаботаСАннотациями.ЭтоОписаниеАннотации):
// *** Имя - Строка - Имя вложенной аннотации.
// *** Параметры - ТаблицаЗначений - Параметры вложенной аннотации.
//
// Возвращаемое значение:
// Произвольный - Объект аннотации с заданными параметрами.
Expand All @@ -123,18 +132,23 @@
Для Каждого Параметр Из Параметры() Цикл

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

ОбъектАннотации = Новый(ИмяТипаАннотации(), ПараметрыКонструктора);

Возврат ОбъектАннотации;
Expand All @@ -145,6 +159,39 @@

#Область СлужебныеПроцедурыИФункции

// Материализовать значение параметра конструктора аннотации.
//
// Если значение является вложенной аннотацией (см. РаботаСАннотациями.ЭтоОписаниеАннотации),
// а её определение зарегистрировано в контейнере данного определения, вложенная аннотация
// рекурсивно превращается в объект своей аннотации. В остальных случаях (литерал либо
// незарегистрированная аннотация) значение возвращается как есть.
//
// Параметры:
// Значение - Произвольный - Значение параметра (литерал или вложенная аннотация).
//
// Возвращаемое значение:
// Произвольный - Материализованное значение (объект вложенной аннотации либо исходное значение).
//
Функция МатериализоватьЗначение(Значение)

Если НЕ РаботаСАннотациями.ЭтоОписаниеАннотации(Значение) Тогда
Возврат Значение;
КонецЕсли;

ОпределениеВложеннойАннотации = КонтейнерАннотаций.ПолучитьОпределениеАннотации(Значение.Имя);
Если ОпределениеВложеннойАннотации = Неопределено Тогда
Возврат Значение;
КонецЕсли;

// Валидируем вложенную аннотацию так же, как верхнеуровневую: иначе неизвестные
// параметры молча игнорировались бы, а обязательные неявно получали бы Неопределено.
ПредставлениеВладельца = СтрШаблон("вложенная аннотация %1", Значение.Имя);
ОпределениеВложеннойАннотации.Проверить(Значение, ПредставлениеВладельца);

Возврат ОпределениеВложеннойАннотации.СоздатьОбъектАннотации(Значение);

Comment thread
coderabbitai[bot] marked this conversation as resolved.
КонецФункции

Процедура ПривестиИменаПараметров(Аннотация)

Для Каждого ПараметрАннотации Из Аннотация.Параметры Цикл
Expand Down Expand Up @@ -263,12 +310,19 @@

#Область Инициализация

Процедура ПриСозданииОбъекта(Знач _Имя, Знач _ИмяТипаАннотации, Знач _Параметры, Знач _Аннотации)

Процедура ПриСозданииОбъекта(
Знач _Имя,
Знач _ИмяТипаАннотации,
Знач _Параметры,
Знач _Аннотации,
Знач _КонтейнерАннотаций
)

Имя = _Имя;
ИмяТипаАннотации = _ИмяТипаАннотации;
Аннотации = _Аннотации;
Параметры = _Параметры;
КонтейнерАннотаций = _КонтейнерАннотаций;

ОпределитьПовторяемостьПараметров();
ОпределитьПсевдонимыПараметров();
Expand Down
23 changes: 23 additions & 0 deletions src/Модули/РаботаСАннотациями.os
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,29 @@
Параметр.Значение = ЗначениеПараметра;
КонецПроцедуры

// Проверить, является ли значение вложенной аннотацией.
//
// Начиная с OneScript 2.0.0 значением параметра аннотации может быть другая
// аннотация. Рефлектор представляет её строкой таблицы значений с колонками
// "Имя" и "Параметры", как и строку таблицы аннотаций.
//
// Параметры:
// Значение - Произвольный - Проверяемое значение параметра аннотации.
//
// Возвращаемое значение:
// Булево - Истина, если значение является вложенной аннотацией.
//
Функция ЭтоОписаниеАннотации(Значение) Экспорт

Если ТипЗнч(Значение) <> Тип("СтрокаТаблицыЗначений") Тогда
Возврат Ложь;
КонецЕсли;

Колонки = Значение.Владелец().Колонки;
Возврат Колонки.Найти("Имя") <> Неопределено И Колонки.Найти("Параметры") <> Неопределено;

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

#КонецОбласти

#Область СлужебныеПроцедурыИФункции
Expand Down
73 changes: 73 additions & 0 deletions tests/ВложенныеАннотации.os
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#Использовать ".."
#Использовать "."
#Использовать asserts

&Тест
Процедура ЭтоОписаниеАннотацииРаспознаетВложеннуюАннотацию() Экспорт

// Дано
Метод = НайтиМетод("МетодСВложеннойАннотацией");
ВнешняяАннотация = РаботаСАннотациями.НайтиАннотацию(Метод.Аннотации, "Внешняя");

// Когда
ЗначениеПараметра = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(ВнешняяАннотация, "Значение");

// Тогда
Ожидаем.Что(РаботаСАннотациями.ЭтоОписаниеАннотации(ЗначениеПараметра)).Равно(Истина);
Ожидаем.Что(РаботаСАннотациями.ЭтоОписаниеАннотации("просто строка")).Равно(Ложь);
Ожидаем.Что(РаботаСАннотациями.ЭтоОписаниеАннотации(Неопределено)).Равно(Ложь);

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

&Тест
Процедура СоздатьОбъектАннотацииРекурсивноМатериализуетВложеннуюАннотацию() Экспорт

// Дано
Метод = НайтиМетод("МетодСВложеннойАннотацией");
ВнешняяАннотация = РаботаСАннотациями.НайтиАннотацию(Метод.Аннотации, "Внешняя");
КонтейнерАннотаций = ПодготовитьКонтейнер();

// Когда
ОпределениеВнешней = КонтейнерАннотаций.ПолучитьОпределениеАннотации("Внешняя");
ОбъектВнешней = ОпределениеВнешней.СоздатьОбъектАннотации(ВнешняяАннотация);

// Тогда
Ожидаем.Что(ОбъектВнешней.УстановленноеЗначение).ИмеетТип("АннотацияЦель");
Ожидаем.Что(ОбъектВнешней.УстановленноеЗначение.УстановленноеЗначение).Равно("вложенное значение");

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

&Тест
Процедура НезарегистрированнаяВложеннаяАннотацияОстаетсяСтрокойТаблицы() Экспорт

// Дано
Метод = НайтиМетод("МетодСВложеннойАннотацией");
ВнешняяАннотация = РаботаСАннотациями.НайтиАннотацию(Метод.Аннотации, "Внешняя");

// Внешняя зарегистрирована, а вложенная Цель не зарегистрирована.
КонтейнерАннотаций = Новый КонтейнерАннотаций();
КонтейнерАннотаций.ДобавитьАннотацию(Тип("АннотацияВнешняя"));

// Когда
ОпределениеВнешней = КонтейнерАннотаций.ПолучитьОпределениеАннотации("Внешняя");
ОбъектВнешней = ОпределениеВнешней.СоздатьОбъектАннотации(ВнешняяАннотация);

// Тогда
Ожидаем.Что(ОбъектВнешней.УстановленноеЗначение).ИмеетТип("СтрокаТаблицыЗначений");

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

Функция ПодготовитьКонтейнер()
КонтейнерАннотаций = Новый КонтейнерАннотаций();
КонтейнерАннотаций.ДобавитьАннотацию(Тип("АннотацияВнешняя"));
КонтейнерАннотаций.ДобавитьАннотацию(Тип("АннотацияЦель"));
Возврат КонтейнерАннотаций;
КонецФункции

Функция НайтиМетод(ИмяМетода)

Рефлектор = Новый Рефлектор();
ТаблицаМетодов = Рефлектор.ПолучитьТаблицуМетодов(Тип("ВладелецВложенныхАннотаций"));
Возврат ТаблицаМетодов.Найти(ИмяМетода, "Имя");

КонецФункции
6 changes: 6 additions & 0 deletions tests/Классы/АннотацияВнешняя.os
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Перем УстановленноеЗначение Экспорт; // BSLLS:ExportVariables-off

&Аннотация("Внешняя")
Процедура ПриСозданииОбъекта(Значение = Неопределено)
УстановленноеЗначение = Значение;
КонецПроцедуры
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Фикстура для проверки вложенных аннотаций как значений параметров аннотаций.
// Требует OneScript 2.0.0 и старше.

&Внешняя(&Цель("вложенное значение"))
Процедура МетодСВложеннойАннотацией() Экспорт
КонецПроцедуры
Loading