mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-02 09:47:45 +03:00
feat(meta-validate): базовая проверка нераспознанных валидных типов + прощающий ввод плоских объектов (Фаза 1.4, v1.9)
20 валидных типов метаданных без глубоких правил (Subsystem/Role/CommonForm/ CommonCommand/CommandGroup/CommonAttribute/CommonTemplate/CommonPicture/ SessionParameter/SettingsStorage/FilterCriterion/FunctionalOption/ FunctionalOptionsParameter/Language/Style/StyleItem/WSReference/XDTOPackage/ DocumentNumerator/Sequence) раньше падали как "Unrecognized" + exit 1 — ложная ошибка на валидном объекте. Теперь для них базовая структурная проверка (root/uuid + Name-идентификатор) с ранним выходом, без type-specific правил. Имена типов взяты из LocalName реальных файлов корпуса. По-настоящему неизвестный тип по-прежнему отвергается. Побочно: прощающий ввод для плоских объектов (один .xml без папки — SessionParameter, CommonAttribute, DefinedType, ...) — раньше не находились по голому имени Dir/Name (fallback покрывал только папочные Dir/Name/Name.xml), добавлено дописывание .xml. Тесты (фикстуры не самописные): valid-sessionparameter-basic (meta-compile preRun) + real-erp-sessionparameter (external, скип на Mac) + error-unknown-type (реальный каталог корпуса с переименованным корневым тип-элементом). meta-validate 21/21 ps1+py. 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
b9ed48ccf2
commit
9b5908c3b2
@@ -1,4 +1,4 @@
|
|||||||
# meta-validate v1.8 — Validate 1C metadata object structure
|
# meta-validate v1.9 — Validate 1C metadata object structure
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
@@ -65,6 +65,12 @@ if (Test-Path $ObjectPath -PathType Container) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# File not found — прощающий ввод для плоских объектов (SessionParameter, CommonAttribute,
|
||||||
|
# DefinedType, WSReference, … — один .xml без папки): дописать .xml к голому имени
|
||||||
|
if (-not (Test-Path $ObjectPath) -and -not [System.IO.Path]::HasExtension($ObjectPath)) {
|
||||||
|
if (Test-Path "$ObjectPath.xml") { $ObjectPath = "$ObjectPath.xml" }
|
||||||
|
}
|
||||||
|
|
||||||
# File not found — check Dir/Name/Name.xml → Dir/Name.xml
|
# File not found — check Dir/Name/Name.xml → Dir/Name.xml
|
||||||
if (-not (Test-Path $ObjectPath)) {
|
if (-not (Test-Path $ObjectPath)) {
|
||||||
$fileName = [System.IO.Path]::GetFileNameWithoutExtension($ObjectPath)
|
$fileName = [System.IO.Path]::GetFileNameWithoutExtension($ObjectPath)
|
||||||
@@ -162,6 +168,15 @@ $validTypes = @(
|
|||||||
"HTTPService","WebService","DefinedType"
|
"HTTPService","WebService","DefinedType"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Валидные типы метаданных без глубоких правил валидации — раньше падали как "Unrecognized"
|
||||||
|
# (ложная ошибка на валидном объекте). Для них выполняется базовая структурная проверка (root/uuid/Name).
|
||||||
|
$structuralOnlyTypes = @(
|
||||||
|
"Subsystem","Role","CommonForm","CommonCommand","CommandGroup","CommonAttribute",
|
||||||
|
"CommonTemplate","CommonPicture","SessionParameter","SettingsStorage","FilterCriterion",
|
||||||
|
"FunctionalOption","FunctionalOptionsParameter","Language","Style","StyleItem",
|
||||||
|
"WSReference","XDTOPackage","DocumentNumerator","Sequence"
|
||||||
|
)
|
||||||
|
|
||||||
# GeneratedType categories by type
|
# GeneratedType categories by type
|
||||||
$generatedTypeCategories = @{
|
$generatedTypeCategories = @{
|
||||||
"Catalog" = @("Object","Ref","Selection","List","Manager")
|
"Catalog" = @("Object","Ref","Selection","List","Manager")
|
||||||
@@ -355,7 +370,7 @@ if ($childElements.Count -eq 0) {
|
|||||||
$typeNode = $childElements[0]
|
$typeNode = $childElements[0]
|
||||||
$mdType = $typeNode.LocalName
|
$mdType = $typeNode.LocalName
|
||||||
|
|
||||||
if ($validTypes -notcontains $mdType) {
|
if (($validTypes -notcontains $mdType) -and ($structuralOnlyTypes -notcontains $mdType)) {
|
||||||
Report-Error "1. Unrecognized metadata type: $mdType"
|
Report-Error "1. Unrecognized metadata type: $mdType"
|
||||||
& $finalize
|
& $finalize
|
||||||
exit 1
|
exit 1
|
||||||
@@ -383,6 +398,20 @@ if ($check1Ok) {
|
|||||||
Report-OK "1. Root structure: MetaDataObject/$mdType, version $version"
|
Report-OK "1. Root structure: MetaDataObject/$mdType, version $version"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# --- Structural-only types: базовая проверка (Name), без type-specific правил ---
|
||||||
|
if ($structuralOnlyTypes -contains $mdType) {
|
||||||
|
if ($objName -eq "(unknown)") {
|
||||||
|
Report-Error "3. Properties: missing or empty Name"
|
||||||
|
} elseif ($objName -notmatch $identPattern) {
|
||||||
|
Report-Error "3. Properties: Name '$objName' is not a valid 1C identifier"
|
||||||
|
} else {
|
||||||
|
Report-OK "3. Properties: Name=`"$objName`" (базовая структурная проверка для $mdType)"
|
||||||
|
}
|
||||||
|
& $finalize
|
||||||
|
if ($script:errors -gt 0) { exit 1 }
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
if ($script:stopped) { & $finalize; exit 1 }
|
if ($script:stopped) { & $finalize; exit 1 }
|
||||||
|
|
||||||
# --- Check 2: InternalInfo ---
|
# --- Check 2: InternalInfo ---
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# meta-validate v1.8 — Validate 1C metadata object structure (Python port)
|
# meta-validate v1.9 — Validate 1C metadata object structure (Python port)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
@@ -70,6 +70,12 @@ if os.path.isdir(object_path):
|
|||||||
print(f"[ERROR] No XML file found in directory: {object_path}")
|
print(f"[ERROR] No XML file found in directory: {object_path}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
# File not found -- прощающий ввод для плоских объектов (SessionParameter, CommonAttribute,
|
||||||
|
# DefinedType, WSReference, ... -- один .xml без папки): дописать .xml к голому имени
|
||||||
|
if not os.path.exists(object_path) and not os.path.splitext(object_path)[1]:
|
||||||
|
if os.path.exists(object_path + ".xml"):
|
||||||
|
object_path = object_path + ".xml"
|
||||||
|
|
||||||
# File not found -- check Dir/Name/Name.xml -> Dir/Name.xml
|
# File not found -- check Dir/Name/Name.xml -> Dir/Name.xml
|
||||||
if not os.path.exists(object_path):
|
if not os.path.exists(object_path):
|
||||||
file_name = os.path.splitext(os.path.basename(object_path))[0]
|
file_name = os.path.splitext(os.path.basename(object_path))[0]
|
||||||
@@ -162,6 +168,15 @@ valid_types = (
|
|||||||
"HTTPService", "WebService", "DefinedType",
|
"HTTPService", "WebService", "DefinedType",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Валидные типы метаданных без глубоких правил валидации — раньше падали как "Unrecognized"
|
||||||
|
# (ложная ошибка на валидном объекте). Для них выполняется базовая структурная проверка (root/uuid/Name).
|
||||||
|
structural_only_types = (
|
||||||
|
"Subsystem", "Role", "CommonForm", "CommonCommand", "CommandGroup", "CommonAttribute",
|
||||||
|
"CommonTemplate", "CommonPicture", "SessionParameter", "SettingsStorage", "FilterCriterion",
|
||||||
|
"FunctionalOption", "FunctionalOptionsParameter", "Language", "Style", "StyleItem",
|
||||||
|
"WSReference", "XDTOPackage", "DocumentNumerator", "Sequence",
|
||||||
|
)
|
||||||
|
|
||||||
# GeneratedType categories by type
|
# GeneratedType categories by type
|
||||||
generated_type_categories = {
|
generated_type_categories = {
|
||||||
"Catalog": ["Object", "Ref", "Selection", "List", "Manager"],
|
"Catalog": ["Object", "Ref", "Selection", "List", "Manager"],
|
||||||
@@ -379,7 +394,7 @@ elif len(child_elements) > 1:
|
|||||||
type_node = child_elements[0]
|
type_node = child_elements[0]
|
||||||
md_type = local_name(type_node)
|
md_type = local_name(type_node)
|
||||||
|
|
||||||
if md_type not in valid_types:
|
if md_type not in valid_types and md_type not in structural_only_types:
|
||||||
report_error(f"1. Unrecognized metadata type: {md_type}")
|
report_error(f"1. Unrecognized metadata type: {md_type}")
|
||||||
finalize()
|
finalize()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@@ -404,6 +419,17 @@ output_lines.insert(0, f"=== Validation: {md_type}.{obj_name} ===")
|
|||||||
if check1_ok:
|
if check1_ok:
|
||||||
report_ok(f"1. Root structure: MetaDataObject/{md_type}, version {version}")
|
report_ok(f"1. Root structure: MetaDataObject/{md_type}, version {version}")
|
||||||
|
|
||||||
|
# ── Structural-only types: базовая проверка (Name), без type-specific правил ──
|
||||||
|
if md_type in structural_only_types:
|
||||||
|
if obj_name == "(unknown)":
|
||||||
|
report_error("3. Properties: missing or empty Name")
|
||||||
|
elif not ident_pattern.match(obj_name):
|
||||||
|
report_error(f"3. Properties: Name '{obj_name}' is not a valid 1C identifier")
|
||||||
|
else:
|
||||||
|
report_ok(f'3. Properties: Name="{obj_name}" (базовая структурная проверка для {md_type})')
|
||||||
|
finalize()
|
||||||
|
sys.exit(1 if errors > 0 else 0)
|
||||||
|
|
||||||
if stopped:
|
if stopped:
|
||||||
finalize()
|
finalize()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "Валидатор всё ещё ловит по-настоящему неизвестный тип метаданных (гейт не стал слепым)",
|
||||||
|
"setup": "fixture:unknown-type",
|
||||||
|
"params": { "objectPath": "Catalogs/Неизвестный.xml" },
|
||||||
|
"expectError": true
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
<?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">
|
||||||
|
<НесуществующийТип uuid="82f554e2-86f6-4bf9-8c7d-d1499fc88bc4">
|
||||||
|
<InternalInfo>
|
||||||
|
<xr:GeneratedType name="CatalogObject.РолиКонтактныхЛиц" category="Object">
|
||||||
|
<xr:TypeId>d394a75c-51d2-457e-a698-e16a37831b71</xr:TypeId>
|
||||||
|
<xr:ValueId>0d654e63-ef5d-4c55-86e8-6775655ae10a</xr:ValueId>
|
||||||
|
</xr:GeneratedType>
|
||||||
|
<xr:GeneratedType name="CatalogRef.РолиКонтактныхЛиц" category="Ref">
|
||||||
|
<xr:TypeId>e486d1d3-8e16-40d1-902d-ae6ec9ac0740</xr:TypeId>
|
||||||
|
<xr:ValueId>07c1b906-d491-4175-bc52-69819c08049e</xr:ValueId>
|
||||||
|
</xr:GeneratedType>
|
||||||
|
<xr:GeneratedType name="CatalogSelection.РолиКонтактныхЛиц" category="Selection">
|
||||||
|
<xr:TypeId>f1d3d2ef-8043-4aad-a124-9d747aa8b45c</xr:TypeId>
|
||||||
|
<xr:ValueId>29896634-18fc-4101-a767-26a1c5755b08</xr:ValueId>
|
||||||
|
</xr:GeneratedType>
|
||||||
|
<xr:GeneratedType name="CatalogList.РолиКонтактныхЛиц" category="List">
|
||||||
|
<xr:TypeId>930a4a7f-c496-4c5c-964a-5d80fb5636c3</xr:TypeId>
|
||||||
|
<xr:ValueId>09212a77-1293-4cca-9e15-3951959ecfcc</xr:ValueId>
|
||||||
|
</xr:GeneratedType>
|
||||||
|
<xr:GeneratedType name="CatalogManager.РолиКонтактныхЛиц" category="Manager">
|
||||||
|
<xr:TypeId>d2a75006-e316-4837-9179-fa2385a20203</xr:TypeId>
|
||||||
|
<xr:ValueId>f4c7d49d-69fd-4f35-9aa9-51b70bc97b9b</xr:ValueId>
|
||||||
|
</xr:GeneratedType>
|
||||||
|
</InternalInfo>
|
||||||
|
<Properties>
|
||||||
|
<Name>РолиКонтактныхЛиц</Name>
|
||||||
|
<Synonym>
|
||||||
|
<v8:item>
|
||||||
|
<v8:lang>ru</v8:lang>
|
||||||
|
<v8:content>Роли контактных лиц</v8:content>
|
||||||
|
</v8:item>
|
||||||
|
</Synonym>
|
||||||
|
<Comment/>
|
||||||
|
<Hierarchical>false</Hierarchical>
|
||||||
|
<HierarchyType>HierarchyFoldersAndItems</HierarchyType>
|
||||||
|
<LimitLevelCount>false</LimitLevelCount>
|
||||||
|
<LevelCount>2</LevelCount>
|
||||||
|
<FoldersOnTop>true</FoldersOnTop>
|
||||||
|
<UseStandardCommands>true</UseStandardCommands>
|
||||||
|
<Owners/>
|
||||||
|
<SubordinationUse>ToItems</SubordinationUse>
|
||||||
|
<CodeLength>9</CodeLength>
|
||||||
|
<DescriptionLength>50</DescriptionLength>
|
||||||
|
<CodeType>String</CodeType>
|
||||||
|
<CodeAllowedLength>Fixed</CodeAllowedLength>
|
||||||
|
<CodeSeries>WholeCatalog</CodeSeries>
|
||||||
|
<CheckUnique>true</CheckUnique>
|
||||||
|
<Autonumbering>true</Autonumbering>
|
||||||
|
<DefaultPresentation>AsDescription</DefaultPresentation>
|
||||||
|
<Characteristics/>
|
||||||
|
<PredefinedDataUpdate>Auto</PredefinedDataUpdate>
|
||||||
|
<EditType>InList</EditType>
|
||||||
|
<QuickChoice>false</QuickChoice>
|
||||||
|
<ChoiceMode>BothWays</ChoiceMode>
|
||||||
|
<InputByString>
|
||||||
|
<xr:Field>Catalog.РолиКонтактныхЛиц.StandardAttribute.Description</xr:Field>
|
||||||
|
<xr:Field>Catalog.РолиКонтактныхЛиц.StandardAttribute.Code</xr:Field>
|
||||||
|
</InputByString>
|
||||||
|
<SearchStringModeOnInputByString>Begin</SearchStringModeOnInputByString>
|
||||||
|
<FullTextSearchOnInputByString>DontUse</FullTextSearchOnInputByString>
|
||||||
|
<ChoiceDataGetModeOnInputByString>Directly</ChoiceDataGetModeOnInputByString>
|
||||||
|
<DefaultObjectForm/>
|
||||||
|
<DefaultFolderForm/>
|
||||||
|
<DefaultListForm/>
|
||||||
|
<DefaultChoiceForm/>
|
||||||
|
<DefaultFolderChoiceForm/>
|
||||||
|
<AuxiliaryObjectForm/>
|
||||||
|
<AuxiliaryFolderForm/>
|
||||||
|
<AuxiliaryListForm/>
|
||||||
|
<AuxiliaryChoiceForm/>
|
||||||
|
<AuxiliaryFolderChoiceForm/>
|
||||||
|
<IncludeHelpInContents>false</IncludeHelpInContents>
|
||||||
|
<BasedOn/>
|
||||||
|
<DataLockFields/>
|
||||||
|
<DataLockControlMode>Automatic</DataLockControlMode>
|
||||||
|
<FullTextSearch>Use</FullTextSearch>
|
||||||
|
<ObjectPresentation/>
|
||||||
|
<ExtendedObjectPresentation/>
|
||||||
|
<ListPresentation/>
|
||||||
|
<ExtendedListPresentation/>
|
||||||
|
<Explanation/>
|
||||||
|
<CreateOnInput>Use</CreateOnInput>
|
||||||
|
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
|
||||||
|
<DataHistory>DontUse</DataHistory>
|
||||||
|
<UpdateDataHistoryImmediatelyAfterWrite>false</UpdateDataHistoryImmediatelyAfterWrite>
|
||||||
|
<ExecuteAfterWriteDataHistoryVersionProcessing>false</ExecuteAfterWriteDataHistoryVersionProcessing>
|
||||||
|
</Properties>
|
||||||
|
<ChildObjects/>
|
||||||
|
</НесуществующийТип>
|
||||||
|
</MetaDataObject>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name": "Валидация реального SessionParameter ERP (базовая структурная проверка)",
|
||||||
|
"setup": "external:C:/WS/tasks/cfsrc/erp_8.3.24",
|
||||||
|
"params": { "objectPath": "SessionParameters/АвторизованныйПользователь" },
|
||||||
|
"args_extra": ["-Detailed"],
|
||||||
|
"expect": {
|
||||||
|
"stdoutContains": "базовая структурная проверка"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "meta-compile создаёт SessionParameter → meta-validate проходит базовую проверку, а не Unrecognized (Фаза 1.4)",
|
||||||
|
"setup": "empty-config",
|
||||||
|
"preRun": [
|
||||||
|
{
|
||||||
|
"script": "meta-compile/scripts/meta-compile",
|
||||||
|
"input": { "type": "SessionParameter", "name": "ТекущийПользователь", "valueType": "CatalogRef.Пользователи" },
|
||||||
|
"args": { "-JsonPath": "{inputFile}", "-OutputDir": "{workDir}" }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"params": { "objectPath": "SessionParameters/ТекущийПользователь" },
|
||||||
|
"args_extra": ["-Detailed"],
|
||||||
|
"expect": {
|
||||||
|
"stdoutContains": "базовая структурная проверка"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user