From 8af6b9d88eaeded63fcf9944e250559670533b43 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Tue, 7 Jul 2026 13:24:49 +0300 Subject: [PATCH] =?UTF-8?q?feat(meta-compile,meta-decompile):=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=BA=D1=80=D1=8B=D1=82=20empty-DTR=20=D1=85=D0=B2=D0=BE?= =?UTF-8?q?=D1=81=D1=82=20+=20LineNumber=20FillValue=20(v1.49/v0.41)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Последний сквозной хвост всех типов — «пустая ссылка» как значение заполнения ( без содержимого). Декомпилятор ловил его как xs:string → тип терялся. Не выводится из типа (DefinedType.X непрозрачен: nil vs empty-DTR зависит от вида). Фикс: маркер fillValue:{emptyRef:true} — декомпилятор проставляет, компилятор воспроизводит (4 точки: Emit-FillValue + Emit-StandardAttribute × захват/эмиссия). Попутно закрыт (B)-хвост Document: FillValue НомерСтроки ТЧ (xs:decimal 0, аномалия 1/1645) — lineNumber-кастомизация расширена ключом fillValue. Чистый выигрыш без регресса: Catalog 52→58/58, Document 142→151/151, BusinessProcess 20→25/25, Task 1→3/3 — все byte-exact TOTAL 0. Регресс 49/49 ps1+py, ps1==py identical (0/20 modulo GUID). Прежнее «принято как инертный шум» снято — закрыто честно. spec §4.2/§7.1.1. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../meta-compile/scripts/meta-compile.ps1 | 5 ++++- .../skills/meta-compile/scripts/meta-compile.py | 9 ++++++++- .../meta-decompile/scripts/meta-decompile.ps1 | 17 ++++++++++++++--- docs/meta-dsl-spec.md | 4 +++- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1 index 8b96df18..1424c784 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.ps1 +++ b/.claude/skills/meta-compile/scripts/meta-compile.ps1 @@ -1,4 +1,4 @@ -# meta-compile v1.48 — Compile 1C metadata object from JSON +# meta-compile v1.49 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -738,6 +738,7 @@ function Emit-FillValue { } if ($null -eq $spec) { X "$indent"; return } # явный nil-override + if ($spec.emptyRef -eq $true) { X "$indent"; return } # пустая ссылка (маркер декомпилятора) if ($spec -is [bool]) { X "$indent$(if ($spec) { 'true' } else { 'false' })"; return } @@ -1133,6 +1134,7 @@ function Emit-StandardAttribute { # FillValue: дефолт nil; override-значение → типизированное (Normalize-ChoiceValue: DTR-путь/строка/bool). $fvRaw = OvOr 'FillValue' $null if ($null -eq $fvRaw) { X "$indent`t" } + elseif ($fvRaw.emptyRef -eq $true) { X "$indent`t" } else { $fvN = Normalize-ChoiceValue $fvRaw if ([string]::IsNullOrEmpty($fvN.Text)) { X "$indent`t" } @@ -1207,6 +1209,7 @@ function Emit-TabularStandardAttributes { if ($null -ne $lineNumber.format) { $ov['Format'] = $lineNumber.format } if ($null -ne $lineNumber.editFormat) { $ov['EditFormat'] = $lineNumber.editFormat } if ($lineNumber.choiceHistoryOnInput) { $ov['ChoiceHistoryOnInput'] = "$($lineNumber.choiceHistoryOnInput)" } + if ($null -ne $lineNumber.fillValue) { $ov['FillValue'] = $lineNumber.fillValue } } X "$indent" Emit-StandardAttribute "$indent`t" "LineNumber" $ov diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py index 277297ef..ddfa5eb7 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.py +++ b/.claude/skills/meta-compile/scripts/meta-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# meta-compile v1.48 — Compile 1C metadata object from JSON +# meta-compile v1.49 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -769,6 +769,9 @@ def emit_fill_value(indent, type_str, spec, has_spec): if spec is None: X(f'{indent}') # явный nil-override return + if isinstance(spec, dict) and spec.get('emptyRef') is True: + X(f'{indent}') # пустая ссылка (маркер декомпилятора) + return if isinstance(spec, bool): X(f'{indent}{"true" if spec else "false"}') return @@ -1152,6 +1155,8 @@ def emit_standard_attribute(indent, attr_name, ov=None): fv_raw = ov.get('FillValue', None) if fv_raw is None: X(f'{indent}\t') + elif isinstance(fv_raw, dict) and fv_raw.get('emptyRef') is True: + X(f'{indent}\t') else: fv_xt, fv_tx = normalize_choice_value(fv_raw) if fv_tx == '' or fv_tx is None: @@ -1242,6 +1247,8 @@ def emit_tabular_standard_attributes(indent, line_number=None): ov['EditFormat'] = line_number['editFormat'] if line_number.get('choiceHistoryOnInput'): ov['ChoiceHistoryOnInput'] = str(line_number['choiceHistoryOnInput']) + if line_number.get('fillValue') is not None: + ov['FillValue'] = line_number['fillValue'] X(f'{indent}') emit_standard_attribute(f'{indent}\t', 'LineNumber', ov) X(f'{indent}') diff --git a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 index 58c8bf8e..02b99852 100644 --- a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 +++ b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 @@ -1,4 +1,4 @@ -# meta-decompile v0.40 — XML объекта метаданных 1С → JSON-черновик формата meta-compile +# meta-decompile v0.41 — XML объекта метаданных 1С → JSON-черновик формата meta-compile # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # # Поддержаны: Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document. Инверс meta-compile (omit-on-default: ключ эмитим только @@ -349,7 +349,8 @@ function Attr-ToDsl { } elseif ($xsiT -match 'dateTime$') { $extra['fillValue'] = $fvText } elseif ($xsiT -match 'DesignTimeRef$') { - $extra['fillValue'] = $fvText + # Пустой DTR (ссылочный fillValue без значения) ≠ nil/xs:string → маркер emptyRef (иначе тип терялся в xs:string). + if ($fvText -eq '') { $extra['fillValue'] = [ordered]@{ emptyRef = $true } } else { $extra['fillValue'] = $fvText } } } @@ -746,7 +747,11 @@ if ($saNode) { $dhN = $sa.SelectSingleNode('xr:DataHistory', $nsm); if ($dhN -and $dhN.InnerText -ne 'Use') { $ov['dataHistory'] = $dhN.InnerText } # FillValue (дефолт nil) — DTR-путь/строка/bool. Comment/Mask/ChoiceForm (дефолт пусто). $fvN = $sa.SelectSingleNode('xr:FillValue', $nsm) - if ($fvN -and $fvN.GetAttribute('nil', 'http://www.w3.org/2001/XMLSchema-instance') -ne 'true') { $ov['fillValue'] = Convert-ChScalarNode $fvN } + if ($fvN -and $fvN.GetAttribute('nil', 'http://www.w3.org/2001/XMLSchema-instance') -ne 'true') { + $fvXt = $fvN.GetAttribute('type', 'http://www.w3.org/2001/XMLSchema-instance') + if ($fvXt -match 'DesignTimeRef$' -and $fvN.InnerText -eq '') { $ov['fillValue'] = [ordered]@{ emptyRef = $true } } + else { $ov['fillValue'] = Convert-ChScalarNode $fvN } + } $saCmt = $sa.SelectSingleNode('xr:Comment', $nsm); if ($saCmt -and $saCmt.InnerText) { $ov['comment'] = $saCmt.InnerText } $saMsk = $sa.SelectSingleNode('xr:Mask', $nsm); if ($saMsk -and $saMsk.InnerText) { $ov['mask'] = $saMsk.InnerText } $saFmt = Get-MLValue ($sa.SelectSingleNode('xr:Format', $nsm)); if ($null -ne $saFmt) { $ov['format'] = $saFmt } @@ -851,6 +856,12 @@ if ($childObjs) { $lnFmt = Get-MLValue ($lnNode.SelectSingleNode('xr:Format', $nsm)); if ($null -ne $lnFmt) { $lnObj['format'] = $lnFmt } $lnEfmt = Get-MLValue ($lnNode.SelectSingleNode('xr:EditFormat', $nsm)); if ($null -ne $lnEfmt) { $lnObj['editFormat'] = $lnEfmt } $lnChiN = $lnNode.SelectSingleNode('xr:ChoiceHistoryOnInput', $nsm); if ($lnChiN -and $lnChiN.InnerText -ne 'Auto') { $lnObj['choiceHistoryOnInput'] = $lnChiN.InnerText } + # FillValue НомерСтроки: дефолт nil; редкая аномалия xs:decimal 0 → захват числом (иначе теряется в nil). + $lnFvN = $lnNode.SelectSingleNode('xr:FillValue', $nsm) + if ($lnFvN -and $lnFvN.GetAttribute('nil', 'http://www.w3.org/2001/XMLSchema-instance') -ne 'true') { + $lnFvT = $lnFvN.GetAttribute('type', 'http://www.w3.org/2001/XMLSchema-instance') + if ($lnFvT -match 'decimal$') { $lnObj['fillValue'] = if ($lnFvN.InnerText -match '^-?\d+$') { [long]$lnFvN.InnerText } else { [double]$lnFvN.InnerText } } + } } if ($tsSynCustom -or ($null -ne $tsTt) -or $tsCmt -or $tsFc -or $lnObj.Count -gt 0 -or (-not $hasBlock)) { $to = [ordered]@{} diff --git a/docs/meta-dsl-spec.md b/docs/meta-dsl-spec.md index 91b97713..be8ab1d5 100644 --- a/docs/meta-dsl-spec.md +++ b/docs/meta-dsl-spec.md @@ -413,7 +413,9 @@ LineNumber дефолтные. Ключ `lineNumber` на объектной ф Переопределяемые поля реквизита: `synonym` (ML — строка/`{ru,en}`), `tooltip` (ML), `fillChecking` (`DontCheck`|`ShowError`|`ShowWarning`), `fillFromFillingValue` (bool), `fullTextSearch` (`Use`|`DontUse`), `dataHistory` (`Use`|`DontUse`), `fillValue` (значение — DTR-путь/строка/bool; см. §4.2), `choiceParameterLinks` / `choiceParameters` (как у реквизита, §4.2), `comment`, `mask`, `choiceForm`. -> Не покрыты (редкие вырожденные формы `fillValue` стандартного реквизита): «пустое» значение с не-nil типом — `xs:string` из одних пробелов и пустой `xr:DesignTimeRef`. +> «Пустая ссылка» как значение заполнения (`` без содержимого) — маркер +> `fillValue: {emptyRef: true}` (декомпилятор проставляет его сам; тип из строки не выводится, т.к. `DefinedType.X` +> непрозрачен). Применимо к реквизиту и стандартному реквизиту (в т.ч. `lineNumber` ТЧ поддерживает `fillValue`). **Профиль материализованного блока** (значения, которые платформа заполняет автоматически — задавать их в DSL не нужно):