Skip to content

feat: параметр Родитель в @ПодкомандаПриложения для гибкой регистрации подкоманд#19

Merged
Nivanchenko merged 1 commit into
autumn-library:masterfrom
Segate-ekb:feature/recursive_commands
Apr 14, 2026
Merged

Conversation

@Segate-ekb

Copy link
Copy Markdown
Contributor

Параметр Родитель в @ПодкомандаПриложения

Проблема

Сейчас связь «родитель → подкоманды» объявляется перечислением в родительской команде:

&КомандаПриложения(Имя = \"date\", Подкоманда = \"ПодкомандаДень\", Подкоманда = \"ПодкомандаМесяц\")

Это приводит к:

  • Жёсткой связанности — добавление подкоманды требует правки родителя
  • Невозможности вложенности более 1 уровня на практике
  • Неудобству перемещения команд между группами

Решение

Подкоманда сама указывает своего родителя через новый параметр Родитель:

&КомандаПриложения(Имя = \"date\", Описание = \"Работа с датами\")

&ПодкомандаПриложения(Имя = \"day\", Родитель = \"КомандаДата\", Описание = \"Начало дня\")

&ПодкомандаПриложения(Имя = \"format\", Родитель = \"ПодкомандаДень\", Описание = \"Вложенная\")
  • Добавление подкоманды — один новый файл, родитель не трогается
  • Перемещение между группами — смена Родитель в одной строке
  • Вложенность любой глубины

Обратная совместимость

Старый способ через Подкоманда = \"...\" в родителе полностью сохранён. Оба способа можно комбинировать, дедупликация по имени бина.

Изменения

  • ИКС_АннотацияПодкомнада.os — добавлен параметр Родитель
  • ИКС_ДекораторКоманд.osПолучитьПодкоманды() собирает детей из обоих источников
  • docs/product/index.md — документация обновлена
  • example/ — пример переведён на Родитель
  • Добавлены тесты на Родитель (уровень 2) и вложенные подкоманды (уровень 3)

Все 24 теста проходят ✅"

@coderabbitai

coderabbitai Bot commented Apr 9, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c754e5df-a13c-433e-a39c-d7bcd6dffc5d

📥 Commits

Reviewing files that changed from the base of the PR and between b830781 and 61a11c1.

📒 Files selected for processing (12)
  • docs/product/index.md
  • example/Классы/КомандаДата.os
  • example/Классы/ПодкомандаДень.os
  • example/Классы/ПодкомандаМесяц.os
  • src/Классы/ИКС_АннотацияПодкомнада.os
  • src/Классы/ИКС_ДекораторКоманд.os
  • tests/alltests.os
  • tests/Классы/КомандаГруппа.os
  • tests/Классы/ПодкомандаВложенная.os
  • tests/Классы/ПодкомандаПромежуточная.os
  • tests/Классы/ПодкомандаСРодителемВторая.os
  • tests/Классы/ПодкомандаСРодителемПервая.os
✅ Files skipped from review due to trivial changes (4)
  • example/Классы/ПодкомандаМесяц.os
  • tests/Классы/КомандаГруппа.os
  • tests/Классы/ПодкомандаВложенная.os
  • tests/Классы/ПодкомандаСРодителемВторая.os
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/Классы/ИКС_АннотацияПодкомнада.os
  • tests/Классы/ПодкомандаПромежуточная.os
  • example/Классы/ПодкомандаДень.os
  • example/Классы/КомандаДата.os
  • tests/Классы/ПодкомандаСРодителемПервая.os
  • docs/product/index.md
  • tests/alltests.os
  • src/Классы/ИКС_ДекораторКоманд.os

Walkthrough

Перенесена регистрация подкоманд с параметра Подкоманда на параметр Родитель в &ПодкомандаПриложения, добавлена поддержка произвольной глубины вложения, обновлены документация и примеры, расширена логика декоратора команд для поиска подкоманд по Родитель с дедупликацией и сохранением обратной совместимости; добавлены тесты для нескольких уровней вложенности.

Changes

Cohort / File(s) Summary
Документация
docs/product/index.md
Переработаны примеры «Подкоманды»: удалены встроенные Подкоманда у родителя, добавлено описание и примеры использования нового параметра Родитель, обновлён раздел обратной совместимости.
Примеры команд
example/Классы/КомандаДата.os, example/Классы/ПодкомандаДень.os, example/Классы/ПодкомандаМесяц.os
Убран список Подкоманда из КомандаДата; каждая подкоманда теперь указывает Родитель = "КомандаДата".
Ядро фреймворка
src/Классы/ИКС_АннотацияПодкомнада.os, src/Классы/ИКС_ДекораторКоманд.os
Добавлен параметр Родитель в аннотацию подкоманды и его передача при разворачивании; декоратор теперь собирает подкоманды по Родитель, сканируя определения команд, и выполняет дедупликацию, сохраняя поддержку старого Подкоманда-подхода.
Тесты и тестовые классы
tests/alltests.os, tests/Классы/КомандаГруппа.os, tests/Классы/ПодкомандаВложенная.os, tests/Классы/ПодкомандаПромежуточная.os, tests/Классы/ПодкомандаСРодителемПервая.os, tests/Классы/ПодкомандаСРодителемВторая.os
Добавлены новые модульные тесты и вспомогательные тестовые команды для проверки подкоманд через Родитель, включая трёхуровневый сценарий; исправлена директива/формат в alltests.os.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Клиент приложения
    participant Decorator as ИКС_ДекораторКоманд
    participant Annotation as ИКС_АннотацияПодкомнада
    participant Registry as Реестр_Определений

    Client->>Decorator: СоздатьКомандуПоАннотациямОбъекта(ДанныеЖелудя)
    activate Decorator

    Decorator->>Annotation: ПриСозданииОбъекта(..., Родитель="КомандаДата")
    activate Annotation
    Annotation->>Annotation: Сохранить _Родитель
    Annotation->>Decorator: УстановитьЗначениеПараметраАннотации("Родитель", _Родитель)
    deactivate Annotation

    Decorator->>Decorator: ПолучитьПодкоманды(ДанныеВладельца)
    activate Decorator

    Decorator->>Registry: Сканировать все КомандаПриложения
    Registry->>Registry: Чтение ПодкомандаПриложения.Родитель
    Registry->>Registry: Сопоставление с ДанныеВладельца.Имя

    rect rgba(100,150,200,0.5)
        Registry->>Registry: Дедупликация через ДобавленныеИмена
    end

    Registry-->>Decorator: Возврат списка подкоманд
    deactivate Decorator

    Decorator-->>Client: Готовая команда с подкомандами
    deactivate Decorator
Loading
sequenceDiagram
    participant CLI as CLI (Пользователь)
    participant Parent as КомандаГруппа
    participant Intermediate as ПодкомандаПромежуточная
    participant Deep as ПодкомандаВложенная

    CLI->>Parent: myapp group
    activate Parent
    Parent->>Parent: ОбработатьКоманду()
    deactivate Parent

    CLI->>Parent: myapp group nested
    activate Intermediate
    Intermediate->>Intermediate: ОбработатьКоманду()
    deactivate Intermediate

    CLI->>Parent: myapp group nested deep ARG=7
    activate Deep
    Deep->>Deep: ПриСозданииОбъекта(ARG=7)
    Deep->>Deep: СформироватьРезультат() -> 7 * 100 = 700
    Deep-->>CLI: Результат = 700
    deactivate Deep
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • наборы опций #16 — вносит изменения в src/Классы/ИКС_ДекораторКоманд.os, схожая область изменения логики обнаружения и сборки команд.

Suggested reviewers

  • Nivanchenko

Poem

🐰
Подкоманды в круг шустро — прыжок,
Родитель зовёт — и строится домок.
Вложенье растёт, как лес во мгле,
Три уровня — морковный пожар в деле,
Старый путь рядом, мир спокоен и весел.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed Заголовок точно описывает основное изменение PR — добавление параметра Родитель в аннотацию @ПодкомандаПриложения для гибкой регистрации подкоманд.
Description check ✅ Passed Описание полностью связано с изменениями в PR, подробно объясняет проблему, решение, обратную совместимость и перечисляет все измененные файлы.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
tests/alltests.os (1)

550-624: Добавьте регрессию на смешанный режим регистрации.

Сейчас покрыты только happy-path сценарии через Родитель. По контракту PR ещё поддерживается комбинация Подкоманда + Родитель с дедупликацией по имени бина, и без отдельного теста этот путь легко сломать незаметно.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/alltests.os` around lines 550 - 624, Добавьте регрессионный тест,
проверяющий смешанный режим регистрации (комбинация "Подкоманда" + "Родитель" с
дедупликацией по имени бина): создайте новую процедура (например
Подкоманды_ЧерезРодитель_СмешанныйРежим) которая использует ПолучитьПоделку(),
Поделка.ЗапуститьПриложение(), затем получает соответствующие объекты через
Поделка.НайтиЖелудь("...") и КонсольноеПриложение, формирует параметры, которые
запускают путь где субкоманда и родитель зарегистрированы одновременно
(убедитесь, что имя бина совпадает для проверки дедупликации), вызывает
КонсольноеПриложение.Запустить(ПараметрыКоманды) и добавляет
Ожидаем.Что(...).Равно(...) ассерты, проверяющие что результат соответствует
ожиданию и что обработка не задублировалась; поместите тест рядом с
существующими процедурам Подкоманды_ЧерезРодитель_ПерваяПодкоманда /
ВтораяПодкоманда / ВложенностьУровня3.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Классы/ИКС_ДекораторКоманд.os`:
- Line 69: Добавьте защиту от циклических родителей при рекурсивном построении
команд: в функциях, которые вызывают ПолучитьОписаниеПодкоманды(ДанныеКоманды) и
СоздатьКомандуПоАннотациямОбъекта(), заведите структуру отслеживания посещённых
объектов (например, Set по уникальному идентификатору класса/конфигурации) и
проверяйте перед рекурсивным вызовом — если узел уже посещён, пропускайте
дальнейшую рекурсию или выбрасывайте понятную ошибку валидации; гарантируйте,
что та же проверка применяется и для вложенных ветвей, где сейчас повторно
вызывается СоздатьКомандуПоАннотациямОбъекта(), чтобы предотвратить бесконечную
инициализацию в циклических графах.
- Around line 61-68: Замените чтение параметра "Родитель" так, чтобы значение
бралось из аннотации ПодкомандаПриложения, а не из КомандаПриложения: вместо
вызова РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(АннотацияКоманды,
"Родитель", "") вызывайте
РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(АннотацияПодкоманды,
"Родитель", ""), оставив остальную логику сравнения с ИмяРодителя и проверки
ЗначениеЗаполнено без изменений; используйте существующие переменные
АннотацияПодкоманды, АннотацияКоманды, Родитель, КонструкторКоманды и
РаботаСАннотациями для локализации правки.

---

Nitpick comments:
In `@tests/alltests.os`:
- Around line 550-624: Добавьте регрессионный тест, проверяющий смешанный режим
регистрации (комбинация "Подкоманда" + "Родитель" с дедупликацией по имени
бина): создайте новую процедура (например
Подкоманды_ЧерезРодитель_СмешанныйРежим) которая использует ПолучитьПоделку(),
Поделка.ЗапуститьПриложение(), затем получает соответствующие объекты через
Поделка.НайтиЖелудь("...") и КонсольноеПриложение, формирует параметры, которые
запускают путь где субкоманда и родитель зарегистрированы одновременно
(убедитесь, что имя бина совпадает для проверки дедупликации), вызывает
КонсольноеПриложение.Запустить(ПараметрыКоманды) и добавляет
Ожидаем.Что(...).Равно(...) ассерты, проверяющие что результат соответствует
ожиданию и что обработка не задублировалась; поместите тест рядом с
существующими процедурам Подкоманды_ЧерезРодитель_ПерваяПодкоманда /
ВтораяПодкоманда / ВложенностьУровня3.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b9b3a21b-b755-4706-922a-e6af45e53c0d

📥 Commits

Reviewing files that changed from the base of the PR and between 0dab051 and b830781.

📒 Files selected for processing (12)
  • docs/product/index.md
  • example/Классы/КомандаДата.os
  • example/Классы/ПодкомандаДень.os
  • example/Классы/ПодкомандаМесяц.os
  • src/Классы/ИКС_АннотацияПодкомнада.os
  • src/Классы/ИКС_ДекораторКоманд.os
  • tests/alltests.os
  • tests/Классы/КомандаГруппа.os
  • tests/Классы/ПодкомандаВложенная.os
  • tests/Классы/ПодкомандаПромежуточная.os
  • tests/Классы/ПодкомандаСРодителемВторая.os
  • tests/Классы/ПодкомандаСРодителемПервая.os

Comment on lines +61 to +68
АннотацияПодкоманды = РаботаСАннотациями.НайтиАннотацию(КонструкторКоманды.Аннотации, "ПодкомандаПриложения");
Если АннотацияПодкоманды = Неопределено Тогда
Продолжить;
КонецЕсли;

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Считывайте Родитель из ПодкомандаПриложения.

Line 67 берёт параметр из аннотации КомандаПриложения, хотя в новой схеме он задаётся на ПодкомандаПриложения. В таком виде поиск детей зависит от неявного дублирования аннотаций и может перестать находить подкоманды после любого расхождения между ними.

Предлагаемое исправление
 		АннотацияПодкоманды = РаботаСАннотациями.НайтиАннотацию(КонструкторКоманды.Аннотации, "ПодкомандаПриложения");
 		Если АннотацияПодкоманды = Неопределено Тогда
 			Продолжить;
 		КонецЕсли;
 
-		АннотацияКоманды = РаботаСАннотациями.НайтиАннотацию(КонструкторКоманды.Аннотации, "КомандаПриложения");
-		Родитель = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(АннотацияКоманды, "Родитель", "");
+		Родитель = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(АннотацияПодкоманды, "Родитель", "");
 		Если ЗначениеЗаполнено(Родитель) И Родитель = ИмяРодителя Тогда
 			Результат.Добавить(ПолучитьОписаниеПодкоманды(ДанныеКоманды));
 		КонецЕсли;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Классы/ИКС_ДекораторКоманд.os` around lines 61 - 68, Замените чтение
параметра "Родитель" так, чтобы значение бралось из аннотации
ПодкомандаПриложения, а не из КомандаПриложения: вместо вызова
РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(АннотацияКоманды,
"Родитель", "") вызывайте
РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(АннотацияПодкоманды,
"Родитель", ""), оставив остальную логику сравнения с ИмяРодителя и проверки
ЗначениеЗаполнено без изменений; используйте существующие переменные
АннотацияПодкоманды, АннотацияКоманды, Родитель, КонструкторКоманды и
РаботаСАннотациями для локализации правки.

Comment thread src/Классы/ИКС_ДекораторКоманд.os
…и подкоманд

- Добавлен параметр Родитель в аннотацию @ПодкомандаПриложения

- Подкоманда сама указывает родительскую команду вместо перечисления в родителе

- Поддержка вложенности подкоманд любой глубины

- Обратная совместимость: параметр Подкоманда в родителе по-прежнему работает

- Обновлены документация, пример и тесты
@Segate-ekb Segate-ekb force-pushed the feature/recursive_commands branch from b830781 to 61a11c1 Compare April 13, 2026 21:04
@Nivanchenko Nivanchenko merged commit b28d1c6 into autumn-library:master Apr 14, 2026
12 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants