mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-13 22:35:16 +03:00
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:
@@ -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:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# meta-decompile v0.52 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
|
||||
# meta-decompile v0.53 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
#
|
||||
# Поддержаны: Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document,
|
||||
@@ -1072,6 +1072,7 @@ if ($saNode) {
|
||||
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 } }
|
||||
elseif ($fvXt -match 'TypeDescription$' -and $fvN.InnerText -eq '') { $ov['fillValue'] = [ordered]@{ typeDescription = $true } } # пустое типизированное (реквизит ValueType ПВХ) ≠ xs:string
|
||||
else { $ov['fillValue'] = Convert-ChScalarNode $fvN }
|
||||
}
|
||||
$saCmt = $sa.SelectSingleNode('xr:Comment', $nsm); if ($saCmt -and $saCmt.InnerText) { $ov['comment'] = $saCmt.InnerText }
|
||||
@@ -1237,6 +1238,8 @@ if ($childObjs) {
|
||||
$tsCmtN = $tsp.SelectSingleNode('md:Comment', $nsm); $tsCmt = if ($tsCmtN) { $tsCmtN.InnerText } else { '' }
|
||||
# FillChecking ТЧ (обязательность заполнения; omit при DontCheck).
|
||||
$tsFcN = $tsp.SelectSingleNode('md:FillChecking', $nsm); $tsFc = if ($tsFcN -and $tsFcN.InnerText -ne 'DontCheck') { $tsFcN.InnerText } else { '' }
|
||||
# Use ТЧ (иерархические Catalog/ПВХ: ForItem/ForFolder/ForFolderAndItem; omit при дефолте ForItem).
|
||||
$tsUseN = $tsp.SelectSingleNode('md:Use', $nsm); $tsUse = if ($tsUseN -and $tsUseN.InnerText -ne 'ForItem') { $tsUseN.InnerText } else { '' }
|
||||
# TS-блок стандартных реквизитов (LineNumber). Наличие блока — пер-ТЧ артефакт (~6% ТЧ его опускают,
|
||||
# правило не выводимо). Faithful roundtrip: нет блока → маркер подавления `lineNumber: ""` (дом-конвенция);
|
||||
# есть блок → захват кастомизации LineNumber (omit-on-default по свойству), all-default → без ключа.
|
||||
@@ -1259,12 +1262,13 @@ if ($childObjs) {
|
||||
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)) {
|
||||
if ($tsSynCustom -or ($null -ne $tsTt) -or $tsCmt -or $tsFc -or $tsUse -or $lnObj.Count -gt 0 -or (-not $hasBlock)) {
|
||||
$to = [ordered]@{}
|
||||
if ($tsSynCustom) { $to['synonym'] = $tsSyn }
|
||||
if ($null -ne $tsTt) { $to['tooltip'] = $tsTt }
|
||||
if ($tsCmt) { $to['comment'] = $tsCmt }
|
||||
if ($tsFc) { $to['fillChecking'] = $tsFc }
|
||||
if ($tsUse) { $to['use'] = $tsUse }
|
||||
if (-not $hasBlock) { $to['lineNumber'] = '' } elseif ($lnObj.Count -gt 0) { $to['lineNumber'] = $lnObj }
|
||||
$to['attributes'] = $cols
|
||||
$tsMap[$tsName] = $to
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# meta-decompile v0.52 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
|
||||
# meta-decompile v0.53 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
#
|
||||
# Зеркало meta-decompile.ps1 (КАНОН). Структура 1:1 — те же имена функций, порядок, комментарии.
|
||||
@@ -1553,6 +1553,8 @@ def build_dsl():
|
||||
fv_xt = _attr(fv_n, 'type', NS_XSI)
|
||||
if re.search(r'DesignTimeRef$', fv_xt, re.I) and _text(fv_n) == '':
|
||||
ov['fillValue'] = {'emptyRef': True}
|
||||
elif re.search(r'TypeDescription$', fv_xt, re.I) and _text(fv_n) == '':
|
||||
ov['fillValue'] = {'typeDescription': True} # пустое типизированное (реквизит ValueType ПВХ) ≠ xs:string
|
||||
else:
|
||||
ov['fillValue'] = convert_ch_scalar_node(fv_n)
|
||||
sa_cmt = _single(sa, 'xr:Comment')
|
||||
@@ -1745,6 +1747,9 @@ def build_dsl():
|
||||
ts_cmt = _text(ts_cmt_n) if ts_cmt_n is not None else ''
|
||||
ts_fc_n = _single(tsp, 'md:FillChecking')
|
||||
ts_fc = _text(ts_fc_n) if (ts_fc_n is not None and _text(ts_fc_n) != 'DontCheck') else ''
|
||||
# Use ТЧ (иерархические Catalog/ПВХ: ForItem/ForFolder/ForFolderAndItem; omit при дефолте ForItem).
|
||||
ts_use_n = _single(tsp, 'md:Use')
|
||||
ts_use = _text(ts_use_n) if (ts_use_n is not None and _text(ts_use_n) != 'ForItem') else ''
|
||||
# TS-блок стандартных реквизитов (LineNumber).
|
||||
ln_obj = {}
|
||||
sa_ts_node = _single(tsp, 'md:StandardAttributes')
|
||||
@@ -1777,7 +1782,7 @@ def build_dsl():
|
||||
ln_fv_t = _attr(ln_fv_n, 'type', NS_XSI)
|
||||
if re.search(r'decimal$', ln_fv_t, re.I):
|
||||
ln_obj['fillValue'] = int(_text(ln_fv_n)) if re.match(r'^-?\d+$', _text(ln_fv_n)) else float(_text(ln_fv_n))
|
||||
if ts_syn_custom or (ts_tt is not None) or ts_cmt or ts_fc or len(ln_obj) > 0 or (not has_block):
|
||||
if ts_syn_custom or (ts_tt is not None) or ts_cmt or ts_fc or ts_use or len(ln_obj) > 0 or (not has_block):
|
||||
to = {}
|
||||
if ts_syn_custom:
|
||||
to['synonym'] = ts_syn
|
||||
@@ -1787,6 +1792,8 @@ def build_dsl():
|
||||
to['comment'] = ts_cmt
|
||||
if ts_fc:
|
||||
to['fillChecking'] = ts_fc
|
||||
if ts_use:
|
||||
to['use'] = ts_use
|
||||
if not has_block:
|
||||
to['lineNumber'] = ''
|
||||
elif len(ln_obj) > 0:
|
||||
|
||||
@@ -308,9 +308,9 @@ JSON-**строка** → `xsi:type="xs:string"` (напр. год `"2000"`, к
|
||||
}
|
||||
```
|
||||
|
||||
Свойства объектной формы ТЧ: `synonym` (ML; нет ключа → авто из имени), `tooltip` (ML), `comment` (строка), `attributes` (колонки; синоним `columns`), `lineNumber` (кастомизация стандартного реквизита НомерСтроки, см. ниже).
|
||||
Свойства объектной формы ТЧ: `synonym` (ML; нет ключа → авто из имени), `tooltip` (ML), `comment` (строка), `fillChecking` (`DontCheck`|`ShowError`|`ShowWarning`), `use` (`ForItem`|`ForFolder`|`ForFolderAndItem`, только Catalog/ПВХ; omit при дефолте `ForItem`), `attributes` (колонки; синоним `columns`), `lineNumber` (кастомизация стандартного реквизита НомерСтроки, см. ниже).
|
||||
|
||||
Для Catalog добавляется `<Use>ForItem</Use>` в Properties табличной части. Для Document Use не применяется.
|
||||
Для Catalog/ChartOfCharacteristicTypes в Properties ТЧ пишется `<Use>` (дефолт `ForItem`; ключ `use` объектной формы → `ForFolder`/`ForFolderAndItem`). Document `<Use>` не имеет.
|
||||
|
||||
### 5.1 `lineNumber` — кастомизация стандартного реквизита НомерСтроки
|
||||
|
||||
@@ -426,6 +426,10 @@ LineNumber дефолтные. Ключ `lineNumber` на объектной ф
|
||||
> «Пустая ссылка» как значение заполнения (`<FillValue xsi:type="xr:DesignTimeRef"/>` без содержимого) — маркер
|
||||
> `fillValue: {emptyRef: true}` (декомпилятор проставляет его сам; тип из строки не выводится, т.к. `DefinedType.X`
|
||||
> непрозрачен). Применимо к реквизиту и стандартному реквизиту (в т.ч. `lineNumber` ТЧ поддерживает `fillValue`).
|
||||
>
|
||||
> Пустое типизированное значение (`<FillValue xsi:type="v8:TypeDescription"/>` без содержимого) — маркер
|
||||
> `fillValue: {typeDescription: true}` (стандартный реквизит `ValueType` ПВХ: его пустое значение — пустое
|
||||
> описание типов, а не пустая строка). Декомпилятор проставляет сам.
|
||||
|
||||
**Профиль материализованного блока** (значения, которые платформа заполняет автоматически — задавать их в DSL не нужно):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user