fix(meta-info,meta-compile,+5): правки по ревью — регистр, BOM, голый менеджер, порог

Семь находок ревью, все подтверждены воспроизведением:

1. Голый менеджер в источниках печатался по-английски: карта объектных видов
   применялась только к форме с точкой, а meta-compile пишет «cfg:DocumentManager»
   обычным v8:Type. Восемнадцать добавленных *Manager-записей были недостижимы.
   Суффикс «(все)» ему не ставится — это сам тип менеджера, а не класс объектов.
2. Новые регулярки прощающего ввода расходились между портами: -replace в
   PowerShell регистронезависим, re.sub — нет. «ДокументОбъект (Все)» проходил в
   ps1 и падал в py. Добавлен re.IGNORECASE — это задокументированная ловушка
   портирования, и она же снова сработала.
3. В шесть py-портов попал BOM (перекодировка при бампе версии), и перед
   «#!/usr/bin/env python3» он ломает shebang на POSIX. Снят там, где его не было
   в HEAD; в mxl-compile.py он был изначально и оставлен.
4. Правило со стрелкой из Resolve-TypeStr убрано. form-compile режет тип по [|+]
   ДО резолвера, поэтому строка глоссария «A -> B | C» молча превращалась в
   составной тип «A | C» вместо одного A. Половина строки, принятая за тип, —
   хуже громкого отказа. Остались суффикс «(все)» и счётчик «— типов: N».
5. py-порт meta-info не переиспользовал общий климб до корня конфигурации:
   правка тогда молча не применилась, и порты разошлись по структуре.
6. Found выставлялся до разбора состава определяемого типа: падение внутри
   давало «состав пуст» — ложь вместо «файл типа не разобран».
7. Порог сворачивания источников считался по сумме множеств и явных типов, а
   сворачивались только явные: пять множеств плюс один тип прятали этот тип, а
   шесть типов без множеств давали «и ещё» после пустоты. Порог теперь по числу
   явных типов, «и ещё» убрано как ложное.

Плюс формы источника подписки описаны в reference самого навыка: раньше они
были только в docs/meta-dsl-spec.md, а навык обязан быть самодостаточным.

Добавлен кейс на голого менеджера — без него находка 1 вернулась бы незамеченной.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-09-20 18:14:27 +03:00
co-authored by Claude Opus 5
parent 510c9163e3
commit e9d45984dc
27 changed files with 555 additions and 107 deletions
@@ -2503,9 +2503,6 @@ function Resolve-TypeStr {
$typeStr = ($typeStr -replace '\s*\((?:все|all)\)\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*\((?:типов|types):\s*\d+\)\s*$', '').Trim()
# Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
# раскрытие справа — берём левую часть, она и есть тип.
if ($typeStr -match '^(.+?)\s*(?:→|->)\s*.+$') { $typeStr = $Matches[1].Trim() }
# Параметризованные типы: Number(15,2), Строка(100)
if ($typeStr -match '^([^(]+)\((.+)\)$') {
@@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python3
# form-compile v1.199 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -3912,14 +3912,9 @@ def resolve_type_str(type_str):
# и счётчик состава. Копипаста строки оттуда — обычный путь, поэтому хвост снимаем молча.
# Срезаем ТОЛЬКО эти известные формы: круглые скобки заняты параметризованными типами
# (Число(15,2)), слепой срез скобок сломал бы их.
type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str).strip()
type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str).strip()
type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str).strip()
# Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
# раскрытие справа — берём левую часть, она и есть тип.
m = re.match(r'^(.+?)\s*(?:→|->)\s*.+$', type_str)
if m:
type_str = m.group(1).strip()
type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str, flags=re.IGNORECASE).strip()
type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
# Параметризованные типы: Number(15,2), Строка(100)
m = re.match(r'^([^(]+)\((.+)\)$', type_str)
if m:
@@ -410,9 +410,6 @@ function Resolve-TypeStr {
$typeStr = ($typeStr -replace '\s*\((?:все|all)\)\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*\((?:типов|types):\s*\d+\)\s*$', '').Trim()
# Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
# раскрытие справа — берём левую часть, она и есть тип.
if ($typeStr -match '^(.+?)\s*(?:→|->)\s*.+$') { $typeStr = $Matches[1].Trim() }
# Параметризованные типы: Number(15,2), Строка(100)
if ($typeStr -match '^([^(]+)\((.+)\)$') {
@@ -1,4 +1,4 @@
# form-edit v1.19 — Edit 1C managed form elements (Python port)
# form-edit v1.19 — Edit 1C managed form elements (Python port)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import json
@@ -534,14 +534,9 @@ def resolve_type_str(type_str):
# и счётчик состава. Копипаста строки оттуда — обычный путь, поэтому хвост снимаем молча.
# Срезаем ТОЛЬКО эти известные формы: круглые скобки заняты параметризованными типами
# (Число(15,2)), слепой срез скобок сломал бы их.
type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str).strip()
type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str).strip()
type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str).strip()
# Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
# раскрытие справа — берём левую часть, она и есть тип.
m = re.match(r'^(.+?)\s*(?:→|->)\s*.+$', type_str)
if m:
type_str = m.group(1).strip()
type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str, flags=re.IGNORECASE).strip()
type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
# Параметризованные типы: Number(15,2), Строка(100)
m = re.match(r'^([^(]+)\((.+)\)$', type_str)
if m:
+20 -1
View File
@@ -43,7 +43,7 @@
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `source` | `[]` | объекты-источники: `["CatalogObject.Контрагенты", "DocumentObject.Реализация"]` |
| `source` | `[]` | объекты-источники (формы ниже): `["CatalogObject.Контрагенты", "DocumentObject.Реализация"]` |
| `event` | `BeforeWrite` | `BeforeWrite` / `OnWrite` / `BeforeDelete` / `OnReadAtServer` / `FillCheckProcessing` … |
| `handler` | пусто | метод-обработчик `"МодульСервер.Процедура"` (дополняется до `CommonModule.…`) |
@@ -53,4 +53,23 @@
"handler": "ОбщегоНазначенияСервер.ПередЗаписьюКонтрагента" }
```
**Формы источника.** Кроме конкретного объекта (`DocumentObject.Реализация`) источник бывает:
| Форма | Смысл | Пример |
|-------|-------|--------|
| голый объектный вид | ВСЕ объекты класса | `"DocumentObject"`, `"CatalogObject"`, `"InformationRegisterRecordSet"`, `"ConstantValueManager"` |
| `DefinedType.<Имя>` | состав определяемого типа | `"DefinedType.ПрисоединенныйФайлОбъект"` |
| `Characteristic.<Имя>` | значение характеристики ПВХ | `"Characteristic.ДополнительныеРеквизитыИСведения"` |
| менеджер объекта | сам менеджер, не класс | `"DocumentManager.Реализация"`, `"CatalogManager.Контрагенты"` |
В типовых конфигурациях источник чаще задан классом или определяемым типом, чем перечислением:
в выгрузке ERP так задана треть подписок. Русские имена принимаются наравне с английскими
(`"ДокументОбъект"`, `"ОпределяемыйТип.Коллекция"`).
```json
{ "type": "EventSubscription", "name": "ПроверкаЗаполненияЛюбогоДокумента",
"source": ["DocumentObject", "DefinedType.ПрисоединенныйФайлОбъект"],
"event": "FillCheckProcessing", "handler": "ОбщегоНазначенияСервер.ПроверитьЗаполнение" }
```
> Процедура-обработчик (`methodName` / `handler`) должна существовать в указанном общем модуле (экспортная).
@@ -739,9 +739,6 @@ function Resolve-TypeStr {
$typeStr = ($typeStr -replace '\s*\((?:все|all)\)\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*\((?:типов|types):\s*\d+\)\s*$', '').Trim()
# Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
# раскрытие справа — берём левую часть, она и есть тип.
if ($typeStr -match '^(.+?)\s*(?:→|->)\s*.+$') { $typeStr = $Matches[1].Trim() }
# Параметризованные типы: Number(15,2), Строка(100)
if ($typeStr -match '^([^(]+)\((.+)\)$') {
@@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python3
# meta-compile v1.113 — Compile 1C metadata object from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
@@ -873,14 +873,9 @@ def resolve_type_str(type_str):
# и счётчик состава. Копипаста строки оттуда — обычный путь, поэтому хвост снимаем молча.
# Срезаем ТОЛЬКО эти известные формы: круглые скобки заняты параметризованными типами
# (Число(15,2)), слепой срез скобок сломал бы их.
type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str).strip()
type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str).strip()
type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str).strip()
# Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
# раскрытие справа — берём левую часть, она и есть тип.
m = re.match(r'^(.+?)\s*(?:→|->)\s*.+$', type_str)
if m:
type_str = m.group(1).strip()
type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str, flags=re.IGNORECASE).strip()
type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
# Параметризованные типы: Number(15,2), Строка(100)
m = re.match(r'^([^(]+)\((.+)\)$', type_str)
if m:
@@ -625,9 +625,6 @@ function Resolve-TypeStr {
$typeStr = ($typeStr -replace '\s*\((?:все|all)\)\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*\((?:типов|types):\s*\d+\)\s*$', '').Trim()
# Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
# раскрытие справа — берём левую часть, она и есть тип.
if ($typeStr -match '^(.+?)\s*(?:→|->)\s*.+$') { $typeStr = $Matches[1].Trim() }
# Параметризованные типы: Number(15,2), Строка(100)
if ($typeStr -match '^([^(]+)\((.+)\)$') {
@@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python3
# meta-edit v1.53 — Edit existing 1C metadata object XML
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
@@ -649,14 +649,9 @@ def resolve_type_str(type_str):
# и счётчик состава. Копипаста строки оттуда — обычный путь, поэтому хвост снимаем молча.
# Срезаем ТОЛЬКО эти известные формы: круглые скобки заняты параметризованными типами
# (Число(15,2)), слепой срез скобок сломал бы их.
type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str).strip()
type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str).strip()
type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str).strip()
# Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
# раскрытие справа — берём левую часть, она и есть тип.
m = re.match(r'^(.+?)\s*(?:→|->)\s*.+$', type_str)
if m:
type_str = m.group(1).strip()
type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str, flags=re.IGNORECASE).strip()
type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
# Параметризованные типы: Number(15,2), Строка(100)
m = re.match(r'^([^(]+)\((.+)\)$', type_str)
if m:
+11 -5
View File
@@ -250,7 +250,6 @@ function Resolve-DefinedType([string]$dtName) {
$dtNs.AddNamespace("v8", "http://v8.1c.ru/8.1/data/core")
$tn = $dtDoc.SelectSingleNode("/md:MetaDataObject/md:DefinedType/md:Properties/md:Type", $dtNs)
if ($tn) {
$res.Found = $true
$members = @()
$script:inTypeSetExpansion = $true
try {
@@ -264,6 +263,9 @@ function Resolve-DefinedType([string]$dtName) {
}
} finally { $script:inTypeSetExpansion = $false }
$res.Members = $members
# Found только после успешного разбора: иначе упавшее раскрытие
# печаталось бы как «состав пуст» — ложь вместо «не разобран».
$res.Found = $true
}
} catch { $res.Broken = $true }
if (-not $res.Found) { $res.Broken = $true }
@@ -728,6 +730,12 @@ function Format-SourceType([string]$raw) {
$prefix = $Matches[1]; $name = $Matches[2]
if ($objectTypeMap.ContainsKey($prefix)) { return "$($objectTypeMap[$prefix]).$name" }
}
# Голый вид без точки тоже бывает источником: meta-compile пишет менеджера (ДокументМенеджер)
# обычным v8:Type. Суффикса «(все)» тут НЕ ставим — это сам тип менеджера, а не класс объектов;
# множеством голый вид приходит через v8:TypeSet, и его форматирует Format-SingleTypeSet.
if ($raw -match '^cfg:(\w+)$' -and $objectTypeMap.ContainsKey($Matches[1])) {
return $objectTypeMap[$Matches[1]]
}
if ($raw -match '^cfg:(.+)$') { return $Matches[1] }
return $raw
}
@@ -1440,12 +1448,10 @@ if (-not $drillDone) {
Out "Источники ($total):"
# full печатает всё: режим для этого и нужен, а длину держит постраничник.
# В overview явные типы сворачиваем в счётчик — их бывает больше тысячи.
$listTypes = ($Mode -eq "full") -or ($total -le $script:composedTypeThreshold)
$listTypes = ($Mode -eq "full") -or ($srcTypes.Count -le $script:composedTypeThreshold)
if ($listTypes) { foreach ($s in $srcTypes) { Out " $s" } }
foreach ($s in $srcSets) { Out " $s" }
if (-not $listTypes -and $srcTypes.Count -gt 0) {
Out " и ещё явных типов: $($srcTypes.Count) (-Mode full)"
}
if (-not $listTypes) { Out " явных типов: $($srcTypes.Count) (-Mode full)" }
}
}
}
+15 -17
View File
@@ -328,7 +328,6 @@ def resolve_defined_type(dt_name):
dt_root = etree.parse(dt_path, parser_xml).getroot()
tn = find(dt_root, "/md:MetaDataObject/md:DefinedType/md:Properties/md:Type")
if tn is not None:
res["found"] = True
members = []
_in_type_set_expansion["on"] = True
try:
@@ -340,6 +339,9 @@ def resolve_defined_type(dt_name):
finally:
_in_type_set_expansion["on"] = False
res["members"] = members
# found только после успешного разбора: иначе упавшее раскрытие
# печаталось бы как «состав пуст» — ложь вместо «не разобран».
res["found"] = True
except Exception:
res["broken"] = True
if not res["found"]:
@@ -793,6 +795,12 @@ def format_source_type(raw):
name = m.group(2)
if prefix in object_type_map:
return f"{object_type_map[prefix]}.{name}"
# Голый вид без точки тоже бывает источником: meta-compile пишет менеджера (ДокументМенеджер)
# обычным v8:Type. Суффикса «(все)» тут НЕ ставим — это сам тип менеджера, а не класс объектов;
# множеством голый вид приходит через v8:TypeSet, и его форматирует format_single_type_set.
m = re.match(r'^cfg:(\w+)$', raw)
if m and m.group(1) in object_type_map:
return object_type_map[m.group(1)]
m = re.match(r'^cfg:(.+)$', raw)
if m:
return m.group(1)
@@ -883,19 +891,9 @@ def get_object_support_status(obj_uuid):
try:
if _sg_is_external_root(object_path):
return None
d = os.path.dirname(object_path)
bin_path = None
for _ in range(8):
if not d:
break
cand = os.path.join(d, "Ext", "ParentConfigurations.bin")
if os.path.exists(cand) or os.path.exists(os.path.join(d, "Configuration.xml")):
bin_path = cand
break
parent = os.path.dirname(d)
if parent == d:
break
d = parent
# Корень конфигурации ищем тем же климбом, что и состав определяемых типов.
root = get_config_root_dir()
bin_path = os.path.join(root, "Ext", "ParentConfigurations.bin") if root else None
if not bin_path or not os.path.exists(bin_path):
return "не на поддержке"
data = open(bin_path, "rb").read()
@@ -1474,14 +1472,14 @@ if not drill_done:
out(f"Источники ({total}):")
# full печатает всё: режим для этого и нужен, а длину держит постраничник.
# В overview явные типы сворачиваем в счётчик — их бывает больше тысячи.
list_types = mode == "full" or total <= COMPOSED_TYPE_THRESHOLD
list_types = mode == "full" or len(src_types) <= COMPOSED_TYPE_THRESHOLD
if list_types:
for s in src_types:
out(f" {s}")
for s in src_sets:
out(f" {s}")
if not list_types and src_types:
out(f" и ещё явных типов: {len(src_types)} (-Mode full)")
if not list_types:
out(f" явных типов: {len(src_types)} (-Mode full)")
# HTTPService
if md_type == "HTTPService":
@@ -783,9 +783,6 @@ function Resolve-TypeStr {
$typeStr = ($typeStr -replace '\s*\((?:все|all)\)\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*\((?:типов|types):\s*\d+\)\s*$', '').Trim()
# Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
# раскрытие справа — берём левую часть, она и есть тип.
if ($typeStr -match '^(.+?)\s*(?:→|->)\s*.+$') { $typeStr = $Matches[1].Trim() }
# Параметризованные типы: Number(15,2), Строка(100)
if ($typeStr -match '^([^(]+)\((.+)\)$') {
@@ -577,14 +577,9 @@ def resolve_type_str(type_str):
# и счётчик состава. Копипаста строки оттуда — обычный путь, поэтому хвост снимаем молча.
# Срезаем ТОЛЬКО эти известные формы: круглые скобки заняты параметризованными типами
# (Число(15,2)), слепой срез скобок сломал бы их.
type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str).strip()
type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str).strip()
type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str).strip()
# Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
# раскрытие справа — берём левую часть, она и есть тип.
m = re.match(r'^(.+?)\s*(?:→|->)\s*.+$', type_str)
if m:
type_str = m.group(1).strip()
type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str, flags=re.IGNORECASE).strip()
type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
# Параметризованные типы: Number(15,2), Строка(100)
m = re.match(r'^([^(]+)\((.+)\)$', type_str)
@@ -443,9 +443,6 @@ function Resolve-TypeStr {
$typeStr = ($typeStr -replace '\s*\((?:все|all)\)\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*\((?:типов|types):\s*\d+\)\s*$', '').Trim()
# Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
# раскрытие справа — берём левую часть, она и есть тип.
if ($typeStr -match '^(.+?)\s*(?:→|->)\s*.+$') { $typeStr = $Matches[1].Trim() }
# Параметризованные типы: Number(15,2), Строка(100)
if ($typeStr -match '^([^(]+)\((.+)\)$') {
@@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python3
# skd-compile v1.123 — Compile 1C DCS from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -427,14 +427,9 @@ def resolve_type_str(type_str):
# и счётчик состава. Копипаста строки оттуда — обычный путь, поэтому хвост снимаем молча.
# Срезаем ТОЛЬКО эти известные формы: круглые скобки заняты параметризованными типами
# (Число(15,2)), слепой срез скобок сломал бы их.
type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str).strip()
type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str).strip()
type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str).strip()
# Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
# раскрытие справа — берём левую часть, она и есть тип.
m = re.match(r'^(.+?)\s*(?:→|->)\s*.+$', type_str)
if m:
type_str = m.group(1).strip()
type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str, flags=re.IGNORECASE).strip()
type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
# Параметризованные типы: Number(15,2), Строка(100)
m = re.match(r'^([^(]+)\((.+)\)$', type_str)
if m:
@@ -274,9 +274,6 @@ function Resolve-TypeStr {
$typeStr = ($typeStr -replace '\s*\((?:все|all)\)\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*\((?:типов|types):\s*\d+\)\s*$', '').Trim()
# Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
# раскрытие справа — берём левую часть, она и есть тип.
if ($typeStr -match '^(.+?)\s*(?:→|->)\s*.+$') { $typeStr = $Matches[1].Trim() }
# Параметризованные типы: Number(15,2), Строка(100)
if ($typeStr -match '^([^(]+)\((.+)\)$') {
+4 -9
View File
@@ -1,4 +1,4 @@
# skd-edit v1.41 — Atomic 1C DCS editor (Python port)
# skd-edit v1.41 — Atomic 1C DCS editor (Python port)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import json
@@ -386,14 +386,9 @@ def resolve_type_str(type_str):
# и счётчик состава. Копипаста строки оттуда — обычный путь, поэтому хвост снимаем молча.
# Срезаем ТОЛЬКО эти известные формы: круглые скобки заняты параметризованными типами
# (Число(15,2)), слепой срез скобок сломал бы их.
type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str).strip()
type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str).strip()
type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str).strip()
# Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
# раскрытие справа — берём левую часть, она и есть тип.
m = re.match(r'^(.+?)\s*(?:→|->)\s*.+$', type_str)
if m:
type_str = m.group(1).strip()
type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str, flags=re.IGNORECASE).strip()
type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
# Параметризованные типы: Number(15,2), Строка(100)
m = re.match(r'^([^(]+)\((.+)\)$', type_str)
if m: