mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-19 09:09:41 +03:00
feat(meta-compile): короткая запись dataPath в linkByType/choiceParameterLinks (v1.23)
dataPath ссылается на реквизит самого объекта — прощающий ввод (компилятор
разворачивает по $objType/$objName):
• стандартный (Ссылка/Ref, Наименование/Description, Владелец/Owner, …) →
<Тип>.<Имя>.StandardAttribute.<EN> (RU→EN);
• обычный (Свойство) → <Тип>.<Имя>.Attribute.Свойство;
• частичное StandardAttribute.X/Attribute.X → +префикс; полный путь → verbatim.
Только компилятор (декомпилятор пишет полный путь) → роундтрип не затронут
(remaining=0 сохраняется). Кейсы choice-params/typeset-linkbytype переведены
на короткую запись (снэпшоты идентичны). Регресс 43/43 ps1+py, ps1↔py identical.
spec §4.2.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
# meta-compile v1.22 — Compile 1C metadata object from JSON
|
# meta-compile v1.23 — Compile 1C metadata object from JSON
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
@@ -1138,6 +1138,35 @@ $script:reservedByContext = @{
|
|||||||
"document" = @("Ref","DeletionMark","Date","Number","Posted")
|
"document" = @("Ref","DeletionMark","Date","Number","Posted")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Стандартный реквизит текущего типа по имени (EN/RU) → EN-имя, либо $null (обычный/неизвестный).
|
||||||
|
function Resolve-StdAttrEn {
|
||||||
|
param([string]$name)
|
||||||
|
$ctx = switch ("$objType") { 'Catalog' { 'catalog' } 'Document' { 'document' } default { $null } }
|
||||||
|
if (-not $ctx) { return $null }
|
||||||
|
$stdSet = $script:reservedByContext[$ctx]
|
||||||
|
foreach ($en in $stdSet) {
|
||||||
|
$ru = $script:reservedAttrNames[$en]
|
||||||
|
if (($name -ieq $en) -or ($ru -and $name -ieq $ru)) { return $en }
|
||||||
|
}
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
# Прощающий ввод пути к реквизиту САМОГО объекта (dataPath в linkByType/choiceParameterLinks):
|
||||||
|
# "Ссылка"/"Ref"/станд. → <Тип>.<Имя>.StandardAttribute.<EN>; обычное имя → <Тип>.<Имя>.Attribute.<Имя>;
|
||||||
|
# частичное "StandardAttribute.X"/"Attribute.X" → префикс <Тип>.<Имя>; полный путь → verbatim.
|
||||||
|
function Expand-DataPath {
|
||||||
|
param([string]$dp)
|
||||||
|
if (-not $dp) { return $dp }
|
||||||
|
$s = "$dp"
|
||||||
|
if ($s -match '^(StandardAttribute|Attribute)\.') { return "$objType.$objName.$s" }
|
||||||
|
if (-not $s.Contains('.')) {
|
||||||
|
$en = Resolve-StdAttrEn $s
|
||||||
|
if ($en) { return "$objType.$objName.StandardAttribute.$en" }
|
||||||
|
return "$objType.$objName.Attribute.$s"
|
||||||
|
}
|
||||||
|
return $s
|
||||||
|
}
|
||||||
|
|
||||||
# <LinkByType> (связь по типу — тип значения реквизита-Характеристики определяется другим реквизитом).
|
# <LinkByType> (связь по типу — тип значения реквизита-Характеристики определяется другим реквизитом).
|
||||||
# Структура как <TypeLink> формы: DataPath + LinkItem. DSL `linkByType`: {dataPath, linkItem?} ИЛИ строка-путь.
|
# Структура как <TypeLink> формы: DataPath + LinkItem. DSL `linkByType`: {dataPath, linkItem?} ИЛИ строка-путь.
|
||||||
# Нет ключа → <LinkByType/> (пусто).
|
# Нет ключа → <LinkByType/> (пусто).
|
||||||
@@ -1150,6 +1179,7 @@ function Emit-LinkByType {
|
|||||||
$li = if ($null -ne $spec.linkItem) { $spec.linkItem } elseif ($null -ne $spec.элементСвязи) { $spec.элементСвязи } else { 0 }
|
$li = if ($null -ne $spec.linkItem) { $spec.linkItem } elseif ($null -ne $spec.элементСвязи) { $spec.элементСвязи } else { 0 }
|
||||||
}
|
}
|
||||||
if (-not $dp) { X "$indent<LinkByType/>"; return }
|
if (-not $dp) { X "$indent<LinkByType/>"; return }
|
||||||
|
$dp = Expand-DataPath $dp
|
||||||
X "$indent<LinkByType>"
|
X "$indent<LinkByType>"
|
||||||
X "$indent`t<xr:DataPath>$(Esc-Xml "$dp")</xr:DataPath>"
|
X "$indent`t<xr:DataPath>$(Esc-Xml "$dp")</xr:DataPath>"
|
||||||
X "$indent`t<xr:LinkItem>$li</xr:LinkItem>"
|
X "$indent`t<xr:LinkItem>$li</xr:LinkItem>"
|
||||||
@@ -1264,7 +1294,7 @@ function Emit-ChoiceParameterLinks {
|
|||||||
foreach ($lk in @($cpl)) {
|
foreach ($lk in @($cpl)) {
|
||||||
if ($lk -is [string]) { $lk = ConvertFrom-ChLinkShorthand $lk }
|
if ($lk -is [string]) { $lk = ConvertFrom-ChLinkShorthand $lk }
|
||||||
$name = Get-ChElProp $lk @('name','имя')
|
$name = Get-ChElProp $lk @('name','имя')
|
||||||
$dp = Get-ChElProp $lk @('dataPath','path','путь')
|
$dp = Expand-DataPath (Get-ChElProp $lk @('dataPath','path','путь'))
|
||||||
$vcRaw = Get-ChElProp $lk @('valueChange','режимИзменения')
|
$vcRaw = Get-ChElProp $lk @('valueChange','режимИзменения')
|
||||||
$vc = 'Clear'
|
$vc = 'Clear'
|
||||||
if ($vcRaw) {
|
if ($vcRaw) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# meta-compile v1.22 — Compile 1C metadata object from JSON
|
# meta-compile v1.23 — Compile 1C metadata object from JSON
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
@@ -1180,6 +1180,40 @@ RESERVED_BY_CONTEXT = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Стандартные реквизиты по типу для разворота dataPath: [(EN, RU), ...].
|
||||||
|
STD_ATTR_BY_TYPE = {
|
||||||
|
'Catalog': [('Ref', 'Ссылка'), ('DeletionMark', 'ПометкаУдаления'), ('Predefined', 'Предопределенный'),
|
||||||
|
('PredefinedDataName', 'ИмяПредопределенныхДанных'), ('Code', 'Код'), ('Description', 'Наименование'),
|
||||||
|
('Owner', 'Владелец'), ('Parent', 'Родитель'), ('IsFolder', 'ЭтоГруппа')],
|
||||||
|
'Document': [('Ref', 'Ссылка'), ('DeletionMark', 'ПометкаУдаления'), ('Date', 'Дата'), ('Number', 'Номер'),
|
||||||
|
('Posted', 'Проведен')],
|
||||||
|
}
|
||||||
|
|
||||||
|
def resolve_std_attr_en(name):
|
||||||
|
pairs = STD_ATTR_BY_TYPE.get(obj_type)
|
||||||
|
if not pairs:
|
||||||
|
return None
|
||||||
|
low = name.lower()
|
||||||
|
for en, ru in pairs:
|
||||||
|
if low == en.lower() or low == ru.lower():
|
||||||
|
return en
|
||||||
|
return None
|
||||||
|
|
||||||
|
def expand_data_path(dp):
|
||||||
|
"""Путь к реквизиту самого объекта: "Ссылка"→<Тип>.<Имя>.StandardAttribute.Ref; обычное имя→.Attribute.имя;
|
||||||
|
частичное StandardAttribute.X/Attribute.X→префикс; полный путь→verbatim."""
|
||||||
|
if not dp:
|
||||||
|
return dp
|
||||||
|
s = str(dp)
|
||||||
|
if re.match(r'^(StandardAttribute|Attribute)\.', s):
|
||||||
|
return f'{obj_type}.{obj_name}.{s}'
|
||||||
|
if '.' not in s:
|
||||||
|
en = resolve_std_attr_en(s)
|
||||||
|
if en:
|
||||||
|
return f'{obj_type}.{obj_name}.StandardAttribute.{en}'
|
||||||
|
return f'{obj_type}.{obj_name}.Attribute.{s}'
|
||||||
|
return s
|
||||||
|
|
||||||
def emit_link_by_type(indent, spec):
|
def emit_link_by_type(indent, spec):
|
||||||
"""<LinkByType> (связь по типу): DataPath + LinkItem. spec — {dataPath, linkItem?} или строка-путь; нет → <LinkByType/>."""
|
"""<LinkByType> (связь по типу): DataPath + LinkItem. spec — {dataPath, linkItem?} или строка-путь; нет → <LinkByType/>."""
|
||||||
if not spec:
|
if not spec:
|
||||||
@@ -1197,6 +1231,7 @@ def emit_link_by_type(indent, spec):
|
|||||||
if not dp:
|
if not dp:
|
||||||
X(f'{indent}<LinkByType/>')
|
X(f'{indent}<LinkByType/>')
|
||||||
return
|
return
|
||||||
|
dp = expand_data_path(dp)
|
||||||
X(f'{indent}<LinkByType>')
|
X(f'{indent}<LinkByType>')
|
||||||
X(f'{indent}\t<xr:DataPath>{esc_xml(str(dp))}</xr:DataPath>')
|
X(f'{indent}\t<xr:DataPath>{esc_xml(str(dp))}</xr:DataPath>')
|
||||||
X(f'{indent}\t<xr:LinkItem>{li}</xr:LinkItem>')
|
X(f'{indent}\t<xr:LinkItem>{li}</xr:LinkItem>')
|
||||||
@@ -1311,7 +1346,7 @@ def emit_choice_parameter_links(indent, cpl):
|
|||||||
if isinstance(lk, str):
|
if isinstance(lk, str):
|
||||||
lk = convert_from_ch_link_shorthand(lk)
|
lk = convert_from_ch_link_shorthand(lk)
|
||||||
name = ch_el_prop(lk, ['name', 'имя'])
|
name = ch_el_prop(lk, ['name', 'имя'])
|
||||||
dp = ch_el_prop(lk, ['dataPath', 'path', 'путь'])
|
dp = expand_data_path(ch_el_prop(lk, ['dataPath', 'path', 'путь']))
|
||||||
vc_raw = ch_el_prop(lk, ['valueChange', 'режимИзменения'])
|
vc_raw = ch_el_prop(lk, ['valueChange', 'режимИзменения'])
|
||||||
vc = 'Clear'
|
vc = 'Clear'
|
||||||
if vc_raw:
|
if vc_raw:
|
||||||
|
|||||||
@@ -152,6 +152,12 @@ JSON DSL для описания объектов метаданных конф
|
|||||||
| `fillValue` | FillValue | по типу (см. ниже) | значение заполнения — bool/число/строка/дата/DTR-путь; `null` → nil |
|
| `fillValue` | FillValue | по типу (см. ниже) | значение заполнения — bool/число/строка/дата/DTR-путь; `null` → nil |
|
||||||
| `linkByType` | LinkByType | пусто | связь по типу: `{dataPath, linkItem?}` ИЛИ строка-путь (linkItem=0). Тип значения реквизита-Характеристики берётся из реквизита по `dataPath` |
|
| `linkByType` | LinkByType | пусто | связь по типу: `{dataPath, linkItem?}` ИЛИ строка-путь (linkItem=0). Тип значения реквизита-Характеристики берётся из реквизита по `dataPath` |
|
||||||
| `choiceParameterLinks` | ChoiceParameterLinks | пусто | связи параметров выбора: массив `{name, dataPath, valueChange?}` ИЛИ строк `"name=dataPath[:DontChange]"`. valueChange по умолч. `Clear` |
|
| `choiceParameterLinks` | ChoiceParameterLinks | пусто | связи параметров выбора: массив `{name, dataPath, valueChange?}` ИЛИ строк `"name=dataPath[:DontChange]"`. valueChange по умолч. `Clear` |
|
||||||
|
|
||||||
|
`dataPath` (в `linkByType` и `choiceParameterLinks`) ссылается на реквизит **самого объекта** — прощающий ввод:
|
||||||
|
- стандартный реквизит: `Ссылка`/`Ref`, `Наименование`/`Description`, `Код`/`Code`, `Владелец`/`Owner`, … →
|
||||||
|
`<Тип>.<Имя>.StandardAttribute.<EN>`;
|
||||||
|
- обычный реквизит: имя (`Свойство`) → `<Тип>.<Имя>.Attribute.Свойство`;
|
||||||
|
- частичное `StandardAttribute.X` / `Attribute.X` → добавит префикс `<Тип>.<Имя>`; полный путь — как есть.
|
||||||
| `choiceParameters` | ChoiceParameters | пусто | параметры выбора: массив `{name, value?}` ИЛИ строк `"name=value"`. value — bool/число/строка/DTR-путь ИЛИ массив (→ FixedArray); без value → nil |
|
| `choiceParameters` | ChoiceParameters | пусто | параметры выбора: массив `{name, value?}` ИЛИ строк `"name=value"`. value — bool/число/строка/DTR-путь ИЛИ массив (→ FixedArray); без value → nil |
|
||||||
| `createOnInput` | CreateOnInput | Auto | Auto/Use/DontUse |
|
| `createOnInput` | CreateOnInput | Auto | Auto/Use/DontUse |
|
||||||
| `quickChoice` | QuickChoice | Auto | Auto/Use/DontUse. Прощаем bool (форм-стиль): `true`→Use, `false`→DontUse |
|
| `quickChoice` | QuickChoice | Auto | Auto/Use/DontUse. Прощаем bool (форм-стиль): `true`→Use, `false`→DontUse |
|
||||||
|
|||||||
@@ -5,13 +5,13 @@
|
|||||||
"name": "ТестВыбора",
|
"name": "ТестВыбора",
|
||||||
"attributes": [
|
"attributes": [
|
||||||
{ "name": "Счет", "type": "CatalogRef.БанковскиеСчета",
|
{ "name": "Счет", "type": "CatalogRef.БанковскиеСчета",
|
||||||
"choiceParameterLinks": [ { "name": "Отбор.Владелец", "dataPath": "Catalog.ТестВыбора.StandardAttribute.Ref", "valueChange": "Clear" } ] },
|
"choiceParameterLinks": [ { "name": "Отбор.Владелец", "dataPath": "Ссылка", "valueChange": "Clear" } ] },
|
||||||
{ "name": "Партнер", "type": "CatalogRef.Партнеры",
|
{ "name": "Партнер", "type": "CatalogRef.Партнеры",
|
||||||
"choiceParameters": "Отбор.ЭтоГруппа=false" },
|
"choiceParameters": "Отбор.ЭтоГруппа=false" },
|
||||||
{ "name": "ТипТТН", "type": "CatalogRef.ВидыТранспорта",
|
{ "name": "ТипТТН", "type": "CatalogRef.ВидыТранспорта",
|
||||||
"choiceParameters": [ { "name": "Отбор.Тип", "value": ["Enum.ТипыВЕТИС.EmptyRef", "Enum.ТипыВЕТИС.EnumValue.ТТН"] } ] },
|
"choiceParameters": [ { "name": "Отбор.Тип", "value": ["Enum.ТипыВЕТИС.EmptyRef", "Enum.ТипыВЕТИС.EnumValue.ТТН"] } ] },
|
||||||
{ "name": "Валюта", "type": "CatalogRef.Валюты",
|
{ "name": "Валюта", "type": "CatalogRef.Валюты",
|
||||||
"choiceParameterLinks": "Отбор.Владелец=Catalog.ТестВыбора.StandardAttribute.Ref" }
|
"choiceParameterLinks": "Отбор.Владелец=Ссылка" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"validatePath": "Catalogs/ТестВыбора",
|
"validatePath": "Catalogs/ТестВыбора",
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
"attributes": [
|
"attributes": [
|
||||||
{ "name": "Свойство", "type": "ChartOfCharacteristicTypesRef.ДополнительныеРеквизиты" },
|
{ "name": "Свойство", "type": "ChartOfCharacteristicTypesRef.ДополнительныеРеквизиты" },
|
||||||
{ "name": "Значение", "type": "Characteristic.ДополнительныеРеквизиты",
|
{ "name": "Значение", "type": "Characteristic.ДополнительныеРеквизиты",
|
||||||
"linkByType": { "dataPath": "Catalog.ТестХарактеристик.Attribute.Свойство", "linkItem": 1 } },
|
"linkByType": { "dataPath": "Свойство", "linkItem": 1 } },
|
||||||
{ "name": "ЗначениеОпредТип", "type": "DefinedType.Сумма" },
|
{ "name": "ЗначениеОпредТип", "type": "DefinedType.Сумма" },
|
||||||
{ "name": "СвязьСтрокой", "type": "Characteristic.ВидыСубконто",
|
{ "name": "СвязьСтрокой", "type": "Characteristic.ВидыСубконто",
|
||||||
"linkByType": "Catalog.ТестХарактеристик.Attribute.Свойство" }
|
"linkByType": "Свойство" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"validatePath": "Catalogs/ТестХарактеристик",
|
"validatePath": "Catalogs/ТестХарактеристик",
|
||||||
|
|||||||
Reference in New Issue
Block a user