From 4855f79403cbc444bf8174109de9ce55b4ccc055 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sat, 13 Jun 2026 17:01:52 +0300 Subject: [PATCH] =?UTF-8?q?fix(form-decompile,form-compile):=20=D0=B7?= =?UTF-8?q?=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=B0=D1=80?= =?UTF-8?q?=D0=B0=D0=BC=D0=B5=D1=82=D1=80=D0=BE=D0=B2=20=D0=B4=D0=B8=D0=BD?= =?UTF-8?q?-=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D0=B0=20=E2=80=94=20ent:-=D1=82?= =?UTF-8?q?=D0=B8=D0=BF,=20multi-value,=20dataParameters=20=D0=B2=20partia?= =?UTF-8?q?l-=D0=B4=D0=B5=D1=81=D0=BA=D1=80=D0=B8=D0=BF=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Форма ПомощникРасчетаНалогаУСН теряла значения параметров дин-списка (3 бага): (1) ent: системное перечисление в значении (ent:AccumulationRecordType=Expense) → компилятор понижал до xs:string. Фикс: ветка ^ent: в Emit-DLValue/emit_dl_value (value несёт тот же xsi:type, что valueType). (2) Параметр с valueListAllowed + НЕСКОЛЬКО — декомпилятор читал ОДНО (SelectSingleNode), 2-е/3-е дропались. Фикс: SelectNodes → массив (компилятор уже эмитит array через Emit-DLValue по каждому). (3) ListSettings с ронялся в канон-fallback (Get-ListSettingsShape unknown top-level → $null) → компилятор додумывал полный канон (лишние userSettingID/ itemsUserSettingID). Фикс: dataParameters → дескриптор + case в partial-пути (ps1+py), контент из settings.dataParameters. Форма → match (8 diff → 0). Корпус: ent:/multi-value по 1 форме (редко). ps1==py байт-в-байт. Регресс 43/43. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../form-compile/scripts/form-compile.ps1 | 4 +++- .../form-compile/scripts/form-compile.py | 7 ++++++- .../form-decompile/scripts/form-decompile.ps1 | 21 ++++++++++++------- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index 037df42d..9a1d3882 100644 --- a/.claude/skills/form-compile/scripts/form-compile.ps1 +++ b/.claude/skills/form-compile/scripts/form-compile.ps1 @@ -1,4 +1,4 @@ -# form-compile v1.165 — Compile 1C managed form from JSON or object metadata +# form-compile v1.166 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$JsonPath, @@ -5230,6 +5230,7 @@ function Emit-DLValue { if ($type -match '^(date|dateTime|time)') { X "$indent$(Esc-Xml $valStr)" } elseif ($type -eq "boolean") { X "$indent$(Esc-Xml $valStr)" } elseif ($type -eq 'v8:Type') { $nsAttr = Get-ValueTypeNsAttr -valueType 'v8:Type' -value $valStr; X "$indent$(Esc-Xml $valStr)" } + elseif ($type -match '^ent:') { X "$indent$(Esc-Xml $valStr)" } # системное перечисление (ent:X) — value несёт тот же xsi:type elseif ($type -match '^decimal') { X "$indent$(Esc-Xml $valStr)" } elseif ($type -match '^string') { X "$indent$(Esc-Xml $valStr)" } elseif ($type -match '^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|BusinessProcessRef|TaskRef|ExchangePlanRef)\.') { X "$indent$(Esc-Xml $valStr)" } @@ -5794,6 +5795,7 @@ function Emit-Attributes { 'itemsViewMode' { X "$lsiNormal" } 'itemsUserSettingID' { X "$lsi$($script:CANON_ITEMS_ID)" } 'itemsUserSettingPresentation' { Emit-USPresentation -val $pv -tag "dcsset:itemsUserSettingPresentation" -indent $lsi } + 'dataParameters' { Emit-DataParameters -items $st.dataParameters -indent $lsi } 'structure' { Emit-ListGrouping (Get-ListGroupingValue $st) $lsi } } } diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index 0dd9a9d0..321a3ea2 100644 --- a/.claude/skills/form-compile/scripts/form-compile.py +++ b/.claude/skills/form-compile/scripts/form-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-compile v1.165 — Compile 1C managed form from JSON or object metadata +# form-compile v1.166 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import copy @@ -4973,6 +4973,9 @@ def emit_dl_value(lines, type_str, val, indent, value_list_allowed=False): elif t == 'v8:Type': ns_attr = _value_type_ns_attr('v8:Type', val_str) lines.append(f'{indent}{esc_xml(val_str)}') + elif re.match(r'^ent:', t): + # системное перечисление (ent:X) — value несёт тот же xsi:type + lines.append(f'{indent}{esc_xml(val_str)}') elif re.match(r'^decimal', t): lines.append(f'{indent}{esc_xml(val_str)}') elif re.match(r'^string', t): @@ -5572,6 +5575,8 @@ def emit_attributes(lines, attrs, indent, conditional_appearance=None): lines.append(f'{lsi}{CANON_ITEMS_ID}') elif tag == 'itemsUserSettingPresentation': emit_us_presentation(lines, lsi, 'dcsset:itemsUserSettingPresentation', pv) + elif tag == 'dataParameters': + emit_data_parameters(lines, s.get('dataParameters'), lsi) elif tag == 'structure': emit_list_grouping(lines, get_list_grouping_value(s), lsi) else: diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1 index 27495365..0e5faca3 100644 --- a/.claude/skills/form-decompile/scripts/form-decompile.ps1 +++ b/.claude/skills/form-decompile/scripts/form-decompile.ps1 @@ -1,4 +1,4 @@ -# form-decompile v0.141 — Decompile 1C managed Form.xml to JSON DSL (draft) +# form-decompile v0.142 — Decompile 1C managed Form.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью. param( @@ -145,8 +145,9 @@ function Get-ListSettingsShape { } elseif ($tag -eq 'itemsViewMode') { $shape['itemsViewMode'] = $true } elseif ($tag -eq 'itemsUserSettingID') { $shape['itemsUserSettingID'] = $true } elseif ($tag -eq 'itemsUserSettingPresentation') { $shape['itemsUserSettingPresentation'] = Get-PresByType $child } # items-уровневая подпись (форма по xsi:type) + elseif ($tag -eq 'dataParameters') { $shape['dataParameters'] = $true } # значения параметров запроса (контент в settings.dataParameters) elseif ($tag -eq 'item') { if ($hasGrouping) { $shape['structure'] = $true } else { return $null } } - else { return $null } # dataParameters/… → канон-fallback + else { return $null } # неизвестный top-level → канон-fallback } # Полный каноничный скелет → опускаем (компилятор регенерит) if ($shape.Count -eq 5 -and $shape['filter'] -eq 'vu' -and $shape['order'] -eq 'vu' -and ` @@ -1485,11 +1486,17 @@ function Build-DLParameter { # value — опускаем nil (дефолт), КРОМЕ valueListAllowed+nil: платформа пишет # не всегда (корпус 27 с / 47 без), а компилятор при valueListAllowed по умолчанию его НЕ эмитит → # явный маркер value:null, чтобы реэмитить nil. (Различается через Has-DLProp в компиляторе.) - $vNode = $pNode.SelectSingleNode("dcssch:value", $ns) - if ($vNode -and ($vNode.GetAttribute("nil", $NS_XSI) -ne 'true')) { - $o['value'] = Convert-TypedValue -raw $vNode.InnerText -xsiType ($vNode.GetAttribute("type", $NS_XSI)) - } elseif ($vNode -and ((Get-Child $pNode 'valueListAllowed') -eq 'true')) { - $o['value'] = $null + $vNodes = @($pNode.SelectNodes("dcssch:value", $ns)) + if ($vNodes.Count -gt 1) { + # valueListAllowed: список значений — захватываем ВСЕ массивом + $o['value'] = @($vNodes | ForEach-Object { Convert-TypedValue -raw $_.InnerText -xsiType ($_.GetAttribute("type", $NS_XSI)) }) + } elseif ($vNodes.Count -eq 1) { + $vNode = $vNodes[0] + if ($vNode.GetAttribute("nil", $NS_XSI) -ne 'true') { + $o['value'] = Convert-TypedValue -raw $vNode.InnerText -xsiType ($vNode.GetAttribute("type", $NS_XSI)) + } elseif ((Get-Child $pNode 'valueListAllowed') -eq 'true') { + $o['value'] = $null + } } # useRestriction — опускаем true (дефолт), фиксируем false if ((Get-Child $pNode 'useRestriction') -eq 'false') { $o['useRestriction'] = $false }