mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-01 17:27:45 +03:00
feat(form-decompile,form-compile): вычисляемые поля + valueType поля DataSet динсписка (кластер C)
Две части пробела DataSet динамического списка:
1. Field valueType (63 формы/54). Поле набора <Field DataSetFieldField> может нести
<dcssch:valueType> (тип значения; кастомные/вычисляемые поля). Декомпилятор ловил
field/dataPath/title/nested, теперь и valueType (переиспользует Decompile-Type);
компилятор эмитит после title через существующий emit_dl_value_type. 0 потерь на выборке.
2. CalculatedField (6 форм, редкое). Новый ключ settings.calculatedFields — зеркало skd:
shorthand "Имя [Заголовок]: тип = Выражение #noField #noFilter #noGroup #noOrder"
(порт Parse-CalcShorthand) или объект. Форм-специфика: dcssch:-теги, presentationExpression,
orderExpression* (структура {expression,orderType,autoOrder} в namespace dcscommon с
локальным xmlns), useRestriction{field,condition,group,order}. Эмиттер форм-специфичный
(skd использует dcscom:-префикс и не имеет pres/orderExpression). Позиция в DataSet —
после Field*, до Parameter*. Декомпилятор Build-CalcField (объектная форма для точного
round-trip). Выборка calc-форм: calc-теги ушли из диффов (3/6 match, остаток — отдельный
field appearance/presentationExpression).
Кейс dynamic-list-form (+grouping +calculatedFields: shorthand с флагами + объект с
presentationExpression/orderExpression/valueType) сертифицирован загрузкой в 1С (порядок
детей CalculatedField подтверждён платформой). Регресс 43/43 (ps1+py).
ps1==py байт-в-байт (сверено на кейсе). Фикс по пути: ps1 Parse-CalcShorthand — `\b` в
generator-heredoc превратился в backspace 0x08 → #-флаги не парсились (py был верен);
поймано прямой сверкой вывода ps1 vs py.
C-остаток (в BACKLOG): свойства обычного <Field> — presentationExpression + appearance
(формат/цвет поля) — отдельный подкластер.
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
43d36119cb
commit
73b07a6fbc
@@ -1,4 +1,4 @@
|
||||
# form-compile v1.139 — Compile 1C managed form from JSON or object metadata
|
||||
# form-compile v1.140 — Compile 1C managed form from JSON or object metadata
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[string]$JsonPath,
|
||||
@@ -2067,6 +2067,80 @@ function Emit-ListGrouping {
|
||||
Emit-ListGroupingLevels $levels 0 $indent
|
||||
}
|
||||
|
||||
# === Вычисляемые поля DataSet динамического списка (<CalculatedField>) ===
|
||||
# Зеркало skd: shorthand "Имя [Заголовок]: тип = Выражение #noField #noFilter #noGroup #noOrder"
|
||||
# или объект. Форм-специфика: dcssch:-теги + presentationExpression/orderExpression (dcscommon ns).
|
||||
$script:calcRestrictMap = @{ 'noField'='field'; 'noFilter'='condition'; 'noCondition'='condition'; 'noGroup'='group'; 'noOrder'='order' }
|
||||
$script:dcsCommonNs = 'http://v8.1c.ru/8.1/data-composition-system/common'
|
||||
|
||||
function Parse-CalcShorthand {
|
||||
param([string]$s)
|
||||
$restrict = @()
|
||||
foreach ($m in [regex]::Matches($s, '#(noField|noFilter|noCondition|noGroup|noOrder)\b')) { $restrict += $m.Groups[1].Value }
|
||||
$s = [regex]::Replace($s, '\s*#(noField|noFilter|noCondition|noGroup|noOrder)\b', '')
|
||||
$eq = $s.IndexOf('=')
|
||||
if ($eq -gt 0) { $lhs = $s.Substring(0, $eq); $rhs = $s.Substring($eq + 1).Trim() } else { $lhs = $s; $rhs = '' }
|
||||
$title = ''
|
||||
if ($lhs -match '\[([^\]]+)\]') { $title = $Matches[1]; $lhs = $lhs -replace '\s*\[[^\]]+\]', '' }
|
||||
$lhs = $lhs.Trim()
|
||||
$type = ''; $dataPath = $lhs
|
||||
if ($lhs.Contains(':')) { $parts = $lhs -split ':', 2; $dataPath = $parts[0].Trim(); $type = Resolve-TypeStr ($parts[1].Trim()) }
|
||||
return @{ dataPath = $dataPath; expression = $rhs; type = $type; title = $title; restrict = $restrict }
|
||||
}
|
||||
|
||||
function Emit-CalcFields {
|
||||
param($calcFields, [string]$indent)
|
||||
if (-not $calcFields) { return }
|
||||
foreach ($cf in $calcFields) {
|
||||
$pres = $null; $orderExpr = $null; $restrict = @()
|
||||
if ($cf -is [string]) {
|
||||
$p = Parse-CalcShorthand $cf
|
||||
$dataPath = "$($p.dataPath)"; $expression = "$($p.expression)"; $title = $p.title; $typeStr = "$($p.type)"
|
||||
foreach ($r in $p.restrict) { if ($script:calcRestrictMap[$r]) { $restrict += $script:calcRestrictMap[$r] } }
|
||||
} else {
|
||||
$dataPath = if ($cf.dataPath) { "$($cf.dataPath)" } elseif ($cf.field) { "$($cf.field)" } else { "$($cf.name)" }
|
||||
$expression = "$($cf.expression)"
|
||||
$title = $cf.title
|
||||
$typeStr = if ($cf.valueType) { "$($cf.valueType)" } elseif ($cf.type) { "$($cf.type)" } else { '' }
|
||||
$ur = if ($cf.useRestriction) { $cf.useRestriction } elseif ($cf.restrict) { $cf.restrict } else { $null }
|
||||
if ($ur -is [System.Management.Automation.PSCustomObject] -or $ur -is [hashtable]) {
|
||||
foreach ($k in 'field','condition','group','order') { if ($ur.$k -eq $true) { $restrict += $k } }
|
||||
} elseif ($ur -is [string]) {
|
||||
foreach ($tok in ($ur -split '\s+')) { $t = $tok.Trim().TrimStart('#'); if ($t) { $restrict += $(if ($script:calcRestrictMap[$t]) { $script:calcRestrictMap[$t] } else { $t }) } }
|
||||
} elseif ($ur) {
|
||||
foreach ($r in $ur) { $rr = "$r"; $restrict += $(if ($script:calcRestrictMap[$rr]) { $script:calcRestrictMap[$rr] } else { $rr }) }
|
||||
}
|
||||
$pres = $cf.presentationExpression
|
||||
$orderExpr = $cf.orderExpression
|
||||
}
|
||||
$ci = "$indent`t"
|
||||
X "$indent<CalculatedField>"
|
||||
X "$ci<dcssch:dataPath>$(Esc-Xml $dataPath)</dcssch:dataPath>"
|
||||
X "$ci<dcssch:expression>$(Esc-Xml $expression)</dcssch:expression>"
|
||||
if ($title) { Emit-MLText -tag 'dcssch:title' -text $title -indent $ci -xsiType 'v8:LocalStringType' }
|
||||
if ($restrict.Count -gt 0) {
|
||||
X "$ci<dcssch:useRestriction>"
|
||||
foreach ($r in @('field','condition','group','order')) { if ($restrict -contains $r) { X "$ci`t<dcssch:$r>true</dcssch:$r>" } }
|
||||
X "$ci</dcssch:useRestriction>"
|
||||
}
|
||||
if ($pres) { X "$ci<dcssch:presentationExpression>$(Esc-Xml "$pres")</dcssch:presentationExpression>" }
|
||||
if ($orderExpr) {
|
||||
$oeList = if ($orderExpr -is [System.Collections.IList]) { $orderExpr } else { @($orderExpr) }
|
||||
foreach ($oe in $oeList) {
|
||||
if ($oe -is [string]) { $exprV = $oe; $oType = 'Asc'; $auto = 'false' }
|
||||
else { $exprV = "$($oe.expression)"; $oType = if ($oe.orderType) { "$($oe.orderType)" } else { 'Asc' }; $auto = if ($oe.autoOrder) { 'true' } else { 'false' } }
|
||||
X "$ci<dcssch:orderExpression>"
|
||||
X "$ci`t<expression xmlns=`"$($script:dcsCommonNs)`">$(Esc-Xml $exprV)</expression>"
|
||||
X "$ci`t<orderType xmlns=`"$($script:dcsCommonNs)`">$oType</orderType>"
|
||||
X "$ci`t<autoOrder xmlns=`"$($script:dcsCommonNs)`">$auto</autoOrder>"
|
||||
X "$ci</dcssch:orderExpression>"
|
||||
}
|
||||
}
|
||||
if ($typeStr) { Emit-DLValueType -typeStr $typeStr -indent $ci }
|
||||
X "$indent</CalculatedField>"
|
||||
}
|
||||
}
|
||||
|
||||
# --- 5. Type emitter ---
|
||||
|
||||
$script:formTypeSynonyms = New-Object System.Collections.Hashtable
|
||||
@@ -5552,9 +5626,13 @@ function Emit-Attributes {
|
||||
Emit-MLItems -val $fld.title -indent "$si`t`t"
|
||||
X "$si`t</dcssch:title>"
|
||||
}
|
||||
# valueType поля набора (тип значения; вычисляемые/кастомные поля)
|
||||
if ($fld.valueType) { Emit-DLValueType -typeStr "$($fld.valueType)" -indent "$si`t" }
|
||||
X "$si</Field>"
|
||||
}
|
||||
}
|
||||
# Вычисляемые поля DataSet (<CalculatedField>) — после Field*, до Parameter*.
|
||||
Emit-CalcFields -calcFields $st.calculatedFields -indent $si
|
||||
# Schema-параметры дин-списка (DataCompositionSchemaParameter) — после Field*, до MainTable.
|
||||
Emit-DLParameters -params $st.parameters -indent $si
|
||||
if ($st.mainTable) { X "$si<MainTable>$(Normalize-MetaTypeRef "$($st.mainTable)")</MainTable>" }
|
||||
|
||||
Reference in New Issue
Block a user