fix(form-compile,form-decompile): ManualQuery=false при наличии QueryText (отклонение эвристики)

Компилятор форсил <ManualQuery>true</ManualQuery> всегда при наличии query (hasQuery →
true). Но платформа изредка хранит QueryText при ManualQuery=false (корпус: 16 форм
query+mainTable+manualQuery=false, против 2447 query+manualQuery=true) — список с
сохранённым авто-запросом, но не в «ручном» режиме.

Декомпилятор: фиксирует manualQuery ТОЛЬКО при отклонении от эвристики hasQuery
(query есть, но ManualQuery=false → settings.manualQuery=false). Компилятор: явный ключ
manualQuery (в т.ч. false) ПОБЕЖДАЕТ эвристику; различает present-false от absent
(раньше $st.manualQuery -eq $true трактовал явный false как absent → forced true). Зеркало py.

Выборка 16 форм (ОснованияЛьготПоИмущественнымНалогам/ФормаВыбора, … acc+erp):
match 0→16, TOTAL→0. ps1==py байт-в-байт. Регресс 43/43. Spec обновлён.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-13 14:25:55 +03:00
parent 8eedca4c22
commit 8465bbc82e
4 changed files with 20 additions and 7 deletions
@@ -1,4 +1,4 @@
# form-compile v1.156 — Compile 1C managed form from JSON or object metadata
# form-compile v1.157 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[string]$JsonPath,
@@ -5682,7 +5682,10 @@ function Emit-Attributes {
# AutoFillAvailableFields — дефолт true; эмитим только при заданном ключе (отклонение).
if ($null -ne $st.autoFillAvailableFields) { X "$si<AutoFillAvailableFields>$(if ($st.autoFillAvailableFields){'true'}else{'false'})</AutoFillAvailableFields>" }
$hasQuery = $st.query -and "$($st.query)".Trim()
$mq = if ($hasQuery -or $st.manualQuery -eq $true) { "true" } else { "false" }
# Явный ключ manualQuery (в т.ч. false) ПОБЕЖДАЕТ эвристику hasQuery (платформа изредка
# хранит QueryText при ManualQuery=false — декомпилятор фиксирует это отклонение).
$hasMQKey = ($st.PSObject.Properties['manualQuery']) -and ($null -ne $st.manualQuery)
$mq = if ($hasMQKey) { if ($st.manualQuery) { "true" } else { "false" } } elseif ($hasQuery) { "true" } else { "false" }
X "$si<ManualQuery>$mq</ManualQuery>"
# DynamicDataRead: дефолт true; false только при явном отключении
$ddr = if ($st.dynamicDataRead -eq $false) { "false" } else { "true" }
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# form-compile v1.156 — Compile 1C managed form from JSON or object metadata
# form-compile v1.157 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import copy
@@ -5438,7 +5438,12 @@ def emit_attributes(lines, attrs, indent, conditional_appearance=None):
lines.append(f'{si}<AutoFillAvailableFields>{"true" if s["autoFillAvailableFields"] else "false"}</AutoFillAvailableFields>')
# Порядок платформы: ManualQuery, DynamicDataRead, QueryText, Field*, MainTable, ListSettings
has_query = bool(s.get('query') and str(s['query']).strip())
mq = 'true' if (has_query or s.get('manualQuery')) else 'false'
# Явный ключ manualQuery (в т.ч. False) ПОБЕЖДАЕТ эвристику has_query (платформа изредка
# хранит QueryText при ManualQuery=false — декомпилятор фиксирует отклонение).
if s.get('manualQuery') is not None:
mq = 'true' if s['manualQuery'] else 'false'
else:
mq = 'true' if has_query else 'false'
lines.append(f'{si}<ManualQuery>{mq}</ManualQuery>')
# DynamicDataRead: дефолт true; false только при явном отключении
ddr = 'false' if s.get('dynamicDataRead') is False else 'true'
@@ -1,4 +1,4 @@
# form-decompile v0.131 — Decompile 1C managed Form.xml to JSON DSL (draft)
# form-decompile v0.132 — Decompile 1C managed Form.xml to JSON DSL (draft)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
param(
@@ -2722,7 +2722,12 @@ if ($attrsNode) {
# дефолт true → платформа эмитит отклонение). Захват факт. значения.
$asus = Get-Child $setNode 'AutoSaveUserSettings'; if ($null -ne $asus) { $so['autoSaveUserSettings'] = ($asus -eq 'true') }
$qtNode = $setNode.SelectSingleNode("lf:QueryText", $ns)
if ($qtNode -and $qtNode.InnerText) { $so['query'] = Maybe-ExternalizeQuery -queryText $qtNode.InnerText -listName "$($ao['name'])" }
$hasQ = [bool]($qtNode -and $qtNode.InnerText)
if ($hasQ) { $so['query'] = Maybe-ExternalizeQuery -queryText $qtNode.InnerText -listName "$($ao['name'])" }
# ManualQuery: компилятор выводит из наличия query (hasQuery → true). Платформа в редких
# случаях (корпус 16) хранит QueryText при ManualQuery=false → фиксируем отклонение от эвристики.
$mqV = Get-Child $setNode 'ManualQuery'
if ($null -ne $mqV) { $mqActual = ($mqV -eq 'true'); if ($mqActual -ne $hasQ) { $so['manualQuery'] = $mqActual } }
# DynamicDataRead: дефолт true → эмитим только false
if ((Get-Child $setNode 'DynamicDataRead') -eq 'false') { $so['dynamicDataRead'] = $false }
# Явные поля набора (редко, ~4.5%) — захват только при наличии Field
+1 -1
View File
@@ -956,7 +956,7 @@ Forgiving-синонимы типа: XML-имя (`SpreadSheetDocumentField`) и
| `conditionalAppearance` | array | Условное оформление списка (грамматика как в СКД) |
| `grouping` | string \| array | Группировка строк списка (см. ниже). Forgiving-синонимы: `structure`, `группировка` |
`ManualQuery` выводится из наличия `query` — отдельным ключом не задаётся.
`ManualQuery` выводится из наличия `query` (есть `query``true`). Редкое отклонение — список с `query`, но `ManualQuery=false` (корпус 16): ключ `manualQuery: false` побеждает эвристику (декомпилятор ставит его только при таком отклонении).
Пустой блок настроек компоновщика (`ListSettings`) генерируется автоматически (каноничный полный скелет платформы — filter+order+conditionalAppearance+itemsViewMode+itemsUserSettingID, ~93% форм); указывать ничего не нужно.