fix(meta-compile,meta-decompile): не-дефолтный TypeReductionMode измерения и nil в FixedArray

Раундтрип по документам и регистрам УТ (1283 объекта) вскрыл два пробела.

TypeReductionMode измерения РС: декомпилятор значение захватывал, но парсер
измерения в компиляторе не переносил ключ дальше, и любое отклонение от
дефолта молча заменялось на TransformValues. Так терялось третье значение
свойства — DeleteData («Удалять данные»); всего у свойства три режима:
Преобразовывать значения (дефолт), Удалять данные, Запрещать.
Синтетика на матрице платформ: DeleteData принимается и переживает роундтрип
на 8.3.25, 8.3.26 и 8.3.27 — порог тот же, что у самого свойства (2.18).

nil-элемент внутри FixedArray (<v8:Value xsi:nil="true"/>) декомпилировался
пустой строкой, компилятор эмитил xs:string. Теперь это JSON null в обе
стороны. Конструкция не новая — есть уже в дампе 8.3.20.

Спеки: у TypeReductionMode перечислены все три значения с названиями из
конфигуратора; версия появления исправлена с 2.20 на 2.18.

Проверка: УТ tier-1 1283 объекта -> 1280 совпадений (было 1273),
сюита meta-compile 76/76 на обоих портах.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-08-01 20:03:28 +03:00
co-authored by Claude Opus 5
parent 75e861da6e
commit 3d5c9e5bee
6 changed files with 36 additions and 4 deletions
@@ -1041,6 +1041,9 @@ function Parse-AttributeShorthand {
accountingFlag = $val.accountingFlag
extDimensionAccountingFlag = $val.extDimensionAccountingFlag
addressingDimension = $val.addressingDimension
# Режим приведения типов измерения РС (формат 2.18). Ключ обязан доехать до эмиттера:
# без него не-дефолтное значение (Deny / DeleteData) молча заменялось на TransformValues.
typeReductionMode = $val.typeReductionMode
}
}
@@ -1647,6 +1650,7 @@ function Emit-ChoiceParameters {
} elseif ($valIsArray) {
X "$indent`t`t<app:value xsi:type=`"v8:FixedArray`">"
foreach ($v in $val) {
if ($null -eq $v) { X "$indent`t`t`t<v8:Value xsi:nil=`"true`"/>"; continue }
if (Is-EmptyRef $v) { X "$indent`t`t`t<v8:Value xsi:type=`"xr:DesignTimeRef`"/>"; continue }
$norm = Normalize-ChoiceValueT $v $ptype
if ([string]::IsNullOrEmpty($norm.Text)) { X "$indent`t`t`t<v8:Value xsi:type=`"$($norm.XsiType)`"/>" }
@@ -4794,6 +4798,9 @@ if ($objType -eq "ExchangePlan") {
[System.IO.File]::WriteAllText($contentPath, $sbC.ToString(), $enc)
$modulesCreated += $contentPath
} elseif (-not (Test-Path $contentPath)) {
# При пустом составе платформа всё равно пишет пустой <ExchangePlanContent/> — проверено на
# ОДНОЙ конфигурации, снятой 8.3.24/8.3.25/8.3.26/8.3.27: во всех четырёх файл есть.
# (Единственный план обмена БЕЗ файла найден в УТ — хвостовая аномалия конфигурации, не правило.)
Ensure-ExtDir
$contentXml = "<?xml version=`"1.0`" encoding=`"UTF-8`"?>`r`n<ExchangePlanContent $xepNs version=`"$($script:formatVersion)`"/>`r`n"
[System.IO.File]::WriteAllText($contentPath, $contentXml, $enc)
@@ -1073,6 +1073,9 @@ def parse_attribute_shorthand(val):
'accountingFlag': val.get('accountingFlag'),
'extDimensionAccountingFlag': val.get('extDimensionAccountingFlag'),
'addressingDimension': val.get('addressingDimension'),
# Режим приведения типов измерения РС (формат 2.18). Ключ обязан доехать до эмиттера:
# без него не-дефолтное значение (Deny / DeleteData) молча заменялось на TransformValues.
'typeReductionMode': val.get('typeReductionMode'),
}
def parse_enum_value_shorthand(val):
@@ -1735,6 +1738,9 @@ def emit_choice_parameters(indent, cp, tag='ChoiceParameters'):
elif val_is_array:
X(f'{indent}\t\t<app:value xsi:type="v8:FixedArray">')
for v in val:
if v is None:
X(f'{indent}\t\t\t<v8:Value xsi:nil="true"/>')
continue
if is_empty_ref(v):
X(f'{indent}\t\t\t<v8:Value xsi:type="xr:DesignTimeRef"/>')
continue
@@ -4684,6 +4690,9 @@ if obj_type == 'ExchangePlan':
write_utf8_bom(content_path, ''.join(parts))
modules_created.append(content_path)
elif not os.path.isfile(content_path):
# При пустом составе платформа всё равно пишет пустой <ExchangePlanContent/> — проверено на
# ОДНОЙ конфигурации, снятой 8.3.24/8.3.25/8.3.26/8.3.27: во всех четырёх файл есть.
# (Единственный план обмена БЕЗ файла найден в УТ — хвостовая аномалия конфигурации, не правило.)
ensure_ext_dir()
content_xml = f'<?xml version="1.0" encoding="UTF-8"?>\r\n<ExchangePlanContent {xep_ns} version="{format_version}"/>\r\n'
write_utf8_bom(content_path, content_xml)