diff --git a/.claude/skills/cfe-patch-method/SKILL.md b/.claude/skills/cfe-patch-method/SKILL.md
index 94e43461f..30ce6a46d 100644
--- a/.claude/skills/cfe-patch-method/SKILL.md
+++ b/.claude/skills/cfe-patch-method/SKILL.md
@@ -44,6 +44,7 @@ allowed-tools:
| `Catalog.X.ManagerModule` | `Catalogs/X/Ext/ManagerModule.bsl` |
| `Catalog.X.Form.Y` | `Catalogs/X/Forms/Y/Ext/Form/Module.bsl` |
| `CommonModule.X` | `CommonModules/X/Ext/Module.bsl` |
+| `CommonForm.X` | `CommonForms/X/Ext/Form/Module.bsl` |
| `Document.X.ObjectModule` | `Documents/X/Ext/ObjectModule.bsl` |
| `Document.X.Form.Y` | `Documents/X/Forms/Y/Ext/Form/Module.bsl` |
diff --git a/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.ps1 b/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.ps1
index 1cbc5965a..d9eaff7ef 100644
--- a/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.ps1
+++ b/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.ps1
@@ -1,4 +1,4 @@
-# cfe-patch-method v2.12 — Source-aware method interceptor for 1C extension (CFE)
+# cfe-patch-method v2.13 — Source-aware method interceptor for 1C extension (CFE)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
[CmdletBinding(PositionalBinding=$false)]
param(
@@ -44,6 +44,7 @@ $script:typeDirMap = @{
"BusinessProcesses"="BusinessProcesses"; "Tasks"="Tasks"
"InformationRegisters"="InformationRegisters"; "AccumulationRegisters"="AccumulationRegisters"
"AccountingRegisters"="AccountingRegisters"; "CalculationRegisters"="CalculationRegisters"
+ "CommonForm"="CommonForms"; "CommonForms"="CommonForms"
}
# InterceptorType -> Russian decorator keyword
@@ -156,7 +157,7 @@ function Get-ModuleRelPath {
param([string]$modulePath)
$parts = $modulePath.Split(".")
if ($parts.Count -lt 2) {
- throw "Invalid ModulePath format: $modulePath. Expected: Type.Name.Module, Type.Name.Form.FormName or CommonModule.Name"
+ throw "Invalid ModulePath format: $modulePath. Expected: Type.Name.Module, Type.Name.Form.FormName, CommonModule.Name or CommonForm.Name"
}
$objType = $parts[0]
$objName = $parts[1]
@@ -167,6 +168,9 @@ function Get-ModuleRelPath {
if ($objType -eq "CommonModule") {
return @($dirName, $objName, "Ext", "Module.bsl")
+ } elseif ($dirName -eq "CommonForms") {
+ # Общая форма — сама форма: модуль лежит прямо у неё, без Forms/<Имя>
+ return @($dirName, $objName, "Ext", "Form", "Module.bsl")
} elseif ($parts.Count -ge 4 -and $parts[2] -eq "Form") {
$formName = $parts[3]
return @($dirName, $objName, "Forms", $formName, "Ext", "Form", "Module.bsl")
@@ -667,7 +671,7 @@ $script:dirToType = @{
"ChartsOfCalculationTypes"="ChartOfCalculationTypes"; "BusinessProcesses"="BusinessProcess"
"Tasks"="Task"; "InformationRegisters"="InformationRegister"
"AccumulationRegisters"="AccumulationRegister"; "AccountingRegisters"="AccountingRegister"
- "CalculationRegisters"="CalculationRegister"
+ "CalculationRegisters"="CalculationRegister"; "CommonForms"="CommonForm"
}
# Rel-path segments (relative to ExtensionPath) -> logical ModulePath (Type.Name.Module / CommonModule.Name)
@@ -676,6 +680,7 @@ function Get-ModulePathFromRel {
$dir0 = $relParts[0]; $name = $relParts[1]
$typ = if ($script:dirToType.ContainsKey($dir0)) { $script:dirToType[$dir0] } else { $dir0 }
if ($dir0 -eq "CommonModules") { return "CommonModule.$name" }
+ if ($dir0 -eq "CommonForms") { return "CommonForm.$name" }
if ($relParts.Count -ge 7 -and $relParts[2] -eq "Forms") { return "$typ.$name.Form.$($relParts[3])" }
$mod = $relParts[$relParts.Count - 1]
if ($mod.EndsWith(".bsl")) { $mod = $mod.Substring(0, $mod.Length - 4) }
diff --git a/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.py b/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.py
index e29c4f003..31169ef5d 100644
--- a/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.py
+++ b/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# cfe-patch-method v2.12 — Source-aware method interceptor for 1C extension (CFE)
+# cfe-patch-method v2.13 — Source-aware method interceptor for 1C extension (CFE)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -41,6 +41,7 @@ TYPE_DIR_MAP = {
"BusinessProcess": "BusinessProcesses", "Task": "Tasks",
"InformationRegister": "InformationRegisters", "AccumulationRegister": "AccumulationRegisters",
"AccountingRegister": "AccountingRegisters", "CalculationRegister": "CalculationRegisters",
+ "CommonForm": "CommonForms",
# Прощающий ввод: имя каталога принимается наравне с именем типа (Catalogs.X ≡ Catalog.X) —
# PS1-порт так умел с самого начала, PY отставал.
"Catalogs": "Catalogs",
@@ -248,7 +249,7 @@ def get_module_rel_path(module_path):
if len(parts) < 2:
raise ValueError(
"Invalid ModulePath format: %s. Expected: Type.Name.Module, "
- "Type.Name.Form.FormName or CommonModule.Name" % module_path
+ "Type.Name.Form.FormName, CommonModule.Name or CommonForm.Name" % module_path
)
obj_type = parts[0]
obj_name = parts[1]
@@ -258,6 +259,9 @@ def get_module_rel_path(module_path):
if obj_type == "CommonModule":
return [dir_name, obj_name, "Ext", "Module.bsl"]
+ if dir_name == "CommonForms":
+ # Общая форма — сама форма: модуль лежит прямо у неё, без Forms/<Имя>
+ return [dir_name, obj_name, "Ext", "Form", "Module.bsl"]
if len(parts) >= 4 and parts[2] == "Form":
form_name = parts[3]
return [dir_name, obj_name, "Forms", form_name, "Ext", "Form", "Module.bsl"]
@@ -1163,7 +1167,7 @@ DIR_TO_TYPE = {
"ChartsOfCalculationTypes": "ChartOfCalculationTypes", "BusinessProcesses": "BusinessProcess",
"Tasks": "Task", "InformationRegisters": "InformationRegister",
"AccumulationRegisters": "AccumulationRegister", "AccountingRegisters": "AccountingRegister",
- "CalculationRegisters": "CalculationRegister",
+ "CalculationRegisters": "CalculationRegister", "CommonForms": "CommonForm",
}
@@ -1172,6 +1176,8 @@ def module_path_from_rel(rel_parts):
typ = DIR_TO_TYPE.get(dir0, dir0)
if dir0 == "CommonModules":
return "CommonModule.%s" % name
+ if dir0 == "CommonForms":
+ return "CommonForm.%s" % name
if len(rel_parts) >= 7 and rel_parts[2] == "Forms":
return "%s.%s.Form.%s" % (typ, name, rel_parts[3])
mod = rel_parts[-1][:-4] if rel_parts[-1].endswith(".bsl") else rel_parts[-1]
diff --git a/tests/skills/cases/cfe-patch-method/common-form-check.json b/tests/skills/cases/cfe-patch-method/common-form-check.json
new file mode 100644
index 000000000..7bfebe90c
--- /dev/null
+++ b/tests/skills/cases/cfe-patch-method/common-form-check.json
@@ -0,0 +1,89 @@
+{
+ "name": "Проверка -Check видит дрейф &ИзменениеИКонтроль в модуле общей формы и называет его CommonForm.Имя",
+ "preRun": [
+ {
+ "script": "meta-compile/scripts/meta-compile",
+ "input": {
+ "type": "CommonForm",
+ "name": "Подбор"
+ },
+ "args": {
+ "-JsonPath": "{inputFile}",
+ "-OutputDir": "{workDir}"
+ }
+ },
+ {
+ "script": "form-compile/scripts/form-compile",
+ "input": {
+ "title": "Подбор",
+ "elements": [
+ {
+ "check": "Режим",
+ "path": "Режим"
+ }
+ ],
+ "attributes": [
+ {
+ "name": "Режим",
+ "type": "boolean"
+ }
+ ]
+ },
+ "args": {
+ "-JsonPath": "{inputFile}",
+ "-OutputPath": "{workDir}/CommonForms/Подбор/Ext/Form.xml"
+ }
+ },
+ {
+ "writeFile": {
+ "path": "CommonForms/Подбор/Ext/Form/Module.bsl",
+ "content": "#Область ОбработчикиСобытийФормы\n\n&НаСервере\nПроцедура Заполнить()\n\tХ = 1;\nКонецПроцедуры\n\n#КонецОбласти\n"
+ }
+ },
+ {
+ "script": "cfe-init/scripts/cfe-init",
+ "args": {
+ "-Name": "Тест",
+ "-OutputDir": "{workDir}/cfe",
+ "-ConfigPath": "{workDir}"
+ }
+ },
+ {
+ "script": "cfe-borrow/scripts/cfe-borrow",
+ "args": {
+ "-ExtensionPath": "{workDir}/cfe",
+ "-ConfigPath": "{workDir}",
+ "-Object": "CommonForm.Подбор"
+ }
+ },
+ {
+ "script": "cfe-patch-method/scripts/cfe-patch-method",
+ "args": {
+ "-ExtensionPath": "{workDir}/cfe",
+ "-ConfigPath": "{workDir}",
+ "-ModulePath": "CommonForm.Подбор",
+ "-MethodName": "Заполнить",
+ "-InterceptorType": "ModificationAndControl"
+ }
+ },
+ {
+ "writeFile": {
+ "path": "CommonForms/Подбор/Ext/Form/Module.bsl",
+ "content": "#Область ОбработчикиСобытийФормы\n\n&НаСервере\nПроцедура Заполнить()\n\tХ = 2;\nКонецПроцедуры\n\n#КонецОбласти\n"
+ }
+ }
+ ],
+ "params": {
+ "extensionPath": "cfe"
+ },
+ "expectError": true,
+ "expect": {
+ "stdoutContains": [
+ "ДРЕЙФ",
+ "CommonForm.Подбор.Заполнить"
+ ]
+ },
+ "args_extra": [
+ "-Check"
+ ]
+}
diff --git a/tests/skills/cases/cfe-patch-method/common-form-handler.json b/tests/skills/cases/cfe-patch-method/common-form-handler.json
new file mode 100644
index 000000000..c840b085d
--- /dev/null
+++ b/tests/skills/cases/cfe-patch-method/common-form-handler.json
@@ -0,0 +1,73 @@
+{
+ "name": "Перехватчик в модуле общей формы: ModulePath CommonForm.Имя → CommonForms/Имя/Ext/Form/Module.bsl",
+ "preRun": [
+ {
+ "script": "meta-compile/scripts/meta-compile",
+ "input": {
+ "type": "CommonForm",
+ "name": "Подбор"
+ },
+ "args": {
+ "-JsonPath": "{inputFile}",
+ "-OutputDir": "{workDir}"
+ }
+ },
+ {
+ "script": "form-compile/scripts/form-compile",
+ "input": {
+ "title": "Подбор",
+ "elements": [
+ {
+ "check": "Режим",
+ "path": "Режим"
+ }
+ ],
+ "attributes": [
+ {
+ "name": "Режим",
+ "type": "boolean"
+ }
+ ]
+ },
+ "args": {
+ "-JsonPath": "{inputFile}",
+ "-OutputPath": "{workDir}/CommonForms/Подбор/Ext/Form.xml"
+ }
+ },
+ {
+ "writeFile": {
+ "path": "CommonForms/Подбор/Ext/Form/Module.bsl",
+ "content": "#Область ОбработчикиСобытийФормы\n\n&НаСервере\nПроцедура Заполнить()\n\tХ = 1;\nКонецПроцедуры\n\n#КонецОбласти\n"
+ }
+ },
+ {
+ "script": "cfe-init/scripts/cfe-init",
+ "args": {
+ "-Name": "Тест",
+ "-OutputDir": "{workDir}/cfe",
+ "-ConfigPath": "{workDir}"
+ }
+ },
+ {
+ "script": "cfe-borrow/scripts/cfe-borrow",
+ "args": {
+ "-ExtensionPath": "{workDir}/cfe",
+ "-ConfigPath": "{workDir}",
+ "-Object": "CommonForm.Подбор"
+ }
+ }
+ ],
+ "params": {
+ "extensionPath": "cfe",
+ "modulePath": "CommonForm.Подбор",
+ "methodName": "Заполнить",
+ "interceptorType": "After"
+ },
+ "expect": {
+ "stdoutContains": "Контекст: &НаСервере",
+ "fileContains": {
+ "file": "cfe/CommonForms/Подбор/Ext/Form/Module.bsl",
+ "text": "&После(\"Заполнить\")"
+ }
+ }
+}
diff --git a/tests/skills/cases/cfe-patch-method/snapshots/common-form-handler/CommonForms/Подбор.xml b/tests/skills/cases/cfe-patch-method/snapshots/common-form-handler/CommonForms/Подбор.xml
new file mode 100644
index 000000000..528d51d56
--- /dev/null
+++ b/tests/skills/cases/cfe-patch-method/snapshots/common-form-handler/CommonForms/Подбор.xml
@@ -0,0 +1,24 @@
+
+