mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-09-07 18:50:53 +03:00
feat(meta-compile,meta-decompile): extra-свойства реквизита minValue/maxValue/extendedEdit + String(N,fixed) (v1.31/v0.21)
Компилятор хардкодил <ExtendedEdit>false</>, <MinValue nil>, <MaxValue nil> и
AllowedLength=Variable; декомпилятор эти свойства не захватывал. Реквизиты с
диапазоном (год 2000-3999, код цены 1-3), фикс-длина строки, расширенное
редактирование теряли данные при роундтрипе.
Зеркало form-compile:
• minValue/maxValue — граница диапазона, типизировано: JSON-число →
xsi:type="xs:decimal", строка → xs:string (тип сохранён декомпилятором из
XML). Хелпер Emit-MinMaxValue (применён к Emit-Attribute/Dimension/Resource).
• extendedEdit — bool (многострочное поле).
• String(N,fixed) → <v8:AllowedLength>Fixed</v8:AllowedLength> (фикс. длина);
String(N)/String(N,variable) → Variable (дефолт). Парсер типа ps1+py.
Ловушка: Parse-AttributeShorthand строит НОВЫЙ hashtable только с известными
ключами — сначала забыл добавить minValue/maxValue/extendedEdit → $parsed.minValue
был $null, компилятор молча писал nil, хотя декомпилятор значение отдавал.
Роундтрип 120: match 100→108, TOTAL 120→78 (−42), Attribute>ExtendedEdit/
MaxValue/MinValue/AllowedLength=0, новых diff нет. Регресс 46/46 ps1+py, ps1↔py
identical. spec §3.2/§4.2, кейс catalog-attr-props (+min/max/String(3,fixed)/extEdit).
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
562f4617bc
commit
177c9bb0fa
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# meta-compile v1.30 — Compile 1C metadata object from JSON
|
||||
# meta-compile v1.31 — Compile 1C metadata object from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -550,14 +550,15 @@ def emit_type_content(indent, type_str):
|
||||
if type_str == 'Boolean':
|
||||
X(f'{indent}<v8:Type>xs:boolean</v8:Type>')
|
||||
return
|
||||
# String or String(N)
|
||||
m = re.match(r'^String(\((\d+)\))?$', type_str)
|
||||
# String or String(N) or String(N,fixed|variable) — AllowedLength: Variable дефолт / Fixed (фикс. длина).
|
||||
m = re.match(r'^String(\((\d+)(\s*,\s*(fixed|variable))?\))?$', type_str)
|
||||
if m:
|
||||
length = m.group(2) if m.group(2) else '10'
|
||||
al = 'Fixed' if (m.group(4) and m.group(4).lower() == 'fixed') else 'Variable'
|
||||
X(f'{indent}<v8:Type>xs:string</v8:Type>')
|
||||
X(f'{indent}<v8:StringQualifiers>')
|
||||
X(f'{indent}\t<v8:Length>{length}</v8:Length>')
|
||||
X(f'{indent}\t<v8:AllowedLength>Variable</v8:AllowedLength>')
|
||||
X(f'{indent}\t<v8:AllowedLength>{al}</v8:AllowedLength>')
|
||||
X(f'{indent}</v8:StringQualifiers>')
|
||||
return
|
||||
# Number without params -> Number(10,0)
|
||||
@@ -853,6 +854,9 @@ def parse_attribute_shorthand(val):
|
||||
'format': val.get('format'),
|
||||
'editFormat': val.get('editFormat'),
|
||||
'mask': str(val['mask']) if val.get('mask') else '',
|
||||
'extendedEdit': True if val.get('extendedEdit') is True else False,
|
||||
'minValue': val.get('minValue'),
|
||||
'maxValue': val.get('maxValue'),
|
||||
'hasFillValue': ('fillValue' in val),
|
||||
'fillValue': val.get('fillValue'),
|
||||
'linkByType': val.get('linkByType'),
|
||||
@@ -1552,6 +1556,14 @@ def emit_characteristics(indent, chars):
|
||||
X(f'{indent}\t</xr:Characteristic>')
|
||||
X(f'{indent}</Characteristics>')
|
||||
|
||||
def emit_min_max_value(indent, tag, val):
|
||||
"""<MinValue>/<MaxValue> — граница диапазона. None → nil. Число → xs:decimal, строка → xs:string."""
|
||||
if val is None:
|
||||
X(f'{indent}<{tag} xsi:nil="true"/>')
|
||||
return
|
||||
t = 'xs:string' if isinstance(val, str) else 'xs:decimal'
|
||||
X(f'{indent}<{tag} xsi:type="{t}">{esc_xml(str(val))}</{tag}>')
|
||||
|
||||
def emit_attribute(indent, parsed, context):
|
||||
attr_name = parsed['name']
|
||||
ctx_reserved = RESERVED_BY_CONTEXT.get(context)
|
||||
@@ -1589,9 +1601,10 @@ def emit_attribute(indent, parsed, context):
|
||||
X(f'{indent}\t\t<Mask/>')
|
||||
multi_line = 'true' if (parsed.get('multiLine') is True or 'multiline' in parsed.get('flags', [])) else 'false'
|
||||
X(f'{indent}\t\t<MultiLine>{multi_line}</MultiLine>')
|
||||
X(f'{indent}\t\t<ExtendedEdit>false</ExtendedEdit>')
|
||||
X(f'{indent}\t\t<MinValue xsi:nil="true"/>')
|
||||
X(f'{indent}\t\t<MaxValue xsi:nil="true"/>')
|
||||
ext_edit = 'true' if parsed.get('extendedEdit') is True else 'false'
|
||||
X(f'{indent}\t\t<ExtendedEdit>{ext_edit}</ExtendedEdit>')
|
||||
emit_min_max_value(f'{indent}\t\t', 'MinValue', parsed.get('minValue'))
|
||||
emit_min_max_value(f'{indent}\t\t', 'MaxValue', parsed.get('maxValue'))
|
||||
# FillFromFillingValue / FillValue — not for tabular/processor/chart/register-other
|
||||
# (Chart*, AccumulationRegister/AccountingRegister/CalculationRegister don't support these)
|
||||
if context not in ('tabular', 'processor', 'chart', 'register-other'):
|
||||
@@ -1776,9 +1789,10 @@ def emit_dimension(indent, parsed, register_type):
|
||||
X(f'{indent}\t\t<Mask/>')
|
||||
multi_line = 'true' if (parsed.get('multiLine') is True or 'multiline' in parsed.get('flags', [])) else 'false'
|
||||
X(f'{indent}\t\t<MultiLine>{multi_line}</MultiLine>')
|
||||
X(f'{indent}\t\t<ExtendedEdit>false</ExtendedEdit>')
|
||||
X(f'{indent}\t\t<MinValue xsi:nil="true"/>')
|
||||
X(f'{indent}\t\t<MaxValue xsi:nil="true"/>')
|
||||
ext_edit = 'true' if parsed.get('extendedEdit') is True else 'false'
|
||||
X(f'{indent}\t\t<ExtendedEdit>{ext_edit}</ExtendedEdit>')
|
||||
emit_min_max_value(f'{indent}\t\t', 'MinValue', parsed.get('minValue'))
|
||||
emit_min_max_value(f'{indent}\t\t', 'MaxValue', parsed.get('maxValue'))
|
||||
flags = parsed.get('flags', [])
|
||||
if register_type == 'InformationRegister':
|
||||
fill_from = 'true' if 'master' in flags else 'false'
|
||||
@@ -1850,9 +1864,10 @@ def emit_resource(indent, parsed, register_type):
|
||||
X(f'{indent}\t\t<Mask/>')
|
||||
multi_line = 'true' if (parsed.get('multiLine') is True or 'multiline' in parsed.get('flags', [])) else 'false'
|
||||
X(f'{indent}\t\t<MultiLine>{multi_line}</MultiLine>')
|
||||
X(f'{indent}\t\t<ExtendedEdit>false</ExtendedEdit>')
|
||||
X(f'{indent}\t\t<MinValue xsi:nil="true"/>')
|
||||
X(f'{indent}\t\t<MaxValue xsi:nil="true"/>')
|
||||
ext_edit = 'true' if parsed.get('extendedEdit') is True else 'false'
|
||||
X(f'{indent}\t\t<ExtendedEdit>{ext_edit}</ExtendedEdit>')
|
||||
emit_min_max_value(f'{indent}\t\t', 'MinValue', parsed.get('minValue'))
|
||||
emit_min_max_value(f'{indent}\t\t', 'MaxValue', parsed.get('maxValue'))
|
||||
if register_type == 'InformationRegister':
|
||||
X(f'{indent}\t\t<FillFromFillingValue>false</FillFromFillingValue>')
|
||||
X(f'{indent}\t\t<FillValue xsi:nil="true"/>')
|
||||
|
||||
Reference in New Issue
Block a user