From 3d5c9e5bee3256cf1d0eb04d880765d6cbf3b0eb Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sat, 1 Aug 2026 20:03:28 +0300 Subject: [PATCH] =?UTF-8?q?fix(meta-compile,meta-decompile):=20=D0=BD?= =?UTF-8?q?=D0=B5-=D0=B4=D0=B5=D1=84=D0=BE=D0=BB=D1=82=D0=BD=D1=8B=D0=B9?= =?UTF-8?q?=20TypeReductionMode=20=D0=B8=D0=B7=D0=BC=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=B8=20nil=20=D0=B2=20FixedArray?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Раундтрип по документам и регистрам УТ (1283 объекта) вскрыл два пробела. TypeReductionMode измерения РС: декомпилятор значение захватывал, но парсер измерения в компиляторе не переносил ключ дальше, и любое отклонение от дефолта молча заменялось на TransformValues. Так терялось третье значение свойства — DeleteData («Удалять данные»); всего у свойства три режима: Преобразовывать значения (дефолт), Удалять данные, Запрещать. Синтетика на матрице платформ: DeleteData принимается и переживает роундтрип на 8.3.25, 8.3.26 и 8.3.27 — порог тот же, что у самого свойства (2.18). nil-элемент внутри FixedArray () декомпилировался пустой строкой, компилятор эмитил 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) --- .claude/skills/meta-compile/scripts/meta-compile.ps1 | 7 +++++++ .claude/skills/meta-compile/scripts/meta-compile.py | 9 +++++++++ .../skills/meta-decompile/scripts/meta-decompile.ps1 | 3 +++ .../skills/meta-decompile/scripts/meta-decompile.py | 4 ++++ docs/1c-config-objects-spec.md | 10 +++++++++- docs/meta-dsl-spec.md | 7 ++++--- 6 files changed, 36 insertions(+), 4 deletions(-) diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1 index 5452c3cf..d640aaf8 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.ps1 +++ b/.claude/skills/meta-compile/scripts/meta-compile.ps1 @@ -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" foreach ($v in $val) { + if ($null -eq $v) { X "$indent`t`t`t"; continue } if (Is-EmptyRef $v) { X "$indent`t`t`t"; continue } $norm = Normalize-ChoiceValueT $v $ptype if ([string]::IsNullOrEmpty($norm.Text)) { X "$indent`t`t`t" } @@ -4794,6 +4798,9 @@ if ($objType -eq "ExchangePlan") { [System.IO.File]::WriteAllText($contentPath, $sbC.ToString(), $enc) $modulesCreated += $contentPath } elseif (-not (Test-Path $contentPath)) { + # При пустом составе платформа всё равно пишет пустой — проверено на + # ОДНОЙ конфигурации, снятой 8.3.24/8.3.25/8.3.26/8.3.27: во всех четырёх файл есть. + # (Единственный план обмена БЕЗ файла найден в УТ — хвостовая аномалия конфигурации, не правило.) Ensure-ExtDir $contentXml = "`r`n`r`n" [System.IO.File]::WriteAllText($contentPath, $contentXml, $enc) diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py index 0d4f1cb6..a13d90cc 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.py +++ b/.claude/skills/meta-compile/scripts/meta-compile.py @@ -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') for v in val: + if v is None: + X(f'{indent}\t\t\t') + continue if is_empty_ref(v): X(f'{indent}\t\t\t') 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): + # При пустом составе платформа всё равно пишет пустой — проверено на + # ОДНОЙ конфигурации, снятой 8.3.24/8.3.25/8.3.26/8.3.27: во всех четырёх файл есть. + # (Единственный план обмена БЕЗ файла найден в УТ — хвостовая аномалия конфигурации, не правило.) ensure_ext_dir() content_xml = f'\r\n\r\n' write_utf8_bom(content_path, content_xml) diff --git a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 index 8bb6d15b..f48a51a6 100644 --- a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 +++ b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 @@ -219,6 +219,9 @@ function Get-TypeShorthand { # string/dateTime/DesignTimeRef → строка (компилятор auto-детектит обратно). function Convert-ChScalarNode { param($vN) + # nil-элемент массива () → JSON null. Без этого он приезжал пустой + # строкой и компилятор эмитил xs:string вместо nil. + if ($vN.GetAttribute('nil', 'http://www.w3.org/2001/XMLSchema-instance') -eq 'true') { return $null } $xt = $vN.GetAttribute('type', 'http://www.w3.org/2001/XMLSchema-instance') $txt = $vN.InnerText if ($xt -match 'boolean$') { return ($txt -eq 'true') } diff --git a/.claude/skills/meta-decompile/scripts/meta-decompile.py b/.claude/skills/meta-decompile/scripts/meta-decompile.py index d09d0b8b..1073df9a 100644 --- a/.claude/skills/meta-decompile/scripts/meta-decompile.py +++ b/.claude/skills/meta-decompile/scripts/meta-decompile.py @@ -291,6 +291,10 @@ def get_type_shorthand(type_node): # Скалярное значение параметра выбора () → JSON-значение (bool/число/строка). def convert_ch_scalar_node(vN): + # nil-элемент массива () -> JSON null. Без этого он приезжал пустой + # строкой и компилятор эмитил xs:string вместо nil. + if _attr(vN, 'nil', NS_XSI) == 'true': + return None xt = _attr(vN, 'type', NS_XSI) txt = _text(vN) if re.search(r'boolean$', xt, re.I): diff --git a/docs/1c-config-objects-spec.md b/docs/1c-config-objects-spec.md index 8c4af818..df4dd388 100644 --- a/docs/1c-config-objects-spec.md +++ b/docs/1c-config-objects-spec.md @@ -1713,7 +1713,15 @@ XML-элемент: ``. Трёхуровневая вложенно ``` -Значения: `TransformValues` (преобразовывать значения) | `Deny` (запретить). У измерений его пишут только регистры сведений. +Свойство «Режим сокращения типа», три значения: + +| XML | В конфигураторе | +|-----|-----------------| +| `TransformValues` | Преобразовывать значения (по умолчанию) | +| `DeleteData` | Удалять данные | +| `Deny` | Запрещать | + +У измерений его пишут только регистры сведений. `DeleteData` в выгрузках редок (7 измерений на всю УТ 11.5.27, ни одного в БП) и принимается платформами 8.3.25–8.3.27 — тот же порог, что у самого свойства. Свойство именно новое: платформа 8.3.24 при загрузке молча его отбраковывает («Свойство не входит в состав объекта метаданных»), сообщая при этом об успехе. diff --git a/docs/meta-dsl-spec.md b/docs/meta-dsl-spec.md index 48467062..b8fd1968 100644 --- a/docs/meta-dsl-spec.md +++ b/docs/meta-dsl-spec.md @@ -466,12 +466,13 @@ LineNumber дефолтные. Ключ `lineNumber` на объектной ф В `standardAttributes` указывают **только отклонения** от профиля (переопределение синонима, нетиповой fillChecking и т.п.). -**Формат 2.20 — `TypeReductionMode`** (режим приведения типов). Платформа 8.3.27 пишет его каждому -стандартному реквизиту; значение выводится компилятором и в DSL обычно не указывается: +**Формат 2.18 — `TypeReductionMode`** (режим приведения типов). Платформа начиная с 8.3.25 пишет его +каждому стандартному реквизиту; значение выводится компилятором и в DSL обычно не указывается: `TransformValues` для всех, кроме `Owner` — там `Deny`. Ключ `TypeReductionMode` в override оставлен на случай отклонения от этого правила (правило выведено на корпусе acc; при расхождении в другой конфигурации значение можно задать явно). У измерений регистра сведений действует то же свойство — -ключ реквизита `typeReductionMode` (дефолт `TransformValues`). В формате 2.17 тег не эмитится. +ключ реквизита `typeReductionMode` (дефолт `TransformValues`). Третье значение — `DeleteData` +(редкое: 7 измерений на всю УТ 11.5.27). В формате 2.17 тег не эмитится. ```json {