From 387f10edf08d09771d6260e54c95adf0d8550433 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sat, 25 Jul 2026 14:27:14 +0300 Subject: [PATCH] =?UTF-8?q?feat(meta-validate):=20=D0=BF=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D0=BA=D0=B0=20=D1=84=D0=BE=D1=80=D0=BC=D1=8B=20MDO?= =?UTF-8?q?bjectRef-=D1=81=D1=81=D1=8B=D0=BB=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Значения xsi:type="xr:MDObjectRef" не проверялись вообще. Ошибка «тип ссылки вместо объекта метаданных» обнаруживалась только платформой при загрузке («Неизвестный объект метаданных»), причём в логе, а не в коде возврата. Проверка 17 по первому сегменту пути (переиспользован $validTypes + $structuralOnlyTypes): - сегмент оканчивается на Ref → Error: вида метаданных с таким именем не существует, ссылка гарантированно нерабочая; в тексте подсказана исправленная форма; - неизвестный сегмент без Ref → Warn (список видов может быть неполон). Ловит дефект статически, без платформы, независимо от происхождения файла. Кейс error-mdobjectref-type-form + фикстура. Регресс 23/23 ps1+py. Co-Authored-By: Claude Opus 5 (1M context) --- .../meta-validate/scripts/meta-validate.ps1 | 32 ++++++- .../meta-validate/scripts/meta-validate.py | 32 ++++++- .../error-mdobjectref-type-form.json | 9 ++ .../Catalogs/ДоговорыТест.xml | 93 +++++++++++++++++++ 4 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 tests/skills/cases/meta-validate/error-mdobjectref-type-form.json create mode 100644 tests/skills/cases/meta-validate/fixtures/catalog-bad-mdobjectref/Catalogs/ДоговорыТест.xml diff --git a/.claude/skills/meta-validate/scripts/meta-validate.ps1 b/.claude/skills/meta-validate/scripts/meta-validate.ps1 index 24aab602..55809ee8 100644 --- a/.claude/skills/meta-validate/scripts/meta-validate.ps1 +++ b/.claude/skills/meta-validate/scripts/meta-validate.ps1 @@ -1,4 +1,4 @@ -# meta-validate v1.10 — Validate 1C metadata object structure (+корневой : скаляр без структуры = ошибка) +# meta-validate v1.11 — Validate 1C metadata object structure (+корневой : скаляр без структуры = ошибка) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -1493,6 +1493,36 @@ if ($script:configDir) { } } +# --- Check 17: MDObjectRef form — ссылка должна указывать на ОБЪЕКТ метаданных, а не на тип ссылки --- +# Owners/BasedOn/RegisterRecords/RegisteredDocuments/References содержат путь вида "Catalog.Валюты". +# "CatalogRef.Валюты" — частая ошибка (тип ссылки вместо объекта): платформа отвечает +# «Неизвестный объект метаданных». Вида метаданных, оканчивающегося на Ref, не существует → ERROR. +# Неизвестный первый сегмент без Ref — только WARN (список видов может быть неполон). + +$mdRefNodes = $xmlDoc.SelectNodes("//*[@xsi:type='xr:MDObjectRef']", $ns) +if ($mdRefNodes -and $mdRefNodes.Count -gt 0) { + $knownRoots = @($validTypes) + @($structuralOnlyTypes) + $badRefForm = @{} # значение -> $true (ссылочная форма, гарантированно нерабочая) + $unknownRoot = @{} # значение -> корень + foreach ($rn in $mdRefNodes) { + $rv = $rn.InnerText.Trim() + if (-not $rv) { continue } + $root = $rv.Split('.')[0] + if ($knownRoots -ccontains $root) { continue } + if ($root -cmatch 'Ref$') { $badRefForm[$rv] = $true } else { $unknownRoot[$rv] = $root } + } + foreach ($bk in ($badRefForm.Keys | Sort-Object)) { + $fixed = $bk -replace '^([A-Za-z]+)Ref\.', '$1.' + Report-Error "17. MDObjectRef '$bk' — ссылка на ТИП, а не на объект метаданных; нужно '$fixed' (иначе «Неизвестный объект метаданных» при загрузке)" + } + foreach ($uk in ($unknownRoot.Keys | Sort-Object)) { + Report-Warn "17. MDObjectRef '$uk' — неизвестный вид метаданных '$($unknownRoot[$uk])' (опечатка?)" + } + if ($badRefForm.Count -eq 0 -and $unknownRoot.Count -eq 0) { + Report-OK "17. MDObjectRef form: $($mdRefNodes.Count) checked" + } +} + # --- Final output --- & $finalize diff --git a/.claude/skills/meta-validate/scripts/meta-validate.py b/.claude/skills/meta-validate/scripts/meta-validate.py index f1543834..994e423a 100644 --- a/.claude/skills/meta-validate/scripts/meta-validate.py +++ b/.claude/skills/meta-validate/scripts/meta-validate.py @@ -1,4 +1,4 @@ -# meta-validate v1.10 — Validate 1C metadata object structure (Python port) (+корневой : скаляр без структуры = ошибка) +# meta-validate v1.11 — Validate 1C metadata object structure (Python port) (+корневой : скаляр без структуры = ошибка) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os @@ -1395,6 +1395,36 @@ if config_dir: elif checked_refs: report_ok(f"16. Reference types: {len(checked_refs)} resolved") +# ── Check 17: MDObjectRef form — ссылка на ОБЪЕКТ метаданных, а не на тип ссылки ── +# Owners/BasedOn/RegisterRecords/RegisteredDocuments/References содержат путь вида "Catalog.Валюты". +# "CatalogRef.Валюты" — частая ошибка (тип ссылки вместо объекта): платформа отвечает +# «Неизвестный объект метаданных». Вида метаданных, оканчивающегося на Ref, не существует → ERROR. +# Неизвестный первый сегмент без Ref — только WARN (список видов может быть неполон). + +md_ref_nodes = find_all(root, "//*[@xsi:type='xr:MDObjectRef']") +if md_ref_nodes: + known_roots = tuple(valid_types) + tuple(structural_only_types) + bad_ref_form = {} # значение -> True (ссылочная форма, гарантированно нерабочая) + unknown_root = {} # значение -> корень + for rn in md_ref_nodes: + rv = inner_text(rn).strip() + if not rv: + continue + rroot = rv.split('.')[0] + if rroot in known_roots: + continue + if rroot.endswith('Ref'): + bad_ref_form[rv] = True + else: + unknown_root[rv] = rroot + for bk in sorted(bad_ref_form): + fixed = re.sub(r'^([A-Za-z]+)Ref\.', r'\1.', bk) + report_error(f"17. MDObjectRef '{bk}' — ссылка на ТИП, а не на объект метаданных; нужно '{fixed}' (иначе «Неизвестный объект метаданных» при загрузке)") + for uk in sorted(unknown_root): + report_warn(f"17. MDObjectRef '{uk}' — неизвестный вид метаданных '{unknown_root[uk]}' (опечатка?)") + if not bad_ref_form and not unknown_root: + report_ok(f"17. MDObjectRef form: {len(md_ref_nodes)} checked") + # ── Final output ────────────────────────────────────────────── finalize() diff --git a/tests/skills/cases/meta-validate/error-mdobjectref-type-form.json b/tests/skills/cases/meta-validate/error-mdobjectref-type-form.json new file mode 100644 index 00000000..aa9af28e --- /dev/null +++ b/tests/skills/cases/meta-validate/error-mdobjectref-type-form.json @@ -0,0 +1,9 @@ +{ + "name": "Валидатор находит ошибку: MDObjectRef указывает на тип ссылки вместо объекта метаданных", + "setup": "fixture:catalog-bad-mdobjectref", + "params": { "objectPath": "Catalogs/ДоговорыТест.xml" }, + "expectError": true, + "expect": { + "stdoutContains": "17. MDObjectRef 'CatalogRef.ВалютыТест'" + } +} diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-bad-mdobjectref/Catalogs/ДоговорыТест.xml b/tests/skills/cases/meta-validate/fixtures/catalog-bad-mdobjectref/Catalogs/ДоговорыТест.xml new file mode 100644 index 00000000..aa058e7f --- /dev/null +++ b/tests/skills/cases/meta-validate/fixtures/catalog-bad-mdobjectref/Catalogs/ДоговорыТест.xml @@ -0,0 +1,93 @@ + + + + + + 6baeb62e-97e6-4499-8b70-f3d01537550d + dddc4ad4-26bd-4419-a730-e52dfd769001 + + + 9d21e0de-25b7-4795-bf56-3b4079d934fc + 6ec351b4-1c1c-4302-b418-8bee2278fe53 + + + 0f6c64e1-d4a2-44c4-beb5-fd1a0c677430 + b8f0c243-2e1a-4fd2-95bd-5cb3ede085ea + + + ebf66c45-7189-483a-9735-69649a113dd7 + cf1b1818-49d8-4dc4-890f-7a08289522e2 + + + 826f6ff2-e21e-4872-a142-23aeab5ffe30 + 98a2519d-35ec-452e-84b6-0717bdcec784 + + + + ДоговорыТест + + + ru + Договоры тест + + + + false + HierarchyOfItems + false + 2 + true + true + + CatalogRef.ВалютыТест + + ToItems + 9 + 25 + String + Variable + WholeCatalog + false + true + AsDescription + + Auto + InDialog + false + BothWays + + Catalog.ДоговорыТест.StandardAttribute.Description + Catalog.ДоговорыТест.StandardAttribute.Code + + Begin + DontUse + Directly + + + + + + + + + + + false + + + Managed + Use + + + + + + Use + Auto + DontUse + false + false + + + +