feat(form-compile,form-decompile): typed-empty значение параметра дин-списка (xs:string vs nil) + SettingsStorage

(1) Пустое значение schema-параметра дин-списка: компилятор ВСЕГДА эмитил
<dcssch:value xsi:nil="true"/>, но платформа часть пустых строковых параметров пишет
типизированным пустым <dcssch:value xsi:type="xs:string"/> (корпус: 27 typed-empty,
все xs:string; 255 nil). Решается ФОРМОЙ value, не valueType: декомпилятор различает
(<value xsi:type="xs:string"/> → value:"", <value xsi:nil/> → ключ опущен/null —
Convert-TypedValue пустого xs:string даёт ""). Компилятор: при value:"" (явная пустая
строка, тип отсутствует или string) → typed-empty xs:string, НЕ nil. Ветка ПЕРЕД vla-nil
(решение не зависит от valueListAllowed). Зеркало py.

(2) SettingsStorage — форменное свойство (ссылка на хранилище настроек, корпус 11) →
KNOWN_FORM_PROPS (декомпилятор; компилятор авто-PascalCase Emit-Properties уже эмитит).

Выборка 17 форм: match 13→15 (типовая МашиночитаемыеДоверенности — 18 typed-empty,
была вся в nil → match). ps1==py байт-в-байт. Регресс 43/43. Spec обновлён.
Остаток 2 формы (другие value-подвиды): DesignTimeValue в dcscor-контексте дропнут;
пустой LocalStringType self-closing vs пара — отдельные находки.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-13 14:18:37 +03:00
parent 670a574249
commit 8eedca4c22
4 changed files with 17 additions and 5 deletions
@@ -1,4 +1,4 @@
# form-compile v1.155 — Compile 1C managed form from JSON or object metadata
# form-compile v1.156 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[string]$JsonPath,
@@ -5434,6 +5434,12 @@ function Emit-DLParameter {
$valIsArray = ($parsed.value -is [array]) -or ($parsed.value -is [System.Collections.IList] -and $parsed.value -isnot [string])
if ($valIsArray) {
foreach ($v in @($parsed.value)) { Emit-DLValue -type $parsed.type -val $v -indent $ci -valueListAllowed $false }
} elseif ($parsed.valueExplicit -and ($null -ne $parsed.value) -and ("$($parsed.value)" -eq '') -and (("$($parsed.type)" -eq '') -or ("$($parsed.type)" -match '^string'))) {
# Явный пустой СТРОКОВЫЙ параметр (value:"" от декомпилятора) → типизированный пустой
# <dcssch:value xsi:type="xs:string"/>, НЕ nil. Решается ФОРМОЙ value (""→typed-empty,
# null/отсутствие→nil), независимо от valueListAllowed; декомпилятор различает ""/null
# (Convert-TypedValue пустого xs:string → "", nil → value опущен/null). Корпус: 26 xs:string.
X "$ci<dcssch:value xsi:type=`"xs:string`"/>"
} elseif ($vla -and (Test-DLEmptyValue $parsed.value) -and $parsed.valueExplicit) {
# valueListAllowed + явный пустой (value:null от декомпилятора) → платформа здесь пишет nil
X "$ci<dcssch:value xsi:nil=`"true`"/>"
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# form-compile v1.155 — Compile 1C managed form from JSON or object metadata
# form-compile v1.156 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import copy
@@ -5198,6 +5198,12 @@ def emit_dl_parameter(lines, p, parsed, indent):
if isinstance(pv, list):
for v in pv:
emit_dl_value(lines, parsed.get('type', ''), v, ci, False)
elif parsed.get('value_explicit') and pv is not None and str(pv) == '' and (str(parsed.get('type', '')) == '' or re.match(r'^string', str(parsed.get('type', '')))):
# Явный пустой СТРОКОВЫЙ параметр (value:"" от декомпилятора) → типизированный пустой
# <dcssch:value xsi:type="xs:string"/>, НЕ nil. Решается ФОРМОЙ value (""→typed-empty,
# null/отсутствие→nil), независимо от valueListAllowed; декомпилятор различает ""/null.
# Корпус: 26 xs:string typed-empty.
lines.append(f'{ci}<dcssch:value xsi:type="xs:string"/>')
elif vla and is_dl_empty_value(pv) and parsed.get('value_explicit'):
# valueListAllowed + явный пустой (value:null от декомпилятора) → платформа пишет nil
lines.append(f'{ci}<dcssch:value xsi:nil="true"/>')
@@ -1,4 +1,4 @@
# form-decompile v0.130 — Decompile 1C managed Form.xml to JSON DSL (draft)
# form-decompile v0.131 — Decompile 1C managed Form.xml to JSON DSL (draft)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
param(
@@ -2474,7 +2474,7 @@ $titleNode = $root.SelectSingleNode("lf:Title", $ns)
if ($titleNode) { $t = Get-LangText $titleNode; if ($null -ne $t) { $dsl['title'] = $t } }
# properties (прямые скаляры под <Form>, PascalCase → camelCase)
$KNOWN_FORM_PROPS = @('AutoTitle','ReportResult','DetailsData','ReportFormType','AutoShowState','ReportResultViewMode','ViewModeApplicationOnSetReportResult','WindowOpeningMode','CommandBarLocation','SaveDataInSettings','AutoSaveDataInSettings','AutoTime','UsePostingMode','RepostOnWrite','AutoURL','AutoFillCheck','Customizable','EnterKeyBehavior','VerticalScroll','Width','Height','Group','UseForFoldersAndItems','SaveWindowSettings','ScalingMode','VerticalSpacing','VariantAppearance','ShowCloseButton','HorizontalAlign','ChildrenAlign','ShowTitle','ConversationsRepresentation','CollapseItemsByImportanceVariant','GroupList','ChildItemsWidth','VerticalAlign','HorizontalSpacing','CustomSettingsFolder')
$KNOWN_FORM_PROPS = @('AutoTitle','ReportResult','DetailsData','ReportFormType','AutoShowState','ReportResultViewMode','ViewModeApplicationOnSetReportResult','WindowOpeningMode','CommandBarLocation','SaveDataInSettings','AutoSaveDataInSettings','AutoTime','UsePostingMode','RepostOnWrite','AutoURL','AutoFillCheck','Customizable','EnterKeyBehavior','VerticalScroll','Width','Height','Group','UseForFoldersAndItems','SaveWindowSettings','ScalingMode','VerticalSpacing','VariantAppearance','ShowCloseButton','HorizontalAlign','ChildrenAlign','ShowTitle','ConversationsRepresentation','CollapseItemsByImportanceVariant','GroupList','ChildItemsWidth','VerticalAlign','HorizontalSpacing','CustomSettingsFolder','SettingsStorage')
$props = [ordered]@{}
foreach ($pn in $KNOWN_FORM_PROPS) {
$v = Get-Child $root $pn
+1 -1
View File
@@ -984,7 +984,7 @@ Forgiving-синонимы типа: XML-имя (`SpreadSheetDocumentField`) и
|-----------|-----------|
| `title` | Авто из имени (camelCase → «Заполнена серия»); явный `title`/`[Заголовок]` — только для переопределения |
| `useRestriction` | Эмитится всегда, **умолчание `true`**; для выключения — объект `{ "useRestriction": false }` |
| `value` | Умолчание — пустое (`xsi:nil`), даже при заданном типе |
| `value` | Нет ключа → `xsi:nil`. **Явная пустая строка `value: ""`** → типизированный пустой `<dcssch:value xsi:type="xs:string"/>` (НЕ nil; платформа так пишет часть пустых строковых параметров — корпус 27). Декомпилятор различает: пустой строковый тег → `""`, nil-тег → ключ опущен/`null` |
Объектные ключи (как в СКД): `name`, `title`, `type`/`valueType`, `value`, `valueListAllowed`, `useRestriction`, `availableAsField`, `expression`, `availableValues` (`[{ value, presentation }]`), `inputParameters`, `denyIncompleteValues`, `use`.