feat(meta-compile,meta-decompile): батч object-свойств каталога (v1.18/v0.13)

Object-уровневые свойства каталога, которые компилятор хардкодил, стали
DSL-ключами omit-on-default (зеркало батча реквизитов). Class-2 фикс:
CreateOnInput дефолт DontUse→Use (модальное значение платформы, 1163).

Новые скалярные ключи: useStandardCommands, editType, includeHelpInContents,
choiceHistoryOnInput, predefinedDataUpdate, searchStringModeOnInputByString,
createOnInput. Object comment теперь пробрасывается. 10 ключей форм по
умолчанию (default*Form/auxiliary*Form) — ссылки verbatim. Декомпилятор
эмитит все эти ключи (+ уже поддержанные defaultPresentation/quickChoice/
choiceMode/fullTextSearch). Хелперы Get-BoolProp (presence-aware) и
Emit-FormRef; +4 enum в validEnumValues.

Все root-уровневые object-property диффы = 0 на выборке (rt-op, baseline
~5.6k), регресс 40/40 ps1+py (12 снэпшотов CreateOnInput DontUse→Use).
spec §7.1, кейс catalog-object-props.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-07-03 18:57:30 +03:00
co-authored by Claude Opus 4.8
parent f11fe6808d
commit ef20f6ece8
22 changed files with 575 additions and 51 deletions
@@ -1,4 +1,4 @@
# meta-compile v1.17 — Compile 1C metadata object from JSON
# meta-compile v1.18 — Compile 1C metadata object from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -259,6 +259,10 @@ $script:validEnumValues = @{
"SubordinationUse" = @("ToItems","ToFolders","ToFoldersAndItems")
"CodeSeries" = @("WholeCatalog","WithinSubordination","WithinOwnerSubordination")
"ChoiceMode" = @("BothWays","QuickChoice","FromForm")
"CreateOnInput" = @("Auto","Use","DontUse")
"ChoiceHistoryOnInput" = @("Auto","DontUse")
"PredefinedDataUpdate" = @("Auto","DontAutoUpdate","AutoUpdate")
"SearchStringModeOnInputByString"= @("Begin","AnyPart")
}
function Normalize-EnumValue {
@@ -289,6 +293,21 @@ function Get-EnumProp {
return (Normalize-EnumValue $propName $raw)
}
# Bool object-свойство: presence-aware (иначе false-значение спутать с отсутствием). Прощаем строки.
function Get-BoolProp {
param([string]$fieldName, [bool]$default)
$val = $def.$fieldName
if ($null -eq $val) { return $default }
if ($val -is [bool]) { return $val }
return ("$val" -match '^(true|1|да|истина)$')
}
# Ссылка на форму по умолчанию: непустая → <Tag>значение</Tag>, иначе <Tag/>.
function Emit-FormRef {
param([string]$i, [string]$tag, $val)
if ($val) { X "$i<$tag>$(Esc-Xml "$val")</$tag>" } else { X "$i<$tag/>" }
}
if (-not $def.type) {
Write-Error "JSON must have 'type' field"
exit 1
@@ -1460,7 +1479,7 @@ function Emit-CatalogProperties {
X "$i<Name>$(Esc-Xml $objName)</Name>"
Emit-MLText $i "Synonym" $synonym
X "$i<Comment/>"
if ($def.comment) { X "$i<Comment>$(Esc-XmlText $def.comment)</Comment>" } else { X "$i<Comment/>" }
$hierarchical = if ($def.hierarchical -eq $true) { "true" } else { "false" }
$hierarchyType = Get-EnumProp "HierarchyType" "hierarchyType" "HierarchyFoldersAndItems"
@@ -1472,7 +1491,8 @@ function Emit-CatalogProperties {
X "$i<LimitLevelCount>$limitLevelCount</LimitLevelCount>"
X "$i<LevelCount>$levelCount</LevelCount>"
X "$i<FoldersOnTop>$foldersOnTop</FoldersOnTop>"
X "$i<UseStandardCommands>true</UseStandardCommands>"
$useStdCmds = if (Get-BoolProp "useStandardCommands" $true) { "true" } else { "false" }
X "$i<UseStandardCommands>$useStdCmds</UseStandardCommands>"
if ($def.owners -and $def.owners.Count -gt 0) {
X "$i<Owners>"
foreach ($ownerRef in $def.owners) {
@@ -1507,8 +1527,8 @@ function Emit-CatalogProperties {
Emit-StandardAttributes $i "Catalog"
X "$i<Characteristics/>"
X "$i<PredefinedDataUpdate>Auto</PredefinedDataUpdate>"
X "$i<EditType>InDialog</EditType>"
X "$i<PredefinedDataUpdate>$(Get-EnumProp 'PredefinedDataUpdate' 'predefinedDataUpdate' 'Auto')</PredefinedDataUpdate>"
X "$i<EditType>$(Get-EnumProp 'EditType' 'editType' 'InDialog')</EditType>"
$quickChoice = if ($def.quickChoice -eq $true) { "true" } else { "false" }
$choiceMode = Get-EnumProp "ChoiceMode" "choiceMode" "BothWays"
X "$i<QuickChoice>$quickChoice</QuickChoice>"
@@ -1517,20 +1537,21 @@ function Emit-CatalogProperties {
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>"
X "$i<SearchStringModeOnInputByString>Begin</SearchStringModeOnInputByString>"
X "$i<SearchStringModeOnInputByString>$(Get-EnumProp 'SearchStringModeOnInputByString' 'searchStringModeOnInputByString' 'Begin')</SearchStringModeOnInputByString>"
X "$i<FullTextSearchOnInputByString>DontUse</FullTextSearchOnInputByString>"
X "$i<ChoiceDataGetModeOnInputByString>Directly</ChoiceDataGetModeOnInputByString>"
X "$i<DefaultObjectForm/>"
X "$i<DefaultFolderForm/>"
X "$i<DefaultListForm/>"
X "$i<DefaultChoiceForm/>"
X "$i<DefaultFolderChoiceForm/>"
X "$i<AuxiliaryObjectForm/>"
X "$i<AuxiliaryFolderForm/>"
X "$i<AuxiliaryListForm/>"
X "$i<AuxiliaryChoiceForm/>"
X "$i<AuxiliaryFolderChoiceForm/>"
X "$i<IncludeHelpInContents>false</IncludeHelpInContents>"
Emit-FormRef $i "DefaultObjectForm" $def.defaultObjectForm
Emit-FormRef $i "DefaultFolderForm" $def.defaultFolderForm
Emit-FormRef $i "DefaultListForm" $def.defaultListForm
Emit-FormRef $i "DefaultChoiceForm" $def.defaultChoiceForm
Emit-FormRef $i "DefaultFolderChoiceForm" $def.defaultFolderChoiceForm
Emit-FormRef $i "AuxiliaryObjectForm" $def.auxiliaryObjectForm
Emit-FormRef $i "AuxiliaryFolderForm" $def.auxiliaryFolderForm
Emit-FormRef $i "AuxiliaryListForm" $def.auxiliaryListForm
Emit-FormRef $i "AuxiliaryChoiceForm" $def.auxiliaryChoiceForm
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/>"
@@ -1545,8 +1566,8 @@ function Emit-CatalogProperties {
Emit-MLText $i "ListPresentation" $def.listPresentation
Emit-MLText $i "ExtendedListPresentation" $def.extendedListPresentation
Emit-MLText $i "Explanation" $def.explanation
X "$i<CreateOnInput>DontUse</CreateOnInput>"
X "$i<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>"
X "$i<CreateOnInput>$(Get-EnumProp 'CreateOnInput' 'createOnInput' 'Use')</CreateOnInput>"
X "$i<ChoiceHistoryOnInput>$(Get-EnumProp 'ChoiceHistoryOnInput' 'choiceHistoryOnInput' 'Auto')</ChoiceHistoryOnInput>"
X "$i<DataHistory>DontUse</DataHistory>"
X "$i<UpdateDataHistoryImmediatelyAfterWrite>false</UpdateDataHistoryImmediatelyAfterWrite>"
X "$i<ExecuteAfterWriteDataHistoryVersionProcessing>false</ExecuteAfterWriteDataHistoryVersionProcessing>"
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# meta-compile v1.17 — Compile 1C metadata object from JSON
# meta-compile v1.18 — Compile 1C metadata object from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -376,6 +376,10 @@ valid_enum_values = {
'SubordinationUse': ['ToItems', 'ToFolders', 'ToFoldersAndItems'],
'CodeSeries': ['WholeCatalog', 'WithinSubordination', 'WithinOwnerSubordination'],
'ChoiceMode': ['BothWays', 'QuickChoice', 'FromForm'],
'CreateOnInput': ['Auto', 'Use', 'DontUse'],
'ChoiceHistoryOnInput': ['Auto', 'DontUse'],
'PredefinedDataUpdate': ['Auto', 'DontAutoUpdate', 'AutoUpdate'],
'SearchStringModeOnInputByString': ['Begin', 'AnyPart'],
}
def normalize_enum_value(prop_name, value):
@@ -399,6 +403,22 @@ def get_enum_prop(prop_name, field_name, default):
raw = str(val) if val else default
return normalize_enum_value(prop_name, raw)
def get_bool_prop(field_name, default):
"""Bool object-свойство: presence-aware (иначе false спутать с отсутствием). Прощаем строки."""
val = defn.get(field_name)
if val is None:
return default
if isinstance(val, bool):
return val
return str(val).lower() in ('true', '1', 'да', 'истина')
def emit_form_ref(i, tag, val):
"""Ссылка на форму по умолчанию: непустая → <Tag>значение</Tag>, иначе <Tag/>."""
if val:
X(f'{i}<{tag}>{esc_xml(str(val))}</{tag}>')
else:
X(f'{i}<{tag}/>')
if not defn.get('type'):
print("JSON must have 'type' field", file=sys.stderr)
sys.exit(1)
@@ -1418,7 +1438,10 @@ def emit_catalog_properties(indent):
i = indent
X(f'{i}<Name>{esc_xml(obj_name)}</Name>')
emit_mltext(i, 'Synonym', synonym)
X(f'{i}<Comment/>')
if defn.get('comment'):
X(f'{i}<Comment>{esc_xml_text(str(defn["comment"]))}</Comment>')
else:
X(f'{i}<Comment/>')
hierarchical = 'true' if defn.get('hierarchical') is True else 'false'
hierarchy_type = get_enum_prop('HierarchyType', 'hierarchyType', 'HierarchyFoldersAndItems')
X(f'{i}<Hierarchical>{hierarchical}</Hierarchical>')
@@ -1429,7 +1452,8 @@ def emit_catalog_properties(indent):
X(f'{i}<LimitLevelCount>{limit_level_count}</LimitLevelCount>')
X(f'{i}<LevelCount>{level_count}</LevelCount>')
X(f'{i}<FoldersOnTop>{folders_on_top}</FoldersOnTop>')
X(f'{i}<UseStandardCommands>true</UseStandardCommands>')
use_std_cmds = 'true' if get_bool_prop('useStandardCommands', True) else 'false'
X(f'{i}<UseStandardCommands>{use_std_cmds}</UseStandardCommands>')
owners = defn.get('owners', [])
if owners:
X(f'{i}<Owners>')
@@ -1459,8 +1483,8 @@ def emit_catalog_properties(indent):
X(f'{i}<DefaultPresentation>{default_presentation}</DefaultPresentation>')
emit_standard_attributes(i, 'Catalog')
X(f'{i}<Characteristics/>')
X(f'{i}<PredefinedDataUpdate>Auto</PredefinedDataUpdate>')
X(f'{i}<EditType>InDialog</EditType>')
X(f'{i}<PredefinedDataUpdate>{get_enum_prop("PredefinedDataUpdate", "predefinedDataUpdate", "Auto")}</PredefinedDataUpdate>')
X(f'{i}<EditType>{get_enum_prop("EditType", "editType", "InDialog")}</EditType>')
quick_choice = 'true' if defn.get('quickChoice') is True else 'false'
choice_mode = get_enum_prop('ChoiceMode', 'choiceMode', 'BothWays')
X(f'{i}<QuickChoice>{quick_choice}</QuickChoice>')
@@ -1469,20 +1493,21 @@ def emit_catalog_properties(indent):
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>')
X(f'{i}<SearchStringModeOnInputByString>Begin</SearchStringModeOnInputByString>')
X(f'{i}<SearchStringModeOnInputByString>{get_enum_prop("SearchStringModeOnInputByString", "searchStringModeOnInputByString", "Begin")}</SearchStringModeOnInputByString>')
X(f'{i}<FullTextSearchOnInputByString>DontUse</FullTextSearchOnInputByString>')
X(f'{i}<ChoiceDataGetModeOnInputByString>Directly</ChoiceDataGetModeOnInputByString>')
X(f'{i}<DefaultObjectForm/>')
X(f'{i}<DefaultFolderForm/>')
X(f'{i}<DefaultListForm/>')
X(f'{i}<DefaultChoiceForm/>')
X(f'{i}<DefaultFolderChoiceForm/>')
X(f'{i}<AuxiliaryObjectForm/>')
X(f'{i}<AuxiliaryFolderForm/>')
X(f'{i}<AuxiliaryListForm/>')
X(f'{i}<AuxiliaryChoiceForm/>')
X(f'{i}<AuxiliaryFolderChoiceForm/>')
X(f'{i}<IncludeHelpInContents>false</IncludeHelpInContents>')
emit_form_ref(i, 'DefaultObjectForm', defn.get('defaultObjectForm'))
emit_form_ref(i, 'DefaultFolderForm', defn.get('defaultFolderForm'))
emit_form_ref(i, 'DefaultListForm', defn.get('defaultListForm'))
emit_form_ref(i, 'DefaultChoiceForm', defn.get('defaultChoiceForm'))
emit_form_ref(i, 'DefaultFolderChoiceForm', defn.get('defaultFolderChoiceForm'))
emit_form_ref(i, 'AuxiliaryObjectForm', defn.get('auxiliaryObjectForm'))
emit_form_ref(i, 'AuxiliaryFolderForm', defn.get('auxiliaryFolderForm'))
emit_form_ref(i, 'AuxiliaryListForm', defn.get('auxiliaryListForm'))
emit_form_ref(i, 'AuxiliaryChoiceForm', defn.get('auxiliaryChoiceForm'))
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/>')
data_lock_control_mode = get_enum_prop('DataLockControlMode', 'dataLockControlMode', 'Automatic')
@@ -1494,8 +1519,8 @@ def emit_catalog_properties(indent):
emit_mltext(i, 'ListPresentation', defn.get('listPresentation'))
emit_mltext(i, 'ExtendedListPresentation', defn.get('extendedListPresentation'))
emit_mltext(i, 'Explanation', defn.get('explanation'))
X(f'{i}<CreateOnInput>DontUse</CreateOnInput>')
X(f'{i}<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>')
X(f'{i}<CreateOnInput>{get_enum_prop("CreateOnInput", "createOnInput", "Use")}</CreateOnInput>')
X(f'{i}<ChoiceHistoryOnInput>{get_enum_prop("ChoiceHistoryOnInput", "choiceHistoryOnInput", "Auto")}</ChoiceHistoryOnInput>')
X(f'{i}<DataHistory>DontUse</DataHistory>')
X(f'{i}<UpdateDataHistoryImmediatelyAfterWrite>false</UpdateDataHistoryImmediatelyAfterWrite>')
X(f'{i}<ExecuteAfterWriteDataHistoryVersionProcessing>false</ExecuteAfterWriteDataHistoryVersionProcessing>')
@@ -1,4 +1,4 @@
# meta-decompile v0.12 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
# meta-decompile v0.13 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
#
# Пилот: только Catalog. Инверс meta-compile (omit-on-default: ключ эмитим только
@@ -303,6 +303,26 @@ Add-BoolProp 'quickChoice' 'QuickChoice' $false
Add-EnumProp 'choiceMode' 'ChoiceMode' 'BothWays'
Add-EnumProp 'dataLockControlMode' 'DataLockControlMode' 'Automatic'
Add-EnumProp 'fullTextSearch' 'FullTextSearch' 'Use'
Add-BoolProp 'useStandardCommands' 'UseStandardCommands' $true
Add-EnumProp 'createOnInput' 'CreateOnInput' 'Use'
Add-EnumProp 'editType' 'EditType' 'InDialog'
Add-BoolProp 'includeHelpInContents' 'IncludeHelpInContents' $false
Add-EnumProp 'choiceHistoryOnInput' 'ChoiceHistoryOnInput' 'Auto'
Add-EnumProp 'predefinedDataUpdate' 'PredefinedDataUpdate' 'Auto'
Add-EnumProp 'searchStringModeOnInputByString' 'SearchStringModeOnInputByString' 'Begin'
# Формы по умолчанию (компилятор пишет пусто → omit-on-empty; значение = ссылка на форму verbatim).
function Add-FormRef { param([string]$key, [string]$tag) $v = P $tag; if ($v) { $dsl[$key] = $v } }
Add-FormRef 'defaultObjectForm' 'DefaultObjectForm'
Add-FormRef 'defaultFolderForm' 'DefaultFolderForm'
Add-FormRef 'defaultListForm' 'DefaultListForm'
Add-FormRef 'defaultChoiceForm' 'DefaultChoiceForm'
Add-FormRef 'defaultFolderChoiceForm' 'DefaultFolderChoiceForm'
Add-FormRef 'auxiliaryObjectForm' 'AuxiliaryObjectForm'
Add-FormRef 'auxiliaryFolderForm' 'AuxiliaryFolderForm'
Add-FormRef 'auxiliaryListForm' 'AuxiliaryListForm'
Add-FormRef 'auxiliaryChoiceForm' 'AuxiliaryChoiceForm'
Add-FormRef 'auxiliaryFolderChoiceForm' 'AuxiliaryFolderChoiceForm'
# Презентации (ML, компилятор пишет пусто → omit-on-empty).
foreach ($pp in @(