fix(form-decompile): ссылки на члена формы по id (N:uuid) — игнорировать с предупреждением, не verbatim

groupList/customSettingsFolder/userSettingsGroup/commandSource в форме "N:uuid" — ссылка на
член формы по id. Наш компилятор переназначает id → verbatim указал бы НЕ ТУДА (тихая порча).
Резолв N→имя ненадёжен: N не всегда соответствует named-элементу (форма ДенежныеДокументы:
GroupList=2:uuid, но элемента id=2 НЕТ; в конфигураторе список пустой — платформа сама не
разрешает эту dangling-ссылку; uuid константный для всех форм). «Страна id=2» в бэклоге —
совпадение.

Решение: декомпилятор захватывает только ИМЯ-форму; "N:uuid" опускает с предупреждением
(stderr) — задаётся вручную через form-edit. Результат идентичен (dangling → пустой список),
но без мусорной ссылки. Имя-форма (GroupList 8, CSF 18, UserSettingsGroup 3127, CommandSource
5116 в корпусе) round-трипится как есть.

Гард `^\d+:[0-9a-fA-F]{8}-` в 4 точках захвата. Harness стрипает "N:uuid"-форму (намеренное
непокрытие). Выборка 118 форм: match 113/118, ref-тег потерь 0, регрессий 0. Отменяет
verbatim-захват CustomSettingsFolder из dd32d2a6 для id-формы (имя остаётся).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-12 23:08:12 +03:00
parent dd32d2a6ca
commit 71ecec6594
2 changed files with 19 additions and 6 deletions
@@ -1,4 +1,4 @@
# form-decompile v0.121 — Decompile 1C managed Form.xml to JSON DSL (draft)
# form-decompile v0.122 — Decompile 1C managed Form.xml to JSON DSL (draft)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
param(
@@ -2038,7 +2038,8 @@ function Decompile-Element {
# RowPictureDataPath: инверсия умного дефолта <Список>.DefaultPicture
if ($null -eq $rpdp) { $obj['rowPictureDataPath'] = '' }
elseif ($rpdp -ne "$($obj['path']).DefaultPicture") { $obj['rowPictureDataPath'] = $rpdp }
$usg = Get-Child $node 'UserSettingsGroup'; if ($usg) { $obj['userSettingsGroup'] = $usg }
$usg = Get-Child $node 'UserSettingsGroup'
if ($usg) { if ($usg -match '^\d+:[0-9a-fA-F]{8}-') { [Console]::Error.WriteLine("form-decompile: UserSettingsGroup '$usg' ($name) — ссылка по id, не воспроизводима, опущена") } else { $obj['userSettingsGroup'] = $usg } }
} elseif ($rpdp) { $obj['rowPictureDataPath'] = $rpdp }
$csNode = $node.SelectSingleNode("lf:CommandSet", $ns)
if ($csNode) {
@@ -2102,7 +2103,8 @@ function Decompile-Element {
'ButtonGroup' {
$obj[$key] = $name
Add-CommonProps $obj $node $name
$cs = Get-Child $node 'CommandSource'; if ($cs) { $obj['commandSource'] = $cs }
$cs = Get-Child $node 'CommandSource'
if ($cs) { if ($cs -match '^\d+:[0-9a-fA-F]{8}-') { [Console]::Error.WriteLine("form-decompile: CommandSource '$cs' ($name) — ссылка по id, не воспроизводима, опущена") } else { $obj['commandSource'] = $cs } }
$rep = Get-Child $node 'Representation'; if ($rep) { $obj['representation'] = $rep }
$kids = Decompile-Children $node
if ($kids) { $obj['children'] = $kids }
@@ -2110,7 +2112,8 @@ function Decompile-Element {
'CommandBar' {
$obj[$key] = $name
Add-CommonProps $obj $node $name
$cs = Get-Child $node 'CommandSource'; if ($cs) { $obj['commandSource'] = $cs }
$cs = Get-Child $node 'CommandSource'
if ($cs) { if ($cs -match '^\d+:[0-9a-fA-F]{8}-') { [Console]::Error.WriteLine("form-decompile: CommandSource '$cs' ($name) — ссылка по id, не воспроизводима, опущена") } else { $obj['commandSource'] = $cs } }
$hl = Get-Child $node 'HorizontalLocation'; if ($hl) { $obj['horizontalLocation'] = $hl.ToLower() }
if ((Get-Child $node 'Autofill') -eq 'true') { $obj['autofill'] = $true }
$kids = Decompile-Children $node
@@ -2449,6 +2452,16 @@ foreach ($pn in $KNOWN_FORM_PROPS) {
else { $props[$camel] = $v }
}
}
# Ссылка на члена формы по id ("N:uuid") в groupList/customSettingsFolder НЕ воспроизводима: наш
# компилятор переназначает id, и ссылка указала бы не туда (либо вовсе dangling — платформа сама их
# часто не разрешает). Резолв в имя ненадёжен (N не всегда соответствует named-элементу). Игнорируем
# с предупреждением (имя задаётся вручную через form-edit). Имя-форма захватывается как есть.
foreach ($refKey in 'groupList','customSettingsFolder') {
if ($props.Contains($refKey) -and "$($props[$refKey])" -match '^\d+:[0-9a-fA-F]{8}-') {
[Console]::Error.WriteLine("form-decompile: $refKey = '$($props[$refKey])' — ссылка на члена формы по id, не воспроизводима (id переназначаются), опущена. Задайте по имени через form-edit.")
$props.Remove($refKey)
}
}
# AutoTitle при наличии title: компилятор инъектит false (~95% форм). Зеркалим:
# - оригинал имеет AutoTitle=false → опускаем ключ (компилятор реинъектит при наличии title);
# - оригинал НЕ имеет AutoTitle (редкие 5%, напр. вспом. формы) → суппресс-маркер "" (не инъектить).
+2 -2
View File
@@ -83,8 +83,8 @@
| `showTitle` | `<ShowTitle>` | `true` / `false` — показывать заголовок формы |
| `conversationsRepresentation` | `<ConversationsRepresentation>` | `Auto`, `Show`, `DontShow` — отображение панели обсуждений; pass-through (редкое) |
| `collapseItemsByImportanceVariant` | `<CollapseItemsByImportanceVariant>` | `DontUse`, `Use` — сворачивание элементов по важности; pass-through (редкое) |
| `groupList` | `<GroupList>` | Ссылка на группу списка (`2:<GUID>` или имя), pass-through verbatim (редкое) |
| `customSettingsFolder` | `<CustomSettingsFolder>` | Группа, куда генерируются пользовательские настройки компоновщика (форма отчёта со СКД). Имя группы или `N:<GUID>`, pass-through verbatim. 1С-синоним «Группа пользовательских настроек» |
| `groupList` | `<GroupList>` | Ссылка на группу списка **по имени**. Форма `N:<GUID>` (ссылка по id) НЕ воспроизводима — id переназначаются при компиляции (часто такая ссылка dangling, платформа сама её не разрешает → пустой список); декомпилятор опускает её с предупреждением. Задавайте по имени |
| `customSettingsFolder` | `<CustomSettingsFolder>` | Группа, куда генерируются пользовательские настройки компоновщика (форма отчёта со СКД)**по имени**. 1С-синоним «Группа пользовательских настроек». Форма `N:<GUID>` не воспроизводима (как `groupList`) — опускается с предупреждением |
Нераспознанные ключи преобразуются с автоматическим PascalCase (первая буква в верхний регистр).