mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-09-07 18:50:53 +03:00
fix(meta-edit): копия эмиттера звала функции, которых в навыке нет
Скопированные из meta-compile Emit-FormRef и Emit-Characteristics тянули за собой хвост хелперов (Normalize-FormRef, Normalize-CharFrom, Expand-CharField, Get-CharIntField), которых в meta-edit нет. Добавление таблицы с ключом defaultListForm или characteristics давало в PS CommandNotFoundException при коде возврата 0: навык отчитывался успехом, а файл таблицы не создавался и в ChildObjects ничего не появлялось. В python то же место падало трейсбеком — порты расходились ещё и потоком ошибки. Причина не в копировании как таковом: копия обязана быть не только идентичной, но и самодостаточной. Форма функции для этого не годилась, поэтому изменена в эталоне и перекопирована — тем же приёмом, что уже применён в этой семье дважды: Emit-EdsTableProperties принимает готовые блоки <Characteristics> и четырёх слотов <Default*Form>, рендерит их вызывающий навык своим эмиттером. Зависимостей у тела не осталось. meta-edit передаёт пустые блоки и отвергает ключи characteristics и default*Form с объяснением, куда идти: форму назначает form-add, характеристики — meta-compile. Попутно исправлено то, что вскрылось при разборе: короткое имя формы в defaultListForm эмитилось как есть, а платформа отвечает «Неизвестный объект метаданных». Теперь оно разворачивается в полный путь ExternalDataSource.И.Table.Т.Form.Ф — как и ссылки на поля. check-inline-drift получил проверку РАЗРЕШИМОСТИ: всё, что зовёт скопированное тело, обязано быть определено в том же навыке. Критерий «своей» функции — имя, определённое в навыке-эталоне, поэтому список командлетов-исключений не нужен. Проверено обратным экспериментом: гард ловит исходный дефект с прямой формулировкой «копия неразрешима». Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NBsZA5cr2WFThtgp7i5WVi
This commit is contained in:
co-authored by
Claude Opus 5
parent
938db35c85
commit
8d1670468a
@@ -1,4 +1,4 @@
|
||||
# meta-compile v1.107 — Compile 1C metadata object from JSON
|
||||
# meta-compile v1.108 — Compile 1C metadata object from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
[CmdletBinding(PositionalBinding=$false)]
|
||||
param(
|
||||
@@ -4466,7 +4466,10 @@ function Emit-EdsFunction {
|
||||
|
||||
# Свойства таблицы: 38 узлов в порядке выгрузки платформы.
|
||||
function Emit-EdsTableProperties {
|
||||
param([string]$indent, [string]$srcName, [string]$tableName, $t)
|
||||
# $charXml и $defaultFormsXml — уже собранные блоки <Characteristics> и четыре слота
|
||||
# <Default*Form>: их рендерит вызывающий навык своим эмиттером. Так тело не зависит
|
||||
# от хелперов конкретного навыка и годится для копирования (check-inline-drift).
|
||||
param([string]$indent, [string]$srcName, [string]$tableName, $t, [string]$charXml, [string]$defaultFormsXml)
|
||||
$i = $indent
|
||||
$tblSynonym = if ($t -and $null -ne $t.synonym) { $t.synonym } else { Split-CamelCase $tableName }
|
||||
X "$i<Name>$(Esc-XmlText $tableName)</Name>"
|
||||
@@ -4493,7 +4496,7 @@ function Emit-EdsTableProperties {
|
||||
# с полем родителя — пустая строка (как после загрузки), а без него — nil.
|
||||
if ($t -and $t.parentField) { X "$i<UnfilledParentValue xsi:type=`"xs:string`"/>" }
|
||||
else { X "$i<UnfilledParentValue xsi:nil=`"true`"/>" }
|
||||
Emit-Characteristics $i $(if ($t) { $t.characteristics } else { $null })
|
||||
if ($charXml) { X $charXml.TrimEnd("`r", "`n") } else { X "$i<Characteristics/>" }
|
||||
|
||||
X "$i<UseStandardCommands>$(if ($t -and $t.useStandardCommands -eq $false) { 'false' } else { 'true' })</UseStandardCommands>"
|
||||
X "$i<QuickChoice>$(if ($t -and $t.quickChoice -eq $true) { 'true' } else { 'false' })</QuickChoice>"
|
||||
@@ -4507,10 +4510,9 @@ function Emit-EdsTableProperties {
|
||||
X "$i<ChoiceDataGetModeOnInputByString>$(if ($t -and $t.choiceDataGetModeOnInputByString) { "$($t.choiceDataGetModeOnInputByString)" } else { 'Directly' })</ChoiceDataGetModeOnInputByString>"
|
||||
X "$i<ChoiceHistoryOnInput>$(if ($t -and $t.choiceHistoryOnInput) { "$($t.choiceHistoryOnInput)" } else { 'Auto' })</ChoiceHistoryOnInput>"
|
||||
|
||||
foreach ($formTag in @("DefaultObjectForm","DefaultRecordForm","DefaultListForm","DefaultChoiceForm")) {
|
||||
$key = $formTag.Substring(0,1).ToLower() + $formTag.Substring(1)
|
||||
Emit-FormRef $i $formTag $(if ($t) { $t.$key } else { $null })
|
||||
}
|
||||
# Пустая строка — четыре слота всё равно обязаны быть: в свойствах таблицы их ровно 38.
|
||||
if ($defaultFormsXml) { X $defaultFormsXml.TrimEnd("`r", "`n") }
|
||||
else { foreach ($formTag in @("DefaultObjectForm","DefaultRecordForm","DefaultListForm","DefaultChoiceForm")) { X "$i<$formTag/>" } }
|
||||
foreach ($presTag in @("ObjectPresentation","ExtendedObjectPresentation","RecordPresentation",
|
||||
"ExtendedRecordPresentation","ListPresentation","ExtendedListPresentation","Explanation")) {
|
||||
$key = $presTag.Substring(0,1).ToLower() + $presTag.Substring(1)
|
||||
@@ -4530,9 +4532,9 @@ function Emit-EdsTableProperties {
|
||||
# поэтому «перехват» — запомнить длину, отдать эмиттерам, вырезать добавленное
|
||||
# (тот же приём, что у составного типа).
|
||||
function Build-EdsTableXml {
|
||||
# $fieldsXml — уже собранные узлы <Field>: их рендерит вызывающий навык своим эмиттером
|
||||
# реквизита. Так тело функции не зависит от того, какой это навык.
|
||||
param([string]$srcName, [string]$tableName, $entry, [string]$fieldsXml)
|
||||
# $fieldsXml, $charXml, $defaultFormsXml — уже собранные узлы: их рендерит вызывающий навык
|
||||
# своими эмиттерами. Так тело функции не зависит от того, какой это навык.
|
||||
param([string]$srcName, [string]$tableName, $entry, [string]$fieldsXml, [string]$charXml, [string]$defaultFormsXml)
|
||||
$before = $script:xml.Length
|
||||
|
||||
$tableUuid = New-Guid-String
|
||||
@@ -4559,7 +4561,7 @@ function Build-EdsTableXml {
|
||||
X "`t`t</InternalInfo>"
|
||||
|
||||
X "`t`t<Properties>"
|
||||
Emit-EdsTableProperties "`t`t`t" $srcName $tableName $entry.props
|
||||
Emit-EdsTableProperties "`t`t`t" $srcName $tableName $entry.props $charXml $defaultFormsXml
|
||||
X "`t`t</Properties>"
|
||||
|
||||
if ($fieldsXml) {
|
||||
@@ -5357,7 +5359,25 @@ if ($objType -eq "ExternalDataSource" -and $script:edsTables.Count -gt 0) {
|
||||
}
|
||||
$fieldsXml = $script:xml.ToString($fieldsBefore, $script:xml.Length - $fieldsBefore)
|
||||
[void]$script:xml.Remove($fieldsBefore, $script:xml.Length - $fieldsBefore)
|
||||
$tableXml = Build-EdsTableXml $objName $tblName $entry $fieldsXml
|
||||
$tp = $entry.props
|
||||
$charBefore = $script:xml.Length
|
||||
Emit-Characteristics "`t`t`t" $(if ($tp) { $tp.characteristics } else { $null })
|
||||
$charXml = $script:xml.ToString($charBefore, $script:xml.Length - $charBefore)
|
||||
[void]$script:xml.Remove($charBefore, $script:xml.Length - $charBefore)
|
||||
|
||||
# Слот формы: короткое имя разворачивается в полный путь таблицы внешнего источника —
|
||||
# голое имя платформа отвергает («Неизвестный объект метаданных»).
|
||||
$formsBefore = $script:xml.Length
|
||||
foreach ($formTag in @("DefaultObjectForm","DefaultRecordForm","DefaultListForm","DefaultChoiceForm")) {
|
||||
$key = $formTag.Substring(0,1).ToLower() + $formTag.Substring(1)
|
||||
$formVal = if ($tp) { $tp.$key } else { $null }
|
||||
if ($formVal -and "$formVal" -notmatch '\.') { $formVal = "ExternalDataSource.$objName.Table.$tblName.Form.$formVal" }
|
||||
Emit-FormRef "`t`t`t" $formTag $formVal
|
||||
}
|
||||
$defaultFormsXml = $script:xml.ToString($formsBefore, $script:xml.Length - $formsBefore)
|
||||
[void]$script:xml.Remove($formsBefore, $script:xml.Length - $formsBefore)
|
||||
|
||||
$tableXml = Build-EdsTableXml $objName $tblName $entry $fieldsXml $charXml $defaultFormsXml
|
||||
$tablePath = Join-Path $tablesDir "$tblName.xml"
|
||||
Write-XmlFileKeepEol $tablePath $tableXml $enc
|
||||
$edsTablesCreated += $tablePath
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# meta-compile v1.107 — Compile 1C metadata object from JSON
|
||||
# meta-compile v1.108 — Compile 1C metadata object from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -4459,8 +4459,12 @@ def emit_eds_function(indent, fn_name, val, type_xml):
|
||||
X(f'{indent}</Function>')
|
||||
|
||||
|
||||
def emit_eds_table_properties(indent, src_name, table_name, t):
|
||||
"""Свойства таблицы: 38 узлов в порядке выгрузки платформы."""
|
||||
def emit_eds_table_properties(indent, src_name, table_name, t, char_xml, default_forms_xml):
|
||||
"""Свойства таблицы: 38 узлов в порядке выгрузки платформы.
|
||||
|
||||
char_xml и default_forms_xml — уже собранные блоки <Characteristics> и четыре слота
|
||||
<Default*Form>: их рендерит вызывающий навык своим эмиттером. Так тело не зависит
|
||||
от хелперов конкретного навыка и годится для копирования (check-inline-drift)."""
|
||||
i = indent
|
||||
t = t or {}
|
||||
tbl_synonym = t['synonym'] if t.get('synonym') is not None else split_camel_case(table_name)
|
||||
@@ -4497,7 +4501,10 @@ def emit_eds_table_properties(indent, src_name, table_name, t):
|
||||
X(f'{i}<UnfilledParentValue xsi:type="xs:string"/>')
|
||||
else:
|
||||
X(f'{i}<UnfilledParentValue xsi:nil="true"/>')
|
||||
emit_characteristics(i, t.get('characteristics'))
|
||||
if char_xml:
|
||||
X(char_xml.rstrip('\r\n'))
|
||||
else:
|
||||
X(f'{i}<Characteristics/>')
|
||||
|
||||
X(f'{i}<UseStandardCommands>{"false" if t.get("useStandardCommands") is False else "true"}</UseStandardCommands>')
|
||||
X(f'{i}<QuickChoice>{"true" if t.get("quickChoice") is True else "false"}</QuickChoice>')
|
||||
@@ -4515,9 +4522,12 @@ def emit_eds_table_properties(indent, src_name, table_name, t):
|
||||
X(f'{i}<ChoiceDataGetModeOnInputByString>{t.get("choiceDataGetModeOnInputByString") or "Directly"}</ChoiceDataGetModeOnInputByString>')
|
||||
X(f'{i}<ChoiceHistoryOnInput>{t.get("choiceHistoryOnInput") or "Auto"}</ChoiceHistoryOnInput>')
|
||||
|
||||
for form_tag in ('DefaultObjectForm', 'DefaultRecordForm', 'DefaultListForm', 'DefaultChoiceForm'):
|
||||
key = form_tag[0].lower() + form_tag[1:]
|
||||
emit_form_ref(i, form_tag, t.get(key))
|
||||
# Пустая строка — четыре слота всё равно обязаны быть: в свойствах таблицы их ровно 38.
|
||||
if default_forms_xml:
|
||||
X(default_forms_xml.rstrip('\r\n'))
|
||||
else:
|
||||
for form_tag in ('DefaultObjectForm', 'DefaultRecordForm', 'DefaultListForm', 'DefaultChoiceForm'):
|
||||
X(f'{i}<{form_tag}/>')
|
||||
for pres_tag in ('ObjectPresentation', 'ExtendedObjectPresentation', 'RecordPresentation',
|
||||
'ExtendedRecordPresentation', 'ListPresentation', 'ExtendedListPresentation', 'Explanation'):
|
||||
key = pres_tag[0].lower() + pres_tag[1:]
|
||||
@@ -4544,9 +4554,10 @@ EDS_TABLE_GENERATED_TYPES = (
|
||||
)
|
||||
|
||||
|
||||
def build_eds_table_xml(src_name, table_name, entry, fields_xml):
|
||||
"""Отдельный XML-документ таблицы. fields_xml — уже собранные узлы <Field>: их рендерит
|
||||
вызывающий навык своим эмиттером реквизита, поэтому тело не зависит от того, какой это навык.
|
||||
def build_eds_table_xml(src_name, table_name, entry, fields_xml, char_xml, default_forms_xml):
|
||||
"""Отдельный XML-документ таблицы. fields_xml, char_xml, default_forms_xml — уже собранные
|
||||
узлы: их рендерит вызывающий навык своими эмиттерами, поэтому тело не зависит от того,
|
||||
какой это навык.
|
||||
Возвращает строку: X пишет в общий список строк,
|
||||
поэтому «перехват» — запомнить длину, отдать эмиттерам, срезать добавленное
|
||||
(в ps1-порте тот же приём выражен через StringBuilder — различие рантаймов, не логики)."""
|
||||
@@ -4566,7 +4577,7 @@ def build_eds_table_xml(src_name, table_name, entry, fields_xml):
|
||||
X('\t\t</InternalInfo>')
|
||||
|
||||
X('\t\t<Properties>')
|
||||
emit_eds_table_properties('\t\t\t', src_name, table_name, entry['props'])
|
||||
emit_eds_table_properties('\t\t\t', src_name, table_name, entry['props'], char_xml, default_forms_xml)
|
||||
X('\t\t</Properties>')
|
||||
|
||||
if fields_xml:
|
||||
@@ -5116,7 +5127,25 @@ if obj_type == 'ExternalDataSource' and eds_tables:
|
||||
emit_attribute('\t\t\t', parse_attribute_shorthand(f), 'eds-field', 'Field')
|
||||
fields_xml = '\r\n'.join(lines[fields_before:])
|
||||
del lines[fields_before:]
|
||||
table_xml = build_eds_table_xml(obj_name, tbl_name, entry, fields_xml)
|
||||
tp = entry['props'] or {}
|
||||
char_before = len(lines)
|
||||
emit_characteristics('\t\t\t', tp.get('characteristics'))
|
||||
char_xml = '\r\n'.join(lines[char_before:])
|
||||
del lines[char_before:]
|
||||
|
||||
# Слот формы: короткое имя разворачивается в полный путь таблицы внешнего источника —
|
||||
# голое имя платформа отвергает («Неизвестный объект метаданных»).
|
||||
forms_before = len(lines)
|
||||
for form_tag in ('DefaultObjectForm', 'DefaultRecordForm', 'DefaultListForm', 'DefaultChoiceForm'):
|
||||
key = form_tag[0].lower() + form_tag[1:]
|
||||
form_val = tp.get(key)
|
||||
if form_val and '.' not in str(form_val):
|
||||
form_val = f'ExternalDataSource.{obj_name}.Table.{tbl_name}.Form.{form_val}'
|
||||
emit_form_ref('\t\t\t', form_tag, form_val)
|
||||
default_forms_xml = '\r\n'.join(lines[forms_before:])
|
||||
del lines[forms_before:]
|
||||
|
||||
table_xml = build_eds_table_xml(obj_name, tbl_name, entry, fields_xml, char_xml, default_forms_xml)
|
||||
table_path = os.path.join(tables_dir, f'{tbl_name}.xml')
|
||||
write_xml_file_keep_eol(table_path, table_xml)
|
||||
eds_tables_created.append(table_path)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# meta-edit v1.45 — Edit existing 1C metadata object XML
|
||||
# meta-edit v1.46 — Edit existing 1C metadata object XML
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
[CmdletBinding(PositionalBinding=$false)]
|
||||
param(
|
||||
@@ -1598,10 +1598,6 @@ $script:childTypeToXmlTag = @{
|
||||
# таблица внешнего источника собирается в ОТДЕЛЬНЫЙ файл, и формат этого файла
|
||||
# должен быть один и тот же, кем бы он ни был создан. Держит check-inline-drift.mjs.
|
||||
|
||||
function Emit-FormRef {
|
||||
param([string]$i, [string]$tag, $val)
|
||||
if ($val) { X "$i<$tag>$(Esc-XmlText (Normalize-FormRef "$val"))</$tag>" } else { X "$i<$tag/>" }
|
||||
}
|
||||
|
||||
# Шапка пространств имён файла таблицы внешнего источника — копия из meta-compile.
|
||||
$script:xmlnsDecl = 'xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
|
||||
@@ -1640,54 +1636,6 @@ function Emit-MLText {
|
||||
X "$indent</$tag>"
|
||||
}
|
||||
|
||||
function Emit-Characteristics {
|
||||
param([string]$indent, $chars)
|
||||
if (-not $chars -or @($chars).Count -eq 0) { X "$indent<Characteristics/>"; return }
|
||||
X "$indent<Characteristics>"
|
||||
foreach ($ch in @($chars)) {
|
||||
$types = Get-ChElProp $ch @('types','characteristicTypes','типы')
|
||||
$values = Get-ChElProp $ch @('values','characteristicValues','значения')
|
||||
$tFrom = Normalize-CharFrom "$(Get-ChElProp $types @('from','source','источник'))"
|
||||
$vFrom = Normalize-CharFrom "$(Get-ChElProp $values @('from','source','источник'))"
|
||||
$key = Expand-CharField "$(Get-ChElProp $types @('key','keyField'))" $tFrom
|
||||
$tff = Expand-CharField "$(Get-ChElProp $types @('filterField','typesFilterField'))" $tFrom
|
||||
$obj = Expand-CharField "$(Get-ChElProp $values @('object','objectField'))" $vFrom
|
||||
$typ = Expand-CharField "$(Get-ChElProp $values @('type','typeField'))" $vFrom
|
||||
$val = Expand-CharField "$(Get-ChElProp $values @('value','valueField'))" $vFrom
|
||||
# числовые поля-флаги (обычно -1; иногда 0)
|
||||
$dpf = Get-CharIntField $types @('dataPathField')
|
||||
$mvu = Get-CharIntField $types @('multipleValuesUseField')
|
||||
$mvk = Get-CharIntField $values @('multipleValuesKeyField')
|
||||
$mvo = Get-CharIntField $values @('multipleValuesOrderField')
|
||||
X "$indent`t<xr:Characteristic>"
|
||||
X "$indent`t`t<xr:CharacteristicTypes from=`"$(Esc-Xml $tFrom)`">"
|
||||
X "$indent`t`t`t<xr:KeyField>$(Esc-XmlText $key)</xr:KeyField>"
|
||||
X "$indent`t`t`t<xr:TypesFilterField>$(Esc-XmlText $tff)</xr:TypesFilterField>"
|
||||
# filterValue: $null→nil; голое→xs:string, полный путь→DTR, bool→xs:boolean.
|
||||
$tfvRaw = Get-ChElProp $types @('filterValue','typesFilterValue')
|
||||
if ($null -eq $tfvRaw) { X "$indent`t`t`t<xr:TypesFilterValue xsi:nil=`"true`"/>" }
|
||||
else {
|
||||
$tfvN = Normalize-ChoiceValue $tfvRaw
|
||||
if ([string]::IsNullOrEmpty($tfvN.Text)) { X "$indent`t`t`t<xr:TypesFilterValue xsi:type=`"$($tfvN.XsiType)`"/>" }
|
||||
else { X "$indent`t`t`t<xr:TypesFilterValue xsi:type=`"$($tfvN.XsiType)`">$(Esc-XmlText $tfvN.Text)</xr:TypesFilterValue>" }
|
||||
}
|
||||
# Числовое значение (обычно -1 или 0) — как есть; разворачивать через Expand-CharField нельзя,
|
||||
# оно примет "0" за короткое имя поля и выдаст "<from>.Attribute.0".
|
||||
$dpfOut = if ("$dpf" -match '^-?\d+$') { "$dpf" } else { Esc-XmlText (Expand-CharField "$dpf" $tFrom) }
|
||||
X "$indent`t`t`t<xr:DataPathField>$dpfOut</xr:DataPathField>"
|
||||
X "$indent`t`t`t<xr:MultipleValuesUseField>$mvu</xr:MultipleValuesUseField>"
|
||||
X "$indent`t`t</xr:CharacteristicTypes>"
|
||||
X "$indent`t`t<xr:CharacteristicValues from=`"$(Esc-Xml $vFrom)`">"
|
||||
X "$indent`t`t`t<xr:ObjectField>$(Esc-XmlText $obj)</xr:ObjectField>"
|
||||
X "$indent`t`t`t<xr:TypeField>$(Esc-XmlText $typ)</xr:TypeField>"
|
||||
X "$indent`t`t`t<xr:ValueField>$(Esc-XmlText $val)</xr:ValueField>"
|
||||
X "$indent`t`t`t<xr:MultipleValuesKeyField>$mvk</xr:MultipleValuesKeyField>"
|
||||
X "$indent`t`t`t<xr:MultipleValuesOrderField>$mvo</xr:MultipleValuesOrderField>"
|
||||
X "$indent`t`t</xr:CharacteristicValues>"
|
||||
X "$indent`t</xr:Characteristic>"
|
||||
}
|
||||
X "$indent</Characteristics>"
|
||||
}
|
||||
|
||||
function Emit-MDRefList {
|
||||
param([string]$indent, [string]$tag, $items)
|
||||
@@ -1784,7 +1732,10 @@ function Emit-EdsFunction {
|
||||
}
|
||||
|
||||
function Emit-EdsTableProperties {
|
||||
param([string]$indent, [string]$srcName, [string]$tableName, $t)
|
||||
# $charXml и $defaultFormsXml — уже собранные блоки <Characteristics> и четыре слота
|
||||
# <Default*Form>: их рендерит вызывающий навык своим эмиттером. Так тело не зависит
|
||||
# от хелперов конкретного навыка и годится для копирования (check-inline-drift).
|
||||
param([string]$indent, [string]$srcName, [string]$tableName, $t, [string]$charXml, [string]$defaultFormsXml)
|
||||
$i = $indent
|
||||
$tblSynonym = if ($t -and $null -ne $t.synonym) { $t.synonym } else { Split-CamelCase $tableName }
|
||||
X "$i<Name>$(Esc-XmlText $tableName)</Name>"
|
||||
@@ -1811,7 +1762,7 @@ function Emit-EdsTableProperties {
|
||||
# с полем родителя — пустая строка (как после загрузки), а без него — nil.
|
||||
if ($t -and $t.parentField) { X "$i<UnfilledParentValue xsi:type=`"xs:string`"/>" }
|
||||
else { X "$i<UnfilledParentValue xsi:nil=`"true`"/>" }
|
||||
Emit-Characteristics $i $(if ($t) { $t.characteristics } else { $null })
|
||||
if ($charXml) { X $charXml.TrimEnd("`r", "`n") } else { X "$i<Characteristics/>" }
|
||||
|
||||
X "$i<UseStandardCommands>$(if ($t -and $t.useStandardCommands -eq $false) { 'false' } else { 'true' })</UseStandardCommands>"
|
||||
X "$i<QuickChoice>$(if ($t -and $t.quickChoice -eq $true) { 'true' } else { 'false' })</QuickChoice>"
|
||||
@@ -1825,10 +1776,9 @@ function Emit-EdsTableProperties {
|
||||
X "$i<ChoiceDataGetModeOnInputByString>$(if ($t -and $t.choiceDataGetModeOnInputByString) { "$($t.choiceDataGetModeOnInputByString)" } else { 'Directly' })</ChoiceDataGetModeOnInputByString>"
|
||||
X "$i<ChoiceHistoryOnInput>$(if ($t -and $t.choiceHistoryOnInput) { "$($t.choiceHistoryOnInput)" } else { 'Auto' })</ChoiceHistoryOnInput>"
|
||||
|
||||
foreach ($formTag in @("DefaultObjectForm","DefaultRecordForm","DefaultListForm","DefaultChoiceForm")) {
|
||||
$key = $formTag.Substring(0,1).ToLower() + $formTag.Substring(1)
|
||||
Emit-FormRef $i $formTag $(if ($t) { $t.$key } else { $null })
|
||||
}
|
||||
# Пустая строка — четыре слота всё равно обязаны быть: в свойствах таблицы их ровно 38.
|
||||
if ($defaultFormsXml) { X $defaultFormsXml.TrimEnd("`r", "`n") }
|
||||
else { foreach ($formTag in @("DefaultObjectForm","DefaultRecordForm","DefaultListForm","DefaultChoiceForm")) { X "$i<$formTag/>" } }
|
||||
foreach ($presTag in @("ObjectPresentation","ExtendedObjectPresentation","RecordPresentation",
|
||||
"ExtendedRecordPresentation","ListPresentation","ExtendedListPresentation","Explanation")) {
|
||||
$key = $presTag.Substring(0,1).ToLower() + $presTag.Substring(1)
|
||||
@@ -1845,9 +1795,9 @@ function Emit-EdsTableProperties {
|
||||
}
|
||||
|
||||
function Build-EdsTableXml {
|
||||
# $fieldsXml — уже собранные узлы <Field>: их рендерит вызывающий навык своим эмиттером
|
||||
# реквизита. Так тело функции не зависит от того, какой это навык.
|
||||
param([string]$srcName, [string]$tableName, $entry, [string]$fieldsXml)
|
||||
# $fieldsXml, $charXml, $defaultFormsXml — уже собранные узлы: их рендерит вызывающий навык
|
||||
# своими эмиттерами. Так тело функции не зависит от того, какой это навык.
|
||||
param([string]$srcName, [string]$tableName, $entry, [string]$fieldsXml, [string]$charXml, [string]$defaultFormsXml)
|
||||
$before = $script:xml.Length
|
||||
|
||||
$tableUuid = New-Guid-String
|
||||
@@ -1874,7 +1824,7 @@ function Build-EdsTableXml {
|
||||
X "`t`t</InternalInfo>"
|
||||
|
||||
X "`t`t<Properties>"
|
||||
Emit-EdsTableProperties "`t`t`t" $srcName $tableName $entry.props
|
||||
Emit-EdsTableProperties "`t`t`t" $srcName $tableName $entry.props $charXml $defaultFormsXml
|
||||
X "`t`t</Properties>"
|
||||
|
||||
if ($fieldsXml) {
|
||||
@@ -2285,6 +2235,19 @@ function Process-Add($addDef) {
|
||||
$tablesDir = Join-Path $srcDir "Tables"
|
||||
foreach ($entry in (Get-EdsTables $items).GetEnumerator()) {
|
||||
$tblName = $entry.Key
|
||||
# Характеристики и слоты форм точечным добавлением не задаются: первые требуют
|
||||
# эмиттера характеристик (живёт в meta-compile), вторые назначает form-add при
|
||||
# добавлении формы. Молча проглотить ключ нельзя — модель решит, что он сработал.
|
||||
$tv = $entry.Value.props
|
||||
if ($tv) {
|
||||
foreach ($k in @("characteristics","defaultObjectForm","defaultRecordForm","defaultListForm","defaultChoiceForm")) {
|
||||
if ($tv.$k) {
|
||||
Warn "Ключ '$k' не поддержан при добавлении таблицы: форму назначает form-add, характеристики — meta-compile. Таблица '$tblName' пропущена."
|
||||
$tblName = $null; break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (-not $tblName) { continue }
|
||||
if ($existingNames.ContainsKey($tblName)) {
|
||||
Warn "Table '$tblName' already exists, skipping"
|
||||
continue
|
||||
@@ -2299,7 +2262,7 @@ function Process-Add($addDef) {
|
||||
$fieldParts += Build-AttributeFragment (Parse-AttributeShorthand $f) "eds-field" "`t`t`t" "Field"
|
||||
}
|
||||
$fieldsXml = $fieldParts -join "`r`n"
|
||||
$tableXml = Build-EdsTableXml $script:objName $tblName $entry.Value $fieldsXml
|
||||
$tableXml = Build-EdsTableXml $script:objName $tblName $entry.Value $fieldsXml "" ""
|
||||
if (-not (Test-Path $tablesDir)) { New-Item -ItemType Directory -Path $tablesDir -Force | Out-Null }
|
||||
[System.IO.File]::WriteAllText($tablePath, $tableXml.TrimEnd("`r", "`n"), (New-Object System.Text.UTF8Encoding($true)))
|
||||
$fragmentXml = "$indent<Table>$(Esc-XmlText $tblName)</Table>"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# meta-edit v1.45 — Edit existing 1C metadata object XML
|
||||
# meta-edit v1.46 — Edit existing 1C metadata object XML
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -1593,12 +1593,6 @@ child_type_to_xml_tag = {
|
||||
xmlns_decl = 'xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
|
||||
lines = []
|
||||
|
||||
def emit_form_ref(i, tag, val):
|
||||
"""Ссылка на форму по умолчанию: непустая → <Tag>значение</Tag>, иначе <Tag/>."""
|
||||
if val:
|
||||
X(f'{i}<{tag}>{esc_xml_text(normalize_form_ref(str(val)))}</{tag}>')
|
||||
else:
|
||||
X(f'{i}<{tag}/>')
|
||||
|
||||
def X(text):
|
||||
lines.append(text)
|
||||
@@ -1627,54 +1621,6 @@ def emit_mltext(indent, tag, text):
|
||||
emit_ml_items(f'{indent}\t', text)
|
||||
X(f'{indent}</{tag}>')
|
||||
|
||||
def emit_characteristics(indent, chars):
|
||||
if not chars:
|
||||
X(f'{indent}<Characteristics/>')
|
||||
return
|
||||
X(f'{indent}<Characteristics>')
|
||||
for ch in chars:
|
||||
types = ch_el_prop(ch, ['types', 'characteristicTypes', 'типы'])
|
||||
values = ch_el_prop(ch, ['values', 'characteristicValues', 'значения'])
|
||||
t_from = normalize_char_from(ch_el_prop(types, ['from', 'source', 'источник']) or '')
|
||||
v_from = normalize_char_from(ch_el_prop(values, ['from', 'source', 'источник']) or '')
|
||||
key = expand_char_field(ch_el_prop(types, ['key', 'keyField']), t_from)
|
||||
tff = expand_char_field(ch_el_prop(types, ['filterField', 'typesFilterField']), t_from)
|
||||
obj = expand_char_field(ch_el_prop(values, ['object', 'objectField']), v_from)
|
||||
typ = expand_char_field(ch_el_prop(values, ['type', 'typeField']), v_from)
|
||||
val = expand_char_field(ch_el_prop(values, ['value', 'valueField']), v_from)
|
||||
dpf = char_int_field(types, ['dataPathField'])
|
||||
mvu = char_int_field(types, ['multipleValuesUseField'])
|
||||
mvk = char_int_field(values, ['multipleValuesKeyField'])
|
||||
mvo = char_int_field(values, ['multipleValuesOrderField'])
|
||||
X(f'{indent}\t<xr:Characteristic>')
|
||||
X(f'{indent}\t\t<xr:CharacteristicTypes from="{esc_xml(t_from)}">')
|
||||
X(f'{indent}\t\t\t<xr:KeyField>{esc_xml_text(key)}</xr:KeyField>')
|
||||
X(f'{indent}\t\t\t<xr:TypesFilterField>{esc_xml_text(tff)}</xr:TypesFilterField>')
|
||||
# filterValue: None→nil; голое→xs:string, полный путь→DTR, bool→xs:boolean.
|
||||
tfv_raw = ch_el_prop(types, ['filterValue', 'typesFilterValue'])
|
||||
if tfv_raw is None:
|
||||
X(f'{indent}\t\t\t<xr:TypesFilterValue xsi:nil="true"/>')
|
||||
else:
|
||||
tfv_xt, tfv_tx = normalize_choice_value(tfv_raw)
|
||||
if tfv_tx == '' or tfv_tx is None:
|
||||
X(f'{indent}\t\t\t<xr:TypesFilterValue xsi:type="{tfv_xt}"/>')
|
||||
else:
|
||||
X(f'{indent}\t\t\t<xr:TypesFilterValue xsi:type="{tfv_xt}">{esc_xml_text(tfv_tx)}</xr:TypesFilterValue>')
|
||||
# Числовое значение (обычно -1 или 0) — как есть; expand_char_field примет "0" за короткое
|
||||
# имя поля и выдаст "<from>.Attribute.0".
|
||||
dpf_out = str(dpf) if re.fullmatch(r'-?\d+', str(dpf)) else esc_xml_text(expand_char_field(str(dpf), t_from))
|
||||
X(f'{indent}\t\t\t<xr:DataPathField>{dpf_out}</xr:DataPathField>')
|
||||
X(f'{indent}\t\t\t<xr:MultipleValuesUseField>{mvu}</xr:MultipleValuesUseField>')
|
||||
X(f'{indent}\t\t</xr:CharacteristicTypes>')
|
||||
X(f'{indent}\t\t<xr:CharacteristicValues from="{esc_xml(v_from)}">')
|
||||
X(f'{indent}\t\t\t<xr:ObjectField>{esc_xml_text(obj)}</xr:ObjectField>')
|
||||
X(f'{indent}\t\t\t<xr:TypeField>{esc_xml_text(typ)}</xr:TypeField>')
|
||||
X(f'{indent}\t\t\t<xr:ValueField>{esc_xml_text(val)}</xr:ValueField>')
|
||||
X(f'{indent}\t\t\t<xr:MultipleValuesKeyField>{mvk}</xr:MultipleValuesKeyField>')
|
||||
X(f'{indent}\t\t\t<xr:MultipleValuesOrderField>{mvo}</xr:MultipleValuesOrderField>')
|
||||
X(f'{indent}\t\t</xr:CharacteristicValues>')
|
||||
X(f'{indent}\t</xr:Characteristic>')
|
||||
X(f'{indent}</Characteristics>')
|
||||
|
||||
def emit_md_ref_list(indent, tag, items):
|
||||
"""Список MDObjectRef (Documents/RegisterRecords/DocumentMap/…) с <xr:Item>. omit-on-empty."""
|
||||
@@ -1771,8 +1717,12 @@ def emit_eds_function(indent, fn_name, val, type_xml):
|
||||
X(f'{indent}\t</Properties>')
|
||||
X(f'{indent}</Function>')
|
||||
|
||||
def emit_eds_table_properties(indent, src_name, table_name, t):
|
||||
"""Свойства таблицы: 38 узлов в порядке выгрузки платформы."""
|
||||
def emit_eds_table_properties(indent, src_name, table_name, t, char_xml, default_forms_xml):
|
||||
"""Свойства таблицы: 38 узлов в порядке выгрузки платформы.
|
||||
|
||||
char_xml и default_forms_xml — уже собранные блоки <Characteristics> и четыре слота
|
||||
<Default*Form>: их рендерит вызывающий навык своим эмиттером. Так тело не зависит
|
||||
от хелперов конкретного навыка и годится для копирования (check-inline-drift)."""
|
||||
i = indent
|
||||
t = t or {}
|
||||
tbl_synonym = t['synonym'] if t.get('synonym') is not None else split_camel_case(table_name)
|
||||
@@ -1809,7 +1759,10 @@ def emit_eds_table_properties(indent, src_name, table_name, t):
|
||||
X(f'{i}<UnfilledParentValue xsi:type="xs:string"/>')
|
||||
else:
|
||||
X(f'{i}<UnfilledParentValue xsi:nil="true"/>')
|
||||
emit_characteristics(i, t.get('characteristics'))
|
||||
if char_xml:
|
||||
X(char_xml.rstrip('\r\n'))
|
||||
else:
|
||||
X(f'{i}<Characteristics/>')
|
||||
|
||||
X(f'{i}<UseStandardCommands>{"false" if t.get("useStandardCommands") is False else "true"}</UseStandardCommands>')
|
||||
X(f'{i}<QuickChoice>{"true" if t.get("quickChoice") is True else "false"}</QuickChoice>')
|
||||
@@ -1827,9 +1780,12 @@ def emit_eds_table_properties(indent, src_name, table_name, t):
|
||||
X(f'{i}<ChoiceDataGetModeOnInputByString>{t.get("choiceDataGetModeOnInputByString") or "Directly"}</ChoiceDataGetModeOnInputByString>')
|
||||
X(f'{i}<ChoiceHistoryOnInput>{t.get("choiceHistoryOnInput") or "Auto"}</ChoiceHistoryOnInput>')
|
||||
|
||||
for form_tag in ('DefaultObjectForm', 'DefaultRecordForm', 'DefaultListForm', 'DefaultChoiceForm'):
|
||||
key = form_tag[0].lower() + form_tag[1:]
|
||||
emit_form_ref(i, form_tag, t.get(key))
|
||||
# Пустая строка — четыре слота всё равно обязаны быть: в свойствах таблицы их ровно 38.
|
||||
if default_forms_xml:
|
||||
X(default_forms_xml.rstrip('\r\n'))
|
||||
else:
|
||||
for form_tag in ('DefaultObjectForm', 'DefaultRecordForm', 'DefaultListForm', 'DefaultChoiceForm'):
|
||||
X(f'{i}<{form_tag}/>')
|
||||
for pres_tag in ('ObjectPresentation', 'ExtendedObjectPresentation', 'RecordPresentation',
|
||||
'ExtendedRecordPresentation', 'ListPresentation', 'ExtendedListPresentation', 'Explanation'):
|
||||
key = pres_tag[0].lower() + pres_tag[1:]
|
||||
@@ -1855,9 +1811,10 @@ EDS_TABLE_GENERATED_TYPES = (
|
||||
)
|
||||
|
||||
|
||||
def build_eds_table_xml(src_name, table_name, entry, fields_xml):
|
||||
"""Отдельный XML-документ таблицы. fields_xml — уже собранные узлы <Field>: их рендерит
|
||||
вызывающий навык своим эмиттером реквизита, поэтому тело не зависит от того, какой это навык.
|
||||
def build_eds_table_xml(src_name, table_name, entry, fields_xml, char_xml, default_forms_xml):
|
||||
"""Отдельный XML-документ таблицы. fields_xml, char_xml, default_forms_xml — уже собранные
|
||||
узлы: их рендерит вызывающий навык своими эмиттерами, поэтому тело не зависит от того,
|
||||
какой это навык.
|
||||
Возвращает строку: X пишет в общий список строк,
|
||||
поэтому «перехват» — запомнить длину, отдать эмиттерам, срезать добавленное
|
||||
(в ps1-порте тот же приём выражен через StringBuilder — различие рантаймов, не логики)."""
|
||||
@@ -1877,7 +1834,7 @@ def build_eds_table_xml(src_name, table_name, entry, fields_xml):
|
||||
X('\t\t</InternalInfo>')
|
||||
|
||||
X('\t\t<Properties>')
|
||||
emit_eds_table_properties('\t\t\t', src_name, table_name, entry['props'])
|
||||
emit_eds_table_properties('\t\t\t', src_name, table_name, entry['props'], char_xml, default_forms_xml)
|
||||
X('\t\t</Properties>')
|
||||
|
||||
if fields_xml:
|
||||
@@ -1893,10 +1850,6 @@ def build_eds_table_xml(src_name, table_name, entry, fields_xml):
|
||||
del lines[before:]
|
||||
return chunk
|
||||
|
||||
# ============================================================
|
||||
# DSL key normalization
|
||||
# ============================================================
|
||||
|
||||
|
||||
def resolve_operation_key(key):
|
||||
k = key.lower().strip()
|
||||
@@ -2236,6 +2189,15 @@ def process_add(add_def):
|
||||
src_dir = os.path.join(os.path.dirname(resolved_path), obj_name)
|
||||
tables_dir = os.path.join(src_dir, "Tables")
|
||||
for tbl_name, entry in get_eds_tables(items).items():
|
||||
# Характеристики и слоты форм точечным добавлением не задаются: первые требуют
|
||||
# эмиттера характеристик (живёт в meta-compile), вторые назначает form-add при
|
||||
# добавлении формы. Молча проглотить ключ нельзя — модель решит, что он сработал.
|
||||
tv = entry['props'] or {}
|
||||
bad_key = next((k for k in ('characteristics', 'defaultObjectForm', 'defaultRecordForm',
|
||||
'defaultListForm', 'defaultChoiceForm') if tv.get(k)), None)
|
||||
if bad_key:
|
||||
warn(f"Ключ '{bad_key}' не поддержан при добавлении таблицы: форму назначает form-add, характеристики — meta-compile. Таблица '{tbl_name}' пропущена.")
|
||||
continue
|
||||
if tbl_name in existing_names:
|
||||
warn(f"Table '{tbl_name}' already exists, skipping")
|
||||
continue
|
||||
@@ -2247,7 +2209,7 @@ def process_add(add_def):
|
||||
for f in entry["fields"]:
|
||||
field_parts.append(build_attribute_fragment(parse_attribute_shorthand(f), "eds-field", "\t\t\t", "Field"))
|
||||
fields_xml = "\r\n".join(field_parts)
|
||||
table_xml = build_eds_table_xml(obj_name, tbl_name, entry, fields_xml)
|
||||
table_xml = build_eds_table_xml(obj_name, tbl_name, entry, fields_xml, '', '')
|
||||
os.makedirs(tables_dir, exist_ok=True)
|
||||
with open(table_path, "w", encoding="utf-8-sig", newline="") as fh:
|
||||
fh.write(table_xml.rstrip("\r\n"))
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "Таблица с формой по умолчанию: отказ с объяснением, а не тихий сбой",
|
||||
"setup": "empty-config",
|
||||
"preRun": [
|
||||
{
|
||||
"script": "meta-compile/scripts/meta-compile",
|
||||
"input": {
|
||||
"type": "ExternalDataSource",
|
||||
"name": "PG",
|
||||
"tables": { "products": { "keyFields": ["id"], "fields": ["id: Number(10,0)"] } }
|
||||
},
|
||||
"args": { "-JsonPath": "{inputFile}", "-OutputDir": "{workDir}" }
|
||||
}
|
||||
],
|
||||
"params": { "objectPath": "ExternalDataSources/PG.xml" },
|
||||
"input": {
|
||||
"add": {
|
||||
"tables": {
|
||||
"sales": {
|
||||
"defaultListForm": "ФормаСписка",
|
||||
"fields": ["id: Number(10,0)"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"expect": {
|
||||
"stdoutContains": ["не поддержан при добавлении таблицы", "form-add"],
|
||||
"filesAbsent": ["ExternalDataSources/PG/Tables/sales.xml"],
|
||||
"fileNotContains": [
|
||||
{ "file": "ExternalDataSources/PG.xml", "text": "<Table>sales</Table>" }
|
||||
]
|
||||
}
|
||||
}
|
||||
+252
@@ -0,0 +1,252 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
||||
<Configuration uuid="UUID-001">
|
||||
<InternalInfo>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-002</xr:ClassId>
|
||||
<xr:ObjectId>UUID-003</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-004</xr:ClassId>
|
||||
<xr:ObjectId>UUID-005</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-006</xr:ClassId>
|
||||
<xr:ObjectId>UUID-007</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-008</xr:ClassId>
|
||||
<xr:ObjectId>UUID-009</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-010</xr:ClassId>
|
||||
<xr:ObjectId>UUID-011</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-012</xr:ClassId>
|
||||
<xr:ObjectId>UUID-013</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-014</xr:ClassId>
|
||||
<xr:ObjectId>UUID-015</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
</InternalInfo>
|
||||
<Properties>
|
||||
<Name>TestConfig</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>TestConfig</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
<NamePrefix/>
|
||||
<ConfigurationExtensionCompatibilityMode>Version8_3_24</ConfigurationExtensionCompatibilityMode>
|
||||
<DefaultRunMode>ManagedApplication</DefaultRunMode>
|
||||
<UsePurposes>
|
||||
<v8:Value xsi:type="app:ApplicationUsePurpose">PlatformApplication</v8:Value>
|
||||
</UsePurposes>
|
||||
<ScriptVariant>Russian</ScriptVariant>
|
||||
<DefaultRoles/>
|
||||
<Vendor/>
|
||||
<Version/>
|
||||
<UpdateCatalogAddress/>
|
||||
<IncludeHelpInContents>false</IncludeHelpInContents>
|
||||
<UseManagedFormInOrdinaryApplication>false</UseManagedFormInOrdinaryApplication>
|
||||
<UseOrdinaryFormInManagedApplication>false</UseOrdinaryFormInManagedApplication>
|
||||
<AdditionalFullTextSearchDictionaries/>
|
||||
<CommonSettingsStorage/>
|
||||
<ReportsUserSettingsStorage/>
|
||||
<ReportsVariantsStorage/>
|
||||
<FormDataSettingsStorage/>
|
||||
<DynamicListsUserSettingsStorage/>
|
||||
<URLExternalDataStorage/>
|
||||
<Content/>
|
||||
<DefaultReportForm/>
|
||||
<DefaultReportVariantForm/>
|
||||
<DefaultReportSettingsForm/>
|
||||
<DefaultReportAppearanceTemplate/>
|
||||
<DefaultDynamicListSettingsForm/>
|
||||
<DefaultSearchForm/>
|
||||
<DefaultDataHistoryChangeHistoryForm/>
|
||||
<DefaultDataHistoryVersionDataForm/>
|
||||
<DefaultDataHistoryVersionDifferencesForm/>
|
||||
<DefaultCollaborationSystemUsersChoiceForm/>
|
||||
<RequiredMobileApplicationPermissions/>
|
||||
<UsedMobileApplicationFunctionalities>
|
||||
<app:functionality>
|
||||
<app:functionality>Biometrics</app:functionality>
|
||||
<app:use>true</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Location</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>BackgroundLocation</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>BluetoothPrinters</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>WiFiPrinters</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Contacts</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Calendars</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>PushNotifications</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>LocalNotifications</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>InAppPurchases</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>PersonalComputerFileExchange</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Ads</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>NumberDialing</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>CallProcessing</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>CallLog</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>AutoSendSMS</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>ReceiveSMS</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>SMSLog</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Camera</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Microphone</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>MusicLibrary</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>PictureAndVideoLibraries</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>AudioPlaybackAndVibration</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>BackgroundAudioPlaybackAndVibration</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>InstallPackages</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>OSBackup</app:functionality>
|
||||
<app:use>true</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>ApplicationUsageStatistics</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>BarcodeScanning</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>BackgroundAudioRecording</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>AllFilesAccess</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Videoconferences</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>NFC</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>DocumentScanning</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>SpeechToText</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Geofences</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>IncomingShareRequests</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>AllIncomingShareRequestsTypesProcessing</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
</UsedMobileApplicationFunctionalities>
|
||||
<StandaloneConfigurationRestrictionRoles/>
|
||||
<MobileApplicationURLs/>
|
||||
<AllowedIncomingShareRequestTypes/>
|
||||
<MainClientApplicationWindowMode>Normal</MainClientApplicationWindowMode>
|
||||
<DefaultInterface/>
|
||||
<DefaultStyle/>
|
||||
<DefaultLanguage>Language.Русский</DefaultLanguage>
|
||||
<BriefInformation/>
|
||||
<DetailedInformation/>
|
||||
<Copyright/>
|
||||
<VendorInformationAddress/>
|
||||
<ConfigurationInformationAddress/>
|
||||
<DataLockControlMode>Managed</DataLockControlMode>
|
||||
<ObjectAutonumerationMode>NotAutoFree</ObjectAutonumerationMode>
|
||||
<ModalityUseMode>DontUse</ModalityUseMode>
|
||||
<SynchronousPlatformExtensionAndAddInCallUseMode>DontUse</SynchronousPlatformExtensionAndAddInCallUseMode>
|
||||
<InterfaceCompatibilityMode>TaxiEnableVersion8_2</InterfaceCompatibilityMode>
|
||||
<DatabaseTablespacesUseMode>DontUse</DatabaseTablespacesUseMode>
|
||||
<CompatibilityMode>Version8_3_24</CompatibilityMode>
|
||||
<DefaultConstantsForm/>
|
||||
</Properties>
|
||||
<ChildObjects>
|
||||
<Language>Русский</Language>
|
||||
<ExternalDataSource>PG</ExternalDataSource>
|
||||
</ChildObjects>
|
||||
</Configuration>
|
||||
</MetaDataObject>
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ClientApplicationInterface xmlns="http://v8.1c.ru/8.2/managed-application/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="InterfaceLayouter">
|
||||
<top>
|
||||
<panel id="UUID-001">
|
||||
<uuid>UUID-002</uuid>
|
||||
</panel>
|
||||
</top>
|
||||
<left>
|
||||
<panel id="UUID-003">
|
||||
<uuid>UUID-004</uuid>
|
||||
</panel>
|
||||
</left>
|
||||
<panelDef id="UUID-004"/>
|
||||
<panelDef id="UUID-005"/>
|
||||
<panelDef id="UUID-006"/>
|
||||
<panelDef id="UUID-002"/>
|
||||
<panelDef id="UUID-007"/>
|
||||
</ClientApplicationInterface>
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
||||
<ExternalDataSource uuid="UUID-001">
|
||||
<InternalInfo>
|
||||
<xr:GeneratedType name="ExternalDataSourceManager.PG" category="Manager">
|
||||
<xr:TypeId>UUID-002</xr:TypeId>
|
||||
<xr:ValueId>UUID-003</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
<xr:GeneratedType name="ExternalDataSourceTablesManager.PG" category="TablesManager">
|
||||
<xr:TypeId>UUID-004</xr:TypeId>
|
||||
<xr:ValueId>UUID-005</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
<xr:GeneratedType name="ExternalDataSourceCubesManager.PG" category="CubesManager">
|
||||
<xr:TypeId>UUID-006</xr:TypeId>
|
||||
<xr:ValueId>UUID-007</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
</InternalInfo>
|
||||
<Properties>
|
||||
<Name>PG</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>PG</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
<DataLockControlMode>Automatic</DataLockControlMode>
|
||||
</Properties>
|
||||
<ChildObjects>
|
||||
<Table>products</Table>
|
||||
</ChildObjects>
|
||||
</ExternalDataSource>
|
||||
</MetaDataObject>
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
||||
<Table uuid="UUID-001">
|
||||
<InternalInfo>
|
||||
<xr:GeneratedType name="ExternalDataSourceTableManager.PG.products" category="Manager">
|
||||
<xr:TypeId>UUID-002</xr:TypeId>
|
||||
<xr:ValueId>UUID-003</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
<xr:GeneratedType name="ExternalDataSourceTableObject.PG.products" category="Object">
|
||||
<xr:TypeId>UUID-004</xr:TypeId>
|
||||
<xr:ValueId>UUID-005</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
<xr:GeneratedType name="ExternalDataSourceTableRef.PG.products" category="Ref">
|
||||
<xr:TypeId>UUID-006</xr:TypeId>
|
||||
<xr:ValueId>UUID-007</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
<xr:GeneratedType name="ExternalDataSourceTableList.PG.products" category="List">
|
||||
<xr:TypeId>UUID-008</xr:TypeId>
|
||||
<xr:ValueId>UUID-009</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
<xr:GeneratedType name="ExternalDataSourceTableRecord.PG.products" category="Record">
|
||||
<xr:TypeId>UUID-010</xr:TypeId>
|
||||
<xr:ValueId>UUID-011</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
<xr:GeneratedType name="ExternalDataSourceTableRecordSet.PG.products" category="RecordSet">
|
||||
<xr:TypeId>UUID-012</xr:TypeId>
|
||||
<xr:ValueId>UUID-013</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
<xr:GeneratedType name="ExternalDataSourceTableRecordKey.PG.products" category="RecordKey">
|
||||
<xr:TypeId>UUID-014</xr:TypeId>
|
||||
<xr:ValueId>UUID-015</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
<xr:GeneratedType name="ExternalDataSourceTableRecordManager.PG.products" category="RecordManager">
|
||||
<xr:TypeId>UUID-016</xr:TypeId>
|
||||
<xr:ValueId>UUID-017</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
</InternalInfo>
|
||||
<Properties>
|
||||
<Name>products</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>products</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
<TableType>Table</TableType>
|
||||
<NameInDataSource>products</NameInDataSource>
|
||||
<ExpressionInDataSource/>
|
||||
<TableDataType>NonobjectData</TableDataType>
|
||||
<KeyFields>
|
||||
<xr:Field>ExternalDataSource.PG.Table.products.Field.id</xr:Field>
|
||||
</KeyFields>
|
||||
<PresentationField/>
|
||||
<ParentField/>
|
||||
<UnfilledParentValue xsi:nil="true"/>
|
||||
<Characteristics/>
|
||||
<UseStandardCommands>true</UseStandardCommands>
|
||||
<QuickChoice>false</QuickChoice>
|
||||
<InputByString/>
|
||||
<CreateOnInput>Auto</CreateOnInput>
|
||||
<SearchStringModeOnInputByString>Begin</SearchStringModeOnInputByString>
|
||||
<ChoiceDataGetModeOnInputByString>Directly</ChoiceDataGetModeOnInputByString>
|
||||
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
|
||||
<DefaultObjectForm/>
|
||||
<DefaultRecordForm/>
|
||||
<DefaultListForm/>
|
||||
<DefaultChoiceForm/>
|
||||
<ObjectPresentation/>
|
||||
<ExtendedObjectPresentation/>
|
||||
<RecordPresentation/>
|
||||
<ExtendedRecordPresentation/>
|
||||
<ListPresentation/>
|
||||
<ExtendedListPresentation/>
|
||||
<Explanation/>
|
||||
<IncludeHelpInContents>false</IncludeHelpInContents>
|
||||
<ReadOnly>false</ReadOnly>
|
||||
<TransactionsIsolationLevel>Auto</TransactionsIsolationLevel>
|
||||
<DataVersionField/>
|
||||
<EditType>InDialog</EditType>
|
||||
<BasedOn/>
|
||||
<DataLockFields/>
|
||||
<DataLockControlMode>Automatic</DataLockControlMode>
|
||||
</Properties>
|
||||
<ChildObjects>
|
||||
<Field uuid="UUID-018">
|
||||
<Properties>
|
||||
<Name>id</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>id</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
<Type>
|
||||
<v8:Type>xs:decimal</v8:Type>
|
||||
<v8:NumberQualifiers>
|
||||
<v8:Digits>10</v8:Digits>
|
||||
<v8:FractionDigits>0</v8:FractionDigits>
|
||||
<v8:AllowedSign>Any</v8:AllowedSign>
|
||||
</v8:NumberQualifiers>
|
||||
</Type>
|
||||
<PasswordMode>false</PasswordMode>
|
||||
<Format/>
|
||||
<EditFormat/>
|
||||
<ToolTip/>
|
||||
<MarkNegatives>false</MarkNegatives>
|
||||
<Mask/>
|
||||
<MultiLine>false</MultiLine>
|
||||
<ExtendedEdit>false</ExtendedEdit>
|
||||
<MinValue xsi:nil="true"/>
|
||||
<MaxValue xsi:nil="true"/>
|
||||
<FillFromFillingValue>false</FillFromFillingValue>
|
||||
<FillValue xsi:type="xs:decimal">0</FillValue>
|
||||
<FillChecking>DontCheck</FillChecking>
|
||||
<ChoiceParameterLinks/>
|
||||
<ChoiceParameters/>
|
||||
<QuickChoice>Auto</QuickChoice>
|
||||
<CreateOnInput>Auto</CreateOnInput>
|
||||
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
|
||||
<ChoiceForm/>
|
||||
<NameInDataSource>id</NameInDataSource>
|
||||
<ReadOnly>false</ReadOnly>
|
||||
<AllowNull>false</AllowNull>
|
||||
</Properties>
|
||||
</Field>
|
||||
</ChildObjects>
|
||||
</Table>
|
||||
</MetaDataObject>
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
||||
<Language uuid="UUID-001">
|
||||
<Properties>
|
||||
<Name>Русский</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Русский</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
<LanguageCode>ru</LanguageCode>
|
||||
</Properties>
|
||||
</Language>
|
||||
</MetaDataObject>
|
||||
@@ -753,6 +753,34 @@ for (const family of FAMILIES) {
|
||||
if (l !== lang || declared.has(skill) || !fns.has(fnName)) continue;
|
||||
errors.push(`${family.name} [${lang}]: ${skill} содержит ${fnName}, но в реестре не объявлен`);
|
||||
}
|
||||
|
||||
// 4. Копия обязана быть не только ИДЕНТИЧНОЙ, но и РАЗРЕШИМОЙ: всё, что её тело зовёт,
|
||||
// должно быть определено в том же навыке. Иначе получаем вызов несуществующей функции —
|
||||
// в PowerShell это тихий ложный успех (CommandNotFoundException, но код возврата 0),
|
||||
// а в python трейсбек, то есть ещё и расхождение потоков ошибок между портами.
|
||||
// Что считать «вызовом своей функции»: имя, определённое в НАВЫКЕ-ЭТАЛОНЕ. Командлеты и
|
||||
// встроенные функции в эталоне не определены, поэтому список исключений не нужен.
|
||||
for (const { v, members } of effective) {
|
||||
const authorityFns = index.get(`${v.authority}|${lang}`);
|
||||
if (!authorityFns) continue;
|
||||
for (const skill of members) {
|
||||
if (skill === v.authority) continue;
|
||||
const skillFns = index.get(`${skill}|${lang}`);
|
||||
if (!skillFns) continue;
|
||||
for (const { file, body: bodyLines } of copiesOf(index, skill, lang, fnName)) {
|
||||
const body = bodyLines.join('\n'); // тело хранится списком строк
|
||||
const called = lang === 'ps1'
|
||||
? body.match(/(?<![\w-])[A-Z][a-z]+-[A-Z]\w*/g) || []
|
||||
: body.match(/(?<![\w.])[a-z_]\w*(?=\s*\()/g) || [];
|
||||
const missing = [...new Set(called)]
|
||||
.filter((c) => c !== fnName && authorityFns.has(c) && !skillFns.has(c));
|
||||
if (missing.length) {
|
||||
const label = file.startsWith(`${skill}.`) ? skill : `${skill} (${file})`;
|
||||
errors.push(`${family.name} [${lang}]: ${label} зовёт ${missing.join(', ')} — этих функций в навыке нет, копия неразрешима`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Долг: отклоняющийся вариант без обоснования. Базовым считаем самый массовый — ему
|
||||
|
||||
Reference in New Issue
Block a user