Skip to content

feat(ide-diagnostics): быстрые исправления для DataExchangeLoading и UnusedLocalMethod - #427

Merged
itrous merged 6 commits into
itrous:developfrom
flamber-dev:pr/diagnostic-quick-fixes-2
Oct 15, 2026
Merged

itrous merged 6 commits into
itrous:developfrom
flamber-dev:pr/diagnostic-quick-fixes-2

Conversation

@flamber-dev

Copy link
Copy Markdown
Contributor

Проблема

Две диагностики точно называют, что сделать, но fixes у них пуст:

Диагностика Сообщение Что нужно сделать
DataExchangeLoading Отсутствует проверка условия ОбменДанными.Загрузка в обработчике события... вставить Если ОбменДанными.Загрузка Тогда Возврат; КонецЕсли; в начало обработчика
UnusedLocalMethod Неиспользуемый локальный метод "X" удалить метод

Это продолжение #425 (там исправления для DeprecatedPlatformApi, InvalidCharacterInFile и
ServerSideExportFormMethod); PR независимы, ветка этого основана на develop, общих строк с #425 нет.

Исправление

Механизм тот же, что в #324 и #425: заполняется Diagnostic::fixes, оба исправления - Fix::manual, в
source.fixAll не входят.

DataExchangeLoading, «Добавить проверку ОбменДанными.Загрузка». Проверка вставляется первым оператором
обработчика - после локальных Перем (они обязаны стоять до любого оператора), с отступом тела. Единица
вложенного отступа - табуляция, если тело отступлено табуляцией (или не отступлено вовсе), иначе отступ самого
тела. Перевод строки берётся из файла (CRLF сохраняется). Для обработчика на английском синтаксисе вставляется
If DataExchange.Load Then Return; EndIf;.

// до
Процедура ПередЗаписью(Отказ)
	Перем Итог;
	Итог = 1;
КонецПроцедуры

// после
Процедура ПередЗаписью(Отказ)
	Перем Итог;
	Если ОбменДанными.Загрузка Тогда
		Возврат;
	КонецЕсли;
	Итог = 1;
КонецПроцедуры

Пустой обработчик получает проверку с отступом в одну табуляцию. Если первый оператор стоит на одной строке с
заголовком или с другим оператором, своей строки для вставки нет - исправление не предлагается.

Почему ручное: при обмене данными обработчик после правки перестаёт выполнять свою логику. Именно этого
требует стандарт, но это изменение поведения, которое автор должен принять сам (бывает, что часть логики обязана
отработать и при загрузке - тогда проверку ставят ниже).

UnusedLocalMethod, «Удалить неиспользуемый метод "X"». Удаляется весь метод вместе с директивой
компиляции (она входит в узел метода), с комментарием-описанием непосредственно над ним (строки //,
занимающие свою строку, без пустой строки между ними и методом) и с остатком строки КонецПроцедуры /
КонецФункции (хвостовой комментарий, перевод строки). Если над удаляемым блоком пустая строка (или начало
файла), удаляется и одна пустая строка под ним - чтобы не осталось двух пустых строк подряд; если над ним код,
пустая строка под ним остаётся разделителем.

// до
Процедура Используемая() Экспорт
	Вспомогательная();
КонецПроцедуры

// Удвоенное значение.
//
// Параметры:
//  Значение - Число
&НаСервере
Функция Удвоить(Значение) // устарело
	Возврат Значение * 2;
КонецФункции // Удвоить

Процедура Вспомогательная()
КонецПроцедуры

// после
Процедура Используемая() Экспорт
	Вспомогательная();
КонецПроцедуры

Процедура Вспомогательная()
КонецПроцедуры

Почему ручное: удаление необратимо, а метод может вызываться по имени из строки, которую анализ не видит
(Выполнить, обработчик, подключённый по имени из другого модуля). Поэтому исправление не предлагается вовсе,
если имя метода встречается как целый идентификатор в любом строковом литерале модуля (Выполнить("Пересчитать()")).
Сама диагностика при этом остаётся как на develop. Имя внутри более длинного идентификатора
("ПересчитатьВсё" для метода Пересчитать) исправлению не мешает. Обработчики, которые диагностика уже
распознаёт (ОписаниеОповещения, ПодключитьОбработчикОжидания, привязки событий формы, УстановитьДействие
и т.д.), диагностику не получают - и исправления тоже.

Доказательство

Новый файл crates/ide-diagnostics/tests/data_exchange_and_unused_method_fixes.rs (13 тестов, через публичный
file_diagnostics, модуль объекта справочника и общий модуль): для каждой диагностики печатается заголовок
исправления, флаг fix_all и текст после применения правки, либо no fix. Файл скопирован в рабочую копию
develop (4467ba9) и прогнан там:

   Compiling ide-diagnostics v0.3.2 (...\wt-pr20-fix2-dev\crates\ide-diagnostics)
running 13 tests
test english_dead_function_is_deleted ... FAILED
test empty_handler_gets_a_tab_indented_guard ... FAILED
test dead_method_without_blank_line_above_keeps_the_one_below ... FAILED
test method_named_in_a_string_literal_gets_no_deletion_fix ... ok
test dead_method_is_deleted_with_crlf_line_breaks ... FAILED
test english_handler_gets_english_guard ... FAILED
test guard_goes_after_local_variables_with_tab_indent ... FAILED
test dead_method_goes_with_its_doc_comment_directive_and_one_blank_line ... FAILED
test guard_keeps_crlf_line_breaks ... FAILED
test guarded_handler_gets_no_diagnostic ... ok
test a_longer_name_in_a_string_does_not_block_the_fix ... FAILED
test notification_handler_gets_no_diagnostic ... ok
test guard_follows_space_indent_and_leading_comment ... FAILED
test result: FAILED. 3 passed; 10 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.13s

Выдержки с develop:

thread 'dead_method_is_deleted_with_crlf_line_breaks' panicked at crates\ide-diagnostics\tests\data_exchange_and_unused_method_fixes.rs:183:5:
assertion `left == right` failed
  left: "UnusedLocalMethod @ 5:11 no fix"
 right: "UnusedLocalMethod @ 5:11 Удалить неиспользуемый метод \"Лишняя\" [fix_all=false]\nПроцедура Первая() Экспорт\r\nКонецПроцедуры\r\n\r\nПроцедура Вторая() Экспорт\r\nКонецПроцедуры\r\n"

thread 'english_handler_gets_english_guard' panicked at crates\ide-diagnostics\tests\data_exchange_and_unused_method_fixes.rs:110:5:
assertion `left == right` failed
  left: "DataExchangeLoading @ 1:11 no fix"
 right: "DataExchangeLoading @ 1:11 Добавить проверку DataExchange.Load [fix_all=false]\nProcedure BeforeWrite(Cancel)\n    If DataExchange.Load Then\n        Return;\n    EndIf;\n    Total = 1;\nEndProcedure\n"

thread 'guard_goes_after_local_variables_with_tab_indent' panicked at crates\ide-diagnostics\tests\data_exchange_and_unused_method_fixes.rs:81:5:
assertion `left == right` failed
  left: "DataExchangeLoading @ 1:11 no fix"
 right: "DataExchangeLoading @ 1:11 Добавить проверку ОбменДанными.Загрузка [fix_all=false]\nПроцедура ПередЗаписью(Отказ)\n\tПерем Итог;\n\tЕсли ОбменДанными.Загрузка Тогда\n\t\tВозврат;\n\tКонецЕсли;\n\tИтог = 1;\nКонецПроцедуры\n"

thread 'dead_method_goes_with_its_doc_comment_directive_and_one_blank_line' panicked at crates\ide-diagnostics\tests\data_exchange_and_unused_method_fixes.rs:157:5:
assertion `left == right` failed
  left: "UnusedLocalMethod @ 10:9 no fix"
 right: "UnusedLocalMethod @ 10:9 Удалить неиспользуемый метод \"Удвоить\" [fix_all=false]\nПроцедура Используемая() Экспорт\n\tВспомогательная();\nКонецПроцедуры\n\nПроцедура Вспомогательная()\nКонецПроцедуры\n"

Три теста, которые проходят и на develop, - контрольные: обработчик с проверкой не получает диагностику;
метод, названный в ОписаниеОповещения, не получает диагностику; метод, названный в строке Выполнить(...),
получает диагностику без исправления. На develop они зелёные тривиально, на ветке доказывают, что
исправление не появляется там, где его быть не должно.

На ветке:

   Compiling ide-diagnostics v0.3.2 (...\wt-pr20-fix2\crates\ide-diagnostics)
running 13 tests
...
test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.90s

Проверка

Вне этого PR

  • Удаление пустой строки, остающейся в конце файла, когда удаляется последний метод модуля.
  • Вставка проверки, когда первый оператор обработчика стоит на одной строке с заголовком.
  • Перекрёстный по модулям учёт обработчиков, подключаемых по имени из другого модуля (исправление в таком случае
    просто не предлагается, если имя есть в строке этого модуля; иначе оно ручное).

🤖 Generated with Claude Code

…LocalMethod

DataExchangeLoading: insert "Если ОбменДанными.Загрузка Тогда Возврат;
КонецЕсли;" (or "If DataExchange.Load Then Return; EndIf;" in an English
handler) as the first statement, after the local Перем declarations, indented
like the body and using the file's line breaks. Manual: the handler stops
running its logic during data exchange.

UnusedLocalMethod: delete the method with its compilation directive, the doc
comment directly above it and the rest of its closing line; one blank line
below goes too when a blank line stays above. Manual: the method may still be
reached by name from a string. Not offered at all when the name appears as a
whole identifier in a string literal of the module.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@itrous

itrous commented Oct 15, 2026

Copy link
Copy Markdown
Owner

🤖 Начата автоматическая приёмка — этот pull request взят в работу ИИ-агентом:
изменения переносятся на актуальную целевую ветку, проходят независимое ревью
и соответствующие тесты, очевидные замечания правятся по ходу. Обновления появятся
в этом треде; merge возможен только после завершения проверки.

Елишев Кирилл and others added 5 commits October 15, 2026 20:17
…directives

The DataExchangeLoading guard went above a leading `#Область`/`#Если`, i.e.
before the local `Перем` declarations it must follow; it now goes before the
first top-level statement past the last declaration, and is not offered when
declarations share a directive with statements. The UnusedLocalMethod
deletion took the byte order mark for code on line 1, so a method or doc
comment on the first line of a BOM file kept its comment or got no fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… body statement

The guard position took the end of every `Перем` in the body, at any depth, and
the first top-level node after it. A `Перем` nested in an ordinary block pushed
the guard past that block, and a `#Если` holding declarations and statements was
skipped in favour of a later statement, so code ran before the check.

Only declarations at the level of the body (directly or through `#Если`
branches) now bound the guard; when the first statement starts before the last
of them, no fix is offered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@itrous
itrous merged commit 2adc8f1 into itrous:develop Oct 15, 2026
4 checks passed
@itrous

itrous commented Oct 15, 2026

Copy link
Copy Markdown
Owner

🤖 Автоматическая приёмка завершена: изменения приняты, PR влит коммитом 2adc8f1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants