feat(form-decompile,form-compile): параметры выбора / связи параметров выбора / связь по типу (кластер ChoiceParameters)

Покрытие трёх конструкций поля ввода (InputField), массовых в корпусе
(ChoiceParameters 844 / ChoiceParameterLinks 685 / TypeLink 84 файлов):

- choiceParameters: [{name, value}] — параметры выбора. value через общий
  Normalize-ChoiceValue (bool/число/строка/ref-путь + синонимы Перечисление./
  Справочник.); массив значений → v8:FixedArray. Presentation всегда пустой.
- choiceParameterLinks: [{name, dataPath, valueChange?}] — связи параметров
  выбора. valueChange дефолт Clear (опускается декомпилятором), forgiving
  Clear/DontChange + рус.синонимы. DataPath xsi:type=xs:string.
- typeLink: {dataPath, linkItem} — связь по типу. linkItem дефолт 0.

Декомпилятор: регистрация app namespace; инверсные хелперы (FixedArray →
массив, дефолт Clear опускается). Компилятор ps1 + зеркало py (байт-в-байт).
Spec: секция в #### input. Тест-кейс input-fields расширен полем со всеми
тремя конструкциями; round-trip бит-в-бит на 3 реальных формах; снэпшот
сертифицирован загрузкой в 1С 8.3.24.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-07 21:59:26 +03:00
parent d88859580f
commit 0397d8f37e
6 changed files with 404 additions and 25 deletions
@@ -26,6 +26,18 @@
{ "value": "Второй", "presentation": "Второй вариант" }
]},
{ "input": "ПолеПодсказка", "path": "ПолеПодсказка", "inputHint": "Введите значение...", "title": "Подсказка" },
{ "input": "ПолеСвязи", "path": "ПолеСвязи", "title": "Поле со связями",
"choiceParameters": [
{ "name": "Отбор.Активный", "value": true },
{ "name": "Отбор.Вид", "value": "Основной" },
{ "name": "Отбор.Список", "value": ["Один", "Два"] }
],
"choiceParameterLinks": [
{ "name": "Отбор.Организация", "dataPath": "ОбычноеПоле" },
{ "name": "Отбор.Тип", "dataPath": "ПолеСписокВыбора", "valueChange": "DontChange" }
],
"typeLink": { "dataPath": "ПолеПодсказка", "linkItem": 0 }
},
{ "check": "Флаг", "path": "Флаг", "title": "Включено" },
{ "check": "ФлагПлатформенный", "path": "ФлагПлатформенный", "title": "Слева", "titleLocation": "" },
{ "check": "ФлагЯвный", "path": "ФлагЯвный", "title": "Сверху", "titleLocation": "top" },
@@ -39,6 +51,7 @@
{ "name": "ПолеСКнопками", "type": "string" },
{ "name": "ПолеСписокВыбора", "type": "string" },
{ "name": "ПолеПодсказка", "type": "string" },
{ "name": "ПолеСвязи", "type": "string" },
{ "name": "Флаг", "type": "boolean" },
{ "name": "ФлагПлатформенный", "type": "boolean" },
{ "name": "ФлагЯвный", "type": "boolean" },
@@ -138,7 +138,63 @@
<ContextMenu name="ПолеПодсказкаКонтекстноеМеню" id="20"/>
<ExtendedTooltip name="ПолеПодсказкаРасширеннаяПодсказка" id="21"/>
</InputField>
<CheckBoxField name="Флаг" id="22">
<InputField name="ПолеСвязи" id="22">
<DataPath>ПолеСвязи</DataPath>
<Title>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Поле со связями</v8:content>
</v8:item>
</Title>
<TypeLink>
<xr:DataPath>ПолеПодсказка</xr:DataPath>
<xr:LinkItem>0</xr:LinkItem>
</TypeLink>
<ChoiceParameterLinks>
<xr:Link>
<xr:Name>Отбор.Организация</xr:Name>
<xr:DataPath xsi:type="xs:string">ОбычноеПоле</xr:DataPath>
<xr:ValueChange>Clear</xr:ValueChange>
</xr:Link>
<xr:Link>
<xr:Name>Отбор.Тип</xr:Name>
<xr:DataPath xsi:type="xs:string">ПолеСписокВыбора</xr:DataPath>
<xr:ValueChange>DontChange</xr:ValueChange>
</xr:Link>
</ChoiceParameterLinks>
<ChoiceParameters>
<app:item name="Отбор.Активный">
<app:value xsi:type="FormChoiceListDesTimeValue">
<Presentation/>
<Value xsi:type="xs:boolean">true</Value>
</app:value>
</app:item>
<app:item name="Отбор.Вид">
<app:value xsi:type="FormChoiceListDesTimeValue">
<Presentation/>
<Value xsi:type="xs:string">Основной</Value>
</app:value>
</app:item>
<app:item name="Отбор.Список">
<app:value xsi:type="FormChoiceListDesTimeValue">
<Presentation/>
<Value xsi:type="v8:FixedArray">
<v8:Value xsi:type="FormChoiceListDesTimeValue">
<Presentation/>
<Value xsi:type="xs:string">Один</Value>
</v8:Value>
<v8:Value xsi:type="FormChoiceListDesTimeValue">
<Presentation/>
<Value xsi:type="xs:string">Два</Value>
</v8:Value>
</Value>
</app:value>
</app:item>
</ChoiceParameters>
<ContextMenu name="ПолеСвязиКонтекстноеМеню" id="23"/>
<ExtendedTooltip name="ПолеСвязиРасширеннаяПодсказка" id="24"/>
</InputField>
<CheckBoxField name="Флаг" id="25">
<DataPath>Флаг</DataPath>
<Title>
<v8:item>
@@ -148,10 +204,10 @@
</Title>
<CheckBoxType>Auto</CheckBoxType>
<TitleLocation>Right</TitleLocation>
<ContextMenu name="ФлагКонтекстноеМеню" id="23"/>
<ExtendedTooltip name="ФлагРасширеннаяПодсказка" id="24"/>
<ContextMenu name="ФлагКонтекстноеМеню" id="26"/>
<ExtendedTooltip name="ФлагРасширеннаяПодсказка" id="27"/>
</CheckBoxField>
<CheckBoxField name="ФлагПлатформенный" id="25">
<CheckBoxField name="ФлагПлатформенный" id="28">
<DataPath>ФлагПлатформенный</DataPath>
<Title>
<v8:item>
@@ -160,10 +216,10 @@
</v8:item>
</Title>
<CheckBoxType>Auto</CheckBoxType>
<ContextMenu name="ФлагПлатформенныйКонтекстноеМеню" id="26"/>
<ExtendedTooltip name="ФлагПлатформенныйРасширеннаяПодсказка" id="27"/>
<ContextMenu name="ФлагПлатформенныйКонтекстноеМеню" id="29"/>
<ExtendedTooltip name="ФлагПлатформенныйРасширеннаяПодсказка" id="30"/>
</CheckBoxField>
<CheckBoxField name="ФлагЯвный" id="28">
<CheckBoxField name="ФлагЯвный" id="31">
<DataPath>ФлагЯвный</DataPath>
<Title>
<v8:item>
@@ -173,10 +229,10 @@
</Title>
<CheckBoxType>Auto</CheckBoxType>
<TitleLocation>Top</TitleLocation>
<ContextMenu name="ФлагЯвныйКонтекстноеМеню" id="29"/>
<ExtendedTooltip name="ФлагЯвныйРасширеннаяПодсказка" id="30"/>
<ContextMenu name="ФлагЯвныйКонтекстноеМеню" id="32"/>
<ExtendedTooltip name="ФлагЯвныйРасширеннаяПодсказка" id="33"/>
</CheckBoxField>
<CheckBoxField name="ФлагТумблер" id="31">
<CheckBoxField name="ФлагТумблер" id="34">
<DataPath>ФлагТумблер</DataPath>
<Title>
<v8:item>
@@ -186,18 +242,18 @@
</Title>
<CheckBoxType>Switcher</CheckBoxType>
<TitleLocation>Right</TitleLocation>
<ContextMenu name="ФлагТумблерКонтекстноеМеню" id="32"/>
<ExtendedTooltip name="ФлагТумблерРасширеннаяПодсказка" id="33"/>
<ContextMenu name="ФлагТумблерКонтекстноеМеню" id="35"/>
<ExtendedTooltip name="ФлагТумблерРасширеннаяПодсказка" id="36"/>
</CheckBoxField>
</ChildItems>
<Attributes>
<Attribute name="Объект" id="34">
<Attribute name="Объект" id="37">
<Type>
<v8:Type>cfg:DataProcessorObject.ПоляВвода</v8:Type>
</Type>
<MainAttribute>true</MainAttribute>
</Attribute>
<Attribute name="ОбычноеПоле" id="35">
<Attribute name="ОбычноеПоле" id="38">
<Title>
<v8:item>
<v8:lang>ru</v8:lang>
@@ -212,7 +268,7 @@
</v8:StringQualifiers>
</Type>
</Attribute>
<Attribute name="МногострочноеПоле" id="36">
<Attribute name="МногострочноеПоле" id="39">
<Title>
<v8:item>
<v8:lang>ru</v8:lang>
@@ -227,7 +283,7 @@
</v8:StringQualifiers>
</Type>
</Attribute>
<Attribute name="ПолеПароля" id="37">
<Attribute name="ПолеПароля" id="40">
<Title>
<v8:item>
<v8:lang>ru</v8:lang>
@@ -242,7 +298,7 @@
</v8:StringQualifiers>
</Type>
</Attribute>
<Attribute name="ПолеСКнопками" id="38">
<Attribute name="ПолеСКнопками" id="41">
<Title>
<v8:item>
<v8:lang>ru</v8:lang>
@@ -257,7 +313,7 @@
</v8:StringQualifiers>
</Type>
</Attribute>
<Attribute name="ПолеСписокВыбора" id="39">
<Attribute name="ПолеСписокВыбора" id="42">
<Title>
<v8:item>
<v8:lang>ru</v8:lang>
@@ -272,7 +328,7 @@
</v8:StringQualifiers>
</Type>
</Attribute>
<Attribute name="ПолеПодсказка" id="40">
<Attribute name="ПолеПодсказка" id="43">
<Title>
<v8:item>
<v8:lang>ru</v8:lang>
@@ -287,7 +343,22 @@
</v8:StringQualifiers>
</Type>
</Attribute>
<Attribute name="Флаг" id="41">
<Attribute name="ПолеСвязи" id="44">
<Title>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Поле связи</v8:content>
</v8:item>
</Title>
<Type>
<v8:Type>xs:string</v8:Type>
<v8:StringQualifiers>
<v8:Length>0</v8:Length>
<v8:AllowedLength>Variable</v8:AllowedLength>
</v8:StringQualifiers>
</Type>
</Attribute>
<Attribute name="Флаг" id="45">
<Title>
<v8:item>
<v8:lang>ru</v8:lang>
@@ -298,7 +369,7 @@
<v8:Type>xs:boolean</v8:Type>
</Type>
</Attribute>
<Attribute name="ФлагПлатформенный" id="42">
<Attribute name="ФлагПлатформенный" id="46">
<Title>
<v8:item>
<v8:lang>ru</v8:lang>
@@ -309,7 +380,7 @@
<v8:Type>xs:boolean</v8:Type>
</Type>
</Attribute>
<Attribute name="ФлагЯвный" id="43">
<Attribute name="ФлагЯвный" id="47">
<Title>
<v8:item>
<v8:lang>ru</v8:lang>
@@ -320,7 +391,7 @@
<v8:Type>xs:boolean</v8:Type>
</Type>
</Attribute>
<Attribute name="ФлагТумблер" id="44">
<Attribute name="ФлагТумблер" id="48">
<Title>
<v8:item>
<v8:lang>ru</v8:lang>