Skip to content

Commit 60af105

Browse files
committed
feat: аннотации как значения параметров аннотаций (внедрение)
Реализован общий механизм резолва значений параметров аннотаций: если значение параметра само является аннотацией, оно трактуется как описание частицы, прилепляется штатным механизмом, и результат её прилепления используется как значение. - ПрилепляторЧастиц.РазрешитьЗначение — единая точка резолва; применяется к имени частицы, значениям Блестяшка, ЗначениеПоУмолчанию и Типу. Рекурсия автоматическая: НайтиПрилепляемуюЧастицу сам прогоняет свои значения через РазрешитьЗначение, поэтому вложенность любой глубины разрешается сама собой. Даёт кейс &Пластилин(&Деталька("Ключ")). - ПрилепляемаяЧастица: имя частицы может нести вложенную аннотацию до резолва; добавлено имя свойства как имя по умолчанию для вложенной аннотации без явного значения. - Зависимость annotations поднята до 1.7.0, версия до 5.1.0. Тест + изолированные фикстуры покрывают внедрение желудя, имя которого берётся из настройки через вложенную &Деталька. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Knr8gmzxGCTqmbLhYXUEue
1 parent f709ed2 commit 60af105

6 files changed

Lines changed: 121 additions & 14 deletions

File tree

packagedef

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66

77
Описание.Имя("autumn")
8-
.Версия("5.0.0")
8+
.Версия("5.1.0")
99
.Автор("Nikita Fedkin")
1010
.АдресАвтора("nixel2007@gmail.com")
1111
.Описание("Dependency injection framework для OneScript")
@@ -14,7 +14,7 @@
1414
.ВключитьФайл("tests")
1515
.ВключитьФайл("LICENSE.md")
1616
.ВключитьФайл("README.md")
17-
.ЗависитОт("annotations", "1.6.0")
17+
.ЗависитОт("annotations", "1.7.0")
1818
.ЗависитОт("asserts", "1.6.2")
1919
.ЗависитОт("configor", "0.12.0")
2020
.ЗависитОт("logos", "1.7.1")

src/internal/Классы/ПрилепляторЧастиц.os

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,15 @@
4242
);
4343
КонецЕсли;
4444

45-
ПрилепляемаяЧастица = Новый ПрилепляемаяЧастица(ТипЧастицы, ИмяЧастицы, Аннотация);
45+
ПрилепляемаяЧастица = Новый ПрилепляемаяЧастица(ТипЧастицы, ИмяЧастицы, Аннотация, Неопределено, ИмяСвойства);
4646

4747
АннотацияТабакерка = РаботаСАннотациями.ПолучитьАннотацию(Свойство, "Табакерка");
4848
Если АннотацияТабакерка <> Неопределено Тогда
4949
ТипЧастицы = ТипыПрилепляемыхЧастиц.Табакерка();
5050
Аннотация = АннотацияТабакерка;
5151
БазоваяПрилепляемаяЧастица = ПрилепляемаяЧастица;
5252

53-
ПрилепляемаяЧастица = Новый ПрилепляемаяЧастица(ТипЧастицы, ИмяЧастицы, Аннотация, БазоваяПрилепляемаяЧастица);
53+
ПрилепляемаяЧастица = Новый ПрилепляемаяЧастица(ТипЧастицы, ИмяЧастицы, Аннотация, БазоваяПрилепляемаяЧастица, ИмяСвойства);
5454
КонецЕсли;
5555

5656
Возврат ПрилепляемаяЧастица;
@@ -66,21 +66,25 @@
6666
Аннотация = ДанныеОПрилепляемойЧастице.Аннотация();
6767
БазоваяПрилепляемаяЧастица = ДанныеОПрилепляемойЧастице.БазоваяПрилепляемаяЧастица();
6868

69+
// Имя частицы может быть задано вложенной аннотацией (например &Пластилин(&Деталька("Ключ"))).
70+
// Резолвим её в конкретное значение; для литералов возвращается само значение.
71+
ИмяЧастицы = РазрешитьЗначение(ИмяЧастицы, ДанныеОПрилепляемойЧастице.ИмяСвойства());
72+
6973
Если ТипЧастицы = ТипыПрилепляемыхЧастиц.Табакерка() Тогда
7074
ПрилепляемаяЧастица = Новый Табакерка(ЭтотОбъект, БазоваяПрилепляемаяЧастица);
7175
ИначеЕсли ТипЧастицы = ТипыПрилепляемыхЧастиц.Желудь() Тогда
7276

73-
ТипЖелудя = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(
77+
ТипЖелудя = РазрешитьЗначение(РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(
7478
Аннотация,
7579
"Тип",
7680
"Желудь"
77-
);
81+
));
7882

7983
Если ПрилепляемыеЧастицы = Неопределено Тогда
8084
ПараметрыАннотации = РаботаСАннотациями.ПолучитьПараметрыАннотации(Аннотация, "Блестяшка");
8185
ПрилепляемыеЧастицы = Новый Массив;
8286
Для Каждого ПараметрБлестяшка Из ПараметрыАннотации Цикл
83-
ПрилепляемыеЧастицы.Добавить(ПараметрБлестяшка.Значение);
87+
ПрилепляемыеЧастицы.Добавить(РазрешитьЗначение(ПараметрБлестяшка.Значение));
8488
КонецЦикла;
8589
КонецЕсли;
8690

@@ -94,12 +98,12 @@
9498

9599
ИначеЕсли ТипЧастицы = ТипыПрилепляемыхЧастиц.Деталька() Тогда
96100

97-
ЗначениеПоУмолчанию = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(
98-
Аннотация,
99-
"ЗначениеПоУмолчанию",
101+
ЗначениеПоУмолчанию = РазрешитьЗначение(РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(
102+
Аннотация,
103+
"ЗначениеПоУмолчанию",
100104
Неопределено,
101105
Истина
102-
);
106+
));
103107

104108
ПрилепляемаяЧастица = Поделка.НайтиДетальку(ИмяЧастицы, ЗначениеПоУмолчанию);
105109
Иначе
@@ -110,6 +114,57 @@
110114

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

117+
// Разрешить значение параметра аннотации.
118+
//
119+
// Если значение является вложенной аннотацией (например &Деталька("Ключ") или &Пластилин("ИмяЖелудя")),
120+
// оно трактуется как описание частицы: аннотация прилепляется штатным механизмом, а результат её
121+
// прилепления возвращается как значение. Литералы возвращаются без изменений.
122+
//
123+
// Механизм общий и рекурсивный: НайтиПрилепляемуюЧастицу сам прогоняет имя, блестяшки и значение
124+
// по умолчанию через РазрешитьЗначение, поэтому вложенность произвольной глубины разрешается сама собой.
125+
//
126+
// Параметры:
127+
// Значение - Произвольный - Значение параметра аннотации (литерал или вложенная аннотация).
128+
// ИмяПоУмолчанию - Строка - Имя частицы по умолчанию для вложенной аннотации без явного значения.
129+
//
130+
// Возвращаемое значение:
131+
// Произвольный - Разрешённое значение.
132+
//
133+
Функция РазрешитьЗначение(Знач Значение, Знач ИмяПоУмолчанию = "")
134+
135+
Если НЕ РаботаСАннотациями.ЭтоАннотация(Значение) Тогда
136+
Возврат Значение;
137+
КонецЕсли;
138+
139+
ПсевдоСвойство = Новый Структура("Имя, Аннотации", ИмяПоУмолчанию, ТаблицаИзОднойАннотации(Значение));
140+
ДанныеОЧастице = ДанныеОПрилепляемойЧастице(ПсевдоСвойство);
141+
142+
Возврат НайтиПрилепляемуюЧастицу(ДанныеОЧастице);
143+
144+
КонецФункции
145+
146+
// Построить таблицу аннотаций из одной вложенной аннотации-значения.
147+
//
148+
// Параметры:
149+
// Аннотация - СтрокаТаблицыЗначений - Вложенная аннотация с колонками Имя и Параметры.
150+
//
151+
// Возвращаемое значение:
152+
// ТаблицаЗначений - Таблица аннотаций с единственной строкой.
153+
//
154+
Функция ТаблицаИзОднойАннотации(Аннотация)
155+
156+
Таблица = Новый ТаблицаЗначений;
157+
Таблица.Колонки.Добавить("Имя");
158+
Таблица.Колонки.Добавить("Параметры");
159+
160+
Строка = Таблица.Добавить();
161+
Строка.Имя = Аннотация.Имя;
162+
Строка.Параметры = Аннотация.Параметры;
163+
164+
Возврат Таблица;
165+
166+
КонецФункции
167+
113168
Процедура ПриСозданииОбъекта(пПоделка, пУправляющийПрилепляемымиКоллекциями)
114169
Поделка = пПоделка;
115170
УправляющийПрилепляемымиКоллекциями = пУправляющийПрилепляемымиКоллекциями;

src/Классы/ПрилепляемаяЧастица.os

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
Перем _ИмяЧастицы;
55
Перем _Аннотация;
66
Перем _БазоваяПрилепляемаяЧастица;
7+
Перем _ИмяСвойства;
78

89
// Тип прилепляемой частицы (желудь, деталька, блестяшка или табакерка).
910
//
@@ -46,6 +47,17 @@
4647
Возврат _БазоваяПрилепляемаяЧастица;
4748
КонецФункции
4849

50+
// Имя свойства/параметра, к которому относится частица.
51+
// Используется как имя по умолчанию при резолве вложенной аннотации-значения,
52+
// у которой не задано собственное значение.
53+
//
54+
// Возвращаемое значение:
55+
// Строка
56+
//
57+
Функция ИмяСвойства() Экспорт
58+
Возврат _ИмяСвойства;
59+
КонецФункции
60+
4961
// Описывает зависимость (частицу), которую нужно прилепить к желудю.
5062
//
5163
// Параметры:
@@ -58,10 +70,14 @@
5870
// ** Значение - Строка - значение параметра аннотации
5971
// БазоваяПрилепляемаяЧастица - ПрилепляемаяЧастица - Базовая частица для коллекций и табакерок. По умолчанию Неопределено.
6072
//
61-
Процедура ПриСозданииОбъекта(ТипЧастицы, ИмяЧастицы, Аннотация, БазоваяПрилепляемаяЧастица = Неопределено)
62-
73+
Процедура ПриСозданииОбъекта(ТипЧастицы, ИмяЧастицы, Аннотация, БазоваяПрилепляемаяЧастица = Неопределено, ИмяСвойства = "")
74+
6375
Утверждения.ПроверитьТип(ТипЧастицы, "Строка");
64-
Утверждения.ПроверитьТип(ИмяЧастицы, "Строка");
76+
// Имя частицы обычно строка, но может быть вложенной аннотацией (СтрокаТаблицыЗначений),
77+
// которая резолвится в конкретное значение при создании желудя.
78+
Если ТипЗнч(ИмяЧастицы) <> Тип("СтрокаТаблицыЗначений") Тогда
79+
Утверждения.ПроверитьТип(ИмяЧастицы, "Строка");
80+
КонецЕсли;
6581
Утверждения.ПроверитьТип(Аннотация, "СтрокаТаблицыЗначений");
6682
Если БазоваяПрилепляемаяЧастица <> Неопределено Тогда
6783
Утверждения.ПроверитьТип(БазоваяПрилепляемаяЧастица, "ПрилепляемаяЧастица");
@@ -71,5 +87,6 @@
7187
_ИмяЧастицы = ИмяЧастицы;
7288
_Аннотация = Аннотация;
7389
_БазоваяПрилепляемаяЧастица = БазоваяПрилепляемаяЧастица;
90+
_ИмяСвойства = ИмяСвойства;
7491

7592
КонецПроцедуры
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// BSLLS:MissingVariablesDescription-off
2+
// BSLLS:ExportVariables-off
3+
4+
// Имя внедряемого желудя берётся из настройки, на которую ссылается вложенная &Деталька.
5+
&Пластилин(&Деталька("ИмяАппендера"))
6+
Перем Зависимость Экспорт;
7+
8+
&Желудь
9+
Процедура ПриСозданииОбъекта()
10+
КонецПроцедуры
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
&Желудь("ЦелевойЖелудь")
2+
Процедура ПриСозданииОбъекта()
3+
КонецПроцедуры

tests/Поделка.os

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,28 @@
322322

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

325+
&Тест
326+
&Изолированный(
327+
Уровень = "Процесс",
328+
Импорты = "./ВложенныеЗначения",
329+
Совет = "() -> {
330+
| Возврат Новый СоветДругогоМастера()
331+
| .ЗначенияДеталек(Новый Соответствие(
332+
| Соответствия.ИзЭлементов(""ИмяАппендера"", ""ЦелевойЖелудь"")
333+
| ));
334+
|}"
335+
)
336+
Процедура ИмяВнедряемогоЖелудяБерётсяИзВложеннойДетальки() Экспорт
337+
338+
// Дано-Когда
339+
// &Пластилин(&Деталька("ИмяАппендера")) — имя внедряемого желудя резолвится из настройки.
340+
Желудь = Поделка.НайтиЖелудь("ЖелудьСВложеннойДеталькой");
341+
342+
// Тогда
343+
Ожидаем.Что(Желудь.Зависимость, "Вложенная деталька не разрешилась в имя желудя").ИмеетТип("ЦелевойЖелудь");
344+
345+
КонецПроцедуры
346+
325347
&Тест
326348
Процедура НапильникПолучаетЖелудьЧерезКонструктор() Экспорт
327349

0 commit comments

Comments
 (0)