Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
55 changes: 49 additions & 6 deletions src/Классы/ОпределениеАннотации.os
Original file line number Diff line number Diff line change
Expand Up @@ -111,30 +111,39 @@
// Аннотация - СтрокаТаблицыЗначений - Данные аннотации:
// * Имя - Строка - Имя аннотации.
// * Параметры - ТаблицаЗначений - Таблица параметров аннотации:
// ** Имя - Строка - Имя параметра аннотации.
// ** Значение - Строка - Значение параметра аннотации.
// ** Имя - Строка - Имя параметра аннотации.
// ** Значение - Произвольный - Значение параметра аннотации (литерал или вложенная аннотация).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Перечисли допутимые типы - все литералы + СтрокаТаблицыЗначений с колонками

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

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Может лучше принимать контейнер аннотаций как параметр конструктора и сохранять в поле?

Функция СоздатьОбъектАннотации(Аннотация, Знач КонтейнерАннотаций = Неопределено) Экспорт

ПараметрыКонструктора = Новый Массив;
Для Каждого Параметр Из Параметры() Цикл

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

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

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

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

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

Если КонтейнерАннотаций = Неопределено ИЛИ НЕ РаботаСАннотациями.ЭтоАннотация(Значение) Тогда

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В каком случае КонтейнерАннотаций может быть пустым?

Возврат Значение;
КонецЕсли;

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

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

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

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

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

Для Каждого ПараметрАннотации Из Аннотация.Параметры Цикл
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
ОпределениеАннотации.Проверить(Аннотация, Строка(ВладелецСвойства));
КонецЕсли;

ОбъектАннотации = ОпределениеАннотации.СоздатьОбъектАннотации(Аннотация);
ОбъектАннотации = ОпределениеАннотации.СоздатьОбъектАннотации(Аннотация, _КонтейнерАннотаций);

Если _Рефлектор.МетодСуществует(ОбъектАннотации, "ПриРазворачиванииАннотации") Тогда
ОбъектАннотации.ПриРазворачиванииАннотации(
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 значением параметра аннотации может быть другая
// аннотация. Рефлектор представляет её строкой таблицы значений с колонками
// "Имя" и "Параметры", как и строку таблицы аннотаций.
//
// Параметры:
// Значение - Произвольный - Проверяемое значение параметра аннотации.
//
// Возвращаемое значение:
// Булево - Истина, если значение является вложенной аннотацией.
//
Функция ЭтоАннотация(Значение) Экспорт

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Имя функции неудачное


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

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

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

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

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