diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1
index f0a881fe..1bd30137 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.50 — Compile 1C metadata object from JSON
+# meta-compile v1.51 — Compile 1C metadata object from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -868,7 +868,7 @@ function Parse-EnumValueShorthand {
$name = "$($val.name)"
return @{
name = $name
- synonym = if ($val.synonym) { "$($val.synonym)" } else { Split-CamelCase $name }
+ synonym = if ($null -ne $val.synonym) { $val.synonym } else { Split-CamelCase $name } # строка ИЛИ {ru,en} → Emit-MLText
comment = if ($val.comment) { "$($val.comment)" } else { "" }
}
}
@@ -1864,7 +1864,7 @@ function Emit-EnumValue {
X "$indent`t"
X "$indent`t`t$(Esc-Xml $parsed.name)"
Emit-MLText "$indent`t`t" "Synonym" $parsed.synonym
- X "$indent`t`t"
+ if ($parsed.comment) { X "$indent`t`t$(Esc-XmlText $parsed.comment)" } else { X "$indent`t`t" }
X "$indent`t"
X "$indent"
}
@@ -2246,23 +2246,24 @@ function Emit-EnumProperties {
X "$i$(Esc-Xml $objName)"
Emit-MLText $i "Synonym" $synonym
- X "$i"
- X "$ifalse"
+ if ($def.comment) { X "$i$(Esc-XmlText $def.comment)" } else { X "$i" }
+ $useStdCmds = if (Get-BoolProp "useStandardCommands" $false) { "true" } else { "false" }
+ X "$i$useStdCmds"
Emit-StandardAttributes $i "Enum"
- X "$i"
+ Emit-Characteristics $i $def.characteristics
$quickChoice = if ($def.quickChoice -eq $false) { "false" } else { "true" }
X "$i$quickChoice"
- X "$iBothWays"
- X "$i"
- X "$i"
- X "$i"
- X "$i"
- X "$i"
- X "$i"
- X "$i"
- X "$iAuto"
+ X "$i$(Get-EnumProp 'ChoiceMode' 'choiceMode' 'BothWays')"
+ Emit-FormRef $i "DefaultListForm" $def.defaultListForm
+ Emit-FormRef $i "DefaultChoiceForm" $def.defaultChoiceForm
+ Emit-FormRef $i "AuxiliaryListForm" $def.auxiliaryListForm
+ Emit-FormRef $i "AuxiliaryChoiceForm" $def.auxiliaryChoiceForm
+ Emit-MLText $i "ListPresentation" $def.listPresentation
+ Emit-MLText $i "ExtendedListPresentation" $def.extendedListPresentation
+ Emit-MLText $i "Explanation" $def.explanation
+ X "$i$(Get-EnumProp 'ChoiceHistoryOnInput' 'choiceHistoryOnInput' 'Auto')"
}
function Emit-ConstantProperties {
diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py
index 66e895ec..b7b83dd7 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.50 — Compile 1C metadata object from JSON
+# meta-compile v1.51 — Compile 1C metadata object from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -891,7 +891,8 @@ def parse_enum_value_shorthand(val):
name = str(val.get('name', ''))
return {
'name': name,
- 'synonym': str(val['synonym']) if val.get('synonym') else split_camel_case(name),
+ # строка ИЛИ {ru,en} → emit_mltext; None → авто из имени
+ 'synonym': val['synonym'] if val.get('synonym') is not None else split_camel_case(name),
'comment': str(val['comment']) if val.get('comment') else '',
}
@@ -1915,7 +1916,10 @@ def emit_enum_value(indent, parsed):
X(f'{indent}\t')
X(f'{indent}\t\t{esc_xml(parsed["name"])}')
emit_mltext(f'{indent}\t\t', 'Synonym', parsed['synonym'])
- X(f'{indent}\t\t')
+ if parsed.get('comment'):
+ X(f'{indent}\t\t{esc_xml_text(parsed["comment"])}')
+ else:
+ X(f'{indent}\t\t')
X(f'{indent}\t')
X(f'{indent}')
@@ -2248,21 +2252,25 @@ def emit_enum_properties(indent):
i = indent
X(f'{i}{esc_xml(obj_name)}')
emit_mltext(i, 'Synonym', synonym)
- X(f'{i}')
- X(f'{i}false')
+ if defn.get('comment'):
+ X(f'{i}{esc_xml_text(defn["comment"])}')
+ else:
+ X(f'{i}')
+ use_std_cmds = 'true' if get_bool_prop('useStandardCommands', False) else 'false'
+ X(f'{i}{use_std_cmds}')
emit_standard_attributes(i, 'Enum')
- X(f'{i}')
+ emit_characteristics(i, defn.get('characteristics'))
quick_choice = 'false' if defn.get('quickChoice') is False else 'true'
X(f'{i}{quick_choice}')
- X(f'{i}BothWays')
- X(f'{i}')
- X(f'{i}')
- X(f'{i}')
- X(f'{i}')
- X(f'{i}')
- X(f'{i}')
- X(f'{i}')
- X(f'{i}Auto')
+ X(f'{i}{get_enum_prop("ChoiceMode", "choiceMode", "BothWays")}')
+ emit_form_ref(i, 'DefaultListForm', defn.get('defaultListForm'))
+ emit_form_ref(i, 'DefaultChoiceForm', defn.get('defaultChoiceForm'))
+ emit_form_ref(i, 'AuxiliaryListForm', defn.get('auxiliaryListForm'))
+ emit_form_ref(i, 'AuxiliaryChoiceForm', defn.get('auxiliaryChoiceForm'))
+ emit_mltext(i, 'ListPresentation', defn.get('listPresentation'))
+ emit_mltext(i, 'ExtendedListPresentation', defn.get('extendedListPresentation'))
+ emit_mltext(i, 'Explanation', defn.get('explanation'))
+ X(f'{i}{get_enum_prop("ChoiceHistoryOnInput", "choiceHistoryOnInput", "Auto")}')
def emit_constant_properties(indent):
i = indent
diff --git a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1
index 02b99852..9ef7f670 100644
--- a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1
+++ b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1
@@ -1,7 +1,8 @@
-# meta-decompile v0.41 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
+# meta-decompile v0.42 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
#
-# Поддержаны: Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document. Инверс meta-compile (omit-on-default: ключ эмитим только
+# Поддержаны: Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document,
+# InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister, BusinessProcess, Task, Enum. Инверс meta-compile (omit-on-default: ключ эмитим только
# когда значение в XML отличается от умолчания компилятора). Неподдерживаемый тип / не-MetaDataObject
# root → exit 3 (ring3, как form-decompile).
param(
@@ -91,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')) {
- [Console]::Error.WriteLine("meta-decompile: тип '$objType' пока не поддержан (Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document, InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister, BusinessProcess, Task)"); exit 3
+if ($objType -notin @('Catalog', 'ExchangePlan', 'ChartOfCharacteristicTypes', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'Document', 'InformationRegister', 'AccumulationRegister', 'AccountingRegister', 'CalculationRegister', 'BusinessProcess', 'Task', 'Enum')) {
+ [Console]::Error.WriteLine("meta-decompile: тип '$objType' пока не поддержан (Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document, InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister, BusinessProcess, Task, Enum)"); exit 3
}
$props = $objNode.SelectSingleNode('md:Properties', $nsm)
@@ -429,11 +430,11 @@ Add-BoolProp 'autonumbering' 'Autonumbering' $true
Add-BoolProp 'checkUnique' 'CheckUnique' $checkUniqueDef
Add-EnumProp 'codeSeries' 'CodeSeries' $codeSeriesDef
Add-EnumProp 'defaultPresentation' 'DefaultPresentation' $defPresDef
-Add-BoolProp 'quickChoice' 'QuickChoice' $false
+Add-BoolProp 'quickChoice' 'QuickChoice' $(if ($objType -eq 'Enum') { $true } else { $false }) # Enum дефолт true (компилятор+корпус); прочие false
Add-EnumProp 'choiceMode' 'ChoiceMode' 'BothWays'
Add-EnumProp 'dataLockControlMode' 'DataLockControlMode' $dataLockDef
Add-EnumProp 'fullTextSearch' 'FullTextSearch' 'Use'
-Add-BoolProp 'useStandardCommands' 'UseStandardCommands' $true
+Add-BoolProp 'useStandardCommands' 'UseStandardCommands' $(if ($objType -eq 'Enum') { $false } else { $true })
Add-EnumProp 'createOnInput' 'CreateOnInput' $createInpDef
Add-EnumProp 'editType' 'EditType' 'InDialog'
Add-BoolProp 'includeHelpInContents' 'IncludeHelpInContents' $false
@@ -717,6 +718,7 @@ $stdFixedByType = @{
'ChartOfAccounts' = @('PredefinedDataName','Order','OffBalance','Type','Description','Code','Parent','Predefined','DeletionMark','Ref')
'ChartOfCalculationTypes' = @('PredefinedDataName','Predefined','Ref','DeletionMark','ActionPeriodIsBasic','Description','Code')
'Document' = @('Ref','DeletionMark','Date','Number','Posted')
+ 'Enum' = @('Order','Ref')
}
$stdFixed = if ($stdFixedByType.ContainsKey($objType)) { $stdFixedByType[$objType] } else { @() }
# Условные типы: блок эмитим-как-триггер даже пустым (материализуется при отклонении ≥1 реквизита от schema-default;
@@ -774,7 +776,7 @@ if ($saNode) {
}
# Условный тип (Catalog): пустой $saMap = триггер блока. Не-условный (ExchangePlan): блок и так эмитится → пустой не пишем.
if ($saMap.Count -gt 0 -or ($stdConditionalTypes -contains $objType)) { $dsl['standardAttributes'] = $saMap }
-} elseif ($objType -in @('InformationRegister', 'AccumulationRegister', 'AccountingRegister', 'CalculationRegister', 'BusinessProcess', 'Task')) {
+} elseif ($objType -in @('InformationRegister', 'AccumulationRegister', 'AccountingRegister', 'CalculationRegister', 'BusinessProcess', 'Task', 'Enum')) {
# Регистр/БП/Задача опускают all-default блок стандартных реквизитов (правило не выводимо) — компилятор эмитит его
# по дефолту, поэтому отсутствие фиксируем opt-out `standardAttributes:""` (дом-конвенция суппресса).
$dsl['standardAttributes'] = ''
@@ -789,6 +791,34 @@ if ($childObjs) {
foreach ($a in $attrs) { [void]$arr.Add((Attr-ToDsl $a)) }
$dsl['attributes'] = $arr
}
+ # Enum: значения перечисления. Плоский элемент name/synonym/comment. Короткая форма — строка "Имя"
+ # (синоним == авто из имени, без comment, не мультиязычный); иначе объект {name, synonym?, comment?}.
+ $evNodes = @($childObjs.SelectNodes('md:EnumValue', $nsm))
+ if ($evNodes.Count -gt 0) {
+ $evArr = [System.Collections.ArrayList]@()
+ foreach ($ev in $evNodes) {
+ $evp = $ev.SelectSingleNode('md:Properties', $nsm)
+ $evName = ($evp.SelectSingleNode('md:Name', $nsm)).InnerText
+ $evSynNode = $evp.SelectSingleNode('md:Synonym', $nsm)
+ $evSyn = Get-MLValue $evSynNode
+ $evCmtN = $evp.SelectSingleNode('md:Comment', $nsm); $evCmt = if ($evCmtN) { $evCmtN.InnerText } else { '' }
+ # $evSynVal: строка ≠ авто → кастом; {ru,en} → кастом; пустой `` (node есть, значения нет) →
+ # явный '' (≠ авто-синоним из имени, аналог object-level фикса); авто/отсутствие → $null (короткая строка).
+ $evSynVal = $null
+ if ($evSyn -is [string]) { if ($evSyn -ne (Split-CamelWords $evName)) { $evSynVal = $evSyn } }
+ elseif ($null -ne $evSyn) { $evSynVal = $evSyn }
+ elseif ($evSynNode) { $evSynVal = '' }
+ if (($null -ne $evSynVal) -or $evCmt) {
+ $o = [ordered]@{ name = $evName }
+ if ($null -ne $evSynVal) { $o['synonym'] = $evSynVal }
+ if ($evCmt) { $o['comment'] = $evCmt }
+ [void]$evArr.Add($o)
+ } else {
+ [void]$evArr.Add($evName)
+ }
+ }
+ $dsl['values'] = $evArr
+ }
# ChartOfAccounts: признаки учёта (AccountingFlag) и признаки учёта субконто (ExtDimensionAccountingFlag) —
# структурно как реквизит, захватываем тем же Attr-ToDsl (тип Boolean уходит в короткую запись).
$acctFlagNodes = @($childObjs.SelectNodes('md:AccountingFlag', $nsm))
diff --git a/docs/meta-dsl-spec.md b/docs/meta-dsl-spec.md
index be8ab1d5..7981279c 100644
--- a/docs/meta-dsl-spec.md
+++ b/docs/meta-dsl-spec.md
@@ -787,13 +787,37 @@ Split-CamelCase имени.
]
```
-### 7.3 Enum
+### 7.3 Enum (Перечисление)
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `values` | `[]` | → EnumValue в ChildObjects |
+| `comment` | пусто | Comment |
+| `useStandardCommands` | `false` | UseStandardCommands (у Enum дефолт **false**, в отличие от прочих типов) |
+| `quickChoice` | `true` | QuickChoice (у Enum дефолт **true**) |
+| `choiceMode` | `BothWays` | ChoiceMode (BothWays/FromForm/QuickChoice) |
+| `choiceHistoryOnInput` | `Auto` | ChoiceHistoryOnInput |
+| `listPresentation` / `extendedListPresentation` / `explanation` | пусто | презентации (ML) |
+| `defaultListForm` / `defaultChoiceForm` / `auxiliaryListForm` / `auxiliaryChoiceForm` | пусто | *ListForm/*ChoiceForm (ссылка на форму) |
+| `standardAttributes` | (блок всегда) | `""` — opt-out: подавить all-default блок стандартных реквизитов (Order/Ref); ~14% перечислений его опускают, правило не выводимо |
-Других настраиваемых свойств нет — все дефолтные.
+**Значения (`values`)** — массив, каждый элемент строка ЛИБО объект:
+- строка `"Имя"` → значение с авто-синонимом из имени (Split-CamelCase);
+- объект `{ "name": "Имя", "synonym"?, "comment"? }`, где `synonym` — строка ИЛИ `{ru, en}` (мультиязычный),
+ либо `""` для явно пустого синонима (когда авто-синоним из имени неуместен).
+
+Пример:
+```json
+{ "type": "Enum", "name": "СтатусыОбработки", "comment": "(Демо)",
+ "useStandardCommands": true, "choiceMode": "QuickChoice",
+ "listPresentation": { "ru": "Статусы обработки", "en": "Processing statuses" },
+ "standardAttributes": "",
+ "values": [
+ { "name": "Новый", "synonym": { "ru": "Новый", "en": "New" }, "comment": "начальный статус" },
+ { "name": "ВРаботе", "synonym": "" },
+ "Завершен"
+ ] }
+```
### 7.4 Constant
diff --git a/tests/skills/cases/meta-compile/enum-full.json b/tests/skills/cases/meta-compile/enum-full.json
new file mode 100644
index 00000000..86a331ba
--- /dev/null
+++ b/tests/skills/cases/meta-compile/enum-full.json
@@ -0,0 +1,21 @@
+{
+ "name": "Перечисление — полный набор возможностей",
+ "input": {
+ "type": "Enum",
+ "name": "СтатусыОбработки",
+ "comment": "(Демо)",
+ "useStandardCommands": true,
+ "choiceMode": "QuickChoice",
+ "listPresentation": { "ru": "Статусы обработки", "en": "Processing statuses" },
+ "standardAttributes": "",
+ "values": [
+ { "name": "Новый", "synonym": { "ru": "Новый", "en": "New" }, "comment": "начальный статус" },
+ { "name": "ВРаботе", "synonym": "" },
+ "Завершен"
+ ]
+ },
+ "validatePath": "Enums/СтатусыОбработки",
+ "expect": {
+ "files": ["Enums/СтатусыОбработки.xml"]
+ }
+}
diff --git a/tests/skills/cases/meta-compile/snapshots/enum-full/Configuration.xml b/tests/skills/cases/meta-compile/snapshots/enum-full/Configuration.xml
new file mode 100644
index 00000000..0622c795
--- /dev/null
+++ b/tests/skills/cases/meta-compile/snapshots/enum-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/enum-full/Enums/СтатусыОбработки.xml b/tests/skills/cases/meta-compile/snapshots/enum-full/Enums/СтатусыОбработки.xml
new file mode 100644
index 00000000..be900ace
--- /dev/null
+++ b/tests/skills/cases/meta-compile/snapshots/enum-full/Enums/СтатусыОбработки.xml
@@ -0,0 +1,87 @@
+
+
+
+
+
+ UUID-002
+ UUID-003
+
+
+ UUID-004
+ UUID-005
+
+
+ UUID-006
+ UUID-007
+
+
+
+ СтатусыОбработки
+
+
+ ru
+ Статусы обработки
+
+
+ (Демо)
+ true
+
+ true
+ QuickChoice
+
+
+
+
+
+
+ ru
+ Статусы обработки
+
+
+ en
+ Processing statuses
+
+
+
+
+ Auto
+
+
+
+
+ Новый
+
+
+ ru
+ Новый
+
+
+ en
+ New
+
+
+ начальный статус
+
+
+
+
+ ВРаботе
+
+
+
+
+
+
+ Завершен
+
+
+ ru
+ Завершен
+
+
+
+
+
+
+
+
diff --git a/tests/skills/cases/meta-compile/snapshots/enum-full/Enums/СтатусыОбработки/Ext/ManagerModule.bsl b/tests/skills/cases/meta-compile/snapshots/enum-full/Enums/СтатусыОбработки/Ext/ManagerModule.bsl
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/skills/cases/meta-compile/snapshots/enum-full/Ext/ClientApplicationInterface.xml b/tests/skills/cases/meta-compile/snapshots/enum-full/Ext/ClientApplicationInterface.xml
new file mode 100644
index 00000000..3c1161b2
--- /dev/null
+++ b/tests/skills/cases/meta-compile/snapshots/enum-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/enum-full/Languages/Русский.xml b/tests/skills/cases/meta-compile/snapshots/enum-full/Languages/Русский.xml
new file mode 100644
index 00000000..37c60d78
--- /dev/null
+++ b/tests/skills/cases/meta-compile/snapshots/enum-full/Languages/Русский.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ Русский
+
+
+ ru
+ Русский
+
+
+
+ ru
+
+
+
\ No newline at end of file