mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-09-05 09:40:52 +03:00
fix(xdto-compile,xdto-info,xdto-edit): правки по итогам прогона на субагентах
Четырём субагентам выданы реалистичные задачи по песочнице, навыки в формулировках не назывались. Разбор — в debug/xdto/FINDINGS.md, §13. ГЛАВНОЕ — дефект компилятора. При уплощении вложенного xs:choice ветки оставались обязательными: схема «самовывоз ИЛИ адрес доставки» давала пакет, требующий заполнить оба, и ни один реальный документ в него не ложился. Компилятор предупреждал о потере выбора, но молчал о последствии, а валидатор показывал «0 ошибок, 0 предупреждений» — структурно пакет корректен, семантически мёртв. Теперь ветки становятся необязательными (единственное уплощение, оставляющее тип заполнимым), предупреждение называет их поимённо. Корневой xs:choice не затронут: он отображается в ordered="false". xdto-edit: -Value "@файл" по конвенции skd-edit — на кавычках при инлайновой передаче XSD споткнулись двое агентов из четырёх, причём сырой LoadXml уводил чинить схему вместо транспорта. При сбое разбора теперь понятное сообщение. xdto-info: поиск, законно ничего не нашедший, падал throw'ом со стектрейсом и читался как поломка инструмента — теперь строка и exit 1. Блок «Создание» покрывал только корневой тип, хотя вся реальная работа в XDTO — вложенные и анонимные типы; добавлены рецепты по факту наличия. Отсутствие раздела «Точки входа» было неоднозначным — теперь явная строка. Новый -RequiredOnly даёт скелет «заполни обязательное»: необязательный объект уходит вместе с поддеревом. По умолчанию выключен — иначе список читался бы как полный. xdto-validate: предупреждение про anyType описывало историю («платформа заменяет при импорте»), хотя в файле уже зафиксирован anyType; сначала состояние, потом происхождение. Проверено: 40 тестов на обоих рантаймах, round-trip 760/760, валидатор 0 ложных срабатываний на корпусе. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
1a1bbbac6f
commit
6486f433de
@@ -493,24 +493,38 @@ function Resolve-Group([System.Xml.XmlElement]$el, [string]$kind) {
|
||||
|
||||
# Модель XDTO знает только плоский список свойств: вложенные частицы уплощаются.
|
||||
# Каждое уплощение — предупреждение, потому что меняется смысл схемы.
|
||||
function Collect-Particle([System.Xml.XmlElement]$particle, $elemList, [ref]$isOpen, [string]$typeName, [int]$depth) {
|
||||
function Collect-Particle([System.Xml.XmlElement]$particle, $elemList, [ref]$isOpen, [string]$typeName, [int]$depth, [bool]$optionalize = $false) {
|
||||
if ($depth -gt 20) { return }
|
||||
foreach ($c in $particle.ChildNodes) {
|
||||
if ($c.NodeType -ne [System.Xml.XmlNodeType]::Element -or $c.NamespaceURI -ne $XS_NS) { continue }
|
||||
switch ($c.get_LocalName()) {
|
||||
"element" { [void]$elemList.Add((Build-Property $c $false)) }
|
||||
"element" {
|
||||
$prop = Build-Property $c $false
|
||||
# Ветка уплощённого xs:choice обязана стать необязательной: иначе
|
||||
# «одно из двух» превращается в «оба сразу», и тип нельзя заполнить
|
||||
if ($optionalize) { Set-AttrValue $prop "lowerBound" "0" }
|
||||
[void]$elemList.Add($prop)
|
||||
}
|
||||
"any" { $isOpen.Value = $true }
|
||||
"sequence" {
|
||||
Warn "$typeName : вложенная xs:sequence уплощена — модель XDTO хранит плоский список свойств"
|
||||
Collect-Particle $c $elemList $isOpen $typeName ($depth + 1)
|
||||
Collect-Particle $c $elemList $isOpen $typeName ($depth + 1) $optionalize
|
||||
}
|
||||
"choice" {
|
||||
Warn "$typeName : вложенная xs:choice уплощена в последовательность — выбор одного из вариантов не сохранён"
|
||||
Collect-Particle $c $elemList $isOpen $typeName ($depth + 1)
|
||||
$branches = @()
|
||||
foreach ($b in $c.ChildNodes) {
|
||||
if ($b.NodeType -eq [System.Xml.XmlNodeType]::Element -and $b.NamespaceURI -eq $XS_NS -and $b.HasAttribute("name")) {
|
||||
$branches += $b.GetAttribute("name")
|
||||
}
|
||||
}
|
||||
$list = if ($branches.Count -gt 0) { " (" + ($branches -join ", ") + ")" } else { "" }
|
||||
Warn ("$typeName : вложенная xs:choice уплощена — ветки$list сделаны необязательными. " +
|
||||
"Выбор одного из вариантов не сохранён: модель не запретит заполнить сразу несколько или ни одного")
|
||||
Collect-Particle $c $elemList $isOpen $typeName ($depth + 1) $true
|
||||
}
|
||||
"all" {
|
||||
Warn "$typeName : xs:all трактуется как последовательность"
|
||||
Collect-Particle $c $elemList $isOpen $typeName ($depth + 1)
|
||||
Collect-Particle $c $elemList $isOpen $typeName ($depth + 1) $optionalize
|
||||
}
|
||||
"group" {
|
||||
$g = Resolve-Group $c "group"
|
||||
@@ -518,7 +532,7 @@ function Collect-Particle([System.Xml.XmlElement]$particle, $elemList, [ref]$isO
|
||||
foreach ($gc in $g.ChildNodes) {
|
||||
if ($gc.NodeType -eq [System.Xml.XmlNodeType]::Element -and $gc.NamespaceURI -eq $XS_NS -and
|
||||
@("sequence", "choice", "all") -contains $gc.get_LocalName()) {
|
||||
Collect-Particle $gc $elemList $isOpen $typeName ($depth + 1)
|
||||
Collect-Particle $gc $elemList $isOpen $typeName ($depth + 1) $optionalize
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -541,7 +541,7 @@ def resolve_group(el, kind):
|
||||
|
||||
# Модель XDTO знает только плоский список свойств: вложенные частицы уплощаются.
|
||||
# Каждое уплощение — предупреждение, потому что меняется смысл схемы.
|
||||
def collect_particle(particle, elem_list, open_flag, type_name, depth):
|
||||
def collect_particle(particle, elem_list, open_flag, type_name, depth, optionalize=False):
|
||||
if depth > 20:
|
||||
return
|
||||
for c in particle:
|
||||
@@ -549,25 +549,35 @@ def collect_particle(particle, elem_list, open_flag, type_name, depth):
|
||||
continue
|
||||
ln = local(c)
|
||||
if ln == "element":
|
||||
elem_list.append(build_property(c, False))
|
||||
prop = build_property(c, False)
|
||||
# Ветка уплощённого xs:choice обязана стать необязательной: иначе
|
||||
# «одно из двух» превращается в «оба сразу», и тип нельзя заполнить
|
||||
if optionalize:
|
||||
set_attr_value(prop, "lowerBound", "0")
|
||||
elem_list.append(prop)
|
||||
elif ln == "any":
|
||||
open_flag[0] = True
|
||||
elif ln == "sequence":
|
||||
warn(type_name + " : вложенная xs:sequence уплощена — модель XDTO хранит плоский список свойств")
|
||||
collect_particle(c, elem_list, open_flag, type_name, depth + 1)
|
||||
collect_particle(c, elem_list, open_flag, type_name, depth + 1, optionalize)
|
||||
elif ln == "choice":
|
||||
warn(type_name + " : вложенная xs:choice уплощена в последовательность — выбор одного из вариантов не сохранён")
|
||||
collect_particle(c, elem_list, open_flag, type_name, depth + 1)
|
||||
branches = [b.get("name") for b in c
|
||||
if isinstance(b.tag, str) and etree.QName(b).namespace == XS_NS and b.get("name")]
|
||||
lst = (" (" + ", ".join(branches) + ")") if branches else ""
|
||||
warn(type_name + " : вложенная xs:choice уплощена — ветки" + lst + " сделаны необязательными. "
|
||||
"Выбор одного из вариантов не сохранён: модель не запретит заполнить "
|
||||
"сразу несколько или ни одного")
|
||||
collect_particle(c, elem_list, open_flag, type_name, depth + 1, True)
|
||||
elif ln == "all":
|
||||
warn(type_name + " : xs:all трактуется как последовательность")
|
||||
collect_particle(c, elem_list, open_flag, type_name, depth + 1)
|
||||
collect_particle(c, elem_list, open_flag, type_name, depth + 1, optionalize)
|
||||
elif ln == "group":
|
||||
g = resolve_group(c, "group")
|
||||
if g is not None:
|
||||
for gc in g:
|
||||
if isinstance(gc.tag, str) and etree.QName(gc).namespace == XS_NS \
|
||||
and local(gc) in ("sequence", "choice", "all"):
|
||||
collect_particle(gc, elem_list, open_flag, type_name, depth + 1)
|
||||
collect_particle(gc, elem_list, open_flag, type_name, depth + 1, optionalize)
|
||||
else:
|
||||
warn(type_name + " : не найдена группа " + str(c.get("ref")) + " — её свойства в пакет не попали")
|
||||
if ln in ("sequence", "choice", "all", "group"):
|
||||
|
||||
Reference in New Issue
Block a user