fix(form,meta,skd): resolve_type_str — одно тело + срезание префикса типа

Шесть копий resolve_type_str разошлись на 6 вариантов в PY и 4 в PS1, а вместе
с формой разошлось и поведение: префикс ссылочного типа срезал только
form-compile.

Проверка на платформе (стенд 8.3.24.1691, cf-init → meta-compile → db-load-xml)
показала, что это не косметика. Префикс ломает поиск в словаре синонимов, из-за
чего русское имя типа остаётся непереведённым:
  СправочникСсылка.Склады      → cfg:CatalogRef.Склады        (верно)
  cfg:СправочникСсылка.Склады  → cfg:СправочникСсылка.Склады  (неверно)
Платформа отвечает «Неизвестное имя типа - СправочникСсылка.Склады» и
отклоняет загрузку. Именно с префиксом тип и написан в выгрузке, откуда
пользователь его копирует.

cfg: снимается всегда, d5p1: — только у ссылочных типов (с точкой): сам по себе
префикс неоднозначен, в формах d5p1:Chart, d5p1:TextDocument и ещё три типа
адресуют свои пространства имён, и там он часть канонического значения. Первая
версия правки срезала его безусловно и уронила 4 кейса form-compile.

Тело общее для всех шести навыков; словари синонимов остаются локальными, навык
объявляет на свой словарь алиас TYPE_SYNONYMS / $script:typeSynonyms.

Регресс-кейс meta-compile/type-prefix-lenient проверяет все три формы ввода.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-08-08 19:44:39 +03:00
co-authored by Claude Opus 5
parent d99d63288e
commit 826ba3de71
19 changed files with 871 additions and 121 deletions
+34 -10
View File
@@ -1,4 +1,4 @@
# form-edit v1.9 — Edit 1C managed form elements
# form-edit v1.10 — Edit 1C managed form elements (+resolve_type_str: срезание префикса cfg:/d5p1:)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -311,24 +311,48 @@ $script:formTypeSynonyms["бизнеспроцессссылка"] = "
$script:formTypeSynonyms["задачассылка"] = "TaskRef"
$script:formTypeSynonyms["определяемыйтип"] = "DefinedType"
# Алиас на локальный словарь: тело Resolve-TypeStr ниже — общая реализация,
# одинаковая во всех навыках (реестр в tests/skills/check-inline-drift.mjs).
$script:typeSynonyms = $script:formTypeSynonyms
function Resolve-TypeStr {
param([string]$typeStr)
if (-not $typeStr) { return $typeStr }
# Прощающий ввод: ведущий префикс приходит копипастой из выгрузки. Без срезания он ломает
# поиск в словаре — русское имя типа остаётся непереведённым, и платформа отвечает
# «Неизвестное имя типа». cfg: снимаем всегда (однозначно = текущая конфигурация), d5p1: —
# только у ССЫЛОЧНЫХ типов (с точкой): сам по себе префикс неоднозначен, в формах d5p1:Chart,
# d5p1:TextDocument, d5p1:GeographicalSchema и др. адресуют свои пространства имён, и там он
# часть канонического значения.
if ($typeStr.StartsWith('cfg:')) {
$typeStr = $typeStr.Substring(4)
} elseif ($typeStr.StartsWith('d5p1:') -and $typeStr.Contains('.')) {
$typeStr = $typeStr.Substring(5)
}
# Параметризованные типы: Number(15,2), Строка(100)
if ($typeStr -match '^([^(]+)\((.+)\)$') {
$base = $Matches[1].Trim(); $params = $Matches[2]
$r = $script:formTypeSynonyms[$base.ToLower()]
if ($r) { return "$r($params)" }
$baseName = $Matches[1].Trim()
$params = $Matches[2]
$resolved = $script:typeSynonyms[$baseName.ToLower()]
if ($resolved) { return "$resolved($params)" }
return $typeStr
}
# Ссылочные типы: СправочникСсылка.Организации → CatalogRef.Организации
if ($typeStr.Contains('.')) {
$i = $typeStr.IndexOf('.')
$prefix = $typeStr.Substring(0, $i); $suffix = $typeStr.Substring($i)
$r = $script:formTypeSynonyms[$prefix.ToLower()]
if ($r) { return "$r$suffix" }
$dotIdx = $typeStr.IndexOf('.')
$prefix = $typeStr.Substring(0, $dotIdx)
$suffix = $typeStr.Substring($dotIdx) # includes the dot
$resolved = $script:typeSynonyms[$prefix.ToLower()]
if ($resolved) { return "$resolved$suffix" }
return $typeStr
}
$r = $script:formTypeSynonyms[$typeStr.ToLower()]
if ($r) { return $r }
# Простое имя
$resolved = $script:typeSynonyms[$typeStr.ToLower()]
if ($resolved) { return $resolved }
return $typeStr
}
+36 -12
View File
@@ -1,4 +1,4 @@
# form-edit v1.9 — Edit 1C managed form elements (Python port)
# form-edit v1.10 — Edit 1C managed form elements (Python port) (+resolve_type_str: срезание префикса cfg:/d5p1:)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import json
@@ -386,23 +386,47 @@ _FORM_TYPE_SYNONYMS = {
}
# Алиас на локальный словарь: тело resolve_type_str ниже — общая реализация,
# одинаковая во всех навыках (реестр в tests/skills/check-inline-drift.mjs).
TYPE_SYNONYMS = _FORM_TYPE_SYNONYMS
def resolve_type_str(type_str):
if not type_str:
return type_str
# Прощающий ввод: ведущий префикс приходит копипастой из выгрузки. Без срезания он ломает
# поиск в словаре — русское имя типа остаётся непереведённым, и платформа отвечает
# «Неизвестное имя типа». cfg: снимаем всегда (однозначно = текущая конфигурация), d5p1: —
# только у ССЫЛОЧНЫХ типов (с точкой): сам по себе префикс неоднозначен, в формах d5p1:Chart,
# d5p1:TextDocument, d5p1:GeographicalSchema и др. адресуют свои пространства имён, и там он
# часть канонического значения.
if type_str.startswith('cfg:'):
type_str = type_str[4:]
elif type_str.startswith('d5p1:') and '.' in type_str:
type_str = type_str[5:]
# Параметризованные типы: Number(15,2), Строка(100)
m = re.match(r'^([^(]+)\((.+)\)$', type_str)
if m:
base, params = m.group(1).strip(), m.group(2)
r = _FORM_TYPE_SYNONYMS.get(base.lower())
return f"{r}({params})" if r else type_str
base_name = m.group(1).strip()
params = m.group(2)
resolved = TYPE_SYNONYMS.get(base_name.lower())
if resolved:
return f'{resolved}({params})'
return type_str
# Ссылочные типы: СправочникСсылка.Организации -> CatalogRef.Организации
if '.' in type_str:
i = type_str.index('.')
prefix, suffix = type_str[:i], type_str[i:]
r = _FORM_TYPE_SYNONYMS.get(prefix.lower())
return f"{r}{suffix}" if r else type_str
r = _FORM_TYPE_SYNONYMS.get(type_str.lower())
return r if r else type_str
dot_idx = type_str.index('.')
prefix = type_str[:dot_idx]
suffix = type_str[dot_idx:] # includes the dot
resolved = TYPE_SYNONYMS.get(prefix.lower())
if resolved:
return f'{resolved}{suffix}'
return type_str
# Простое имя
resolved = TYPE_SYNONYMS.get(type_str.lower())
if resolved:
return resolved
return type_str
def emit_type(type_str, indent):
if not type_str:
X(f"{indent}<Type/>")