feat(form-decompile,form-compile): presentation элемента CA/фильтра — сохранение формы xs:string vs LocalStringType

Топ-кластер нового baseline (~190 impact). <dcsset:presentation> элемента условного
оформления и групп/сравнений фильтра: платформа хранит ru-only текст и как xs:string
(плоский), и как LocalStringType (мультиязык-обёртка с одним ru). Декомпилятор схлопывал
ru-only LocalStringType в строку (Get-MLText) → компилятор писал xs:string → mismatch.
Плюс компилятор-баг: filter-item presentation эмитился через Emit-MLText (всегда мультиязык
БЕЗ xsi:type), даже для плоской строки.

Фикс:
- Декомпилятор: Get-PresByType — ветвь по xsi:type, сохраняет {lang:text} объект для
  LocalStringType (даже один ru) vs плоскую строку для xs:string. Применён к presentation
  элемента CA (Build-ConditionalAppearance) и фильтра (group + comparison, Build-FilterItem).
- Компилятор (ps1+py): filter-item presentation через by-form Emit-USPresentation/
  emit_us_presentation (строка→xs:string, объект→LocalStringType с xsi:type). CA-item
  presentation компилятор уже эмитил by-form — не трогаем.

Выборка 45 форм с LocalStringType-presentation: presentation-потерь 0, match 27→33,
TOTAL 127→63, регрессий 0 (сверка с baseline). Кейс dynamic-list-form (+CA presentation
{ru} ru-only + filter presentation объект/строка) сертифицирован загрузкой в 1С. Регресс
43/43, ps1==py (общий снэпшот на обоих рантаймах).

baseline после кластера ListSettings/DataSet (A+B+C): match 1869→1975, TOTAL 3495→2557.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-12 20:55:00 +03:00
co-authored by Claude Opus 4.8
parent aa39973ae6
commit abcd5be2b0
6 changed files with 53 additions and 20 deletions
@@ -34,10 +34,10 @@
],
"order": [ "Description", "Code desc" ],
"filter": [ "Артикул = _ @off @user", "Артикул like %тест%", "Description подобно %abc%",
{ "field": "Code", "op": "=", "userSettingID": "auto", "userSettingPresentation": "Код товара" },
{ "field": "Description", "op": "=", "userSettingID": "auto", "userSettingPresentation": { "ru": "Наименование", "en": "Name" } } ],
{ "field": "Code", "op": "=", "userSettingID": "auto", "userSettingPresentation": "Код товара", "presentation": { "ru": "Код равно" } },
{ "field": "Description", "op": "=", "userSettingID": "auto", "userSettingPresentation": { "ru": "Наименование", "en": "Name" }, "presentation": "Имя равно" } ],
"dataParameters": [ "ВыборТовара @off" ],
"conditionalAppearance": [ { "filter": ["Артикул = _"], "appearance": { "ЦветТекста": "web:Red" } } ]
"conditionalAppearance": [ { "filter": ["Артикул = _"], "appearance": { "ЦветТекста": "web:Red" }, "presentation": { "ru": "Выделение пустых" } } ]
} }
],
"elements": [
@@ -210,12 +210,19 @@
<dcsset:item xsi:type="dcsset:FilterItemComparison">
<dcsset:left xsi:type="dcscor:Field">Code</dcsset:left>
<dcsset:comparisonType>Equal</dcsset:comparisonType>
<dcsset:presentation xsi:type="v8:LocalStringType">
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Код равно</v8:content>
</v8:item>
</dcsset:presentation>
<dcsset:userSettingID>UUID-003</dcsset:userSettingID>
<dcsset:userSettingPresentation xsi:type="xs:string">Код товара</dcsset:userSettingPresentation>
</dcsset:item>
<dcsset:item xsi:type="dcsset:FilterItemComparison">
<dcsset:left xsi:type="dcscor:Field">Description</dcsset:left>
<dcsset:comparisonType>Equal</dcsset:comparisonType>
<dcsset:presentation xsi:type="xs:string">Имя равно</dcsset:presentation>
<dcsset:userSettingID>UUID-004</dcsset:userSettingID>
<dcsset:userSettingPresentation xsi:type="v8:LocalStringType">
<v8:item>
@@ -264,6 +271,12 @@
<dcscor:value xsi:type="v8ui:Color">web:Red</dcscor:value>
</dcscor:item>
</dcsset:appearance>
<dcsset:presentation xsi:type="v8:LocalStringType">
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Выделение пустых</v8:content>
</v8:item>
</dcsset:presentation>
</dcsset:item>
<dcsset:viewMode>Normal</dcsset:viewMode>
<dcsset:userSettingID>UUID-007</dcsset:userSettingID>