feat(cfe-patch-method): conflict.md — обрамление вставки якорями + нумерация (v2.3)

- непереносимый блок показывается в контексте (строки-до/#Вставка/строки-после),
  вместо раздельных списков «после:/перед:» + «Блок:»
- нумерация конфликтов: ### Конфликт №N в conflict.md и // [РЕСИНК-КОНФЛИКТ №N]
  над припаркованным блоком в .bsl — сопоставление один-к-одному при нескольких
  конфликтах в одном методе
- локатор в модуле — по метке №N (grep-стабильно), без номеров строк
- зеркально в .py, снэпшот resync-conflict обновлён

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-07-19 12:54:55 +03:00
co-authored by Claude Opus 4.8
parent 1f8d611a00
commit 4b6ced87c4
3 changed files with 48 additions and 31 deletions
@@ -1,4 +1,4 @@
# cfe-patch-method v2.2 — Source-aware method interceptor for 1C extension (CFE) # cfe-patch-method v2.3 — Source-aware method interceptor for 1C extension (CFE)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param( param(
[Parameter(Mandatory)] [Parameter(Mandatory)]
@@ -531,18 +531,25 @@ function Write-ConflictFolder {
$md += "Причина: $(Get-ResyncConflictReason $disputed)" $md += "Причина: $(Get-ResyncConflictReason $disputed)"
$md += "" $md += ""
$md += "## Не размещено — перенести вручную" $md += "## Не размещено — перенести вручную"
$cn = 0
foreach ($d in $disputed) { foreach ($d in $disputed) {
$cn++
$md += "" $md += ""
if ($d.Kind -eq 'insert') { if ($d.Kind -eq 'insert') {
$md += "Вставка. В вашей версии (local) блок стоял по якорю:" $md += "### Конфликт №$cn — вставка"
if ($d.Before -and $d.Before.Count -gt 0) { $md += " после:"; foreach ($l in $d.Before) { $md += " $l" } } else { $md += " после: (начало метода)" } $md += "Как блок стоял в вашей версии (local):"
if ($d.After -and $d.After.Count -gt 0) { $md += " перед:"; foreach ($l in $d.After) { $md += " $l" } } else { $md += " перед: (конец метода)" } if ($d.Before -and $d.Before.Count -gt 0) { foreach ($l in $d.Before) { $md += $l } }
$md += "Якорь изменился/исчез в новом оригинале (remote) — потому блок не лёг автоматически (см. дифф base→remote ниже)."
$md += "Куда переносить: если якорного кода в новом методе больше нет — он, вероятно, вынесен/отрефакторен (ищите в диффе новый вызов/процедуру). Размести адаптацию по смыслу: например пост-обработкой после нового вызова, либо в заимствованной процедуре, куда переехал код. При правке файла сохрани кодировку (UTF-8 с BOM). Блок:"
$md += "#Вставка"; foreach ($l in $d.Lines) { $md += $l }; $md += "#КонецВставки" $md += "#Вставка"; foreach ($l in $d.Lines) { $md += $l }; $md += "#КонецВставки"
if ($d.After -and $d.After.Count -gt 0) { foreach ($l in $d.After) { $md += $l } }
$md += ""
$md += "Якорь (строки вокруг #Вставка) изменился/исчез в новом оригинале — блок не лёг автоматически (см. дифф base→remote ниже)."
$md += "В модуле расширения блок припаркован в конце метода под меткой // [РЕСИНК-КОНФЛИКТ №$cn] — найди по ней."
$md += "Куда переносить: если якорного кода в новом методе больше нет — он, вероятно, вынесен/отрефакторен (ищите в диффе новый вызов/процедуру). Размести адаптацию по смыслу: например пост-обработкой после нового вызова, либо в заимствованной процедуре, куда переехал код. При правке файла сохрани кодировку (UTF-8 с BOM)."
} else { } else {
$md += "Удаление. Строки для удаления не найдены в новом оригинале (изменились/исчезли):" $md += "### Конфликт №$cn — удаление"
$md += "Строки для удаления не найдены в новом оригинале (изменились/исчезли):"
foreach ($l in $d.Lines) { $md += " - $($l.Trim())" } foreach ($l in $d.Lines) { $md += " - $($l.Trim())" }
$md += "В модуле расширения помечено меткой // [РЕСИНК-КОНФЛИКТ №$cn]."
} }
} }
$md += "" $md += ""
@@ -628,11 +635,18 @@ function Invoke-Resync {
if ($insertAfter.ContainsKey($k)) { foreach ($blk in $insertAfter[$k]) { $newBody += "#Вставка"; foreach ($l in $blk) { $newBody += $l }; $newBody += "#КонецВставки" } } if ($insertAfter.ContainsKey($k)) { foreach ($blk in $insertAfter[$k]) { $newBody += "#Вставка"; foreach ($l in $blk) { $newBody += $l }; $newBody += "#КонецВставки" } }
} }
if ($disputed.Count -gt 0) { if ($disputed.Count -gt 0) {
$newBody += "`t// [РЕСИНК-КОНФЛИКТ] перенесите блоки ниже вручную — исходный якорь изменился в новой версии оригинала." $newBody += "`t// [РЕСИНК-КОНФЛИКТ] блоки ниже не легли автоматически — перенесите вручную (по № см. conflict.md / index.md в merge-воркспейсе, путь в выводе)."
$newBody += "`t// Материалы: см. index.md / conflict.md в merge-воркспейсе (путь в выводе)." $cn = 0
foreach ($d in $disputed) { foreach ($d in $disputed) {
if ($d.Kind -eq 'insert') { $newBody += "#Вставка"; foreach ($l in $d.Lines) { $newBody += $l }; $newBody += "#КонецВставки" } $cn++
else { $newBody += "`t// [РЕСИНК-КОНФЛИКТ] не удалось найти для удаления:"; foreach ($l in $d.Lines) { $newBody += ("`t// " + $l.Trim()) } } if ($d.Kind -eq 'insert') {
$newBody += "`t// [РЕСИНК-КОНФЛИКТ №$cn] вставка — исходный якорь изменён в новом оригинале."
$newBody += "#Вставка"; foreach ($l in $d.Lines) { $newBody += $l }; $newBody += "#КонецВставки"
}
else {
$newBody += "`t// [РЕСИНК-КОНФЛИКТ №$cn] удаление — строки не найдены в новом оригинале:"
foreach ($l in $d.Lines) { $newBody += ("`t// " + $l.Trim()) }
}
} }
} }
$asyncPrefix = if ($method.IsAsync) { "Асинх " } else { "" } $asyncPrefix = if ($method.IsAsync) { "Асинх " } else { "" }
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# cfe-patch-method v2.2 — Source-aware method interceptor for 1C extension (CFE) # cfe-patch-method v2.3 — Source-aware method interceptor for 1C extension (CFE)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
@@ -869,29 +869,30 @@ def write_conflict_folder(folder, method_id, ext_bsl, existing_name, method, v1,
md.append("Причина: %s" % conflict_reason(disputed)) md.append("Причина: %s" % conflict_reason(disputed))
md.append("") md.append("")
md.append("## Не размещено — перенести вручную") md.append("## Не размещено — перенести вручную")
cn = 0
for d in disputed: for d in disputed:
cn += 1
md.append("") md.append("")
if d["kind"] == "insert": if d["kind"] == "insert":
md.append("Вставка. В вашей версии (local) блок стоял по якорю:") md.append("### Конфликт №%d — вставка" % cn)
md.append("Как блок стоял в вашей версии (local):")
if d.get("before"): if d.get("before"):
md.append(" после:")
for l in d["before"]: for l in d["before"]:
md.append(" " + l) md.append(l)
else:
md.append(" после: (начало метода)")
if d.get("after"):
md.append(" перед:")
for l in d["after"]:
md.append(" " + l)
else:
md.append(" перед: (конец метода)")
md.append("Якорь изменился/исчез в новом оригинале (remote) — потому блок не лёг автоматически (см. дифф base→remote ниже).")
md.append("Куда переносить: если якорного кода в новом методе больше нет — он, вероятно, вынесен/отрефакторен (ищите в диффе новый вызов/процедуру). Размести адаптацию по смыслу: например пост-обработкой после нового вызова, либо в заимствованной процедуре, куда переехал код. При правке файла сохрани кодировку (UTF-8 с BOM). Блок:")
md.append("#Вставка"); md.extend(d["lines"]); md.append("#КонецВставки") md.append("#Вставка"); md.extend(d["lines"]); md.append("#КонецВставки")
if d.get("after"):
for l in d["after"]:
md.append(l)
md.append("")
md.append("Якорь (строки вокруг #Вставка) изменился/исчез в новом оригинале — блок не лёг автоматически (см. дифф base→remote ниже).")
md.append("В модуле расширения блок припаркован в конце метода под меткой // [РЕСИНК-КОНФЛИКТ №%d] — найди по ней." % cn)
md.append("Куда переносить: если якорного кода в новом методе больше нет — он, вероятно, вынесен/отрефакторен (ищите в диффе новый вызов/процедуру). Размести адаптацию по смыслу: например пост-обработкой после нового вызова, либо в заимствованной процедуре, куда переехал код. При правке файла сохрани кодировку (UTF-8 с BOM).")
else: else:
md.append("Удаление. Строки для удаления не найдены в новом оригинале (изменились/исчезли):") md.append("### Конфликт №%d — удаление" % cn)
md.append("Строки для удаления не найдены в новом оригинале (изменились/исчезли):")
for l in d["lines"]: for l in d["lines"]:
md.append(" - " + l.strip()) md.append(" - " + l.strip())
md.append("В модуле расширения помечено меткой // [РЕСИНК-КОНФЛИКТ №%d]." % cn)
md.append("") md.append("")
md.append("## Дифф base→remote (что изменилось в оригинале)") md.append("## Дифф base→remote (что изменилось в оригинале)")
for l in v1: for l in v1:
@@ -978,13 +979,15 @@ def resync_one(ext_bsl, ext_lines, dup, method, logical_module, conflict_folder,
for blk in insert_after[k]: for blk in insert_after[k]:
new_body.append("#Вставка"); new_body.extend(blk); new_body.append("#КонецВставки") new_body.append("#Вставка"); new_body.extend(blk); new_body.append("#КонецВставки")
if disputed: if disputed:
new_body.append("\t// [РЕСИНК-КОНФЛИКТ] перенесите блоки ниже вручную — исходный якорь изменился в новой версии оригинала.") new_body.append("\t// [РЕСИНК-КОНФЛИКТ] блоки ниже не легли автоматически — перенесите вручную (по № см. conflict.md / index.md в merge-воркспейсе, путь в выводе).")
new_body.append("\t// Материалы: см. index.md / conflict.md в merge-воркспейсе (путь в выводе).") cn = 0
for d in disputed: for d in disputed:
cn += 1
if d["kind"] == "insert": if d["kind"] == "insert":
new_body.append("\t// [РЕСИНК-КОНФЛИКТ №%d] вставка — исходный якорь изменён в новом оригинале." % cn)
new_body.append("#Вставка"); new_body.extend(d["lines"]); new_body.append("#КонецВставки") new_body.append("#Вставка"); new_body.extend(d["lines"]); new_body.append("#КонецВставки")
else: else:
new_body.append("\t// [РЕСИНК-КОНФЛИКТ] не удалось найти для удаления:") new_body.append("\t// [РЕСИНК-КОНФЛИКТ%d] удаление — строки не найдены в новом оригинале:" % cn)
for l in d["lines"]: for l in d["lines"]:
new_body.append("\t// " + l.strip()) new_body.append("\t// " + l.strip())
@@ -2,8 +2,8 @@
&ИзменениеИКонтроль("Расчёт") &ИзменениеИКонтроль("Расчёт")
Функция Тест_Расчёт(А, Б) Функция Тест_Расчёт(А, Б)
Возврат 0; Возврат 0;
// [РЕСИНК-КОНФЛИКТ] перенесите блоки ниже вручную — исходный якорь изменился в новой версии оригинала. // [РЕСИНК-КОНФЛИКТ] блоки ниже не легли автоматически — перенесите вручную (по № см. conflict.md / index.md в merge-воркспейсе, путь в выводе).
// Материалы: см. index.md / conflict.md в merge-воркспейсе (путь в выводе). // [РЕСИНК-КОНФЛИКТ №1] вставка — исходный якорь изменён в новом оригинале.
#Вставка #Вставка
Итог = Итог + Б; Итог = Итог + Б;
#КонецВставки #КонецВставки