From a13538cd16a86ab503290de4f967cbc140dff0e4 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Thu, 9 Jul 2026 20:55:20 +0300 Subject: [PATCH] =?UTF-8?q?feat(meta-compile,meta-decompile):=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6=D0=BA=D0=B0=20=D1=82=D0=B8?= =?UTF-8?q?=D0=BF=D0=BE=D0=B2=20Constant=20+=20DefinedType=20(v1.53/v0.44)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 16-й/17-й типы, 2692 объекта acc+erp. ПОЛНЫЙ КОРПУС 2692/2692 match, TOTAL 0 — byte-exact order-preserved. Регресс 54/54 ps1+py, ps1==py identical. - Constant — «богатый одиночный реквизит»: рерайт Emit-ConstantProperties на общие leaf-хелперы (Emit-MinMaxValue/ChoiceParameterLinks/ChoiceParameters/LinkByType/MLText), был легаси-хардкод всех свойств. Декомпилятор: захват valueType + свойств значения (passwordMode/format/tooltip/mask/min-maxValue/fillChecking/choiceFoldersAndItems/ choiceParameter*/quickChoice[enum]/choiceForm/linkByType) + object-уровень. QuickChoice у Constant — ENUM (Auto), не bool → гард общего bool-хендлера. - DefinedType — тип-псевдоним: рерайт Emit-DefinedTypeProperties на единый Emit-ValueType (был дубль-эмиттер типа; составной через ' + '). Декомпилятор: valueType. - Class-2: Constant DataLockControlMode Automatic→Managed (корпус 965/78). - Общий фикс: cfg_object_kinds +ConstantValue — тип ConstantValueManager.X (менеджер значения константы, 321) терял cfg:-префикс (regex greedy бил ConstantValue+Manager). Дефолт UseStandardCommands true (как Report/DataProcessor). spec §7.4/§7.7, кейсы constant-full/defined-type-full. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../meta-compile/scripts/meta-compile.ps1 | 104 +++----- .../meta-compile/scripts/meta-compile.py | 116 ++++---- .../meta-decompile/scripts/meta-decompile.ps1 | 55 +++- docs/meta-dsl-spec.md | 46 +++- .../cases/meta-compile/constant-full.json | 20 ++ .../cases/meta-compile/defined-type-full.json | 13 + .../snapshots/constant-full/Configuration.xml | 252 ++++++++++++++++++ .../constant-full/Constants/СтавкаНДС.xml | 77 ++++++ .../Constants/СтавкаНДС/Ext/ManagerModule.bsl | 0 .../СтавкаНДС/Ext/ValueManagerModule.bsl | 0 .../Ext/ClientApplicationInterface.xml | 18 ++ .../constant-full/Languages/Русский.xml | 16 ++ .../constant/Constants/ОсновнаяВалюта.xml | 2 +- .../defined-type-full/Configuration.xml | 252 ++++++++++++++++++ .../DefinedTypes/СсылкаНаКонтрагента.xml | 30 +++ .../Ext/ClientApplicationInterface.xml | 18 ++ .../defined-type-full/Languages/Русский.xml | 16 ++ 17 files changed, 899 insertions(+), 136 deletions(-) create mode 100644 tests/skills/cases/meta-compile/constant-full.json create mode 100644 tests/skills/cases/meta-compile/defined-type-full.json create mode 100644 tests/skills/cases/meta-compile/snapshots/constant-full/Configuration.xml create mode 100644 tests/skills/cases/meta-compile/snapshots/constant-full/Constants/СтавкаНДС.xml create mode 100644 tests/skills/cases/meta-compile/snapshots/constant-full/Constants/СтавкаНДС/Ext/ManagerModule.bsl create mode 100644 tests/skills/cases/meta-compile/snapshots/constant-full/Constants/СтавкаНДС/Ext/ValueManagerModule.bsl create mode 100644 tests/skills/cases/meta-compile/snapshots/constant-full/Ext/ClientApplicationInterface.xml create mode 100644 tests/skills/cases/meta-compile/snapshots/constant-full/Languages/Русский.xml create mode 100644 tests/skills/cases/meta-compile/snapshots/defined-type-full/Configuration.xml create mode 100644 tests/skills/cases/meta-compile/snapshots/defined-type-full/DefinedTypes/СсылкаНаКонтрагента.xml create mode 100644 tests/skills/cases/meta-compile/snapshots/defined-type-full/Ext/ClientApplicationInterface.xml create mode 100644 tests/skills/cases/meta-compile/snapshots/defined-type-full/Languages/Русский.xml diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1 index bf3ac5fd..bf989b91 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.52 — Compile 1C metadata object from JSON +# meta-compile v1.53 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -466,7 +466,7 @@ $script:typeNamespaceMap = @{ $script:cfgBareTypes = @("ConstantsSet", "ReportBuilder", "FilterCriterion") $script:cfgObjectKinds = @("Catalog","Document","Enum","ChartOfAccounts","ChartOfCharacteristicTypes", "ChartOfCalculationTypes","ExchangePlan","BusinessProcess","Task","InformationRegister","AccumulationRegister", - "AccountingRegister","CalculationRegister","DataProcessor","Report","DocumentJournal","Constant") + "AccountingRegister","CalculationRegister","DataProcessor","Report","DocumentJournal","Constant","ConstantValue") $script:typeSynonyms["таблицазначений"] = "ValueTable" $script:typeSynonyms["деревозначений"] = "ValueTree" $script:typeSynonyms["списокзначений"] = "ValueListType" @@ -2331,41 +2331,42 @@ function Emit-ConstantProperties { X "$i$(Esc-Xml $objName)" Emit-MLText $i "Synonym" $synonym - X "$i" + if ($def.comment) { X "$i$(Esc-XmlText $def.comment)" } else { X "$i" } - # Type + # Type — valueType (пустой явный '' → , реквизит без типа; отсутствие → String дефолт). $valueType = Build-TypeStr $def - if (-not $valueType) { $valueType = "String" } - Emit-ValueType $i $valueType + $typeEmpty = ($null -ne $def.valueType -and "$($def.valueType)".Trim() -eq '') -or ($null -ne $def.type -and "$($def.type)".Trim() -eq '') + if ($typeEmpty) { X "$i" } + else { if (-not $valueType) { $valueType = "String" }; Emit-ValueType $i $valueType } - X "$itrue" - X "$i" - X "$i" - X "$i" - X "$ifalse" - X "$i" - X "$i" - X "$i" - X "$ifalse" - X "$i" - X "$ifalse" - X "$ifalse" - X "$i" - X "$i" - X "$iDontCheck" - X "$iItems" - X "$i" - X "$i" - X "$iAuto" - X "$i" - X "$i" - X "$iAuto" + $useStdCmds = if (Get-BoolProp "useStandardCommands" $true) { "true" } else { "false" } + X "$i$useStdCmds" + Emit-VerbatimRef $i "DefaultForm" $def.defaultForm + Emit-MLText $i "ExtendedPresentation" $def.extendedPresentation + Emit-MLText $i "Explanation" $def.explanation + X "$i$(if (Get-BoolProp 'passwordMode' $false) { 'true' } else { 'false' })" + Emit-MLText $i "Format" $def.format + Emit-MLText $i "EditFormat" $def.editFormat + Emit-MLText $i "ToolTip" $def.tooltip + X "$i$(if (Get-BoolProp 'markNegatives' $false) { 'true' } else { 'false' })" + if ($def.mask) { X "$i$(Esc-XmlText $def.mask)" } else { X "$i" } + X "$i$(if (Get-BoolProp 'multiLine' $false) { 'true' } else { 'false' })" + X "$i$(if (Get-BoolProp 'extendedEdit' $false) { 'true' } else { 'false' })" + Emit-MinMaxValue $i "MinValue" $def.minValue + Emit-MinMaxValue $i "MaxValue" $def.maxValue + X "$i$(Get-EnumProp 'FillChecking' 'fillChecking' 'DontCheck')" + X "$i$(Get-EnumProp 'ChoiceFoldersAndItems' 'choiceFoldersAndItems' 'Items')" + Emit-ChoiceParameterLinks $i $def.choiceParameterLinks + Emit-ChoiceParameters $i $def.choiceParameters + X "$i$(Get-EnumProp 'QuickChoice' 'quickChoice' 'Auto')" + if ($def.choiceForm) { X "$i$(Esc-Xml "$($def.choiceForm)")" } else { X "$i" } + Emit-LinkByType $i $def.linkByType + X "$i$(Get-EnumProp 'ChoiceHistoryOnInput' 'choiceHistoryOnInput' 'Auto')" - $dataLockControlMode = Get-EnumProp "DataLockControlMode" "dataLockControlMode" "Automatic" - X "$i$dataLockControlMode" - X "$iDontUse" - X "$ifalse" - X "$ifalse" + X "$i$(Get-EnumProp 'DataLockControlMode' 'dataLockControlMode' 'Managed')" + X "$i$(Get-EnumProp 'DataHistory' 'dataHistory' 'DontUse')" + X "$i$(if (Get-BoolProp 'updateDataHistoryImmediatelyAfterWrite' $false) { 'true' } else { 'false' })" + X "$i$(if (Get-BoolProp 'executeAfterWriteDataHistoryVersionProcessing' $false) { 'true' } else { 'false' })" } function Emit-InformationRegisterProperties { @@ -2461,37 +2462,14 @@ function Emit-DefinedTypeProperties { X "$i$(Esc-Xml $objName)" Emit-MLText $i "Synonym" $synonym - X "$i" + if ($def.comment) { X "$i$(Esc-XmlText $def.comment)" } else { X "$i" } - # Type — composite type with multiple v8:Type entries (accept both valueType and valueTypes) - $valueTypes = @() - if ($def.valueTypes) { - $valueTypes = @($def.valueTypes) - } elseif ($def.valueType) { - $valueTypes = @($def.valueType) - } - if ($valueTypes.Count -gt 0) { - X "$i" - foreach ($vt in $valueTypes) { - $resolved = Resolve-TypeStr "$vt" - if ($resolved -match '^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|ExchangePlanRef|BusinessProcessRef|TaskRef)\.') { - X "$i`td5p1:$resolved" - } elseif ($resolved -eq "Boolean") { - X "$i`txs:boolean" - } elseif ($resolved -match '^String') { - X "$i`txs:string" - X "$i`t" - X "$i`t`t0" - X "$i`t`tVariable" - X "$i`t" - } else { - X "$i`tcfg:$resolved" - } - } - X "$i" - } else { - X "$i" - } + # Type — тип-значение (составной через ' + '); принимаем valueType (строка) или valueTypes (массив). + # Единый эмиттер Emit-ValueType/Emit-TypeContent (refs d5p1, cfg:, платформенные, квалификаторы). Пусто → . + $vt = if ($def.valueType) { "$($def.valueType)" } + elseif ($def.valueTypes) { (@($def.valueTypes) | ForEach-Object { "$_" }) -join ' + ' } + else { '' } + if ($vt) { Emit-ValueType $i $vt } else { X "$i" } } function Emit-CommonModuleProperties { diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py index 2b9d0949..3213e62e 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.52 — Compile 1C metadata object from JSON +# meta-compile v1.53 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -539,7 +539,7 @@ cfg_bare_types = {"ConstantsSet", "ReportBuilder", "FilterCriterion"} cfg_object_kinds = {"Catalog", "Document", "Enum", "ChartOfAccounts", "ChartOfCharacteristicTypes", "ChartOfCalculationTypes", "ExchangePlan", "BusinessProcess", "Task", "InformationRegister", "AccumulationRegister", "AccountingRegister", "CalculationRegister", "DataProcessor", "Report", - "DocumentJournal", "Constant"} + "DocumentJournal", "Constant", "ConstantValue"} def resolve_type_str(type_str): if not type_str: @@ -2331,37 +2331,51 @@ def emit_constant_properties(indent): i = indent X(f'{i}{esc_xml(obj_name)}') emit_mltext(i, 'Synonym', synonym) - X(f'{i}') - # Type - value_type = build_type_str(defn) or 'String' - emit_value_type(i, value_type) - X(f'{i}true') - X(f'{i}') - X(f'{i}') - X(f'{i}') - X(f'{i}false') - X(f'{i}') - X(f'{i}') - X(f'{i}') - X(f'{i}false') - X(f'{i}') - X(f'{i}false') - X(f'{i}false') - X(f'{i}') - X(f'{i}') - X(f'{i}DontCheck') - X(f'{i}Items') - X(f'{i}') - X(f'{i}') - X(f'{i}Auto') - X(f'{i}') - X(f'{i}') - X(f'{i}Auto') - data_lock_control_mode = get_enum_prop('DataLockControlMode', 'dataLockControlMode', 'Automatic') - X(f'{i}{data_lock_control_mode}') - X(f'{i}DontUse') - X(f'{i}false') - X(f'{i}false') + if defn.get('comment'): + X(f'{i}{esc_xml_text(str(defn["comment"]))}') + else: + X(f'{i}') + # Type — valueType (явный '' → , реквизит без типа; отсутствие → String дефолт). + value_type = build_type_str(defn) + type_empty = (defn.get('valueType') is not None and str(defn.get('valueType')).strip() == '') or \ + (defn.get('type') is not None and str(defn.get('type')).strip() == '') + if type_empty: + X(f'{i}') + else: + emit_value_type(i, value_type or 'String') + use_std_cmds = 'true' if get_bool_prop('useStandardCommands', True) else 'false' + X(f'{i}{use_std_cmds}') + emit_verbatim_ref(i, 'DefaultForm', defn.get('defaultForm')) + emit_mltext(i, 'ExtendedPresentation', defn.get('extendedPresentation')) + emit_mltext(i, 'Explanation', defn.get('explanation')) + X(f'{i}{"true" if get_bool_prop("passwordMode", False) else "false"}') + emit_mltext(i, 'Format', defn.get('format')) + emit_mltext(i, 'EditFormat', defn.get('editFormat')) + emit_mltext(i, 'ToolTip', defn.get('tooltip')) + X(f'{i}{"true" if get_bool_prop("markNegatives", False) else "false"}') + if defn.get('mask'): + X(f'{i}{esc_xml_text(str(defn["mask"]))}') + else: + X(f'{i}') + X(f'{i}{"true" if get_bool_prop("multiLine", False) else "false"}') + X(f'{i}{"true" if get_bool_prop("extendedEdit", False) else "false"}') + emit_min_max_value(i, 'MinValue', defn.get('minValue')) + emit_min_max_value(i, 'MaxValue', defn.get('maxValue')) + X(f'{i}{get_enum_prop("FillChecking", "fillChecking", "DontCheck")}') + X(f'{i}{get_enum_prop("ChoiceFoldersAndItems", "choiceFoldersAndItems", "Items")}') + emit_choice_parameter_links(i, defn.get('choiceParameterLinks')) + emit_choice_parameters(i, defn.get('choiceParameters')) + X(f'{i}{get_enum_prop("QuickChoice", "quickChoice", "Auto")}') + if defn.get('choiceForm'): + X(f'{i}{esc_xml(str(defn["choiceForm"]))}') + else: + X(f'{i}') + emit_link_by_type(i, defn.get('linkByType')) + X(f'{i}{get_enum_prop("ChoiceHistoryOnInput", "choiceHistoryOnInput", "Auto")}') + X(f'{i}{get_enum_prop("DataLockControlMode", "dataLockControlMode", "Managed")}') + X(f'{i}{get_enum_prop("DataHistory", "dataHistory", "DontUse")}') + X(f'{i}{"true" if get_bool_prop("updateDataHistoryImmediatelyAfterWrite", False) else "false"}') + X(f'{i}{"true" if get_bool_prop("executeAfterWriteDataHistoryVersionProcessing", False) else "false"}') def emit_information_register_properties(indent): i = indent @@ -2439,29 +2453,19 @@ def emit_defined_type_properties(indent): i = indent X(f'{i}{esc_xml(obj_name)}') emit_mltext(i, 'Synonym', synonym) - X(f'{i}') - # Accept both valueType and valueTypes - value_types = list(defn.get('valueTypes', [])) - if not value_types and defn.get('valueType'): - vt_raw = defn['valueType'] - value_types = list(vt_raw) if isinstance(vt_raw, list) else [vt_raw] - if value_types: - X(f'{i}') - for vt in value_types: - resolved = resolve_type_str(str(vt)) - if re.match(r'^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|ExchangePlanRef|BusinessProcessRef|TaskRef)\.', resolved): - X(f'{i}\td5p1:{resolved}') - elif resolved == 'Boolean': - X(f'{i}\txs:boolean') - elif re.match(r'^String', resolved): - X(f'{i}\txs:string') - X(f'{i}\t') - X(f'{i}\t\t0') - X(f'{i}\t\tVariable') - X(f'{i}\t') - else: - X(f'{i}\tcfg:{resolved}') - X(f'{i}') + if defn.get('comment'): + X(f'{i}{esc_xml_text(str(defn["comment"]))}') + else: + X(f'{i}') + # Type — единый эмиттер emit_value_type/emit_type_content (составной через ' + '); valueType или valueTypes. + if defn.get('valueType'): + vt = str(defn['valueType']) + elif defn.get('valueTypes'): + vt = ' + '.join(str(x) for x in defn['valueTypes']) + else: + vt = '' + if vt: + emit_value_type(i, vt) else: X(f'{i}') diff --git a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 index 59edcf40..bd18580b 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.43 — XML объекта метаданных 1С → JSON-черновик формата meta-compile +# meta-decompile v0.44 — XML объекта метаданных 1С → JSON-черновик формата meta-compile # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # # Поддержаны: Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document, @@ -92,8 +92,8 @@ foreach ($c in $rootEl.ChildNodes) { if ($c.NodeType -eq 'Element') { $objNode = if (-not $objNode) { [Console]::Error.WriteLine("meta-decompile: пустой MetaDataObject"); exit 3 } $objType = $objNode.LocalName -if ($objType -notin @('Catalog', 'ExchangePlan', 'ChartOfCharacteristicTypes', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'Document', 'InformationRegister', 'AccumulationRegister', 'AccountingRegister', 'CalculationRegister', 'BusinessProcess', 'Task', 'Enum', 'Report', 'DataProcessor')) { - [Console]::Error.WriteLine("meta-decompile: тип '$objType' пока не поддержан (Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document, InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister, BusinessProcess, Task, Enum, Report, DataProcessor)"); exit 3 +if ($objType -notin @('Catalog', 'ExchangePlan', 'ChartOfCharacteristicTypes', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'Document', 'InformationRegister', 'AccumulationRegister', 'AccountingRegister', 'CalculationRegister', 'BusinessProcess', 'Task', 'Enum', 'Report', 'DataProcessor', 'Constant', 'DefinedType')) { + [Console]::Error.WriteLine("meta-decompile: тип '$objType' пока не поддержан (Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document, InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister, BusinessProcess, Task, Enum, Report, DataProcessor, Constant, DefinedType)"); exit 3 } $props = $objNode.SelectSingleNode('md:Properties', $nsm) @@ -433,7 +433,7 @@ Add-BoolProp 'autonumbering' 'Autonumbering' $true Add-BoolProp 'checkUnique' 'CheckUnique' $checkUniqueDef Add-EnumProp 'codeSeries' 'CodeSeries' $codeSeriesDef Add-EnumProp 'defaultPresentation' 'DefaultPresentation' $defPresDef -Add-BoolProp 'quickChoice' 'QuickChoice' $(if ($objType -eq 'Enum') { $true } else { $false }) # Enum дефолт true (компилятор+корпус); прочие false +if ($objType -ne 'Constant') { Add-BoolProp 'quickChoice' 'QuickChoice' $(if ($objType -eq 'Enum') { $true } else { $false }) } # Enum дефолт true; прочие false. Constant: QuickChoice — ENUM (Auto), не bool → ловим отдельно ниже Add-EnumProp 'choiceMode' 'ChoiceMode' 'BothWays' Add-EnumProp 'dataLockControlMode' 'DataLockControlMode' $dataLockDef Add-EnumProp 'fullTextSearch' 'FullTextSearch' 'Use' @@ -594,6 +594,53 @@ if ($objType -eq 'DataProcessor') { $afm = P 'AuxiliaryForm'; if ($afm) { $dsl['auxiliaryForm'] = $afm } $ep = Get-MLValue ($props.SelectSingleNode('md:ExtendedPresentation', $nsm)); if ($null -ne $ep) { $dsl['extendedPresentation'] = $ep } } +# DefinedType — тип-псевдоним: только Name/Synonym/Comment/Type. valueType (составной через ' + '). +if ($objType -eq 'DefinedType') { + $vt = Get-TypeShorthand ($props.SelectSingleNode('md:Type', $nsm)) + if ($vt) { $dsl['valueType'] = $vt } +} +# Constant — богатый одиночный реквизит: Type + свойства значения (как у реквизита) + object-уровень. +if ($objType -eq 'Constant') { + $vt = Get-TypeShorthand ($props.SelectSingleNode('md:Type', $nsm)) + if ($vt) { $dsl['valueType'] = $vt } else { $dsl['valueType'] = '' } + $dfm = P 'DefaultForm'; if ($dfm) { $dsl['defaultForm'] = $dfm } + $ep = Get-MLValue ($props.SelectSingleNode('md:ExtendedPresentation', $nsm)); if ($null -ne $ep) { $dsl['extendedPresentation'] = $ep } + Add-BoolProp 'passwordMode' 'PasswordMode' $false + $fmt = Get-MLValue ($props.SelectSingleNode('md:Format', $nsm)); if ($null -ne $fmt) { $dsl['format'] = $fmt } + $efmt = Get-MLValue ($props.SelectSingleNode('md:EditFormat', $nsm)); if ($null -ne $efmt) { $dsl['editFormat'] = $efmt } + $tt = Get-MLValue ($props.SelectSingleNode('md:ToolTip', $nsm)); if ($null -ne $tt) { $dsl['tooltip'] = $tt } + Add-BoolProp 'markNegatives' 'MarkNegatives' $false + $msk = P 'Mask'; if ($msk) { $dsl['mask'] = $msk } + Add-BoolProp 'multiLine' 'MultiLine' $false + Add-BoolProp 'extendedEdit' 'ExtendedEdit' $false + # MinValue/MaxValue (дефолт nil) — типизированное значение при наличии. + foreach ($mm in @(@('MinValue','minValue'), @('MaxValue','maxValue'))) { + $mn = $props.SelectSingleNode("md:$($mm[0])", $nsm) + if ($mn -and $mn.GetAttribute('nil', 'http://www.w3.org/2001/XMLSchema-instance') -ne 'true') { + $mxt = $mn.GetAttribute('type', 'http://www.w3.org/2001/XMLSchema-instance') + if ($mxt -match 'decimal$') { $dsl[$mm[1]] = if ($mn.InnerText -match '^-?\d+$') { [long]$mn.InnerText } else { [double]$mn.InnerText } } + else { $dsl[$mm[1]] = $mn.InnerText } + } + } + Add-EnumProp 'fillChecking' 'FillChecking' 'DontCheck' + Add-EnumProp 'choiceFoldersAndItems' 'ChoiceFoldersAndItems' 'Items' + $cpl = Parse-ChoiceParameterLinks $props 'md:ChoiceParameterLinks'; if ($null -ne $cpl) { $dsl['choiceParameterLinks'] = $cpl } + $cp = Parse-ChoiceParameters $props 'md:ChoiceParameters'; if ($null -ne $cp) { $dsl['choiceParameters'] = $cp } + Add-EnumProp 'quickChoice' 'QuickChoice' 'Auto' + $cf = P 'ChoiceForm'; if ($cf) { $dsl['choiceForm'] = $cf } + $lbtNode = $props.SelectSingleNode('md:LinkByType', $nsm) + if ($lbtNode) { + $dpN = $lbtNode.SelectSingleNode('md:DataPath', $nsm) + if ($dpN -and $dpN.InnerText) { + $liN = $lbtNode.SelectSingleNode('md:LinkItem', $nsm) + $li = if ($liN -and $liN.InnerText) { [int]$liN.InnerText } else { 0 } + $dsl['linkByType'] = if ($li -eq 0) { $dpN.InnerText } else { [ordered]@{ dataPath = $dpN.InnerText; linkItem = $li } } + } + } + Add-EnumProp 'dataHistory' 'DataHistory' 'DontUse' + Add-BoolProp 'updateDataHistoryImmediatelyAfterWrite' 'UpdateDataHistoryImmediatelyAfterWrite' $false + Add-BoolProp 'executeAfterWriteDataHistoryVersionProcessing' 'ExecuteAfterWriteDataHistoryVersionProcessing' $false +} # Короткая форма поля: ..StandardAttribute.X / .Attribute.X → StandardAttribute.X / Attribute.X # (Expand-DataPath компилятора разворачивает частичную форму обратно — dogfood резолвера). diff --git a/docs/meta-dsl-spec.md b/docs/meta-dsl-spec.md index e5b50a0a..4f6d93ec 100644 --- a/docs/meta-dsl-spec.md +++ b/docs/meta-dsl-spec.md @@ -819,17 +819,35 @@ Split-CamelCase имени. ] } ``` -### 7.4 Constant +### 7.4 Constant (Константа) + +Константа — «богатый одиночный реквизит»: тип-значение + все свойства значения (как у реквизита, §4.2) + object-уровень. | Поле JSON | Умолчание | XML элемент | |-----------|----------|-------------| -| `valueType` | `String` | Type | -| `length` | — | Длина строки (если valueType=String) | -| `precision` | — | Точность числа (если valueType=Number) | -| `dataLockControlMode` | `Automatic` | DataLockControlMode | +| `valueType` | `String` | Type (пустой явный `""` → ``, без типа); `length`/`precision` как в §4.2 | +| `comment` | пусто | Comment | +| `useStandardCommands` | `true` | UseStandardCommands (при `false` доступ лишь по навигационной ссылке — см. §7.11) | +| `defaultForm` | `""` | DefaultForm (ссылка verbatim) | +| `extendedPresentation` / `explanation` | пусто | ExtendedPresentation / Explanation (ML) | +| `dataLockControlMode` | `Managed` | DataLockControlMode | +| `passwordMode` / `markNegatives` / `multiLine` / `extendedEdit` | `false` | одноимённые булевы | +| `format` / `editFormat` / `tooltip` | пусто | Format / EditFormat / ToolTip (ML) | +| `mask` | `""` | Mask | +| `minValue` / `maxValue` | nil | MinValue / MaxValue (число → xs:decimal, строка → xs:string) | +| `fillChecking` | `DontCheck` | FillChecking | +| `choiceFoldersAndItems` | `Items` | ChoiceFoldersAndItems | +| `choiceParameterLinks` / `choiceParameters` | `[]` | ChoiceParameterLinks / ChoiceParameters (§4.2) | +| `quickChoice` | `Auto` | QuickChoice (**enum** Auto/Use/DontUse, не bool) | +| `choiceForm` | `""` | ChoiceForm | +| `linkByType` | — | LinkByType (§4.2) | +| `choiceHistoryOnInput` | `Auto` | ChoiceHistoryOnInput | +| `dataHistory` (+ триплет) | `DontUse` | DataHistory / UpdateDataHistoryImmediatelyAfterWrite / ExecuteAfterWriteDataHistoryVersionProcessing | -`valueType` + `length`/`precision` работают аналогично раздельной форме типа (§4.2): -`"valueType": "String", "length": 100` → `String(100)`. +```json +{ "type": "Constant", "name": "СтавкаНДС", "valueType": "Number(15,2,nonneg)", + "minValue": 0, "maxValue": 100, "fillChecking": "ShowError" } +``` ### 7.5 InformationRegister @@ -927,17 +945,21 @@ true); `characteristics` (§7.1.4); `basedOn`/`inputByString`/`dataLockFields` ( Дети: `attributes`, `commands` и **`addressingAttributes`** — реквизиты адресации (полный object-слой реквизита + `addressingDimension`: ссылка на измерение регистра исполнителей). -### 7.7 DefinedType +### 7.7 DefinedType (Определяемый тип) + +Тип-псевдоним: Name/Synonym/Comment + Type. Без ChildObjects и модулей. | Поле JSON | Умолчание | XML элемент | |-----------|----------|-------------| -| `valueTypes` | `[]` | Type (составной — массив `v8:Type`) | -| `valueType` | — | Алиас для `valueTypes` (принимает строку или массив) | +| `valueType` | — | Type (составной через ` + `, единый эмиттер §3: refs/cfg:/платформенные/квалификаторы) | +| `valueTypes` | `[]` | Алиас — массив типов (склеивается через ` + `) | +| `comment` | пусто | Comment | -Без ChildObjects и модулей. Принимается как `valueTypes` (мн.ч.), так и `valueType` (ед.ч.). +Принимается как `valueType` (строка, в т.ч. составная `A + B`), так и `valueTypes` (массив). Пусто → ``. ```json -{ "type": "DefinedType", "name": "ДенежныеСредства", "valueTypes": ["CatalogRef.БанковскиеСчета", "CatalogRef.Кассы"] } +{ "type": "DefinedType", "name": "СсылкаНаКонтрагента", + "valueType": "CatalogRef.Контрагенты + CatalogRef.Организации + String(150)" } { "type": "DefinedType", "name": "ФлагАктивности", "valueType": "Boolean" } ``` diff --git a/tests/skills/cases/meta-compile/constant-full.json b/tests/skills/cases/meta-compile/constant-full.json new file mode 100644 index 00000000..a0d9014e --- /dev/null +++ b/tests/skills/cases/meta-compile/constant-full.json @@ -0,0 +1,20 @@ +{ + "name": "Константа — полный набор возможностей", + "input": { + "type": "Constant", + "name": "СтавкаНДС", + "comment": "(Демо)", + "valueType": "Number(15,2,nonneg)", + "useStandardCommands": false, + "dataLockControlMode": "Automatic", + "format": { "ru": "ЧДЦ=2", "en": "NFD=2" }, + "tooltip": "Основная ставка", + "minValue": 0, + "maxValue": 100, + "fillChecking": "ShowError" + }, + "validatePath": "Constants/СтавкаНДС", + "expect": { + "files": ["Constants/СтавкаНДС.xml"] + } +} diff --git a/tests/skills/cases/meta-compile/defined-type-full.json b/tests/skills/cases/meta-compile/defined-type-full.json new file mode 100644 index 00000000..76bdba45 --- /dev/null +++ b/tests/skills/cases/meta-compile/defined-type-full.json @@ -0,0 +1,13 @@ +{ + "name": "Определяемый тип — составной", + "input": { + "type": "DefinedType", + "name": "СсылкаНаКонтрагента", + "comment": "(Демо)", + "valueType": "CatalogRef.Контрагенты + CatalogRef.Организации + String(150)" + }, + "validatePath": "DefinedTypes/СсылкаНаКонтрагента", + "expect": { + "files": ["DefinedTypes/СсылкаНаКонтрагента.xml"] + } +} diff --git a/tests/skills/cases/meta-compile/snapshots/constant-full/Configuration.xml b/tests/skills/cases/meta-compile/snapshots/constant-full/Configuration.xml new file mode 100644 index 00000000..ae3e4bab --- /dev/null +++ b/tests/skills/cases/meta-compile/snapshots/constant-full/Configuration.xml @@ -0,0 +1,252 @@ + + + + + + UUID-002 + UUID-003 + + + UUID-004 + UUID-005 + + + UUID-006 + UUID-007 + + + UUID-008 + UUID-009 + + + UUID-010 + UUID-011 + + + UUID-012 + UUID-013 + + + UUID-014 + UUID-015 + + + + TestConfig + + + ru + TestConfig + + + + + Version8_3_24 + ManagedApplication + + PlatformApplication + + Russian + + + + + false + false + false + + + + + + + + + + + + + + + + + + + + + + Biometrics + true + + + Location + false + + + BackgroundLocation + false + + + BluetoothPrinters + false + + + WiFiPrinters + false + + + Contacts + false + + + Calendars + false + + + PushNotifications + false + + + LocalNotifications + false + + + InAppPurchases + false + + + PersonalComputerFileExchange + false + + + Ads + false + + + NumberDialing + false + + + CallProcessing + false + + + CallLog + false + + + AutoSendSMS + false + + + ReceiveSMS + false + + + SMSLog + false + + + Camera + false + + + Microphone + false + + + MusicLibrary + false + + + PictureAndVideoLibraries + false + + + AudioPlaybackAndVibration + false + + + BackgroundAudioPlaybackAndVibration + false + + + InstallPackages + false + + + OSBackup + true + + + ApplicationUsageStatistics + false + + + BarcodeScanning + false + + + BackgroundAudioRecording + false + + + AllFilesAccess + false + + + Videoconferences + false + + + NFC + false + + + DocumentScanning + false + + + SpeechToText + false + + + Geofences + false + + + IncomingShareRequests + false + + + AllIncomingShareRequestsTypesProcessing + false + + + + + + Normal + + + Language.Русский + + + + + + Managed + NotAutoFree + DontUse + DontUse + TaxiEnableVersion8_2 + DontUse + Version8_3_24 + + + + Русский + СтавкаНДС + + + \ No newline at end of file diff --git a/tests/skills/cases/meta-compile/snapshots/constant-full/Constants/СтавкаНДС.xml b/tests/skills/cases/meta-compile/snapshots/constant-full/Constants/СтавкаНДС.xml new file mode 100644 index 00000000..cdd2f953 --- /dev/null +++ b/tests/skills/cases/meta-compile/snapshots/constant-full/Constants/СтавкаНДС.xml @@ -0,0 +1,77 @@ + + + + + + UUID-002 + UUID-003 + + + UUID-004 + UUID-005 + + + UUID-006 + UUID-007 + + + + СтавкаНДС + + + ru + Ставка ндс + + + (Демо) + + xs:decimal + + 15 + 2 + Nonnegative + + + false + + + + false + + + ru + ЧДЦ=2 + + + en + NFD=2 + + + + + + ru + Основная ставка + + + false + + false + false + 0 + 100 + ShowError + Items + + + Auto + + + Auto + Automatic + DontUse + false + false + + + diff --git a/tests/skills/cases/meta-compile/snapshots/constant-full/Constants/СтавкаНДС/Ext/ManagerModule.bsl b/tests/skills/cases/meta-compile/snapshots/constant-full/Constants/СтавкаНДС/Ext/ManagerModule.bsl new file mode 100644 index 00000000..e69de29b diff --git a/tests/skills/cases/meta-compile/snapshots/constant-full/Constants/СтавкаНДС/Ext/ValueManagerModule.bsl b/tests/skills/cases/meta-compile/snapshots/constant-full/Constants/СтавкаНДС/Ext/ValueManagerModule.bsl new file mode 100644 index 00000000..e69de29b diff --git a/tests/skills/cases/meta-compile/snapshots/constant-full/Ext/ClientApplicationInterface.xml b/tests/skills/cases/meta-compile/snapshots/constant-full/Ext/ClientApplicationInterface.xml new file mode 100644 index 00000000..3c1161b2 --- /dev/null +++ b/tests/skills/cases/meta-compile/snapshots/constant-full/Ext/ClientApplicationInterface.xml @@ -0,0 +1,18 @@ + + + + + UUID-002 + + + + + UUID-004 + + + + + + + + \ No newline at end of file diff --git a/tests/skills/cases/meta-compile/snapshots/constant-full/Languages/Русский.xml b/tests/skills/cases/meta-compile/snapshots/constant-full/Languages/Русский.xml new file mode 100644 index 00000000..37c60d78 --- /dev/null +++ b/tests/skills/cases/meta-compile/snapshots/constant-full/Languages/Русский.xml @@ -0,0 +1,16 @@ + + + + + Русский + + + ru + Русский + + + + ru + + + \ No newline at end of file diff --git a/tests/skills/cases/meta-compile/snapshots/constant/Constants/ОсновнаяВалюта.xml b/tests/skills/cases/meta-compile/snapshots/constant/Constants/ОсновнаяВалюта.xml index de7df0ee..6daa3afd 100644 --- a/tests/skills/cases/meta-compile/snapshots/constant/Constants/ОсновнаяВалюта.xml +++ b/tests/skills/cases/meta-compile/snapshots/constant/Constants/ОсновнаяВалюта.xml @@ -49,7 +49,7 @@ Auto - Automatic + Managed DontUse false false diff --git a/tests/skills/cases/meta-compile/snapshots/defined-type-full/Configuration.xml b/tests/skills/cases/meta-compile/snapshots/defined-type-full/Configuration.xml new file mode 100644 index 00000000..ff8ad27d --- /dev/null +++ b/tests/skills/cases/meta-compile/snapshots/defined-type-full/Configuration.xml @@ -0,0 +1,252 @@ + + + + + + UUID-002 + UUID-003 + + + UUID-004 + UUID-005 + + + UUID-006 + UUID-007 + + + UUID-008 + UUID-009 + + + UUID-010 + UUID-011 + + + UUID-012 + UUID-013 + + + UUID-014 + UUID-015 + + + + TestConfig + + + ru + TestConfig + + + + + Version8_3_24 + ManagedApplication + + PlatformApplication + + Russian + + + + + false + false + false + + + + + + + + + + + + + + + + + + + + + + Biometrics + true + + + Location + false + + + BackgroundLocation + false + + + BluetoothPrinters + false + + + WiFiPrinters + false + + + Contacts + false + + + Calendars + false + + + PushNotifications + false + + + LocalNotifications + false + + + InAppPurchases + false + + + PersonalComputerFileExchange + false + + + Ads + false + + + NumberDialing + false + + + CallProcessing + false + + + CallLog + false + + + AutoSendSMS + false + + + ReceiveSMS + false + + + SMSLog + false + + + Camera + false + + + Microphone + false + + + MusicLibrary + false + + + PictureAndVideoLibraries + false + + + AudioPlaybackAndVibration + false + + + BackgroundAudioPlaybackAndVibration + false + + + InstallPackages + false + + + OSBackup + true + + + ApplicationUsageStatistics + false + + + BarcodeScanning + false + + + BackgroundAudioRecording + false + + + AllFilesAccess + false + + + Videoconferences + false + + + NFC + false + + + DocumentScanning + false + + + SpeechToText + false + + + Geofences + false + + + IncomingShareRequests + false + + + AllIncomingShareRequestsTypesProcessing + false + + + + + + Normal + + + Language.Русский + + + + + + Managed + NotAutoFree + DontUse + DontUse + TaxiEnableVersion8_2 + DontUse + Version8_3_24 + + + + Русский + СсылкаНаКонтрагента + + + \ No newline at end of file diff --git a/tests/skills/cases/meta-compile/snapshots/defined-type-full/DefinedTypes/СсылкаНаКонтрагента.xml b/tests/skills/cases/meta-compile/snapshots/defined-type-full/DefinedTypes/СсылкаНаКонтрагента.xml new file mode 100644 index 00000000..c9ff6bb9 --- /dev/null +++ b/tests/skills/cases/meta-compile/snapshots/defined-type-full/DefinedTypes/СсылкаНаКонтрагента.xml @@ -0,0 +1,30 @@ + + + + + + UUID-002 + UUID-003 + + + + СсылкаНаКонтрагента + + + ru + Ссылка на контрагента + + + (Демо) + + d5p1:CatalogRef.Контрагенты + d5p1:CatalogRef.Организации + xs:string + + 150 + Variable + + + + + diff --git a/tests/skills/cases/meta-compile/snapshots/defined-type-full/Ext/ClientApplicationInterface.xml b/tests/skills/cases/meta-compile/snapshots/defined-type-full/Ext/ClientApplicationInterface.xml new file mode 100644 index 00000000..3c1161b2 --- /dev/null +++ b/tests/skills/cases/meta-compile/snapshots/defined-type-full/Ext/ClientApplicationInterface.xml @@ -0,0 +1,18 @@ + + + + + UUID-002 + + + + + UUID-004 + + + + + + + + \ No newline at end of file diff --git a/tests/skills/cases/meta-compile/snapshots/defined-type-full/Languages/Русский.xml b/tests/skills/cases/meta-compile/snapshots/defined-type-full/Languages/Русский.xml new file mode 100644 index 00000000..37c60d78 --- /dev/null +++ b/tests/skills/cases/meta-compile/snapshots/defined-type-full/Languages/Русский.xml @@ -0,0 +1,16 @@ + + + + + Русский + + + ru + Русский + + + + ru + + + \ No newline at end of file