feat(form-decompile,form-compile): доступ по ролям — userVisible/view/edit/use (единый xr-механизм)

Кластер «доступ по ролям»: единый role-adjustable boolean платформы
(xr:Common + 0..N xr:Value name="Role.X") для четырёх владельцев одним
грамматиком значения:
  - элемент   → userVisible  (<UserVisible>)
  - реквизит  → view, edit    (<View>/<Edit>)
  - команда   → use           (<Use>)

Значение DSL: скаляр false/true → голый <xr:Common>; объект
{ common, roles:{ Имя: bool } } → пер-ролевые исключения (три-state как в
конфигураторе: роль не указана → наследует common; указана → явный bool).
Имя роли forgiving: без префикса / Role. / Роль. → нормализуется в Role.
Отсутствие ключа = полный доступ (платформа тег не пишет) — дефолт не эмитим.

Декомпилятор инвертирует: голый Common → скаляр, есть Value → объект.
Компилятор: общий хелпер Emit-XrFlag / emit_xr_flag (ps1+py).
Порядок схемы: View → Edit после MainAttribute; Use после ToolTip до Action.

Раньше: userVisible умел только голый false (компилятор), декомпилятор не
захватывал ничего; view/edit/use не умел никто.

TOTAL diff lines выборки 2.17: 7911 → 7560 (-351), match 9 → 11.
Снапшоты attributes-types/commands сертифицированы в 1С (8.3.24);
регресс form-compile 33/33 зелёный на ps + python.
decompile v0.28, compile v1.47.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-06 20:40:01 +03:00
parent f34993b805
commit d484a5b7ec
8 changed files with 151 additions and 16 deletions
@@ -17,14 +17,14 @@
"title": "Разные типы",
"elements": [
{ "input": "Строка", "path": "Строка" },
{ "input": "Число", "path": "Число" },
{ "input": "Число", "path": "Число", "userVisible": false },
{ "input": "Дата", "path": "Дата" },
{ "input": "Булево", "path": "Булево" }
],
"attributes": [
{ "name": "Объект", "type": "DataProcessorObject.Типы", "main": true },
{ "name": "Строка", "type": "string(200)" },
{ "name": "Число", "type": "decimal(10,0,nonneg)" },
{ "name": "Строка", "type": "string(200)", "view": false },
{ "name": "Число", "type": "decimal(10,0,nonneg)", "edit": false },
{ "name": "Дата", "type": "dateTime" },
{ "name": "Булево", "type": "boolean" }
]
@@ -27,7 +27,7 @@
{ "name": "Результат", "type": "string" }
],
"commands": [
{ "name": "Выполнить", "action": "ВыполнитьОбработка", "shortcut": "Ctrl+Enter" }
{ "name": "Выполнить", "action": "ВыполнитьОбработка", "shortcut": "Ctrl+Enter", "use": false }
]
}
}
@@ -16,6 +16,9 @@
</InputField>
<InputField name="Число" id="4">
<DataPath>Число</DataPath>
<UserVisible>
<xr:Common>false</xr:Common>
</UserVisible>
<ContextMenu name="ЧислоКонтекстноеМеню" id="5"/>
<ExtendedTooltip name="ЧислоРасширеннаяПодсказка" id="6"/>
</InputField>
@@ -51,6 +54,9 @@
<v8:AllowedLength>Variable</v8:AllowedLength>
</v8:StringQualifiers>
</Type>
<View>
<xr:Common>false</xr:Common>
</View>
</Attribute>
<Attribute name="Число" id="15">
<Title>
@@ -67,6 +73,9 @@
<v8:AllowedSign>Nonnegative</v8:AllowedSign>
</v8:NumberQualifiers>
</Type>
<Edit>
<xr:Common>false</xr:Common>
</Edit>
</Attribute>
<Attribute name="Дата" id="16">
<Title>
@@ -68,6 +68,9 @@
<v8:content>Выполнить</v8:content>
</v8:item>
</Title>
<Use>
<xr:Common>false</xr:Common>
</Use>
<Action>ВыполнитьОбработка</Action>
<Shortcut>Ctrl+Enter</Shortcut>
</Command>