mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-17 16:50:30 +03:00
fix(tests): экстракторы гарда пропускали копии — ложное «OK»
Разбор остатка по support-guard показал, что расхождения портов у *-info нет:
они читают тем же хелпером состояние поддержки для вывода, и фича есть в обоих
портах. Пропускал копии сам гард.
Два дефекта извлечения, оба давали ложное «OK», а не ложную тревогу:
1. PY: вложенные определения. Пять *-info объявляют is_external_root внутри
другой функции; экстрактор искал только `^def` и перескакивал через тело
внешней функции, так что вложенные для гарда не существовали.
2. PS1: однострочные функции. subsystem-info.ps1:18 — `function Out(...) { ... }`
в одну строку; поиск закрывающей `}` на отдельной строке делал «телом» Out всё
до следующей одиночной скобки, проглатывая следующую функцию.
После починки гард увидел 9 копий, которых не видел, — все совпали с эталонами.
Побочно вскрылось, что Report-OK в interface/subsystem/xdto-validate тоже был
невидим и потому не попал в прошлое сведение Report-*; теперь сведён.
Осталось расхождение имён: одно тело называлось _sg_is_external_root (17),
is_external_root (5 *-info) и _meta_is_external_root (meta-info). В PS1 имя было
единым изначально; PY сведён к _sg_is_external_root.
Реестр: 24 семьи, 319 копий (было 310), долг ноль.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
78ac3a8c36
commit
63e711905c
@@ -353,7 +353,7 @@ def get_support_status_for_path(target_path):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return None
|
return None
|
||||||
def is_external_root(xml_path):
|
def _sg_is_external_root(xml_path):
|
||||||
if not os.path.isfile(xml_path):
|
if not os.path.isfile(xml_path):
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
@@ -367,14 +367,14 @@ def get_support_status_for_path(target_path):
|
|||||||
rp = os.path.abspath(target_path)
|
rp = os.path.abspath(target_path)
|
||||||
# The target file itself may be the element meta-xml (e.g. Subsystems/X.xml).
|
# The target file itself may be the element meta-xml (e.g. Subsystems/X.xml).
|
||||||
elem_uuid = root_uuid(rp)
|
elem_uuid = root_uuid(rp)
|
||||||
if is_external_root(rp):
|
if _sg_is_external_root(rp):
|
||||||
return None
|
return None
|
||||||
bin_path = None
|
bin_path = None
|
||||||
d = os.path.dirname(rp)
|
d = os.path.dirname(rp)
|
||||||
for _ in range(12):
|
for _ in range(12):
|
||||||
if not d:
|
if not d:
|
||||||
break
|
break
|
||||||
if is_external_root(d + ".xml"):
|
if _sg_is_external_root(d + ".xml"):
|
||||||
return None
|
return None
|
||||||
if not elem_uuid:
|
if not elem_uuid:
|
||||||
elem_uuid = root_uuid(d + ".xml")
|
elem_uuid = root_uuid(d + ".xml")
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ $script:output = New-Object System.Text.StringBuilder 8192
|
|||||||
$script:allCommandNames = @()
|
$script:allCommandNames = @()
|
||||||
|
|
||||||
function Out-Line([string]$msg) { $script:output.AppendLine($msg) | Out-Null }
|
function Out-Line([string]$msg) { $script:output.AppendLine($msg) | Out-Null }
|
||||||
function Report-OK([string]$msg) {
|
function Report-OK {
|
||||||
|
param([string]$msg)
|
||||||
$script:okCount++
|
$script:okCount++
|
||||||
if ($Detailed) { Out-Line "[OK] $msg" }
|
if ($Detailed) { Out-Line "[OK] $msg" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -674,7 +674,7 @@ def get_ws_operations(child_objs):
|
|||||||
# ── Support status of this object (Ext/ParentConfigurations.bin) ──
|
# ── Support status of this object (Ext/ParentConfigurations.bin) ──
|
||||||
# See docs/1c-support-state-spec.md. Walks up to the config root, decodes the
|
# See docs/1c-support-state-spec.md. Walks up to the config root, decodes the
|
||||||
# object's support rule. Never throws — degrades to "не на поддержке".
|
# object's support rule. Never throws — degrades to "не на поддержке".
|
||||||
def _meta_is_external_root(xml_path):
|
def _sg_is_external_root(xml_path):
|
||||||
if not os.path.isfile(xml_path):
|
if not os.path.isfile(xml_path):
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
@@ -689,7 +689,7 @@ def _meta_is_external_root(xml_path):
|
|||||||
|
|
||||||
def get_object_support_status(obj_uuid):
|
def get_object_support_status(obj_uuid):
|
||||||
try:
|
try:
|
||||||
if _meta_is_external_root(object_path):
|
if _sg_is_external_root(object_path):
|
||||||
return None
|
return None
|
||||||
d = os.path.dirname(object_path)
|
d = os.path.dirname(object_path)
|
||||||
bin_path = None
|
bin_path = None
|
||||||
|
|||||||
@@ -321,7 +321,7 @@ def get_support_status_for_path(target_path):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return None
|
return None
|
||||||
def is_external_root(xml_path):
|
def _sg_is_external_root(xml_path):
|
||||||
if not os.path.isfile(xml_path):
|
if not os.path.isfile(xml_path):
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
@@ -335,14 +335,14 @@ def get_support_status_for_path(target_path):
|
|||||||
rp = os.path.abspath(target_path)
|
rp = os.path.abspath(target_path)
|
||||||
# The target file itself may be the element meta-xml (e.g. Subsystems/X.xml).
|
# The target file itself may be the element meta-xml (e.g. Subsystems/X.xml).
|
||||||
elem_uuid = root_uuid(rp)
|
elem_uuid = root_uuid(rp)
|
||||||
if is_external_root(rp):
|
if _sg_is_external_root(rp):
|
||||||
return None
|
return None
|
||||||
bin_path = None
|
bin_path = None
|
||||||
d = os.path.dirname(rp)
|
d = os.path.dirname(rp)
|
||||||
for _ in range(12):
|
for _ in range(12):
|
||||||
if not d:
|
if not d:
|
||||||
break
|
break
|
||||||
if is_external_root(d + ".xml"):
|
if _sg_is_external_root(d + ".xml"):
|
||||||
return None
|
return None
|
||||||
if not elem_uuid:
|
if not elem_uuid:
|
||||||
elem_uuid = root_uuid(d + ".xml")
|
elem_uuid = root_uuid(d + ".xml")
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ def get_support_status_for_path(target_path):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return None
|
return None
|
||||||
def is_external_root(xml_path):
|
def _sg_is_external_root(xml_path):
|
||||||
if not os.path.isfile(xml_path):
|
if not os.path.isfile(xml_path):
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
@@ -175,14 +175,14 @@ def get_support_status_for_path(target_path):
|
|||||||
rp = os.path.abspath(target_path)
|
rp = os.path.abspath(target_path)
|
||||||
# The target file itself may be the element meta-xml (e.g. Subsystems/X.xml).
|
# The target file itself may be the element meta-xml (e.g. Subsystems/X.xml).
|
||||||
elem_uuid = root_uuid(rp)
|
elem_uuid = root_uuid(rp)
|
||||||
if is_external_root(rp):
|
if _sg_is_external_root(rp):
|
||||||
return None
|
return None
|
||||||
bin_path = None
|
bin_path = None
|
||||||
d = os.path.dirname(rp)
|
d = os.path.dirname(rp)
|
||||||
for _ in range(12):
|
for _ in range(12):
|
||||||
if not d:
|
if not d:
|
||||||
break
|
break
|
||||||
if is_external_root(d + ".xml"):
|
if _sg_is_external_root(d + ".xml"):
|
||||||
return None
|
return None
|
||||||
if not elem_uuid:
|
if not elem_uuid:
|
||||||
elem_uuid = root_uuid(d + ".xml")
|
elem_uuid = root_uuid(d + ".xml")
|
||||||
|
|||||||
@@ -278,7 +278,7 @@ def get_support_status_for_path(target_path):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return None
|
return None
|
||||||
def is_external_root(xml_path):
|
def _sg_is_external_root(xml_path):
|
||||||
if not os.path.isfile(xml_path):
|
if not os.path.isfile(xml_path):
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
@@ -292,14 +292,14 @@ def get_support_status_for_path(target_path):
|
|||||||
rp = os.path.abspath(target_path)
|
rp = os.path.abspath(target_path)
|
||||||
# The target file itself may be the element meta-xml (e.g. Subsystems/X.xml).
|
# The target file itself may be the element meta-xml (e.g. Subsystems/X.xml).
|
||||||
elem_uuid = root_uuid(rp)
|
elem_uuid = root_uuid(rp)
|
||||||
if is_external_root(rp):
|
if _sg_is_external_root(rp):
|
||||||
return None
|
return None
|
||||||
bin_path = None
|
bin_path = None
|
||||||
d = os.path.dirname(rp)
|
d = os.path.dirname(rp)
|
||||||
for _ in range(12):
|
for _ in range(12):
|
||||||
if not d:
|
if not d:
|
||||||
break
|
break
|
||||||
if is_external_root(d + ".xml"):
|
if _sg_is_external_root(d + ".xml"):
|
||||||
return None
|
return None
|
||||||
if not elem_uuid:
|
if not elem_uuid:
|
||||||
elem_uuid = root_uuid(d + ".xml")
|
elem_uuid = root_uuid(d + ".xml")
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ def get_support_status_for_path(target_path):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return None
|
return None
|
||||||
def is_external_root(xml_path):
|
def _sg_is_external_root(xml_path):
|
||||||
if not os.path.isfile(xml_path):
|
if not os.path.isfile(xml_path):
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
@@ -164,14 +164,14 @@ def get_support_status_for_path(target_path):
|
|||||||
rp = os.path.abspath(target_path)
|
rp = os.path.abspath(target_path)
|
||||||
# The target file itself may be the element meta-xml (e.g. Subsystems/X.xml).
|
# The target file itself may be the element meta-xml (e.g. Subsystems/X.xml).
|
||||||
elem_uuid = root_uuid(rp)
|
elem_uuid = root_uuid(rp)
|
||||||
if is_external_root(rp):
|
if _sg_is_external_root(rp):
|
||||||
return None
|
return None
|
||||||
bin_path = None
|
bin_path = None
|
||||||
d = os.path.dirname(rp)
|
d = os.path.dirname(rp)
|
||||||
for _ in range(12):
|
for _ in range(12):
|
||||||
if not d:
|
if not d:
|
||||||
break
|
break
|
||||||
if is_external_root(d + ".xml"):
|
if _sg_is_external_root(d + ".xml"):
|
||||||
return None
|
return None
|
||||||
if not elem_uuid:
|
if not elem_uuid:
|
||||||
elem_uuid = root_uuid(d + ".xml")
|
elem_uuid = root_uuid(d + ".xml")
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ $script:okCount = 0
|
|||||||
$script:output = New-Object System.Text.StringBuilder 8192
|
$script:output = New-Object System.Text.StringBuilder 8192
|
||||||
|
|
||||||
function Out-Line([string]$msg) { $script:output.AppendLine($msg) | Out-Null }
|
function Out-Line([string]$msg) { $script:output.AppendLine($msg) | Out-Null }
|
||||||
function Report-OK([string]$msg) {
|
function Report-OK {
|
||||||
|
param([string]$msg)
|
||||||
$script:okCount++
|
$script:okCount++
|
||||||
if ($Detailed) { Out-Line "[OK] $msg" }
|
if ($Detailed) { Out-Line "[OK] $msg" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ $script:stopped = $false
|
|||||||
$script:output = New-Object System.Text.StringBuilder
|
$script:output = New-Object System.Text.StringBuilder
|
||||||
|
|
||||||
function Out-Line([string]$s) { [void]$script:output.AppendLine($s) }
|
function Out-Line([string]$s) { [void]$script:output.AppendLine($s) }
|
||||||
function Report-OK([string]$msg) {
|
function Report-OK {
|
||||||
|
param([string]$msg)
|
||||||
$script:okCount++
|
$script:okCount++
|
||||||
if ($Detailed) { Out-Line "[OK] $msg" }
|
if ($Detailed) { Out-Line "[OK] $msg" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,9 +56,10 @@ const FAMILIES = [
|
|||||||
{ id: 'full', authority: 'cf-edit',
|
{ id: 'full', authority: 'cf-edit',
|
||||||
consumers: ['form-add', 'form-compile', 'form-edit', 'help-add', 'interface-edit', 'meta-compile',
|
consumers: ['form-add', 'form-compile', 'form-edit', 'help-add', 'interface-edit', 'meta-compile',
|
||||||
'meta-edit', 'meta-remove', 'mxl-compile', 'role-compile', 'skd-compile', 'skd-edit',
|
'meta-edit', 'meta-remove', 'mxl-compile', 'role-compile', 'skd-compile', 'skd-edit',
|
||||||
'subsystem-compile', 'subsystem-edit', 'template-add', 'xdto-compile', 'xdto-edit'],
|
'subsystem-compile', 'subsystem-edit', 'template-add', 'xdto-compile', 'xdto-edit',
|
||||||
// *-info навыки несут хелпер только в PS1-порте — см. debug/inline-utils/FINDINGS.md.
|
// *-info навыки читают тем же хелпером СОСТОЯНИЕ поддержки для вывода, а не запрещают
|
||||||
consumersPs1: ['form-info', 'meta-info', 'mxl-info', 'role-info', 'skd-info'] },
|
// правку. Тело то же, поэтому семья общая.
|
||||||
|
'form-info', 'meta-info', 'mxl-info', 'role-info', 'skd-info', 'subsystem-info'] },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -77,7 +78,9 @@ const FAMILIES = [
|
|||||||
consumers: ['form-add', 'form-compile', 'form-edit', 'help-add', 'interface-edit', 'meta-compile',
|
consumers: ['form-add', 'form-compile', 'form-edit', 'help-add', 'interface-edit', 'meta-compile',
|
||||||
'meta-edit', 'meta-remove', 'mxl-compile', 'role-compile', 'skd-compile', 'skd-edit',
|
'meta-edit', 'meta-remove', 'mxl-compile', 'role-compile', 'skd-compile', 'skd-edit',
|
||||||
'subsystem-compile', 'subsystem-edit', 'template-add', 'xdto-compile', 'xdto-edit'],
|
'subsystem-compile', 'subsystem-edit', 'template-add', 'xdto-compile', 'xdto-edit'],
|
||||||
consumersPs1: ['support-edit'] },
|
// support-edit и *-info читают uuid для ОТОБРАЖЕНИЯ состояния поддержки; в PY-портах
|
||||||
|
// *-info пользуются другим путём, поэтому копия только в PS1.
|
||||||
|
consumersPs1: ['form-info', 'mxl-info', 'role-info', 'skd-info', 'subsystem-info', 'support-edit'] },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -151,7 +154,8 @@ const FAMILIES = [
|
|||||||
name: 'validate: report_ok', py: null, ps1: 'Report-OK',
|
name: 'validate: report_ok', py: null, ps1: 'Report-OK',
|
||||||
variants: [
|
variants: [
|
||||||
{ id: 'buffered', authority: 'cf-validate',
|
{ id: 'buffered', authority: 'cf-validate',
|
||||||
consumers: ['cfe-validate', 'epf-validate', 'meta-validate', 'role-validate', 'skd-validate'] },
|
consumers: ['cfe-validate', 'epf-validate', 'interface-validate', 'meta-validate',
|
||||||
|
'role-validate', 'skd-validate', 'subsystem-validate', 'xdto-validate'] },
|
||||||
{ id: 'streamed', authority: 'form-validate', consumers: ['mxl-validate'],
|
{ id: 'streamed', authority: 'form-validate', consumers: ['mxl-validate'],
|
||||||
why: 'потоковый вывод вместо буферизованного — эти навыки не поддерживают -OutFile' },
|
why: 'потоковый вывод вместо буферизованного — эти навыки не поддерживают -OutFile' },
|
||||||
],
|
],
|
||||||
@@ -295,17 +299,22 @@ function extractPy(text) {
|
|||||||
const lines = text.split('\n');
|
const lines = text.split('\n');
|
||||||
const out = new Map();
|
const out = new Map();
|
||||||
for (let i = 0; i < lines.length; i++) {
|
for (let i = 0; i < lines.length; i++) {
|
||||||
const m = /^def ([A-Za-z_]\w*)\(/.exec(lines[i]);
|
// Определение бывает вложенным: *-info объявляют is_external_root внутри другой функции.
|
||||||
|
// Поиск только по `^def` делал такие копии невидимыми для гарда — то есть давал ложное «OK».
|
||||||
|
const m = /^(\s*)def ([A-Za-z_]\w*)\(/.exec(lines[i]);
|
||||||
if (!m) continue;
|
if (!m) continue;
|
||||||
|
const indent = m[1].length;
|
||||||
const body = [lines[i]];
|
const body = [lines[i]];
|
||||||
let j = i + 1;
|
let j = i + 1;
|
||||||
for (; j < lines.length; j++) {
|
for (; j < lines.length; j++) {
|
||||||
const l = lines[j];
|
const l = lines[j];
|
||||||
if (l.trim() === '' || l[0] === ' ' || l[0] === '\t') { body.push(l); continue; }
|
if (l.trim() === '') { body.push(l); continue; }
|
||||||
|
const li = l.length - l.trimStart().length;
|
||||||
|
if (li > indent) { body.push(l); continue; }
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
out.set(m[1], body);
|
if (!out.has(m[2])) out.set(m[2], body);
|
||||||
i = j - 1;
|
// НЕ перескакиваем через тело: иначе вложенные определения внутри него остались бы невидимыми.
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -318,6 +327,15 @@ function extractPs1(text) {
|
|||||||
// поэтому конец ищем по закрывающей скобке НА ТОМ ЖЕ отступе, что и слово function.
|
// поэтому конец ищем по закрывающей скобке НА ТОМ ЖЕ отступе, что и слово function.
|
||||||
const m = /^(\s*)function\s+([A-Za-z][\w-]*)/.exec(lines[i]);
|
const m = /^(\s*)function\s+([A-Za-z][\w-]*)/.exec(lines[i]);
|
||||||
if (!m) continue;
|
if (!m) continue;
|
||||||
|
// Однострочное определение (`function Out(...) { ... }`) закрывается на своей же строке.
|
||||||
|
// Без этой ветки «телом» такой функции становилось всё до следующей одиночной `}` — то есть
|
||||||
|
// следующая функция проглатывалась и была невидима для гарда.
|
||||||
|
const opens = (lines[i].match(/\{/g) || []).length;
|
||||||
|
const closes = (lines[i].match(/\}/g) || []).length;
|
||||||
|
if (opens > 0 && opens === closes) {
|
||||||
|
if (!out.has(m[2])) out.set(m[2], [lines[i]]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const closing = m[1] + '}';
|
const closing = m[1] + '}';
|
||||||
const body = [lines[i]];
|
const body = [lines[i]];
|
||||||
let j = i + 1;
|
let j = i + 1;
|
||||||
@@ -326,7 +344,6 @@ function extractPs1(text) {
|
|||||||
if (lines[j].replace(/\s+$/, '') === closing) break;
|
if (lines[j].replace(/\s+$/, '') === closing) break;
|
||||||
}
|
}
|
||||||
if (!out.has(m[2])) out.set(m[2], body);
|
if (!out.has(m[2])) out.set(m[2], body);
|
||||||
i = j;
|
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user