mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-23 21:21:04 +03:00
feat(meta-compile,meta-decompile): предопределённые элементы Catalog (Ext/Predefined.xml) (v1.19/v0.5)
Раундтрип-находка (класс-3, непокрытый блок — крупнейшая категория ~56k). meta-compile вообще не генерил Ext/Predefined.xml. DSL спроектирован по данным корпуса (9309 элементов) + совместно. DSL `predefined` (массив; строка ИЛИ объект): - строка "(Код) Имя [Наименование]": Имя обяз.; Наименование — нет [..] → авто(Split-CamelCase), [] → пусто (системные/placeholder, 29% корпуса), [текст] → задано; - объект (группа/иерархия): name/code/description/isFolder/childItems + рус.синонимы имя/код/наименование/группа/подчиненные (прощающий ввод). - Код: по codeType каталога (Number→xs:decimal, String→без типа), пусто→<Code/>. meta-compile (дуал-порт): генерация Ext/Predefined.xml (root CatalogPredefinedItems + рекурсия Item). Заодно фикс: Esc-XmlText для ТЕКСТА элемента (& < > без экранирования кавычек — в тексте 1С держит raw). meta-decompile: захват predefined → компактный DSL (строка/объект). Фикс PS-ловушки распаковки одноэлементного @() из if → папки с ОДНИМ ребёнком теряли его. spec meta-dsl-spec.md v2.4 §7.1.2; тест-кейс catalog-predefined. Валидация: PS==PY паритет; predefined-категории 0 (PredefinedData/Item/ChildItems/Description/Code); полный прогон −56620 (218537→161917); регресс 36/36 (ps+py); 1С-cert зелёный (грузится в платформу). 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
58bc95264e
commit
253a4fbce0
@@ -1,4 +1,4 @@
|
||||
# meta-decompile v0.4 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
|
||||
# meta-decompile v0.5 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
#
|
||||
# Пилот: только Catalog. Инверс meta-compile (omit-on-default: ключ эмитим только
|
||||
@@ -310,34 +310,51 @@ if ($childObjs) {
|
||||
}
|
||||
}
|
||||
|
||||
# --- Предопределённые (соседний Ext/Predefined.xml). meta-compile пока их НЕ потребляет (пробел DSL).
|
||||
# ⚠️ ЧЕРНОВАЯ/ВРЕМЕННАЯ форма `predefined` — предложение по факту корпуса, НЕ утверждённый DSL.
|
||||
# Правило: непокрытый блок проектируем в DSL СНАЧАЛА (совместно), потом переписываем этот захват под него. ---
|
||||
# --- Предопределённые (соседний Ext/Predefined.xml) → DSL predefined.
|
||||
# Плоский элемент → строка "(Код) Имя [Наименование]" (Наименование: ==авто → опустить; '' → []; иначе [текст]).
|
||||
# Группа/иерархия → object {name, [code], [description], isFolder, childItems}. codeType — из свойства каталога. ---
|
||||
$objDir = Split-Path -Parent (Resolve-Path -LiteralPath $ObjectPath).Path
|
||||
$predefPath = Join-Path (Join-Path (Join-Path $objDir $objName) 'Ext') 'Predefined.xml'
|
||||
if (Test-Path -LiteralPath $predefPath) {
|
||||
$pdoc = New-Object System.Xml.XmlDocument
|
||||
$pdoc.Load($predefPath)
|
||||
function Parse-PredefItem {
|
||||
function PredefItem-ToDsl {
|
||||
param($itemEl)
|
||||
$o = [ordered]@{}
|
||||
$o['name'] = ($itemEl.SelectSingleNode("*[local-name()='Name']")).InnerText
|
||||
$name = ($itemEl.SelectSingleNode("*[local-name()='Name']")).InnerText
|
||||
$codeEl = $itemEl.SelectSingleNode("*[local-name()='Code']")
|
||||
if ($codeEl -and $codeEl.InnerText) { $o['code'] = $codeEl.InnerText }
|
||||
$code = if ($codeEl -and $codeEl.InnerText) { $codeEl.InnerText } else { '' }
|
||||
$descEl = $itemEl.SelectSingleNode("*[local-name()='Description']")
|
||||
if ($descEl -and $descEl.InnerText) { $o['description'] = $descEl.InnerText }
|
||||
$desc = if ($descEl) { $descEl.InnerText } else { '' }
|
||||
$folderEl = $itemEl.SelectSingleNode("*[local-name()='IsFolder']")
|
||||
if ($folderEl -and $folderEl.InnerText -eq 'true') { $o['isFolder'] = $true }
|
||||
$isFolder = ($folderEl -and $folderEl.InnerText -eq 'true')
|
||||
$childContainer = $itemEl.SelectSingleNode("*[local-name()='ChildItems']")
|
||||
if ($childContainer) {
|
||||
$kids = [System.Collections.ArrayList]@()
|
||||
foreach ($k in @($childContainer.SelectNodes("*[local-name()='Item']"))) { [void]$kids.Add((Parse-PredefItem $k)) }
|
||||
if ($kids.Count -gt 0) { $o['children'] = $kids }
|
||||
# ВАЖНО: обернуть весь if в @(), иначе PS распаковывает одноэлементный @(...) из if-блока
|
||||
# обратно в узел → $kids.Count = $null → папки с ОДНИМ ребёнком теряют его.
|
||||
$kids = @(if ($childContainer) { $childContainer.SelectNodes("*[local-name()='Item']") } else { @() })
|
||||
$auto = Split-CamelWords $name
|
||||
|
||||
if (-not $isFolder -and $kids.Count -eq 0) {
|
||||
# Плоский → компактная строка.
|
||||
$s = if ($code) { "($code) $name" } else { $name }
|
||||
if ($desc -eq '') { $s = "$s []" }
|
||||
elseif ($desc -ne $auto) { $s = "$s [$desc]" }
|
||||
return $s
|
||||
}
|
||||
# Группа/иерархия → объект.
|
||||
$o = [ordered]@{ name = $name }
|
||||
if ($code) { $o['code'] = $code }
|
||||
if ($desc -eq '') { $o['description'] = '' }
|
||||
elseif ($desc -ne $auto) { $o['description'] = $desc }
|
||||
if ($isFolder) { $o['isFolder'] = $true }
|
||||
if ($kids.Count -gt 0) {
|
||||
$sub = [System.Collections.ArrayList]@()
|
||||
foreach ($k in $kids) { [void]$sub.Add((PredefItem-ToDsl $k)) }
|
||||
$o['childItems'] = $sub
|
||||
}
|
||||
return $o
|
||||
}
|
||||
$rootItems = [System.Collections.ArrayList]@()
|
||||
foreach ($it in @($pdoc.DocumentElement.SelectNodes("*[local-name()='Item']"))) { [void]$rootItems.Add((Parse-PredefItem $it)) }
|
||||
foreach ($it in @($pdoc.DocumentElement.SelectNodes("*[local-name()='Item']"))) { [void]$rootItems.Add((PredefItem-ToDsl $it)) }
|
||||
if ($rootItems.Count -gt 0) { $dsl['predefined'] = $rootItems }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user