mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-09-15 22:35:23 +03:00
feat(form-compile,form-edit): add type synonym resolution for resilient DSL
Add Resolve-TypeStr/resolve_type_str to form-compile and form-edit (PS+PY) that silently normalizes Russian type names (Строка→string, Число→decimal, Булево→boolean, etc.), Number→decimal alias, and Russian reference prefixes (СправочникСсылка→CatalogRef, etc.). Also accept + as composite type separator alongside |. This makes form skills more forgiving when the model uses meta-compile DSL conventions instead of form-specific ones. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
66eb0b19ec
commit
0a1f8888dc
@@ -58,6 +58,49 @@ function Emit-MLText {
|
|||||||
|
|
||||||
# --- 5. Type emitter ---
|
# --- 5. Type emitter ---
|
||||||
|
|
||||||
|
$script:formTypeSynonyms = New-Object System.Collections.Hashtable
|
||||||
|
$script:formTypeSynonyms["строка"] = "string"
|
||||||
|
$script:formTypeSynonyms["число"] = "decimal"
|
||||||
|
$script:formTypeSynonyms["булево"] = "boolean"
|
||||||
|
$script:formTypeSynonyms["дата"] = "date"
|
||||||
|
$script:formTypeSynonyms["датавремя"]= "dateTime"
|
||||||
|
$script:formTypeSynonyms["number"] = "decimal"
|
||||||
|
$script:formTypeSynonyms["bool"] = "boolean"
|
||||||
|
$script:formTypeSynonyms["справочникссылка"] = "CatalogRef"
|
||||||
|
$script:formTypeSynonyms["справочникобъект"] = "CatalogObject"
|
||||||
|
$script:formTypeSynonyms["документссылка"] = "DocumentRef"
|
||||||
|
$script:formTypeSynonyms["документобъект"] = "DocumentObject"
|
||||||
|
$script:formTypeSynonyms["перечислениессылка"] = "EnumRef"
|
||||||
|
$script:formTypeSynonyms["плансчетовссылка"] = "ChartOfAccountsRef"
|
||||||
|
$script:formTypeSynonyms["планвидовхарактеристикссылка"] = "ChartOfCharacteristicTypesRef"
|
||||||
|
$script:formTypeSynonyms["планвидоврасчётассылка"] = "ChartOfCalculationTypesRef"
|
||||||
|
$script:formTypeSynonyms["планвидоврасчетассылка"] = "ChartOfCalculationTypesRef"
|
||||||
|
$script:formTypeSynonyms["планобменассылка"] = "ExchangePlanRef"
|
||||||
|
$script:formTypeSynonyms["бизнеспроцессссылка"] = "BusinessProcessRef"
|
||||||
|
$script:formTypeSynonyms["задачассылка"] = "TaskRef"
|
||||||
|
$script:formTypeSynonyms["определяемыйтип"] = "DefinedType"
|
||||||
|
|
||||||
|
function Resolve-TypeStr {
|
||||||
|
param([string]$typeStr)
|
||||||
|
if (-not $typeStr) { return $typeStr }
|
||||||
|
if ($typeStr -match '^([^(]+)\((.+)\)$') {
|
||||||
|
$base = $Matches[1].Trim(); $params = $Matches[2]
|
||||||
|
$r = $script:formTypeSynonyms[$base.ToLower()]
|
||||||
|
if ($r) { return "$r($params)" }
|
||||||
|
return $typeStr
|
||||||
|
}
|
||||||
|
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" }
|
||||||
|
return $typeStr
|
||||||
|
}
|
||||||
|
$r = $script:formTypeSynonyms[$typeStr.ToLower()]
|
||||||
|
if ($r) { return $r }
|
||||||
|
return $typeStr
|
||||||
|
}
|
||||||
|
|
||||||
function Emit-Type {
|
function Emit-Type {
|
||||||
param($typeStr, [string]$indent)
|
param($typeStr, [string]$indent)
|
||||||
|
|
||||||
@@ -68,8 +111,8 @@ function Emit-Type {
|
|||||||
|
|
||||||
$typeString = "$typeStr"
|
$typeString = "$typeStr"
|
||||||
|
|
||||||
# Composite type: "Type1 | Type2"
|
# Composite type: "Type1 | Type2" or "Type1 + Type2"
|
||||||
$parts = $typeString -split '\s*\|\s*'
|
$parts = $typeString -split '\s*[|+]\s*'
|
||||||
|
|
||||||
X "$indent<Type>"
|
X "$indent<Type>"
|
||||||
foreach ($part in $parts) {
|
foreach ($part in $parts) {
|
||||||
@@ -82,6 +125,8 @@ function Emit-Type {
|
|||||||
function Emit-SingleType {
|
function Emit-SingleType {
|
||||||
param([string]$typeStr, [string]$indent)
|
param([string]$typeStr, [string]$indent)
|
||||||
|
|
||||||
|
$typeStr = Resolve-TypeStr $typeStr
|
||||||
|
|
||||||
# boolean
|
# boolean
|
||||||
if ($typeStr -eq "boolean") {
|
if ($typeStr -eq "boolean") {
|
||||||
X "$indent<v8:Type>xs:boolean</v8:Type>"
|
X "$indent<v8:Type>xs:boolean</v8:Type>"
|
||||||
|
|||||||
@@ -208,7 +208,43 @@ CFG_REF_PATTERN = re.compile(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_FORM_TYPE_SYNONYMS = {
|
||||||
|
"строка": "string", "число": "decimal", "булево": "boolean",
|
||||||
|
"дата": "date", "датавремя": "dateTime",
|
||||||
|
"number": "decimal", "bool": "boolean",
|
||||||
|
"справочникссылка": "CatalogRef", "справочникобъект": "CatalogObject",
|
||||||
|
"документссылка": "DocumentRef", "документобъект": "DocumentObject",
|
||||||
|
"перечислениессылка": "EnumRef",
|
||||||
|
"плансчетовссылка": "ChartOfAccountsRef",
|
||||||
|
"планвидовхарактеристикссылка": "ChartOfCharacteristicTypesRef",
|
||||||
|
"планвидоврасчётассылка": "ChartOfCalculationTypesRef",
|
||||||
|
"планвидоврасчетассылка": "ChartOfCalculationTypesRef",
|
||||||
|
"планобменассылка": "ExchangePlanRef",
|
||||||
|
"бизнеспроцессссылка": "BusinessProcessRef",
|
||||||
|
"задачассылка": "TaskRef",
|
||||||
|
"определяемыйтип": "DefinedType",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_type_str(type_str):
|
||||||
|
if not type_str:
|
||||||
|
return type_str
|
||||||
|
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
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
def emit_single_type(lines, type_str, indent):
|
def emit_single_type(lines, type_str, indent):
|
||||||
|
type_str = resolve_type_str(type_str)
|
||||||
# boolean
|
# boolean
|
||||||
if type_str == 'boolean':
|
if type_str == 'boolean':
|
||||||
lines.append(f'{indent}<v8:Type>xs:boolean</v8:Type>')
|
lines.append(f'{indent}<v8:Type>xs:boolean</v8:Type>')
|
||||||
@@ -289,7 +325,7 @@ def emit_type(lines, type_str, indent):
|
|||||||
return
|
return
|
||||||
|
|
||||||
type_string = str(type_str)
|
type_string = str(type_str)
|
||||||
parts = [p.strip() for p in type_string.split('|')]
|
parts = [p.strip() for p in re.split(r'[|+]', type_string)]
|
||||||
|
|
||||||
lines.append(f'{indent}<Type>')
|
lines.append(f'{indent}<Type>')
|
||||||
for part in parts:
|
for part in parts:
|
||||||
|
|||||||
@@ -153,11 +153,54 @@ function Emit-MLText {
|
|||||||
|
|
||||||
# --- Type emitter ---
|
# --- Type emitter ---
|
||||||
|
|
||||||
|
$script:formTypeSynonyms = New-Object System.Collections.Hashtable
|
||||||
|
$script:formTypeSynonyms["строка"] = "string"
|
||||||
|
$script:formTypeSynonyms["число"] = "decimal"
|
||||||
|
$script:formTypeSynonyms["булево"] = "boolean"
|
||||||
|
$script:formTypeSynonyms["дата"] = "date"
|
||||||
|
$script:formTypeSynonyms["датавремя"]= "dateTime"
|
||||||
|
$script:formTypeSynonyms["number"] = "decimal"
|
||||||
|
$script:formTypeSynonyms["bool"] = "boolean"
|
||||||
|
$script:formTypeSynonyms["справочникссылка"] = "CatalogRef"
|
||||||
|
$script:formTypeSynonyms["справочникобъект"] = "CatalogObject"
|
||||||
|
$script:formTypeSynonyms["документссылка"] = "DocumentRef"
|
||||||
|
$script:formTypeSynonyms["документобъект"] = "DocumentObject"
|
||||||
|
$script:formTypeSynonyms["перечислениессылка"] = "EnumRef"
|
||||||
|
$script:formTypeSynonyms["плансчетовссылка"] = "ChartOfAccountsRef"
|
||||||
|
$script:formTypeSynonyms["планвидовхарактеристикссылка"] = "ChartOfCharacteristicTypesRef"
|
||||||
|
$script:formTypeSynonyms["планвидоврасчётассылка"] = "ChartOfCalculationTypesRef"
|
||||||
|
$script:formTypeSynonyms["планвидоврасчетассылка"] = "ChartOfCalculationTypesRef"
|
||||||
|
$script:formTypeSynonyms["планобменассылка"] = "ExchangePlanRef"
|
||||||
|
$script:formTypeSynonyms["бизнеспроцессссылка"] = "BusinessProcessRef"
|
||||||
|
$script:formTypeSynonyms["задачассылка"] = "TaskRef"
|
||||||
|
$script:formTypeSynonyms["определяемыйтип"] = "DefinedType"
|
||||||
|
|
||||||
|
function Resolve-TypeStr {
|
||||||
|
param([string]$typeStr)
|
||||||
|
if (-not $typeStr) { return $typeStr }
|
||||||
|
if ($typeStr -match '^([^(]+)\((.+)\)$') {
|
||||||
|
$base = $Matches[1].Trim(); $params = $Matches[2]
|
||||||
|
$r = $script:formTypeSynonyms[$base.ToLower()]
|
||||||
|
if ($r) { return "$r($params)" }
|
||||||
|
return $typeStr
|
||||||
|
}
|
||||||
|
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" }
|
||||||
|
return $typeStr
|
||||||
|
}
|
||||||
|
$r = $script:formTypeSynonyms[$typeStr.ToLower()]
|
||||||
|
if ($r) { return $r }
|
||||||
|
return $typeStr
|
||||||
|
}
|
||||||
|
|
||||||
function Emit-Type {
|
function Emit-Type {
|
||||||
param($typeStr, [string]$indent)
|
param($typeStr, [string]$indent)
|
||||||
if (-not $typeStr) { X "$indent<Type/>"; return }
|
if (-not $typeStr) { X "$indent<Type/>"; return }
|
||||||
$typeString = "$typeStr"
|
$typeString = "$typeStr"
|
||||||
$parts = $typeString -split '\s*\|\s*'
|
$parts = $typeString -split '\s*[|+]\s*'
|
||||||
X "$indent<Type>"
|
X "$indent<Type>"
|
||||||
foreach ($part in $parts) {
|
foreach ($part in $parts) {
|
||||||
Emit-SingleType -typeStr $part.Trim() -indent "$indent`t"
|
Emit-SingleType -typeStr $part.Trim() -indent "$indent`t"
|
||||||
@@ -168,6 +211,8 @@ function Emit-Type {
|
|||||||
function Emit-SingleType {
|
function Emit-SingleType {
|
||||||
param([string]$typeStr, [string]$indent)
|
param([string]$typeStr, [string]$indent)
|
||||||
|
|
||||||
|
$typeStr = Resolve-TypeStr $typeStr
|
||||||
|
|
||||||
if ($typeStr -eq "boolean") {
|
if ($typeStr -eq "boolean") {
|
||||||
X "$indent<v8:Type>xs:boolean</v8:Type>"; return
|
X "$indent<v8:Type>xs:boolean</v8:Type>"; return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,12 +189,47 @@ def X(text):
|
|||||||
|
|
||||||
# --- Type emitter ---
|
# --- Type emitter ---
|
||||||
|
|
||||||
|
_FORM_TYPE_SYNONYMS = {
|
||||||
|
"строка": "string", "число": "decimal", "булево": "boolean",
|
||||||
|
"дата": "date", "датавремя": "dateTime",
|
||||||
|
"number": "decimal", "bool": "boolean",
|
||||||
|
"справочникссылка": "CatalogRef", "справочникобъект": "CatalogObject",
|
||||||
|
"документссылка": "DocumentRef", "документобъект": "DocumentObject",
|
||||||
|
"перечислениессылка": "EnumRef",
|
||||||
|
"плансчетовссылка": "ChartOfAccountsRef",
|
||||||
|
"планвидовхарактеристикссылка": "ChartOfCharacteristicTypesRef",
|
||||||
|
"планвидоврасчётассылка": "ChartOfCalculationTypesRef",
|
||||||
|
"планвидоврасчетассылка": "ChartOfCalculationTypesRef",
|
||||||
|
"планобменассылка": "ExchangePlanRef",
|
||||||
|
"бизнеспроцессссылка": "BusinessProcessRef",
|
||||||
|
"задачассылка": "TaskRef",
|
||||||
|
"определяемыйтип": "DefinedType",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_type_str(type_str):
|
||||||
|
if not type_str:
|
||||||
|
return type_str
|
||||||
|
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
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
def emit_type(type_str, indent):
|
def emit_type(type_str, indent):
|
||||||
if not type_str:
|
if not type_str:
|
||||||
X(f"{indent}<Type/>")
|
X(f"{indent}<Type/>")
|
||||||
return
|
return
|
||||||
type_string = str(type_str)
|
type_string = str(type_str)
|
||||||
parts = [p.strip() for p in type_string.split("|")]
|
parts = [p.strip() for p in re.split(r'[|+]', type_string)]
|
||||||
X(f"{indent}<Type>")
|
X(f"{indent}<Type>")
|
||||||
for part in parts:
|
for part in parts:
|
||||||
emit_single_type(part, indent + "\t")
|
emit_single_type(part, indent + "\t")
|
||||||
@@ -202,6 +237,7 @@ def emit_type(type_str, indent):
|
|||||||
|
|
||||||
|
|
||||||
def emit_single_type(type_str, indent):
|
def emit_single_type(type_str, indent):
|
||||||
|
type_str = resolve_type_str(type_str)
|
||||||
if type_str == "boolean":
|
if type_str == "boolean":
|
||||||
X(f"{indent}<v8:Type>xs:boolean</v8:Type>")
|
X(f"{indent}<v8:Type>xs:boolean</v8:Type>")
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user