feat(meta-compile,meta-decompile): роундтрип TabularSection.Use + пустой FillValue v8:TypeDescription (v1.62/v0.53)

Два пре-существующих хвоста, вскрытых регистрочувствительным харнесом на 8.3.24.

A. Свойство Use табличной части (ForItem/ForFolder/ForFolderAndItem — иерархические
   Catalog/ПВХ). Компилятор хардкодил ForItem, декомпилятор не захватывал. Фикс:
   параметр tsUse в Emit-TabularSection (дефолт ForItem) + захват <Use> ТЧ + DSL-ключ
   `use` объектной формы ТЧ (omit при ForItem). Оба порта.

B. Пустой типизированный FillValue стандартного реквизита ValueType ПВХ:
   <xr:FillValue xsi:type="v8:TypeDescription"/> декомпилятор ловил как пустую строку →
   компилятор писал xs:string. Фикс — маркер fillValue:{typeDescription:true} по образцу
   emptyRef (SA-ридер захват + Emit-StandardAttribute эмиссия; только SA-уровень, на
   реквизитах не встречается). Оба порта.

Валидация: корпус 8.3.24 (1765) roundtrip 1765/1765 byte-exact TOTAL 0 (было 6 diff).
Декомпилятор ps1==py. Регресс 511/511 ps+py (правки аддитивные, снэпшоты не поехали).
spec §5 (use) + §4.2 (typeDescription).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-07-11 12:26:58 +03:00
co-authored by Claude Opus 4.8
parent e5746c33bd
commit f3a9880d96
5 changed files with 39 additions and 19 deletions
@@ -1,4 +1,4 @@
# meta-compile v1.61 — Compile 1C metadata object from JSON
# meta-compile v1.62 — Compile 1C metadata object from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -1270,6 +1270,7 @@ function Emit-StandardAttribute {
$fvRaw = OvOr 'FillValue' $null
if ($null -eq $fvRaw) { X "$indent`t<xr:FillValue xsi:nil=`"true`"/>" }
elseif ($fvRaw.emptyRef -eq $true) { X "$indent`t<xr:FillValue xsi:type=`"xr:DesignTimeRef`"/>" }
elseif ($fvRaw.typeDescription -eq $true) { X "$indent`t<xr:FillValue xsi:type=`"v8:TypeDescription`"/>" } # пустое типизированное (ValueType ПВХ)
else {
$fvN = Normalize-ChoiceValue $fvRaw
if ([string]::IsNullOrEmpty($fvN.Text)) { X "$indent`t<xr:FillValue xsi:type=`"$($fvN.XsiType)`"/>" }
@@ -1944,7 +1945,7 @@ function Emit-Command {
# --- 9. TabularSection emitter ---
function Emit-TabularSection {
param([string]$indent, [string]$tsName, $columns, [string]$objectType, [string]$objectName, $tsSynonymArg = $null, $tsTooltip = $null, $tsComment = $null, $tsLineNumber = $null, $tsFillChecking = $null)
param([string]$indent, [string]$tsName, $columns, [string]$objectType, [string]$objectName, $tsSynonymArg = $null, $tsTooltip = $null, $tsComment = $null, $tsLineNumber = $null, $tsFillChecking = $null, $tsUse = $null)
$uuid = New-Guid-String
X "$indent<TabularSection uuid=`"$uuid`">"
@@ -1977,9 +1978,11 @@ function Emit-TabularSection {
if (-not ($tsLineNumber -is [string] -and $tsLineNumber -eq '')) {
Emit-TabularStandardAttributes "$indent`t`t" $tsLineNumber
}
# Use=ForItem у ТЧ иерархических ссылочных типов (Catalog, ChartOfCharacteristicTypes); Document не имеет Use.
# Use у ТЧ иерархических ссылочных типов (Catalog, ChartOfCharacteristicTypes); Document не имеет Use.
# Дефолт ForItem; ForFolderAndItem/ForFolder — при явном ключе `use` объектной формы ТЧ.
if ($objectType -in @("Catalog", "ChartOfCharacteristicTypes")) {
X "$indent`t`t<Use>ForItem</Use>"
$use = if ($tsUse) { "$tsUse" } else { "ForItem" }
X "$indent`t`t<Use>$use</Use>"
}
X "$indent`t</Properties>"
@@ -3987,10 +3990,10 @@ if ($objType -in $typesWithAttrTS) {
# Нормализуем в $tsSections[name] = @{ columns; synonym; tooltip; comment }.
function New-TsEntry { param($val)
if ($val -is [array] -or $val.GetType().Name -eq 'Object[]') {
return @{ columns = @($val); synonym = $null; tooltip = $null; comment = $null; lineNumber = $null; fillChecking = $null }
return @{ columns = @($val); synonym = $null; tooltip = $null; comment = $null; lineNumber = $null; fillChecking = $null; use = $null }
}
$cols = if ($val.attributes) { @($val.attributes) } elseif ($val.columns) { @($val.columns) } else { @() }
return @{ columns = $cols; synonym = $val.synonym; tooltip = $val.tooltip; comment = if ($val.comment) { "$($val.comment)" } else { $null }; lineNumber = $val.lineNumber; fillChecking = $val.fillChecking }
return @{ columns = $cols; synonym = $val.synonym; tooltip = $val.tooltip; comment = if ($val.comment) { "$($val.comment)" } else { $null }; lineNumber = $val.lineNumber; fillChecking = $val.fillChecking; use = $val.use }
}
if ($def.tabularSections -is [array] -or $def.tabularSections.GetType().Name -eq "Object[]") {
foreach ($ts in $def.tabularSections) { $tsSections[$ts.name] = New-TsEntry $ts }
@@ -4040,7 +4043,7 @@ if ($objType -in $typesWithAttrTS) {
}
foreach ($tsName in $tsSections.Keys) {
$tsE = $tsSections[$tsName]
Emit-TabularSection "`t`t`t" $tsName $tsE.columns $objType $objName $tsE.synonym $tsE.tooltip $tsE.comment $tsE.lineNumber $tsE.fillChecking
Emit-TabularSection "`t`t`t" $tsName $tsE.columns $objType $objName $tsE.synonym $tsE.tooltip $tsE.comment $tsE.lineNumber $tsE.fillChecking $tsE.use
}
foreach ($af in $acctFlags) {
Emit-Attribute "`t`t`t" $af "account-flag" "AccountingFlag"
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# meta-compile v1.61 — Compile 1C metadata object from JSON
# meta-compile v1.62 — Compile 1C metadata object from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -1294,6 +1294,8 @@ def emit_standard_attribute(indent, attr_name, ov=None):
X(f'{indent}\t<xr:FillValue xsi:nil="true"/>')
elif isinstance(fv_raw, dict) and fv_raw.get('emptyRef') is True:
X(f'{indent}\t<xr:FillValue xsi:type="xr:DesignTimeRef"/>')
elif isinstance(fv_raw, dict) and fv_raw.get('typeDescription') is True:
X(f'{indent}\t<xr:FillValue xsi:type="v8:TypeDescription"/>') # пустое типизированное (ValueType ПВХ)
else:
fv_xt, fv_tx = normalize_choice_value(fv_raw)
if fv_tx == '' or fv_tx is None:
@@ -2007,7 +2009,7 @@ def emit_command(indent, cmd_name, cmd):
X(f'{indent}\t</Properties>')
X(f'{indent}</Command>')
def emit_tabular_section(indent, ts_name, columns, object_type, object_name, ts_synonym_arg=None, ts_tooltip=None, ts_comment=None, ts_line_number=None, ts_fill_checking=None):
def emit_tabular_section(indent, ts_name, columns, object_type, object_name, ts_synonym_arg=None, ts_tooltip=None, ts_comment=None, ts_line_number=None, ts_fill_checking=None, ts_use=None):
uid = new_uuid()
X(f'{indent}<TabularSection uuid="{uid}">')
type_prefix = f'{object_type}TabularSection'
@@ -2037,7 +2039,7 @@ def emit_tabular_section(indent, ts_name, columns, object_type, object_name, ts_
if not (isinstance(ts_line_number, str) and ts_line_number == ''):
emit_tabular_standard_attributes(f'{indent}\t\t', ts_line_number)
if object_type in ('Catalog', 'ChartOfCharacteristicTypes'):
X(f'{indent}\t\t<Use>ForItem</Use>')
X(f'{indent}\t\t<Use>{ts_use if ts_use else "ForItem"}</Use>')
X(f'{indent}\t</Properties>')
ts_context = 'processor-tabular' if object_type in ('DataProcessor', 'Report') else 'tabular'
X(f'{indent}\t<ChildObjects>')
@@ -3900,10 +3902,10 @@ if obj_type in types_with_attr_ts:
# Значение ТЧ: массив колонок (синоним авто) ЛИБО объект {attributes/columns, synonym, tooltip, comment}.
def new_ts_entry(val):
if isinstance(val, list):
return {'columns': val, 'synonym': None, 'tooltip': None, 'comment': None, 'lineNumber': None, 'fillChecking': None}
return {'columns': val, 'synonym': None, 'tooltip': None, 'comment': None, 'lineNumber': None, 'fillChecking': None, 'use': None}
cols = _as_list(val.get('attributes') or val.get('columns') or [])
return {'columns': cols, 'synonym': val.get('synonym'), 'tooltip': val.get('tooltip'),
'comment': str(val['comment']) if val.get('comment') else None, 'lineNumber': val.get('lineNumber'), 'fillChecking': val.get('fillChecking')}
'comment': str(val['comment']) if val.get('comment') else None, 'lineNumber': val.get('lineNumber'), 'fillChecking': val.get('fillChecking'), 'use': val.get('use')}
if isinstance(ts_data, list):
for ts in ts_data:
ts_sections[ts['name']] = new_ts_entry(ts)
@@ -3955,7 +3957,7 @@ if obj_type in types_with_attr_ts:
emit_attribute('\t\t\t', a, context)
for ts_name in ts_order:
e = ts_sections[ts_name]
emit_tabular_section('\t\t\t', ts_name, e['columns'], obj_type, obj_name, e['synonym'], e['tooltip'], e['comment'], e.get('lineNumber'), e.get('fillChecking'))
emit_tabular_section('\t\t\t', ts_name, e['columns'], obj_type, obj_name, e['synonym'], e['tooltip'], e['comment'], e.get('lineNumber'), e.get('fillChecking'), e.get('use'))
for af in acct_flags:
emit_attribute('\t\t\t', af, 'account-flag', 'AccountingFlag')
for edf in ext_dim_flags: