feat(cfe-borrow): add -BorrowMainAttribute for borrowing object attributes with form

When adding a new attribute to a borrowed form, -BorrowMainAttribute
borrows the form's main attribute ("Объект") and all referenced object
attributes, tabular sections, and their transitive type dependencies.

Two modes: Form (default — only attributes referenced by form DataPath)
and All (all object attributes). Deep paths like Объект.A.B are resolved
transitively. Already-borrowed objects are not overwritten.

Also fixed: CommonPicture auto-borrow from AutoCommandBar, form-attribute
DataPath stripping (keep only Объект.* paths).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-03-25 19:56:26 +03:00
co-authored by Claude Opus 4.6
parent 252105396b
commit f7695a9534
5 changed files with 1308 additions and 55 deletions
+65 -11
View File
@@ -310,7 +310,47 @@ Enums/ # Перечисления
Собственный реквизит **не имеет** `ObjectBelonging` и `ExtendedConfigurationObject`. Содержит полный набор свойств.
### 5.3. Заимствованные значения перечислений
### 5.3. Заимствование реквизитов объекта для работы с формой
Когда в расширении заимствуется форма объекта и требуется сохранить привязки к данным (`DataPath`), необходимо заимствовать реквизиты объекта, на которые форма ссылается. Это позволяет добавлять новые элементы на форму через расширение.
**Что заимствуется**:
- Реквизиты объекта, на которые ссылается форма через `Объект.XXX` в `<DataPath>`
- Табличные части целиком (все колонки), если форма обращается к `Объект.ТЧ`
- Зависимые объекты по типам реквизитов (`CatalogRef.X` → заимствуется `Catalog.X` как оболочка)
- Глубокие ссылки: `Объект.A.B` → реквизит B заимствуется внутри каталога A
**Обогащение Properties**: заимствованный объект с реквизитами содержит дополнительные свойства из источника (`Hierarchical`, `CodeLength`, `DescriptionLength`, `CodeType`, `CodeAllowedLength`), которые отсутствуют у простой оболочки.
**Заимствованная табличная часть** содержит `InternalInfo` с `GeneratedType` (категории `TabularSection` и `TabularSectionRow`):
```xml
<TabularSection uuid="...">
<InternalInfo>
<xr:GeneratedType name="CatalogTabularSection.Номенклатура.ДрагоценныеМатериалы" category="TabularSection">
<xr:TypeId>...</xr:TypeId>
<xr:ValueId>...</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="CatalogTabularSectionRow.Номенклатура.ДрагоценныеМатериалы" category="TabularSectionRow">
<xr:TypeId>...</xr:TypeId>
<xr:ValueId>...</xr:ValueId>
</xr:GeneratedType>
</InternalInfo>
<Properties>
<ObjectBelonging>Adopted</ObjectBelonging>
<Name>ДрагоценныеМатериалы</Name>
<Comment/>
<ExtendedConfigurationObject>...</ExtendedConfigurationObject>
</Properties>
<ChildObjects>
<!-- все реквизиты ТЧ — adopted -->
</ChildObjects>
</TabularSection>
```
**Типы в реквизитах**: `v8:Type` для обычных типов (`cfg:CatalogRef.X`, `cfg:EnumRef.X`), `v8:TypeSet` для определяемых типов (`cfg:DefinedType.X`).
### 5.4. Заимствованные значения перечислений
```xml
<EnumValue uuid="9bc7380f-...">
@@ -324,7 +364,7 @@ Enums/ # Перечисления
</EnumValue>
```
### 5.4. Формы в расширениях
### 5.5. Формы в расширениях
В расширении существуют **два принципиально разных сценария** работы с формами:
@@ -335,7 +375,7 @@ Enums/ # Перечисления
> **Как отличить:** Если файл метаданных формы (`.xml`) содержит `<ObjectBelonging>Adopted</ObjectBelonging>` — это заимствованная форма. Собственные формы не имеют `ObjectBelonging`.
#### 5.4.1. Метаданные заимствованной формы
#### 5.5.1. Метаданные заимствованной формы
Файл `.xml` в каталоге `Forms/`:
@@ -354,7 +394,7 @@ Enums/ # Перечисления
Содержимое формы хранится в `Forms/ФормаСписка/Ext/Form.xml`, модуль формы — в `Forms/ФормаСписка/Ext/Form/Module.bsl`.
#### 5.4.2. Структура Form.xml заимствованной формы
#### 5.5.2. Структура Form.xml заимствованной формы
Form.xml заимствованной формы — **двухчастный файл**: Part 1 (результирующая форма) и BaseForm (исходная форма). Существуют **два варианта** в зависимости от наличия модификаций модуля формы.
@@ -415,13 +455,27 @@ Form.xml заимствованной формы — **двухчастный ф
2. **AutoCommandBar** — присутствует всегда с `id="-1"`, но без `<ChildItems>` (кнопки удаляются). `<Autofill>` = `false`.
3. **Attributes** — пустой `<Attributes/>` в обеих секциях. Атрибуты базовой конфигурации **не включаются**. Реквизиты расширения (id ≥ 1000000) добавляются только в Part 1.
3. **Attributes**по умолчанию пустой `<Attributes/>` в обеих секциях. Атрибуты базовой конфигурации **не включаются**. Реквизиты расширения (id ≥ 1000000) добавляются только в Part 1.
**Вариант с заимствованным основным реквизитом**: если реквизиты объекта заимствованы (см. раздел 5.3), секция `<Attributes>` содержит основной реквизит формы:
```xml
<Attributes>
<Attribute name="Объект" id="1000001">
<Type><v8:Type>cfg:CatalogObject.Номенклатура</v8:Type></Type>
<MainAttribute>true</MainAttribute>
<SavedData>true</SavedData>
</Attribute>
</Attributes>
```
Присутствует в обеих секциях (Part 1 и BaseForm). Тип зависит от родительского объекта: `CatalogObject`, `DocumentObject` и т.д.
4. **BaseForm** — последний элемент в `<Form>`, атрибут `version`. В BaseForm **нет** Events, Commands, Parameters.
5. **DataPath: удаление** (вариант B) — все `<DataPath>` из базовых элементов удаляются в обеих секциях. DataPath ссылается на реквизиты, не включённые в расширение.
5. **DataPath** — два варианта в зависимости от наличия заимствованного основного реквизита:
- **Без основного реквизита**: все `<DataPath>` удаляются в обеих секциях (ссылаются на реквизиты, не включённые в расширение).
- **С основным реквизитом**: `<DataPath>`, начинающиеся с `Объект.` **сохраняются** (реквизиты заимствованы и привязки валидны). DataPath формовых реквизитов (не начинающиеся с `Объект.`) — удаляются.
6. **TitleDataPath: удаление** (вариант B) — все `<TitleDataPath>` удаляются (напр. `Объект.Товары.RowsCount` — путь недействителен без базовых атрибутов).
6. **TitleDataPath** — аналогично DataPath: удаляются без основного реквизита, `Объект.*` сохраняются с ним.
7. **TypeLink: удаление** (вариант B) — блоки `<TypeLink>` с `<xr:DataPath>Items.*</xr:DataPath>` удаляются (человекочитаемые пути, которые нельзя преобразовать в UUID-формат Конфигуратора).
@@ -435,7 +489,7 @@ Form.xml заимствованной формы — **двухчастный ф
12. **Авто-заимствование Enums + EnumValues** — `<ChoiceParameters>` могут содержать `<Value xsi:type="xr:DesignTimeRef">Enum.XXX.EnumValue.YYY</Value>`. Перечисление `Enum.XXX` заимствуется вместе с конкретными `EnumValue` (borrowed с `ExtendedConfigurationObject` указывающим на UUID оригинального значения).
#### 5.4.3. Нумерация ID элементов
#### 5.5.3. Нумерация ID элементов
| Диапазон | Принадлежность |
|----------|---------------|
@@ -445,7 +499,7 @@ Form.xml заимствованной формы — **двухчастный ф
> **Важно:** Визуальные элементы форм (элементы в `ChildItems`), добавленные расширением в тело базовой формы, могут использовать ID из обычного диапазона (продолжая нумерацию базовой формы). Диапазон 1000000+ гарантирован для `Attributes` и `Commands`.
#### 5.4.4. Атрибут callType — перехват событий и команд
#### 5.5.4. Атрибут callType — перехват событий и команд
В заимствованных формах события и действия команд используют атрибут `callType` для определения момента перехвата:
@@ -509,7 +563,7 @@ Form.xml заимствованной формы — **двухчастный ф
> **Отличие от обычной формы:** В обычной форме (конфигурации или собственной форме расширения) у `<Event>` и `<Action>` **нет** атрибута `callType` — обработчик вызывается напрямую.
#### 5.4.5. Собственная форма на заимствованном объекте
#### 5.5.5. Собственная форма на заимствованном объекте
Расширение может добавить к заимствованному объекту **собственную форму**, не существующую в базовой конфигурации. Такая форма:
@@ -543,7 +597,7 @@ Form.xml заимствованной формы — **двухчастный ф
</Form>
```
#### 5.4.6. Модуль заимствованной формы
#### 5.5.6. Модуль заимствованной формы
Модуль формы (`Forms/Имя/Ext/Form/Module.bsl`) в заимствованной форме использует те же декораторы перехвата, что и другие модули расширений (см. раздел 7.2):