mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-21 02:29:42 +03:00
feat(cfe-borrow,cfe-patch-method,cfe-validate): модули заимствованных объектов и пометка расширенного свойства
Объект заимствуют, чтобы дописать в него модуль, — теперь пустой файл модуля создаётся навыком, а не руками. Тип с единственным модулем (CommonModule, HTTPService, WebService) получает его без указаний, остальные — по -Module; -Module None отменяет. Существующий файл не перезаписывается никогда. Вместе с файлом проставляется <xr:PropertyState> со State=Extended. Замер по лестнице платформ 8.3.20…8.5.1: элемент появился в формате 2.19 (8.3.26), ниже платформа молча выбрасывает его при загрузке — отсюда гейт по версии формата. Имя свойства равно базовому имени файла модуля, у заимствованной формы — Form. Правило владения одно: пометку ставит тот, кто создал файл, поэтому её ставит и cfe-patch-method. Заодно закрыта перезапись при повторном заимствовании: прямая ветка писала XML уже заимствованного объекта начисто, унося собственные реквизиты расширения и регистрацию формы, — молча, с успешным отчётом. Повторный вызов теперь безопасен и служит способом дозаимствовать модуль. cfe-validate сверяет «файл модуля ↔ пометка» в обе стороны (предупреждение: перекос платформа принимает, но выгрузка Конфигуратора так не выглядит). Проверено: полный регресс 827/0/8 (ps1) и 824/0/11 (py), гарды 5/5, сквозной раундтрип на 8.3.26 и 8.3.27 — InternalInfo совпадает с выгрузкой платформы. Закрывает #70. Разбор и эталоны выгрузки — Romandredan. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
89f65ca6a6
commit
8fe727e32f
@@ -1,4 +1,4 @@
|
||||
# cfe-validate v1.11 — Validate 1C configuration extension structure (CFE)
|
||||
# cfe-validate v1.12 — Validate 1C configuration extension structure (CFE)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -107,7 +107,28 @@ function Get-FormatRank([string]$ver) {
|
||||
}
|
||||
|
||||
# --- Reference tables ---
|
||||
$guidPattern = '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'
|
||||
# Модули заимствованных объектов: тип → виды модулей. Имя свойства в <xr:PropertyState>
|
||||
# совпадает с базовым именем файла модуля. Копия таблицы есть в cfe-borrow (навыки автономны).
|
||||
$moduleKindsByType = @{
|
||||
"CommonModule"=@("Module"); "HTTPService"=@("Module"); "WebService"=@("Module")
|
||||
"Catalog"=@("ObjectModule","ManagerModule"); "Document"=@("ObjectModule","ManagerModule")
|
||||
"Report"=@("ObjectModule","ManagerModule"); "DataProcessor"=@("ObjectModule","ManagerModule")
|
||||
"ExchangePlan"=@("ObjectModule","ManagerModule")
|
||||
"ChartOfCharacteristicTypes"=@("ObjectModule","ManagerModule")
|
||||
"ChartOfAccounts"=@("ObjectModule","ManagerModule")
|
||||
"ChartOfCalculationTypes"=@("ObjectModule","ManagerModule")
|
||||
"BusinessProcess"=@("ObjectModule","ManagerModule"); "Task"=@("ObjectModule","ManagerModule")
|
||||
"InformationRegister"=@("RecordSetModule","ManagerModule")
|
||||
"AccumulationRegister"=@("RecordSetModule","ManagerModule")
|
||||
"AccountingRegister"=@("RecordSetModule","ManagerModule")
|
||||
"CalculationRegister"=@("RecordSetModule","ManagerModule")
|
||||
"Sequence"=@("RecordSetModule","ManagerModule")
|
||||
"Constant"=@("ValueManagerModule","ManagerModule")
|
||||
"Enum"=@("ManagerModule"); "DocumentJournal"=@("ManagerModule")
|
||||
"FilterCriterion"=@("ManagerModule")
|
||||
}
|
||||
|
||||
$guidPattern ='^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'
|
||||
$identPattern = '^[A-Za-z\u0410-\u042F\u0401\u0430-\u044F\u0451_][A-Za-z0-9\u0410-\u042F\u0401\u0430-\u044F\u0451_]*$'
|
||||
|
||||
# 7 fixed ClassIds for Configuration
|
||||
@@ -1234,6 +1255,48 @@ if ($defaultRoleNodes.Count -gt 0) {
|
||||
|
||||
if ($script:stopped) { & $finalize; exit 1 }
|
||||
|
||||
# --- Check 16: модуль заимствованного объекта и пометка расширенного свойства ---
|
||||
# Свойство <xr:PropertyState> появилось в формате 2.19 (8.3.26); ниже платформа его молча
|
||||
# выбрасывает, поэтому там проверять нечего. С 2.19 состояние обязано соответствовать факту:
|
||||
# есть файл модуля — есть пометка, и наоборот. Перекос платформа принимает (проверено на стенде),
|
||||
# но выгрузка Конфигуратора так не выглядит — отсюда предупреждение, а не ошибка.
|
||||
if ($versionRank -ge 219 -and $childObjNode) {
|
||||
$stateIssues = @()
|
||||
$stateChecked = 0
|
||||
foreach ($child in $childObjNode.ChildNodes) {
|
||||
if ($child.NodeType -ne 'Element') { continue }
|
||||
$typeName = $child.LocalName
|
||||
if (-not $moduleKindsByType.ContainsKey($typeName)) { continue }
|
||||
if (-not $childTypeDirMap.ContainsKey($typeName)) { continue }
|
||||
$objName = $child.InnerText.Trim()
|
||||
if (-not $objName) { continue }
|
||||
$typeDir = Join-Path $configDir $childTypeDirMap[$typeName]
|
||||
$objFile = Join-Path $typeDir "$objName.xml"
|
||||
if (-not (Test-Path $objFile)) { continue }
|
||||
$objText = [System.IO.File]::ReadAllText($objFile, [System.Text.Encoding]::UTF8)
|
||||
if ($objText -notmatch '<ObjectBelonging>Adopted</ObjectBelonging>') { continue }
|
||||
|
||||
foreach ($kind in $moduleKindsByType[$typeName]) {
|
||||
$stateChecked++
|
||||
$hasFile = Test-Path (Join-Path (Join-Path (Join-Path $typeDir $objName) "Ext") "$kind.bsl")
|
||||
$hasFlag = $objText -match "<xr:Property>$kind</xr:Property>"
|
||||
if ($hasFile -and -not $hasFlag) {
|
||||
$stateIssues += "$typeName.$objName — есть $kind.bsl, но нет <xr:PropertyState> для $kind"
|
||||
} elseif ($hasFlag -and -not $hasFile) {
|
||||
$stateIssues += "$typeName.$objName — есть <xr:PropertyState> для $kind, но нет $kind.bsl"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($stateChecked -gt 0) {
|
||||
if ($stateIssues.Count -eq 0) {
|
||||
Report-OK "16. Модули заимствованных объектов: пометки расширенных свойств согласованы ($stateChecked)"
|
||||
} else {
|
||||
foreach ($issue in $stateIssues) { Report-Warn "16. $issue" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# --- Breadcrumb: controlled methods (&ИзменениеИКонтроль) drift is not checked here ---
|
||||
$extRootDir = Split-Path $resolvedPath -Parent
|
||||
$ctrlCount = 0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# cfe-validate v1.11 — Validate 1C configuration extension XML structure (CFE)
|
||||
# cfe-validate v1.12 — Validate 1C configuration extension XML structure (CFE)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
"""Validates extension Configuration.xml: root, InternalInfo, extension properties, ChildObjects, borrowed objects."""
|
||||
import sys, os, argparse, re
|
||||
@@ -71,6 +71,27 @@ CHILD_OBJECT_TYPES = [
|
||||
'BusinessProcess', 'Task', 'IntegrationService',
|
||||
]
|
||||
|
||||
# Модули заимствованных объектов: тип → виды модулей. Имя свойства в <xr:PropertyState>
|
||||
# совпадает с базовым именем файла модуля. Копия таблицы есть в cfe-borrow (навыки автономны).
|
||||
MODULE_KINDS_BY_TYPE = {
|
||||
"CommonModule": ["Module"], "HTTPService": ["Module"], "WebService": ["Module"],
|
||||
"Catalog": ["ObjectModule", "ManagerModule"], "Document": ["ObjectModule", "ManagerModule"],
|
||||
"Report": ["ObjectModule", "ManagerModule"], "DataProcessor": ["ObjectModule", "ManagerModule"],
|
||||
"ExchangePlan": ["ObjectModule", "ManagerModule"],
|
||||
"ChartOfCharacteristicTypes": ["ObjectModule", "ManagerModule"],
|
||||
"ChartOfAccounts": ["ObjectModule", "ManagerModule"],
|
||||
"ChartOfCalculationTypes": ["ObjectModule", "ManagerModule"],
|
||||
"BusinessProcess": ["ObjectModule", "ManagerModule"], "Task": ["ObjectModule", "ManagerModule"],
|
||||
"InformationRegister": ["RecordSetModule", "ManagerModule"],
|
||||
"AccumulationRegister": ["RecordSetModule", "ManagerModule"],
|
||||
"AccountingRegister": ["RecordSetModule", "ManagerModule"],
|
||||
"CalculationRegister": ["RecordSetModule", "ManagerModule"],
|
||||
"Sequence": ["RecordSetModule", "ManagerModule"],
|
||||
"Constant": ["ValueManagerModule", "ManagerModule"],
|
||||
"Enum": ["ManagerModule"], "DocumentJournal": ["ManagerModule"],
|
||||
"FilterCriterion": ["ManagerModule"],
|
||||
}
|
||||
|
||||
# Type -> directory mapping
|
||||
CHILD_TYPE_DIR_MAP = {
|
||||
'Language': 'Languages', 'Subsystem': 'Subsystems', 'StyleItem': 'StyleItems', 'Style': 'Styles',
|
||||
@@ -1201,6 +1222,48 @@ def main():
|
||||
r.finalize(out_file)
|
||||
sys.exit(1)
|
||||
|
||||
# --- Check 16: модуль заимствованного объекта и пометка расширенного свойства ---
|
||||
# Свойство <xr:PropertyState> появилось в формате 2.19 (8.3.26); ниже платформа его молча
|
||||
# выбрасывает, поэтому там проверять нечего. С 2.19 состояние обязано соответствовать факту:
|
||||
# есть файл модуля — есть пометка, и наоборот. Перекос платформа принимает (проверено на
|
||||
# стенде), но выгрузка Конфигуратора так не выглядит — отсюда предупреждение, а не ошибка.
|
||||
if version_rank >= 219 and child_obj_node is not None:
|
||||
state_issues = []
|
||||
state_checked = 0
|
||||
for child in child_obj_node:
|
||||
if not isinstance(child.tag, str):
|
||||
continue
|
||||
type_name = etree.QName(child.tag).localname
|
||||
if type_name not in MODULE_KINDS_BY_TYPE or type_name not in CHILD_TYPE_DIR_MAP:
|
||||
continue
|
||||
obj_name_val = (child.text or '').strip()
|
||||
if not obj_name_val:
|
||||
continue
|
||||
type_dir = os.path.join(config_dir, CHILD_TYPE_DIR_MAP[type_name])
|
||||
obj_file = os.path.join(type_dir, f'{obj_name_val}.xml')
|
||||
if not os.path.isfile(obj_file):
|
||||
continue
|
||||
with open(obj_file, 'r', encoding='utf-8-sig') as f:
|
||||
obj_text = f.read()
|
||||
if '<ObjectBelonging>Adopted</ObjectBelonging>' not in obj_text:
|
||||
continue
|
||||
|
||||
for kind in MODULE_KINDS_BY_TYPE[type_name]:
|
||||
state_checked += 1
|
||||
has_file = os.path.isfile(os.path.join(type_dir, obj_name_val, 'Ext', f'{kind}.bsl'))
|
||||
has_flag = f'<xr:Property>{kind}</xr:Property>' in obj_text
|
||||
if has_file and not has_flag:
|
||||
state_issues.append(f'{type_name}.{obj_name_val} — есть {kind}.bsl, но нет <xr:PropertyState> для {kind}')
|
||||
elif has_flag and not has_file:
|
||||
state_issues.append(f'{type_name}.{obj_name_val} — есть <xr:PropertyState> для {kind}, но нет {kind}.bsl')
|
||||
|
||||
if state_checked > 0:
|
||||
if not state_issues:
|
||||
r.ok(f'16. Модули заимствованных объектов: пометки расширенных свойств согласованы ({state_checked})')
|
||||
else:
|
||||
for issue in state_issues:
|
||||
r.warn(f'16. {issue}')
|
||||
|
||||
# --- Breadcrumb: controlled methods (&ИзменениеИКонтроль) drift is not checked here ---
|
||||
ctrl_count = 0
|
||||
for dp, _dn, files in os.walk(config_dir):
|
||||
|
||||
Reference in New Issue
Block a user