mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-09-04 01:00:52 +03:00
feat(meta-compile,meta-decompile): object-списки InputByString/DataLockFields/BasedOn (v1.28/v0.19)
Три object-блока каталога компилятор хардкодил (InputByString={Descr,Code},
DataLockFields/BasedOn пустые), декомпилятор не захватывал.
Class-2 фикс InputByString: хардкод → вывод из Code/DescriptionLength
([Descr при D>0]+[Code при C>0]) — покрывает 88.5% каталогов, убил каскад
Field ADDED=80 (у 1057/1640 InputByString = только Наименование).
Class-3 DSL:
• inputByString — массив имён полей (авто-резолв через Expand-DataPath,
как dataPath), [] = пусто; декомпилятор эмитит только при отличии от дефолта.
• dataLockFields — поля блокировки, omit-on-empty.
• basedOn — «ввод на основании», MDObjectRef verbatim, omit-on-empty.
Хелперы Emit-FieldBlock/Emit-BasedOn (+py-порт); декомпилятор Short-Field
(частичная форма StandardAttribute.X/Attribute.X для dogfood резолвера).
Class-2 ловушка PS: пустой @() в позиц.параметр схлопывается в $null, а
@($null) = массив из 1 null → пустой <xr:Field>. Фикс — Where-Object фильтр.
Роундтрип 120 объектов: match 20→94, TOTAL 305→183 (−122), DataLockFields
35→0, InputByString/BasedOn=0, новых diff не внесено. Override-кейсы (реверс,
+реквизит, пустой, codeonly, dlf, basedOn) роундтрипятся чисто. Регресс 46/46
ps1+py, ps1↔py identical. spec §7.1.5, кейс catalog-inputbystring-datalock.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
e95fb6b619
commit
65c4fba471
@@ -1,4 +1,4 @@
|
||||
# meta-compile v1.27 — Compile 1C metadata object from JSON
|
||||
# meta-compile v1.28 — Compile 1C metadata object from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -1202,6 +1202,29 @@ function Emit-LinkByType {
|
||||
X "$indent</LinkByType>"
|
||||
}
|
||||
|
||||
# Есть ли ключ в $def (отличаем отсутствие от пустого массива [] = явно пусто).
|
||||
function Test-DefKey { param([string]$name) return ($def.PSObject -and $def.PSObject.Properties -and ($def.PSObject.Properties.Name -contains $name)) }
|
||||
|
||||
# <Tag> со списком <xr:Field> (InputByString/DataLockFields). $fields — готовые полные пути. Пусто → self-close.
|
||||
function Emit-FieldBlock {
|
||||
param([string]$indent, [string]$tag, $fields)
|
||||
$arr = @($fields | Where-Object { "$_" -ne '' })
|
||||
if ($arr.Count -eq 0) { X "$indent<$tag/>"; return }
|
||||
X "$indent<$tag>"
|
||||
foreach ($f in $arr) { X "$indent`t<xr:Field>$(Esc-Xml "$f")</xr:Field>" }
|
||||
X "$indent</$tag>"
|
||||
}
|
||||
|
||||
# <BasedOn> — «ввод на основании», список MDObjectRef ("Catalog.X"/"Document.Y"). Нет ключа/пусто → self-close.
|
||||
function Emit-BasedOn {
|
||||
param([string]$indent, $items)
|
||||
$arr = @($items | Where-Object { $_ })
|
||||
if ($arr.Count -eq 0) { X "$indent<BasedOn/>"; return }
|
||||
X "$indent<BasedOn>"
|
||||
foreach ($it in $arr) { X "$indent`t<xr:Item xsi:type=`"xr:MDObjectRef`">$(Esc-Xml "$it")</xr:Item>" }
|
||||
X "$indent</BasedOn>"
|
||||
}
|
||||
|
||||
# --- Параметры/связи выбора (порт из form-compile; структура реквизита ⟷ элемента формы совпадает) ---
|
||||
|
||||
# Свойство из dict/PSCustomObject по списку синонимов (первый найденный, иначе $null).
|
||||
@@ -1879,10 +1902,15 @@ function Emit-CatalogProperties {
|
||||
$choiceMode = Get-EnumProp "ChoiceMode" "choiceMode" "BothWays"
|
||||
X "$i<QuickChoice>$quickChoice</QuickChoice>"
|
||||
X "$i<ChoiceMode>$choiceMode</ChoiceMode>"
|
||||
X "$i<InputByString>"
|
||||
X "$i`t<xr:Field>Catalog.$objName.StandardAttribute.Description</xr:Field>"
|
||||
X "$i`t<xr:Field>Catalog.$objName.StandardAttribute.Code</xr:Field>"
|
||||
X "$i</InputByString>"
|
||||
# InputByString: override `inputByString` (массив имён, авто-резолв; [] = пусто) ЛИБО дефолт [Descr при D>0]+[Code при C>0].
|
||||
if (Test-DefKey 'inputByString') {
|
||||
$ibFields = @($def.inputByString | ForEach-Object { Expand-DataPath "$_" })
|
||||
} else {
|
||||
$ibFields = @()
|
||||
if ([int]$descriptionLength -gt 0) { $ibFields += "Catalog.$objName.StandardAttribute.Description" }
|
||||
if ([int]$codeLength -gt 0) { $ibFields += "Catalog.$objName.StandardAttribute.Code" }
|
||||
}
|
||||
Emit-FieldBlock $i "InputByString" $ibFields
|
||||
X "$i<SearchStringModeOnInputByString>$(Get-EnumProp 'SearchStringModeOnInputByString' 'searchStringModeOnInputByString' 'Begin')</SearchStringModeOnInputByString>"
|
||||
X "$i<FullTextSearchOnInputByString>DontUse</FullTextSearchOnInputByString>"
|
||||
X "$i<ChoiceDataGetModeOnInputByString>Directly</ChoiceDataGetModeOnInputByString>"
|
||||
@@ -1898,8 +1926,9 @@ function Emit-CatalogProperties {
|
||||
Emit-FormRef $i "AuxiliaryFolderChoiceForm" $def.auxiliaryFolderChoiceForm
|
||||
$inclHelp = if (Get-BoolProp "includeHelpInContents" $false) { "true" } else { "false" }
|
||||
X "$i<IncludeHelpInContents>$inclHelp</IncludeHelpInContents>"
|
||||
X "$i<BasedOn/>"
|
||||
X "$i<DataLockFields/>"
|
||||
Emit-BasedOn $i $def.basedOn
|
||||
$dlFields = if (Test-DefKey 'dataLockFields') { @($def.dataLockFields | ForEach-Object { Expand-DataPath "$_" }) } else { @() }
|
||||
Emit-FieldBlock $i "DataLockFields" $dlFields
|
||||
|
||||
$dataLockControlMode = Get-EnumProp "DataLockControlMode" "dataLockControlMode" "Automatic"
|
||||
X "$i<DataLockControlMode>$dataLockControlMode</DataLockControlMode>"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# meta-compile v1.27 — Compile 1C metadata object from JSON
|
||||
# meta-compile v1.28 — Compile 1C metadata object from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -1269,6 +1269,28 @@ def emit_link_by_type(indent, spec):
|
||||
X(f'{indent}\t<xr:LinkItem>{li}</xr:LinkItem>')
|
||||
X(f'{indent}</LinkByType>')
|
||||
|
||||
def emit_field_block(indent, tag, fields):
|
||||
"""<Tag> со списком <xr:Field> (InputByString/DataLockFields). Пусто → self-close."""
|
||||
arr = [f for f in (fields or []) if str(f) != '']
|
||||
if not arr:
|
||||
X(f'{indent}<{tag}/>')
|
||||
return
|
||||
X(f'{indent}<{tag}>')
|
||||
for f in arr:
|
||||
X(f'{indent}\t<xr:Field>{esc_xml(str(f))}</xr:Field>')
|
||||
X(f'{indent}</{tag}>')
|
||||
|
||||
def emit_based_on(indent, items):
|
||||
"""<BasedOn> — «ввод на основании», список MDObjectRef. Нет/пусто → self-close."""
|
||||
arr = [it for it in (items or []) if it]
|
||||
if not arr:
|
||||
X(f'{indent}<BasedOn/>')
|
||||
return
|
||||
X(f'{indent}<BasedOn>')
|
||||
for it in arr:
|
||||
X(f'{indent}\t<xr:Item xsi:type="xr:MDObjectRef">{esc_xml(str(it))}</xr:Item>')
|
||||
X(f'{indent}</BasedOn>')
|
||||
|
||||
# --- Параметры/связи выбора (порт из form-compile) ---
|
||||
|
||||
def ch_el_prop(obj, names):
|
||||
@@ -1879,10 +1901,16 @@ def emit_catalog_properties(indent):
|
||||
choice_mode = get_enum_prop('ChoiceMode', 'choiceMode', 'BothWays')
|
||||
X(f'{i}<QuickChoice>{quick_choice}</QuickChoice>')
|
||||
X(f'{i}<ChoiceMode>{choice_mode}</ChoiceMode>')
|
||||
X(f'{i}<InputByString>')
|
||||
X(f'{i}\t<xr:Field>Catalog.{obj_name}.StandardAttribute.Description</xr:Field>')
|
||||
X(f'{i}\t<xr:Field>Catalog.{obj_name}.StandardAttribute.Code</xr:Field>')
|
||||
X(f'{i}</InputByString>')
|
||||
# InputByString: override `inputByString` (массив имён, авто-резолв; [] = пусто) ЛИБО дефолт [Descr при D>0]+[Code при C>0].
|
||||
if 'inputByString' in defn:
|
||||
ib_fields = [expand_data_path(str(x)) for x in (defn.get('inputByString') or [])]
|
||||
else:
|
||||
ib_fields = []
|
||||
if int(description_length) > 0:
|
||||
ib_fields.append(f'Catalog.{obj_name}.StandardAttribute.Description')
|
||||
if int(code_length) > 0:
|
||||
ib_fields.append(f'Catalog.{obj_name}.StandardAttribute.Code')
|
||||
emit_field_block(i, 'InputByString', ib_fields)
|
||||
X(f'{i}<SearchStringModeOnInputByString>{get_enum_prop("SearchStringModeOnInputByString", "searchStringModeOnInputByString", "Begin")}</SearchStringModeOnInputByString>')
|
||||
X(f'{i}<FullTextSearchOnInputByString>DontUse</FullTextSearchOnInputByString>')
|
||||
X(f'{i}<ChoiceDataGetModeOnInputByString>Directly</ChoiceDataGetModeOnInputByString>')
|
||||
@@ -1898,8 +1926,9 @@ def emit_catalog_properties(indent):
|
||||
emit_form_ref(i, 'AuxiliaryFolderChoiceForm', defn.get('auxiliaryFolderChoiceForm'))
|
||||
incl_help = 'true' if get_bool_prop('includeHelpInContents', False) else 'false'
|
||||
X(f'{i}<IncludeHelpInContents>{incl_help}</IncludeHelpInContents>')
|
||||
X(f'{i}<BasedOn/>')
|
||||
X(f'{i}<DataLockFields/>')
|
||||
emit_based_on(i, defn.get('basedOn'))
|
||||
dl_fields = [expand_data_path(str(x)) for x in defn.get('dataLockFields', [])] if 'dataLockFields' in defn else []
|
||||
emit_field_block(i, 'DataLockFields', dl_fields)
|
||||
data_lock_control_mode = get_enum_prop('DataLockControlMode', 'dataLockControlMode', 'Automatic')
|
||||
X(f'{i}<DataLockControlMode>{data_lock_control_mode}</DataLockControlMode>')
|
||||
full_text_search = get_enum_prop('FullTextSearch', 'fullTextSearch', 'Use')
|
||||
|
||||
Reference in New Issue
Block a user