From 227423ee1f528f51258f696234eca8f2681e1e58 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Fri, 12 Jun 2026 22:25:19 +0300 Subject: [PATCH] =?UTF-8?q?feat(form-decompile,form-compile):=20KeyType/Ke?= =?UTF-8?q?yField=20=D0=BD=D0=B0=D0=B1=D0=BE=D1=80=D0=B0=20=D0=B4=D0=B8?= =?UTF-8?q?=D0=BD=D0=B0=D0=BC=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=BE=D0=B3?= =?UTF-8?q?=D0=BE=20=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D0=B0=20(=D0=B7=D0=B0?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D1=81=D0=BD=D1=8B=D0=B9=20=D1=81=D0=BF=D0=B8?= =?UTF-8?q?=D1=81=D0=BE=D0=BA)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Запросный динамический список (без MainTable) задаёт ключ набора: (FieldValue/RowKey/RowNumber) + * (0+ полей) — после Parameter*, до MainTable. Декомпилятор не ловил → терялось (21 форма, напр. ВыборПрисоединенногоФайла). DSL: settings.keyType (строка-enum) + settings.keyFields (массив). Взаимоисключающи с mainTable (запросный список vs таблично-ориентированный — 1С: KeyField+MainTable ломает пути данных списка). Декомпилятор: захват KeyType + всех KeyField; компилятор (ps1+py): эмит после Emit-DLParameters, до MainTable (позиция из корпус-сигнатур). Выборка 22 формы: match 17/22, KeyType/KeyField-потерь 0 (остаток — др. кластеры: CheckBox ItemWidth, order-use, SearchControlAddition, empty-right), регрессий 0. Регресс 43/43, ps1==py. Cert: corpus round-trip (запросные списки — 22 shipped-формы грузятся; синтетический кейс = полный query-based список с Table, непропорционально для verbatim 2-тег; MainTable+KeyField несовместимы → к dynamic-list-form не добавить). Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude/skills/form-compile/scripts/form-compile.ps1 | 6 +++++- .claude/skills/form-compile/scripts/form-compile.py | 9 ++++++++- .claude/skills/form-decompile/scripts/form-decompile.ps1 | 6 +++++- docs/form-dsl-spec.md | 4 +++- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index 24f26345..57b6f6e7 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.146 — Compile 1C managed form from JSON or object metadata +# form-compile v1.147 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$JsonPath, @@ -5685,6 +5685,10 @@ function Emit-Attributes { Emit-CalcFields -calcFields $st.calculatedFields -indent $si # Schema-параметры дин-списка (DataCompositionSchemaParameter) — после Field*, до MainTable. Emit-DLParameters -params $st.parameters -indent $si + # Ключ набора (query-based список без MainTable): KeyType (RowNumber/FieldValue/RowKey) + # + KeyField* — после Parameter*, до MainTable. Захват/эмит факт. значений. + if ($st.keyType) { X "$si$(Esc-Xml "$($st.keyType)")" } + if ($st.keyFields) { foreach ($kf in @($st.keyFields)) { X "$si$(Esc-Xml "$kf")" } } if ($st.mainTable) { X "$si$(Normalize-MetaTypeRef "$($st.mainTable)")" } # AutoSaveUserSettings — после MainTable (дефолт true; эмитим только при заданном ключе = отклонении). if ($null -ne $st.autoSaveUserSettings) { X "$si$(if ($st.autoSaveUserSettings){'true'}else{'false'})" } diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index 22be177f..5f438f71 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.146 — Compile 1C managed form from JSON or object metadata +# form-compile v1.147 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import copy @@ -5434,6 +5434,13 @@ def emit_attributes(lines, attrs, indent, conditional_appearance=None): emit_calc_fields(lines, s.get('calculatedFields'), si) # Schema-параметры дин-списка (DataCompositionSchemaParameter) — после Field*, до MainTable. emit_dl_parameters(lines, s.get('parameters'), si) + # Ключ набора (query-based список без MainTable): KeyType (RowNumber/FieldValue/RowKey) + # + KeyField* — после Parameter*, до MainTable. Захват/эмит факт. значений. + if s.get('keyType'): + lines.append(f'{si}{esc_xml(str(s["keyType"]))}') + if s.get('keyFields'): + for kf in s['keyFields']: + lines.append(f'{si}{esc_xml(str(kf))}') if s.get('mainTable'): lines.append(f'{si}{normalize_meta_type_ref(str(s["mainTable"]))}') # AutoSaveUserSettings — после MainTable (дефолт true; эмитим только при заданном ключе = отклонении). diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1 index 952bb304..51d3707f 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.119 — Decompile 1C managed Form.xml to JSON DSL (draft) +# form-decompile v0.120 — Decompile 1C managed Form.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью. param( @@ -2665,6 +2665,10 @@ if ($attrsNode) { # AutoFillAvailableFields — дефолт true, платформа эмитит только отклонение (false). Захват «как есть». $afaf = Get-Child $setNode 'AutoFillAvailableFields'; if ($null -ne $afaf) { $so['autoFillAvailableFields'] = ($afaf -eq 'true') } $mt = Get-Child $setNode 'MainTable'; if ($mt) { $so['mainTable'] = $mt } + # Ключ набора (query-based список): KeyType (RowNumber/FieldValue/RowKey) + KeyField* (0+). + $kt = Get-Child $setNode 'KeyType'; if ($kt) { $so['keyType'] = $kt } + $kfNodes = @($setNode.SelectNodes("lf:KeyField", $ns) | ForEach-Object { $_.InnerText }) + if ($kfNodes.Count -gt 0) { $so['keyFields'] = @($kfNodes) } # AutoSaveUserSettings — авто-сохранение польз. настроек дин-списка (в корпусе только false; # дефолт true → платформа эмитит отклонение). Захват факт. значения. $asus = Get-Child $setNode 'AutoSaveUserSettings'; if ($null -ne $asus) { $so['autoSaveUserSettings'] = ($asus -eq 'true') } diff --git a/docs/form-dsl-spec.md b/docs/form-dsl-spec.md index 6f61f05f..c2fbad4b 100644 --- a/docs/form-dsl-spec.md +++ b/docs/form-dsl-spec.md @@ -936,7 +936,9 @@ Forgiving-синонимы типа: XML-имя (`SpreadSheetDocumentField`) и | Ключ | Тип | Описание | |------|-----|----------| -| `mainTable` | string | Основная таблица. Принимает рус-имена метаданных (`Справочник.X` → `Catalog.X`) | +| `mainTable` | string | Основная таблица. Принимает рус-имена метаданных (`Справочник.X` → `Catalog.X`). Взаимоисключающа с `keyType`/`keyFields` (таблично-ориентированный список vs запросный) | +| `keyType` | string | Тип ключа набора запросного списка (без `mainTable`): `FieldValue` / `RowKey` / `RowNumber` | +| `keyFields` | array | Поля ключа набора (``, 0+) — для запросного списка без `mainTable`. Эмитятся после параметров | | `autoSaveUserSettings` | bool | Авто-сохранение пользовательских настроек дин-списка (``, после `MainTable`). **Умолчание `true`** — указывать только для отключения (`false`) | | `query` | string | Текст запроса (`ManualQuery=true`). Поддерживает `@file.sql` (путь относительно JSON) | | `dynamicDataRead` | bool | Динамическое считывание. **Умолчание `true`** — указывать только для отключения (`false`) |