feat(form-decompile,form-compile): string(N,fixed) — AllowedLength=Fixed для строк фикс. длины

Колонки/реквизиты строк фиксированной длины (ИНН/КПП/коды) несут
<v8:AllowedLength>Fixed</v8:AllowedLength>, но DSL выражал только Variable:
компилятор хардкодил Variable, декомпилятор не читал AllowedLength → Fixed терялся
(форма ЭлектроннаяТранспортнаяНакладная/ТитулПеревозчика*: 3 LOST Fixed + 3 ADDED
Variable — мультимножественный учёт тех же колонок).

Корпус 8.3.24: AllowedLength ВСЕГДА присутствует в StringQualifiers (Variable
443127 + Fixed 2687, ABSENT=0) → always-эмиссия Variable верна. Fixed (2687)
всегда с длиной > 0 (12/10/3/1/36…); при Length=0 — всегда Variable.

Грамматика `string(N,fixed)` (по аналогии с `decimal(D,F,nonneg)`). Variable —
дефолт (опускаем суффикс); `variable` принимается forgiving. Emit-SingleType
(ps1+py) эмитит Fixed при суффиксе; декомпилятор Decompile-Type читает AllowedLength
(Fixed → суффикс, Variable/Length=0 → плоский string(N)). Общий путь типов
(реквизиты/колонки/valueType/составные).

Выборка 46 форм с Fixed (вкл. указанную): 0 потерь AllowedLength, целевая форма →
match. Round-trip декомпиляции снэпшота: string(12,fixed)/string(9,fixed) читаются
обратно. Кейс attributes-types (+ValueTable с Fixed-колонками ИНН/Код) сертифицирован
в 1С. Регресс 43/43 (ps1+py).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-11 17:29:09 +03:00
co-authored by Claude Opus 4.8
parent b2eaa9e129
commit b781f97832
6 changed files with 65 additions and 13 deletions
@@ -1,4 +1,4 @@
# form-decompile v0.90 — Decompile 1C managed Form.xml to JSON DSL (draft)
# form-decompile v0.91 — Decompile 1C managed Form.xml to JSON DSL (draft)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
param(
@@ -1080,7 +1080,11 @@ function Decompile-Type {
switch -regex ($raw) {
'^xs:string$' {
$len = $typeNode.SelectSingleNode("v8:StringQualifiers/v8:Length", $ns)
if ($len -and [int]$len.InnerText -gt 0) { $short = "string($($len.InnerText))" } else { $short = "string" }
$al = $typeNode.SelectSingleNode("v8:StringQualifiers/v8:AllowedLength", $ns)
$fixed = ($al -and $al.InnerText -eq 'Fixed') # Variable = дефолт (опускаем); Fixed — явно
if ($len -and [int]$len.InnerText -gt 0) {
$short = if ($fixed) { "string($($len.InnerText),fixed)" } else { "string($($len.InnerText))" }
} else { $short = "string" } # Length=0 → всегда Variable (корпус)
break
}
'^xs:decimal$' {