feat(meta-edit): support composite types via + separator

Build-TypeContentXml / build_type_content_xml now detect " + " in type
string, split into parts and recursively generate separate <v8:Type>
entries with qualifiers for each type. JSON DSL supports type as array.

Also fix reference types to use local xmlns:d5p1 declaration instead of
root-level cfg: prefix — prevents "Неизвестное имя типа" build errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-03-05 11:32:59 +03:00
parent 6958cc558b
commit 4490aeb533
5 changed files with 57 additions and 6 deletions
+3
View File
@@ -81,6 +81,9 @@ Batch через `;;` во всех операциях. Подробный си
# Добавить реквизиты
-Operation add-attribute -Value "Комментарий: Строка(200) ;; Сумма: Число(15,2) | index"
# Составной тип (несколько типов через +)
-Operation add-attribute -Value "Значение: Строка + Число(15,2) + Дата + CatalogRef.Контрагенты"
# Добавить ТЧ с реквизитами
-Operation add-ts -Value "Товары: Ном: CatalogRef.Ном | req, Кол: Число(15,3), Цена: Число(15,2)"
@@ -18,6 +18,20 @@
-Operation add-attribute -Value "Склад: CatalogRef.Склады >> after Организация"
```
## Составные типы
Для реквизитов с несколькими допустимыми типами — разделитель `+`:
```powershell
-Operation add-attribute -Value "Значение: Строка + Число(15,2) + Дата + CatalogRef.Контрагенты"
-Operation add-attribute -Value "Значение: Строка + Число(15,2) | req"
-Operation modify-ts-attribute -Value "Данные.Значение: type=Строка + Число(15,2) + Дата"
```
В JSON DSL — массив в `type`:
```json
{ "name": "Значение", "type": ["Строка", "Число(15,2)", "Дата", "CatalogRef.Контрагенты"] }
```
## add-attribute / add-dimension / add-resource / add-column
```powershell
+13
View File
@@ -120,6 +120,19 @@ powershell.exe -NoProfile -File .claude/skills/meta-edit/scripts/meta-edit.ps1 -
| commands | команды |
| properties | свойства |
## Составные типы
Для полей с несколькими допустимыми типами — массив в `type`:
```json
{ "name": "Значение", "type": ["Строка", "Число(15,2)", "Дата", "CatalogRef.Контрагенты"] }
```
В inline-формате — через `+`:
```
"Значение: Строка + Число(15,2) + Дата + CatalogRef.Контрагенты"
```
## Синонимы типов
`Строка(200)`, `Число(15,2)`, `Булево`, `Дата`, `ДатаВремя`, `ХранилищеЗначения`, `СправочникСсылка.XXX`, `ДокументСсылка.XXX`, `ПеречислениеСсылка.XXX`, `ОпределяемыйТип.XXX`.
+14 -3
View File
@@ -269,6 +269,17 @@ function Build-TypeContentXml {
param([string]$indent, [string]$typeStr)
if (-not $typeStr) { return "" }
# Composite type: "Type1 + Type2 + Type3"
if ($typeStr.Contains(' + ')) {
$parts = $typeStr -split '\s*\+\s*'
$sb = New-Object System.Text.StringBuilder
foreach ($part in $parts) {
$inner = Build-TypeContentXml $indent $part.Trim()
if ($inner) { $sb.AppendLine($inner) | Out-Null }
}
return $sb.ToString().TrimEnd("`r","`n")
}
$typeStr = Resolve-TypeStr $typeStr
$sb = New-Object System.Text.StringBuilder
@@ -342,9 +353,9 @@ function Build-TypeContentXml {
return $sb.ToString().TrimEnd("`r","`n")
}
# Reference types
# Reference types — use local xmlns declaration for 1C compatibility
if ($typeStr -match '^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|ExchangePlanRef|BusinessProcessRef|TaskRef)\.(.+)$') {
$sb.AppendLine("$indent<v8:Type>cfg:$typeStr</v8:Type>") | Out-Null
$sb.AppendLine("$indent<v8:Type xmlns:d5p1=`"http://v8.1c.ru/8.1/data/enterprise/current-config`">d5p1:$typeStr</v8:Type>") | Out-Null
return $sb.ToString().TrimEnd("`r","`n")
}
@@ -624,7 +635,7 @@ function Parse-AttributeShorthand {
$name = "$($val.name)"
$result = @{
name = $name
type = if ($val.type) { "$($val.type)" } else { "" }
type = if ($val.type -is [array]) { ($val.type | ForEach-Object { "$_" }) -join ' + ' } elseif ($val.type) { "$($val.type)" } else { "" }
synonym = if ($val.synonym) { "$($val.synonym)" } else { Split-CamelCase $name }
comment = if ($val.comment) { "$($val.comment)" } else { "" }
flags = @(if ($val.flags) { $val.flags } else { @() })
+13 -3
View File
@@ -188,6 +188,16 @@ def build_type_content_xml(indent, type_str):
if not type_str:
return ""
# Composite type: "Type1 + Type2 + Type3"
if " + " in type_str:
parts = [p.strip() for p in type_str.split("+")]
results = []
for part in parts:
inner = build_type_content_xml(indent, part)
if inner:
results.append(inner)
return "\r\n".join(results)
type_str = resolve_type_str(type_str)
lines = []
@@ -258,14 +268,14 @@ def build_type_content_xml(indent, type_str):
lines.append(f"{indent}<v8:TypeSet>cfg:DefinedType.{dt_name}</v8:TypeSet>")
return "\r\n".join(lines)
# Reference types
# Reference types — use local xmlns declaration for 1C compatibility
m = re.match(
r"^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|"
r"ChartOfCalculationTypesRef|ExchangePlanRef|BusinessProcessRef|TaskRef)\.(.+)$",
type_str,
)
if m:
lines.append(f"{indent}<v8:Type>cfg:{type_str}</v8:Type>")
lines.append(f'{indent}<v8:Type xmlns:d5p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d5p1:{type_str}</v8:Type>')
return "\r\n".join(lines)
# Fallback
@@ -538,7 +548,7 @@ def parse_attribute_shorthand(val):
name = str(val.get("name", ""))
result = {
"name": name,
"type": str(val.get("type", "")),
"type": " + ".join(str(t) for t in val["type"]) if isinstance(val.get("type"), list) else str(val.get("type", "")),
"synonym": str(val.get("synonym", "")) if val.get("synonym") else split_camel_case(name),
"comment": str(val.get("comment", "")),
"flags": list(val.get("flags", [])),