feat(meta-compile,meta-decompile): состав плана обмена — Content.xml (v1.42/v0.31)

Соседний Ext/Content.xml (состав плана обмена: объекты-участники + признак
авторегистрации) был вне скоупа раундтрипа → при декомпиляции→компиляции состав
терялся (компилятор писал пустой <ExchangePlanContent/>, декомпилятор не захватывал).

DSL content/Состав: массив MDObjectRef — строка "Type.Name" (AutoRecord=Deny,
дефолт) / "Type.Name: autoRecord" (Allow; токен-признак autoRecord/АвтоРегистрация,
регистронезав.; прощающе : Allow/: Разрешить) ЛИБО объект {metadata, autoRecord:
bool|Allow/Deny/Разрешить/Запретить} (синонимы Метаданные/объект, АвтоРегистрация).
Декомпилятор пишет короткую строковую форму.

Class-2 фикс заголовка: пустой <ExchangePlanContent/> писался с 2 namespace,
реальный 1С — с 4 (+xmlns:xs/xsi); чинил и пустой шаблон.

Роундтрип 42 ЭП (acc+erp): match 39/42, TOTAL 146 без новых диффов (остаток —
известный хвост TS-LineNumber/FillValue-пробелы). Регресс 48/48 ps1+py, ps1↔py
identical. 1С-cert ✓ (пустой 4-ns корень + непустой состав); verify-snapshots
расширен: getStructuralDeps стабит объекты состава ЭП по MDObjectRef + стаб Constant.
spec §7.2a, кейс exchange-plan-content.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-07-06 12:55:08 +03:00
co-authored by Claude Opus 4.8
parent 126ce0bbd8
commit 11e7abfc3f
13 changed files with 567 additions and 9 deletions
+18
View File
@@ -177,6 +177,23 @@ function getStructuralDeps(input) {
}
}
break;
case 'ExchangePlan':
// Состав плана обмена (Content.xml) ссылается на объекты по MDObjectRef "Type.Name" —
// 1С требует их существования при загрузке. Стабим каждый.
if (inp.content) {
const entries = Array.isArray(inp.content) ? inp.content : [inp.content];
for (const e of entries) {
let ref = typeof e === 'string' ? e : (e.metadata || e['Метаданные'] || e['объект'] || '');
ref = String(ref).split(':')[0].trim(); // отбросить ": autoRecord"/флаг
const dot = ref.indexOf('.');
if (dot < 0) continue;
const t = ref.substring(0, dot);
const n = ref.substring(dot + 1);
const dsl = makeStubDSL(t, n);
if (dsl) deps.push({ type: t, name: n, dsl });
}
}
break;
}
}
return deps;
@@ -189,6 +206,7 @@ function makeStubDSL(type, name) {
case 'Catalog': return { type: 'Catalog', name };
case 'Document': return { type: 'Document', name };
case 'Enum': return { type: 'Enum', name, values: ['Значение1'] };
case 'Constant': return { type: 'Constant', name, valueType: 'Boolean' };
case 'InformationRegister': return { type: 'InformationRegister', name, dimensions: ['Ключ: String(10)'] };
case 'AccumulationRegister': return { type: 'AccumulationRegister', name, dimensions: ['Ключ: String(10)'], resources: ['Значение: Number(15,2)'] };
case 'ChartOfAccounts': return { type: 'ChartOfAccounts', name, codeLength: 4, descriptionLength: 100, maxExtDimensionCount: 0 };