feat(meta-validate): проверка ссылок на поля таблицы внешнего источника

Свойства таблицы ссылаются на её же поля шестичастным путём
(ExternalDataSource.И.Table.Т.Field.П). Опечатка в имени поля даёт «Неизвестный объект
метаданных» при загрузке, а глазами в таком пути её не видно. Проверка 21 разбирает форму
пути, требует, чтобы таблица в ссылке была той же самой, и чтобы поле существовало —
в сообщении перечисляются имеющиеся поля.

Отдельно: таблица без ключевых полей даёт предупреждение, а не ошибку. Загрузку XML такой
таблицы платформа принимает молча (измерено на 8.3.24.1691), Конфигуратор интерактивно
требует ключ, а рабочие конфигурации без ключей существуют — значит это повод предупредить,
а не отвергнуть.

Закрыты последние пункты плана: раздел про внешние источники в docs/meta-dsl-spec.md
(формой и связями с общими конвенциями, без дублирования таблицы свойств — она живёт
в reference навыка) и кейсы meta-validate, включая негативный.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NBsZA5cr2WFThtgp7i5WVi
This commit is contained in:
Nick Shirokov
2026-09-06 15:35:56 +03:00
co-authored by Claude Opus 5
parent 24cfe6a0a6
commit 89ce1af9fa
18 changed files with 1576 additions and 2 deletions
@@ -1,4 +1,4 @@
# meta-validate v1.26 — Validate 1C metadata object structure
# meta-validate v1.27 — Validate 1C metadata object structure
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
[CmdletBinding(PositionalBinding=$false)]
param(
@@ -1836,6 +1836,60 @@ if (-not $isAdopted) {
}
}
# --- Check 21: таблица внешнего источника — ссылки на поля и наличие ключа ---
# Свойства таблицы ссылаются на её же поля полным путём. Опечатка в имени поля даёт
# «Неизвестный объект метаданных» при загрузке, а найти её глазами в шестичастном пути трудно.
if ($mdType -eq "Table") {
$fieldNames = @{}
if ($childObjNode) {
foreach ($f in $childObjNode.SelectNodes("md:Field/md:Properties/md:Name", $ns)) {
$fieldNames[$f.InnerText] = $true
}
}
$edsRefsChecked = 0
$edsRefsBad = $false
foreach ($spec in @(
@("KeyFields", "xr:Field"), @("InputByString", "xr:Field"), @("DataLockFields", "xr:Field"),
@("PresentationField", $null), @("ParentField", $null), @("DataVersionField", $null))) {
$tag = $spec[0]
$refs = @()
if ($spec[1]) {
foreach ($n in $propsNode.SelectNodes("md:$tag/$($spec[1])", $ns)) { $refs += $n.InnerText }
} else {
$n = $propsNode.SelectSingleNode("md:$tag", $ns)
if ($n -and $n.InnerText) { $refs += $n.InnerText }
}
foreach ($ref in $refs) {
$edsRefsChecked++
$parts = $ref -split '\.'
# Ожидается ExternalDataSource.<Источник>.Table.<Таблица>.Field.<Поле>
if ($parts.Count -ne 6 -or $parts[0] -ne "ExternalDataSource" -or $parts[2] -ne "Table" -or $parts[4] -ne "Field") {
Report-Error "21. $tag '$ref' — ожидается ExternalDataSource.<Источник>.Table.<Таблица>.Field.<Поле>"
$edsRefsBad = $true
continue
}
if ($parts[3] -ne $objName) {
Report-Error "21. $tag '$ref' — ссылка на поле ЧУЖОЙ таблицы (эта: $objName)"
$edsRefsBad = $true
continue
}
if (-not $fieldNames.ContainsKey($parts[5])) {
$known = if ($fieldNames.Count -gt 0) { ($fieldNames.Keys | Sort-Object) -join ", " } else { "полей нет" }
Report-Error "21. $tag '$ref' — поля '$($parts[5])' нет в таблице (есть: $known)"
$edsRefsBad = $true
}
}
}
if ($edsRefsChecked -gt 0 -and -not $edsRefsBad) { Report-OK "21. Field refs: $edsRefsChecked resolved" }
# Ключ: загрузка XML таблицу без ключа принимает (проверено на платформе), а Конфигуратор
# интерактивно требует. Отсюда предупреждение, а не ошибка: рабочие конфигурации без ключа есть.
$keyNodes = @($propsNode.SelectNodes("md:KeyFields/xr:Field", $ns))
if ($keyNodes.Count -eq 0) {
Report-Warn "21. KeyFields пуст — платформа такую таблицу загрузит, но форма записи и набор записей будут недоступны"
}
}
# --- Final output ---
& $finalize