mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-02 17:57:45 +03:00
feat(meta-compile,meta-decompile): поддержка типа FunctionalOption (v1.54/v0.45)
18-й тип, 1381 объект acc+erp. Компилятор НЕ поддерживал FO вовсе (новый тип с нуля): +validTypes/typePluralMap/dispatch/Emit-FunctionalOptionProperties + рус.синоним ФункциональнаяОпция. FO без InternalInfo/ChildObjects/модулей — Emit-InternalInfo уже раннее-возвращает без generatedTypes-записи, ChildObjects/ модули гейтятся списками типов → FO их не получает. - Свойства: Location (хранилище значения), PrivilegedGetMode (дефолт true — корпус 2864/2864), Content (список зависимых объектов → <xr:Object>). Декомпилятор снят гейт +FO; захват location/privilegedGetMode(omit-true)/content. - Прощающий ввод MDObjectRef-путей (Normalize-MDObjectRef): русские корни метаданных+подвидов (Документ→Document/ТабличнаяЧасть→TabularSection/Реквизит→ Attribute/Измерение→Dimension/Ресурс→Resource/…) на чётных позициях-видах; имена не трогаются. Только компилятор (декомпилятор пишет полный англ. путь → роундтрип byte-exact). Location/Content — полные внешние ссылки, self-формы нет. ПОЛНЫЙ КОРПУС 1381: 1380 byte-exact order-preserved + 1 MAX_PATH-артефакт харнеса (имя 157 симв.; объект компилируется в короткий путь ✓). Регресс 55/55 ps1+py, ps1==py identical. spec §7.7a, кейс functional-option. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
47134425f3
commit
edc8474ddd
@@ -1,4 +1,4 @@
|
||||
# meta-compile v1.53 — Compile 1C metadata object from JSON
|
||||
# meta-compile v1.54 — Compile 1C metadata object from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -197,6 +197,7 @@ $script:objectTypeSynonyms = @{
|
||||
"HTTPСервис" = "HTTPService"
|
||||
"ВебСервис" = "WebService"
|
||||
"ОпределяемыйТип" = "DefinedType"
|
||||
"ФункциональнаяОпция" = "FunctionalOption"
|
||||
}
|
||||
|
||||
# Enum property value synonyms — model often gets these slightly wrong
|
||||
@@ -346,7 +347,7 @@ $validTypes = @("Catalog","Document","Enum","Constant","InformationRegister","Ac
|
||||
"AccountingRegister","CalculationRegister","ChartOfAccounts","ChartOfCharacteristicTypes",
|
||||
"ChartOfCalculationTypes","BusinessProcess","Task","ExchangePlan","DocumentJournal",
|
||||
"Report","DataProcessor","CommonModule","ScheduledJob","EventSubscription",
|
||||
"HTTPService","WebService","DefinedType")
|
||||
"HTTPService","WebService","DefinedType","FunctionalOption")
|
||||
if ($objType -notin $validTypes) {
|
||||
Write-Error "Unsupported type: $objType. Valid: $($validTypes -join ', ')"
|
||||
exit 1
|
||||
@@ -680,6 +681,31 @@ $script:fillEmptyRefWords = @('emptyref','пустаяссылка')
|
||||
$script:fillEnumValWords = @('enumvalue','значениеперечисления')
|
||||
$script:fillBoolTrue = @('true','истина','да')
|
||||
$script:fillBoolFalse = @('false','ложь','нет')
|
||||
# Прощающий ввод MDObjectRef-путей (Location/Content функц. опции, registerRecords и т.п.): русские корни
|
||||
# метаданных + подвиды → английские. Виды стоят на ЧЁТНЫХ позициях (0,2,4…), имена (нечётные) не трогаем.
|
||||
# Английские пути проходят без изменений (в мапе только русские ключи) → роундтрип byte-exact сохраняется.
|
||||
$script:mdRefRoots = @{
|
||||
'справочник'='Catalog'; 'документ'='Document'; 'перечисление'='Enum'; 'константа'='Constant';
|
||||
'регистрсведений'='InformationRegister'; 'регистрнакопления'='AccumulationRegister';
|
||||
'регистрбухгалтерии'='AccountingRegister'; 'регистррасчета'='CalculationRegister'; 'регистррасчёта'='CalculationRegister';
|
||||
'плансчетов'='ChartOfAccounts'; 'планвидовхарактеристик'='ChartOfCharacteristicTypes';
|
||||
'планвидоврасчета'='ChartOfCalculationTypes'; 'планвидоврасчёта'='ChartOfCalculationTypes';
|
||||
'планобмена'='ExchangePlan'; 'бизнеспроцесс'='BusinessProcess'; 'задача'='Task';
|
||||
'журналдокументов'='DocumentJournal'; 'отчет'='Report'; 'отчёт'='Report'; 'обработка'='DataProcessor';
|
||||
'табличнаячасть'='TabularSection'; 'реквизит'='Attribute'; 'измерение'='Dimension'; 'ресурс'='Resource';
|
||||
'стандартныйреквизит'='StandardAttribute'; 'значениеперечисления'='EnumValue'; 'команда'='Command';
|
||||
'признакучета'='AccountingFlag'; 'признакучёта'='AccountingFlag'
|
||||
}
|
||||
function Normalize-MDObjectRef {
|
||||
param([string]$ref)
|
||||
if (-not $ref -or -not $ref.Contains('.')) { return $ref }
|
||||
$parts = $ref -split '\.'
|
||||
for ($k = 0; $k -lt $parts.Count; $k += 2) {
|
||||
$t = $script:mdRefRoots[$parts[$k].ToLower()]
|
||||
if ($t) { $parts[$k] = $t }
|
||||
}
|
||||
return ($parts -join '.')
|
||||
}
|
||||
# Значения платформенного перечисления ВидСчета (ent:AccountType) — FillValue стандартного реквизита Тип у Плана счетов.
|
||||
$script:accountTypeValues = @('Active','Passive','ActivePassive')
|
||||
# XxxRef (тип реквизита) → корень DTR-пути (для разворота короткой записи значения).
|
||||
@@ -2472,6 +2498,31 @@ function Emit-DefinedTypeProperties {
|
||||
if ($vt) { Emit-ValueType $i $vt } else { X "$i<Type/>" }
|
||||
}
|
||||
|
||||
function Emit-FunctionalOptionProperties {
|
||||
param([string]$indent)
|
||||
$i = $indent
|
||||
|
||||
X "$i<Name>$(Esc-Xml $objName)</Name>"
|
||||
Emit-MLText $i "Synonym" $synonym
|
||||
if ($def.comment) { X "$i<Comment>$(Esc-XmlText $def.comment)</Comment>" } else { X "$i<Comment/>" }
|
||||
# Location — хранилище значения опции (Constant.X / InformationRegister.X.Resource.Y / <Тип>.X.Attribute.Y).
|
||||
# Ссылка verbatim (MDObjectRef-путь; принимаем location или value).
|
||||
$loc = if ($def.location) { "$($def.location)" } elseif ($def.value) { "$($def.value)" } else { "" }
|
||||
if ($loc) { X "$i<Location>$(Esc-Xml (Normalize-MDObjectRef $loc))</Location>" } else { X "$i<Location/>" }
|
||||
# PrivilegedGetMode — привилегированный режим чтения (корпус 2864/2864 = true → дефолт true).
|
||||
X "$i<PrivilegedGetMode>$(if (Get-BoolProp 'privilegedGetMode' $true) { 'true' } else { 'false' })</PrivilegedGetMode>"
|
||||
# Content — объекты, зависящие от опции (список MDObjectRef-путей к реквизитам/измерениям/ресурсам). omit-on-empty.
|
||||
$content = @()
|
||||
if ($def.content) { $content = @($def.content) }
|
||||
if ($content.Count -gt 0) {
|
||||
X "$i<Content>"
|
||||
foreach ($obj in $content) { X "$i`t<xr:Object>$(Esc-Xml (Normalize-MDObjectRef "$obj"))</xr:Object>" }
|
||||
X "$i</Content>"
|
||||
} else {
|
||||
X "$i<Content/>"
|
||||
}
|
||||
}
|
||||
|
||||
function Emit-CommonModuleProperties {
|
||||
param([string]$indent)
|
||||
$i = $indent
|
||||
@@ -3565,6 +3616,7 @@ switch ($objType) {
|
||||
"InformationRegister" { Emit-InformationRegisterProperties "`t`t`t" }
|
||||
"AccumulationRegister" { Emit-AccumulationRegisterProperties "`t`t`t" }
|
||||
"DefinedType" { Emit-DefinedTypeProperties "`t`t`t" }
|
||||
"FunctionalOption" { Emit-FunctionalOptionProperties "`t`t`t" }
|
||||
"CommonModule" { Emit-CommonModuleProperties "`t`t`t" }
|
||||
"ScheduledJob" { Emit-ScheduledJobProperties "`t`t`t" }
|
||||
"EventSubscription" { Emit-EventSubscriptionProperties "`t`t`t" }
|
||||
@@ -3848,6 +3900,7 @@ $script:typePluralMap = @{
|
||||
"HTTPService" = "HTTPServices"
|
||||
"WebService" = "WebServices"
|
||||
"DefinedType" = "DefinedTypes"
|
||||
"FunctionalOption" = "FunctionalOptions"
|
||||
}
|
||||
|
||||
$typePlural = $script:typePluralMap[$objType]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# meta-compile v1.53 — Compile 1C metadata object from JSON
|
||||
# meta-compile v1.54 — Compile 1C metadata object from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -314,6 +314,7 @@ object_type_synonyms = {
|
||||
'HTTPСервис': 'HTTPService',
|
||||
'ВебСервис': 'WebService',
|
||||
'ОпределяемыйТип': 'DefinedType',
|
||||
'ФункциональнаяОпция': 'FunctionalOption',
|
||||
}
|
||||
|
||||
# Enum property value synonyms — model often gets these slightly wrong
|
||||
@@ -460,6 +461,7 @@ valid_types = [
|
||||
'BusinessProcess', 'Task', 'ExchangePlan', 'DocumentJournal',
|
||||
'Report', 'DataProcessor', 'CommonModule', 'ScheduledJob',
|
||||
'EventSubscription', 'HTTPService', 'WebService', 'DefinedType',
|
||||
'FunctionalOption',
|
||||
]
|
||||
if obj_type not in valid_types:
|
||||
print(f"Unsupported type: {obj_type}. Valid: {', '.join(valid_types)}", file=sys.stderr)
|
||||
@@ -707,6 +709,30 @@ fill_empty_ref_words = ('emptyref', 'пустаяссылка')
|
||||
fill_enum_val_words = ('enumvalue', 'значениеперечисления')
|
||||
fill_bool_true = ('true', 'истина', 'да')
|
||||
fill_bool_false = ('false', 'ложь', 'нет')
|
||||
# Прощающий ввод MDObjectRef-путей (Location/Content функц. опции): русские корни метаданных + подвиды →
|
||||
# английские. Виды на ЧЁТНЫХ позициях (0,2,4…); имена (нечётные) не трогаем. Английские пути неизменны.
|
||||
md_ref_roots = {
|
||||
'справочник': 'Catalog', 'документ': 'Document', 'перечисление': 'Enum', 'константа': 'Constant',
|
||||
'регистрсведений': 'InformationRegister', 'регистрнакопления': 'AccumulationRegister',
|
||||
'регистрбухгалтерии': 'AccountingRegister', 'регистррасчета': 'CalculationRegister', 'регистррасчёта': 'CalculationRegister',
|
||||
'плансчетов': 'ChartOfAccounts', 'планвидовхарактеристик': 'ChartOfCharacteristicTypes',
|
||||
'планвидоврасчета': 'ChartOfCalculationTypes', 'планвидоврасчёта': 'ChartOfCalculationTypes',
|
||||
'планобмена': 'ExchangePlan', 'бизнеспроцесс': 'BusinessProcess', 'задача': 'Task',
|
||||
'журналдокументов': 'DocumentJournal', 'отчет': 'Report', 'отчёт': 'Report', 'обработка': 'DataProcessor',
|
||||
'табличнаячасть': 'TabularSection', 'реквизит': 'Attribute', 'измерение': 'Dimension', 'ресурс': 'Resource',
|
||||
'стандартныйреквизит': 'StandardAttribute', 'значениеперечисления': 'EnumValue', 'команда': 'Command',
|
||||
'признакучета': 'AccountingFlag', 'признакучёта': 'AccountingFlag',
|
||||
}
|
||||
|
||||
def normalize_md_object_ref(ref):
|
||||
if not ref or '.' not in ref:
|
||||
return ref
|
||||
parts = ref.split('.')
|
||||
for k in range(0, len(parts), 2):
|
||||
t = md_ref_roots.get(parts[k].lower())
|
||||
if t:
|
||||
parts[k] = t
|
||||
return '.'.join(parts)
|
||||
# Значения платформенного перечисления ВидСчета (ent:AccountType) — FillValue реквизита Тип у Плана счетов.
|
||||
ACCOUNT_TYPE_VALUES = ('Active', 'Passive', 'ActivePassive')
|
||||
# «Только обороты» (<Turnover>) — предопределённый признак учёта субконто; токен в списке flags наравне с добавленными.
|
||||
@@ -2469,6 +2495,32 @@ def emit_defined_type_properties(indent):
|
||||
else:
|
||||
X(f'{i}<Type/>')
|
||||
|
||||
def emit_functional_option_properties(indent):
|
||||
i = indent
|
||||
X(f'{i}<Name>{esc_xml(obj_name)}</Name>')
|
||||
emit_mltext(i, 'Synonym', synonym)
|
||||
if defn.get('comment'):
|
||||
X(f'{i}<Comment>{esc_xml_text(str(defn["comment"]))}</Comment>')
|
||||
else:
|
||||
X(f'{i}<Comment/>')
|
||||
# Location — хранилище значения опции (ссылка verbatim; location или value).
|
||||
loc = str(defn['location']) if defn.get('location') else (str(defn['value']) if defn.get('value') else '')
|
||||
if loc:
|
||||
X(f'{i}<Location>{esc_xml(normalize_md_object_ref(loc))}</Location>')
|
||||
else:
|
||||
X(f'{i}<Location/>')
|
||||
# PrivilegedGetMode — дефолт true (корпус 2864/2864).
|
||||
X(f'{i}<PrivilegedGetMode>{"true" if get_bool_prop("privilegedGetMode", True) else "false"}</PrivilegedGetMode>')
|
||||
# Content — зависимые объекты (список MDObjectRef-путей). omit-on-empty.
|
||||
content = list(defn['content']) if defn.get('content') else []
|
||||
if content:
|
||||
X(f'{i}<Content>')
|
||||
for obj in content:
|
||||
X(f'{i}\t<xr:Object>{esc_xml(normalize_md_object_ref(str(obj)))}</xr:Object>')
|
||||
X(f'{i}</Content>')
|
||||
else:
|
||||
X(f'{i}<Content/>')
|
||||
|
||||
def emit_common_module_properties(indent):
|
||||
i = indent
|
||||
X(f'{i}<Name>{esc_xml(obj_name)}</Name>')
|
||||
@@ -3418,6 +3470,7 @@ property_emitters = {
|
||||
'InformationRegister': emit_information_register_properties,
|
||||
'AccumulationRegister': emit_accumulation_register_properties,
|
||||
'DefinedType': emit_defined_type_properties,
|
||||
'FunctionalOption': emit_functional_option_properties,
|
||||
'CommonModule': emit_common_module_properties,
|
||||
'ScheduledJob': emit_scheduled_job_properties,
|
||||
'EventSubscription': emit_event_subscription_properties,
|
||||
@@ -3687,6 +3740,7 @@ type_plural_map = {
|
||||
'HTTPService': 'HTTPServices',
|
||||
'WebService': 'WebServices',
|
||||
'DefinedType': 'DefinedTypes',
|
||||
'FunctionalOption': 'FunctionalOptions',
|
||||
}
|
||||
|
||||
type_plural = type_plural_map[obj_type]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# meta-decompile v0.44 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
|
||||
# meta-decompile v0.45 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
#
|
||||
# Поддержаны: Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document,
|
||||
@@ -92,8 +92,8 @@ foreach ($c in $rootEl.ChildNodes) { if ($c.NodeType -eq 'Element') { $objNode =
|
||||
if (-not $objNode) { [Console]::Error.WriteLine("meta-decompile: пустой MetaDataObject"); exit 3 }
|
||||
$objType = $objNode.LocalName
|
||||
|
||||
if ($objType -notin @('Catalog', 'ExchangePlan', 'ChartOfCharacteristicTypes', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'Document', 'InformationRegister', 'AccumulationRegister', 'AccountingRegister', 'CalculationRegister', 'BusinessProcess', 'Task', 'Enum', 'Report', 'DataProcessor', 'Constant', 'DefinedType')) {
|
||||
[Console]::Error.WriteLine("meta-decompile: тип '$objType' пока не поддержан (Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document, InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister, BusinessProcess, Task, Enum, Report, DataProcessor, Constant, DefinedType)"); exit 3
|
||||
if ($objType -notin @('Catalog', 'ExchangePlan', 'ChartOfCharacteristicTypes', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'Document', 'InformationRegister', 'AccumulationRegister', 'AccountingRegister', 'CalculationRegister', 'BusinessProcess', 'Task', 'Enum', 'Report', 'DataProcessor', 'Constant', 'DefinedType', 'FunctionalOption')) {
|
||||
[Console]::Error.WriteLine("meta-decompile: тип '$objType' пока не поддержан (Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document, InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister, BusinessProcess, Task, Enum, Report, DataProcessor, Constant, DefinedType, FunctionalOption)"); exit 3
|
||||
}
|
||||
|
||||
$props = $objNode.SelectSingleNode('md:Properties', $nsm)
|
||||
@@ -599,6 +599,16 @@ if ($objType -eq 'DefinedType') {
|
||||
$vt = Get-TypeShorthand ($props.SelectSingleNode('md:Type', $nsm))
|
||||
if ($vt) { $dsl['valueType'] = $vt }
|
||||
}
|
||||
# FunctionalOption — функциональная опция: Location (хранилище значения) + PrivilegedGetMode + Content (зависимые объекты).
|
||||
if ($objType -eq 'FunctionalOption') {
|
||||
$loc = P 'Location'; if ($loc) { $dsl['location'] = $loc }
|
||||
Add-BoolProp 'privilegedGetMode' 'PrivilegedGetMode' $true # корпус 2864/2864 true → дефолт true, ловим false
|
||||
$contentNode = $props.SelectSingleNode('md:Content', $nsm)
|
||||
if ($contentNode) {
|
||||
$items = @($contentNode.SelectNodes('xr:Object', $nsm) | ForEach-Object { $_.InnerText })
|
||||
if ($items.Count -gt 0) { $dsl['content'] = [System.Collections.ArrayList]@($items) }
|
||||
}
|
||||
}
|
||||
# Constant — богатый одиночный реквизит: Type + свойства значения (как у реквизита) + object-уровень.
|
||||
if ($objType -eq 'Constant') {
|
||||
$vt = Get-TypeShorthand ($props.SelectSingleNode('md:Type', $nsm))
|
||||
|
||||
Reference in New Issue
Block a user