--- name: cfe-patch-method description: Генерация и актуализация перехватчика метода в расширении 1С (CFE). Используй когда нужно перехватить метод заимствованного объекта — вставить код до, после, вместо оригинала, изменить его тело (ИзменениеИКонтроль) — или актуализировать перехватчик после изменения оригинала argument-hint: -ExtensionPath -ConfigPath -ModulePath "Catalog.X.ObjectModule" -MethodName "ПриЗаписи" -InterceptorType Before allowed-tools: - Bash - Read - Glob --- # /cfe-patch-method — Генерация перехватчика метода Читает оригинал метода из конфигурации-источника и генерирует `.bsl`-перехватчик заимствованного объекта: с правильной директивой контекста, полной сигнатурой, обрамляющими инструкциями препроцессора и областями. Для `ИзменениеИКонтроль` копирует всё тело оригинала. Создаёт файл модуля, дописывает в существующий или актуализирует уже заимствованный метод. ## Предусловие Объект должен быть заимствован в расширение (`/cfe-borrow`). Нужен доступ к исходникам базовой конфигурации (`-ConfigPath`) — оттуда читается оригинал метода. `NamePrefix` берётся из `Configuration.xml` расширения. ### Авто-определение ConfigPath Если пользователь не указал `-ConfigPath` — попробуй определить автоматически: 1. Прочитай `.v8-project.json` из корня проекта 2. Разреши целевую базу (по имени, ветке или `default` — алгоритм из `/db-list`) 3. Если у базы есть поле `configSrc` — используй как `-ConfigPath` 4. Если `configSrc` нет — спроси у пользователя ## Параметры | Параметр | Описание | По умолчанию | |----------|----------|--------------| | `ExtensionPath` | Путь к расширению (обязат.) | — | | `ConfigPath` | Путь к конфигурации-источнику | обязат., кроме случая, когда `ModulePath` — путь к файлу | | `ModulePath` | Логическое имя (`Тип.Имя.Модуль`) **или** путь к файлу модуля `.bsl` | обязат. для генерации | | `MethodName` | Имя перехватываемого метода | обязат. для генерации | | `InterceptorType` | `Before` / `After` / `Instead` / `ModificationAndControl` | обязат. для генерации | | `Check` | Проверить контролируемые методы на дрейф (только отчёт) | — | | `Actualize` | Актуализировать дрейфнувшие контролируемые методы | — | ## Формат ModulePath | ModulePath | Файл | |------------|------| | `Catalog.X.ObjectModule` | `Catalogs/X/Ext/ObjectModule.bsl` | | `Catalog.X.ManagerModule` | `Catalogs/X/Ext/ManagerModule.bsl` | | `Catalog.X.Form.Y` | `Catalogs/X/Forms/Y/Ext/Form/Module.bsl` | | `CommonModule.X` | `CommonModules/X/Ext/Module.bsl` | | `Document.X.ObjectModule` | `Documents/X/Ext/ObjectModule.bsl` | | `Document.X.Form.Y` | `Documents/X/Forms/Y/Ext/Form/Module.bsl` | Аналогично для Report, DataProcessor, InformationRegister и других типов. Вместо логического имени в `ModulePath` можно передать **путь к файлу** модуля-источника `.bsl` — тогда `-ConfigPath` указывать не нужно (оригинал читается прямо из этого файла). Путь модуля расширения определяется от типовой папки в пути автоматически. ## Типы перехвата | InterceptorType | Декоратор | Назначение | Применим к | |-----------------|-----------|------------|------------| | `Before` | `&Перед` | Код до вызова оригинального метода | процедуры | | `After` | `&После` | Код после вызова оригинального метода | процедуры | | `Instead` | `&Вместо` | Замена метода; в теле — скаффолд `ПродолжитьВызов(...)` | процедуры и функции | | `ModificationAndControl` | `&ИзменениеИКонтроль` | Копия тела оригинала для правки маркерами `#Вставка`/`#Удаление` | процедуры и функции | ## Маркеры `#Вставка` / `#Удаление` (для `ModificationAndControl`) `&ИзменениеИКонтроль` вставляет в перехватчик **копию тела оригинала**. Дальше отредактируй тело под свою доработку, **помечая каждое изменение** — платформа так отличает твою правку от неизменного оригинала: - **Добавляешь код** → оберни его `#Вставка` … `#КонецВставки`. - **Удаляешь код оригинала** → оберни удаляемые строки `#Удаление` … `#КонецУдаления`, но сами строки **оставь между маркерами** (платформа сверяет их с оригиналом). - **Заменяешь** → `#Удаление` старое `#КонецУдаления` сразу за ним `#Вставка` новое `#КонецВставки`. Пример: ```bsl &ИзменениеИКонтроль("ПриЗаписи") Процедура Расш_ПриЗаписи(Отказ) СуммаДокумента = РассчитатьСумму(); #Вставка // доработка: округляем СуммаДокумента = Окр(СуммаДокумента, 2); #КонецВставки #Удаление Записать(); #КонецУдаления #Вставка ЗаписатьСПроверкой(Отказ); #КонецВставки КонецПроцедуры ``` Правила: - Маркеры — на **отдельной строке с 0-й колонки** (без отступа), даже внутри отступов и текста запроса (`|…`). - **Незамеченные (unmarked) строки должны совпадать с оригиналом дословно** — это и есть «контроль». Если оригинал в конфигурации-источнике изменится, unmarked-контекст разойдётся → метод потребует актуализации (см. ниже; проверить пачкой — `-Check`). - Меняешь только свои `#Вставка`/`#Удаление`; чужой оригинал не трогай. ## Актуализация После изменения оригинала в конфигурации-источнике перехватчик `&ИзменениеИКонтроль` может рассинхронизироваться — unmarked-контекст разойдётся с новым оригиналом. Платформа при загрузке об этом молчит, поэтому актуализируй сам: - **Проверить** — `-Check`: отчёт по всем контролируемым методам расширения, ничего не пишет (`exit 1`, если есть дрейф или конфликт). - **Актуализировать** — `-Actualize`: переносит правки (`#Вставка`/`#Удаление`) на новый оригинал по всему расширению. Сузить область: `-ModulePath` — один модуль, `+ -MethodName` — один метод. Для одного метода то же делает повторный вызов с `-InterceptorType ModificationAndControl`. Статусы в выводе: - `[АКТУАЛЕН]` — оригинал не менялся, правок нет; - `[АКТУАЛИЗИРОВАН]` — тело обновлено по новому оригиналу, правки сохранены (в выводе — сводка); - `[АКТУАЛИЗИРОВАН-ЧАСТИЧНО]` — часть правок не удалось разместить (якорь изменился в новом оригинале). Они помечены `// [РЕСИНК-КОНФЛИКТ]` в модуле и не потеряны; путь к merge-воркспейсу — в выводе (начни с `index.md`, дальше по каждому конфликту его `conflict.md`, размести блоки вручную в `.bsl` расширения); - `[ПЕРЕНЕСЕНО В ОСНОВНУЮ]` — правка уже есть в новом оригинале (вставленный код внесён вендором) или удаляемый блок уже вырезан. Правка неактуальна — убирается из тела, дублировать/конфликтовать не нужно. Если так со всеми правками метода — перехватчик можно удалить. `-Check` этим не роняет `exit`. Повторный вызов `Before`/`After`/`Instead` для уже перехваченного метода дубль не создаёт (`[ПРОПУЩЕН]`). ## Команда ```powershell powershell.exe -NoProfile -File ".github/skills/cfe-patch-method/scripts/cfe-patch-method.ps1" -ExtensionPath src\cfe\ИмяРасширения -ConfigPath src\cf -ModulePath "Catalog.Контрагенты.ObjectModule" -MethodName "ПриЗаписи" -InterceptorType Before ``` ## Примеры ```powershell # Код перед записью ... -ExtensionPath src\cfe\ИмяРасширения -ConfigPath src\cf -ModulePath "Catalog.Контрагенты.ObjectModule" -MethodName "ПриЗаписи" -InterceptorType Before # Перехват После на форме ... -ExtensionPath src\cfe\ИмяРасширения -ConfigPath src\cf -ModulePath "Document.Заказ.Form.ФормаДокумента" -MethodName "ПослеЗаписиНаСервере" -InterceptorType After # Замена функции (ПродолжитьВызов) ... -ExtensionPath src\cfe\ИмяРасширения -ConfigPath src\cf -ModulePath "CommonModule.ОбщийМодуль" -MethodName "ПолучитьДанные" -InterceptorType Instead # ИзменениеИКонтроль — копия тела для правки маркерами ... -ExtensionPath src\cfe\ИмяРасширения -ConfigPath src\cf -ModulePath "Document.РеализацияТоваров.ObjectModule" -MethodName "ОбработкаПроведения" -InterceptorType ModificationAndControl # ModulePath как путь к файлу модуля-источника (без -ConfigPath) ... -ExtensionPath src\cfe\ИмяРасширения -ModulePath "src\cf\CommonModules\ОбщийМодуль\Ext\Module.bsl" -MethodName "ПолучитьДанные" -InterceptorType Instead # Проверить все контролируемые методы расширения на дрейф ... -ExtensionPath src\cfe\ИмяРасширения -ConfigPath src\cf -Check # Актуализировать дрейфнувшие контролируемые методы пачкой ... -ExtensionPath src\cfe\ИмяРасширения -ConfigPath src\cf -Actualize ``` ## Верификация ``` /cfe-validate ```