Skip to content

feat(ide-diagnostics): быстрые исправления для устаревших Найти/ТекущаяДата, недопустимых символов и серверного экспорта в форме - #425

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

Conversation

@flamber-dev

Copy link
Copy Markdown
Contributor

Проблема

Четыре диагностики говорят, что именно поправить, но fixes у них пуст - правку приходится набирать руками:

Диагностика Сообщение Что нужно сделать
DeprecatedPlatformApi на Найти(...) Используйте "СтрНайти" вместо устаревшего "Найти" переименовать вызов
DeprecatedPlatformApi на ТекущаяДата() Используйте "ТекущаяДатаСеанса" вместо устаревшего "ТекущаяДата" переименовать вызов
InvalidCharacterInFile Нужно заменить символ неразрывного пробела на обычный пробел / Нужно исправить на правильный символ "-" заменить символ
ServerSideExportFormMethod Запрещено создавать серверные экспортные методы в форме убрать Экспорт

Исправление

Исправления подключены тем же путём, что и в #324: заполняется Diagnostic::fixes, флаг safe_for_fix_all решает,
войдёт ли правка в source.fixAll.

Найти -> СтрНайти, Fix::safe, «Заменить на "СтрНайти"». По справке платформы у обеих функций одинаковые
первые два параметра (Строка, ПодстрокаПоиска), поиск с учётом регистра и одинаковый результат (0 - не найдено,
1 - пустая подстрока), остальные параметры СтрНайти необязательны. Английское имя даёт StrFind.

Позиция = Найти("Строка", "о");     // до
Позиция = СтрНайти("Строка", "о");  // после

Исправление НЕ предлагается там, где СтрНайти не скомпилируется: режим совместимости конфигурации ниже 8.3.6
(платформа прячет СтрНайти, порог берётся из hir::compat_mode::hidden_global) или min_platform_version проекта
ниже версии, в которой функция появилась (hir::min_platform::global_function). Сама диагностика в этих случаях
остаётся как есть - меняется только наличие исправления. Чтобы режим совместимости был виден диагностикам, в
AnalysisProvider добавлен compatibility_mode() (по умолчанию None), в AnalysisContext - разобранный
compatibility_mode(). Та же проверка стоит и на ТекущаяДатаСеанса, хотя её сейчас ни один режим не прячет.

ТекущаяДата -> ТекущаяДатаСеанса, Fix::manual, «Заменить на "ТекущаяДатаСеанса" (время в часовом поясе
сеанса)».
Функции отличаются часовым поясом: ТекущаяДата() - местное время компьютера, на котором выполняется код,
ТекущаяДатаСеанса() - время в часовом поясе сеанса. Замена может изменить записываемое или сравниваемое значение,
поэтому в source.fixAll она не входит, а пояснение вынесено в заголовок исправления.

InvalidCharacterInFile, «Заменить недопустимые символы». Все недопустимые символы токена заменяются: неразрывный
пробел - на пробел, тире и знак минус - на -, мягкий перенос (U+00AD) удаляется (он невидим, и превращать его в видимый
дефис значило бы менять текст). В пробелах и комментариях программа этого текста не видит - Fix::safe. В строковом
литерале замена меняет значение (неразрывный пробел бывает ровно тем, что код ищет, например в
СтрЗаменить(Текст, " ", "")), а в токене ошибки меняет разбор строки - там Fix::manual с пометкой
«(меняет текст программы)».

// Итог — сумма   ->   // Итог - сумма          (safe)
СтрЗаменить(Текст, "<НПП>", "")   ->   СтрЗаменить(Текст, " ", "")   (manual)

ServerSideExportFormMethod, Fix::manual, «Убрать "Экспорт"». Удаляется ключевое слово и пробелы перед ним на той
же строке; комментарий после него остаётся.

&НаСервере
Процедура Пересчитать() Экспорт // итог   ->   Процедура Пересчитать() // итог

Исправление ручное: вызов этого метода через ЭтаФорма./ЭтотОбъект. после правки по-прежнему компилируется, но
падает при выполнении - платформа ищет метод объекта только среди экспортных.

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

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

   Compiling ide-diagnostics v0.3.2 (...\wt-pr18-fix-dev\crates\ide-diagnostics)
running 11 tests
test server_export_of_a_form_method_loses_export_as_a_manual_fix ... FAILED
test illegal_characters_in_a_comment_are_replaced_safely ... FAILED
test client_export_of_a_form_method_gets_no_diagnostic ... ok
test english_current_date_becomes_current_session_date ... FAILED
test current_date_fix_is_manual ... FAILED
test illegal_character_in_a_string_is_a_manual_fix ... FAILED
test english_find_becomes_strfind ... FAILED
test find_has_no_fix_below_the_project_minimum_platform ... ok
test find_is_renamed_to_strfind_as_a_safe_fix ... FAILED
test find_has_no_fix_where_the_compatibility_mode_hides_strfind ... ok
test find_keeps_the_fix_from_compatibility_mode_8_3_6 ... FAILED
test result: FAILED. 3 passed; 8 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.04s

Выдержки с develop:

thread 'find_is_renamed_to_strfind_as_a_safe_fix' panicked at crates\ide-diagnostics\tests\diagnostic_quick_fixes.rs:102:5:
assertion `left == right` failed
  left: "DeprecatedPlatformApi @ 2:15 no fix"
 right: "DeprecatedPlatformApi @ 2:15 Заменить на \"СтрНайти\" [fix_all=true]\nПроцедура Тест()\n    Позиция = СтрНайти(\"Строка\", \"о\");\nКонецПроцедуры\n"

thread 'current_date_fix_is_manual' panicked at crates\ide-diagnostics\tests\diagnostic_quick_fixes.rs:155:5:
assertion `left == right` failed
  left: "DeprecatedPlatformApi @ 2:12 no fix"
 right: "DeprecatedPlatformApi @ 2:12 Заменить на \"ТекущаяДатаСеанса\" (время в часовом поясе сеанса) [fix_all=false]\nПроцедура Тест()\n    Дата = ТекущаяДатаСеанса();\nКонецПроцедуры\n"

thread 'illegal_character_in_a_string_is_a_manual_fix' panicked at crates\ide-diagnostics\tests\diagnostic_quick_fixes.rs:189:5:
assertion `left == right` failed
  left: "InvalidCharacterInFile @ 2:32 no fix"
 right: "InvalidCharacterInFile @ 2:32 Заменить недопустимые символы (меняет текст программы) [fix_all=false]\nПроцедура Тест(Текст)\n    Текст = СтрЗаменить(Текст, \" \", \"\");\nКонецПроцедуры\n"

thread 'server_export_of_a_form_method_loses_export_as_a_manual_fix' panicked at crates\ide-diagnostics\tests\diagnostic_quick_fixes.rs:203:5:
assertion `left == right` failed
  left: "ServerSideExportFormMethod @ 2:11 no fix\n---\nServerSideExportFormMethod @ 6:9 no fix"

Три теста, которые проходят и на develop, - контрольные: они проверяют ОТСУТСТВИЕ исправления (режим совместимости
8.3.5, min_platform_version = 8.3.5) и отсутствие диагностики у клиентского экспорта. На develop они зелёные
тривиально, на ветке доказывают, что исправление не предлагается там, где замена не скомпилируется.

На ветке:

   Compiling ide-diagnostics v0.3.2 (...\wt-pr18-fix\crates\ide-diagnostics)
running 11 tests
...
test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.96s

Проверка

  • cargo test -p ide-db -p ide-diagnostics --no-fail-fast: ide-diagnostics lib 2128 passed / 0 failed на обеих
    сторонах, плюс 11 новых на ветке. ide-db lib 171 passed / 4 failed на обеих сторонах, список упавших совпадает
    (database_impl_tests::an_external_root_binds_its_files_through_the_snapshot_not_the_disk,
    extension_metadata_substrate_reacts_to_common_module_and_document_edits,
    extension_metadata_substrate_rejects_wrong_adoption_target_and_own_namesake,
    per_file_lookups_serve_an_extension_only_project_from_its_chain - сравнение путей под Windows, к правке не
    относятся).
  • cargo fmt --all --check: чисто.
  • cargo clippy -p ide-db -p ide-diagnostics --all-targets: предупреждений нет ни на develop, ни на ветке.

Вне этого PR

  • Вставка Если ОбменДанными.Загрузка Тогда Возврат; КонецЕсли; для DataExchangeLoading.
  • Удаление неиспользуемого метода для UnusedLocalMethod.

🤖 Generated with Claude Code

…illegal characters and server form exports

DeprecatedPlatformApi (deprecated global functions):
- Найти -> СтрНайти: same two leading parameters and the same result, so the
  rename is safe for source.fixAll. Offered only where the replacement compiles:
  not when the configuration's compatibility mode hides СтрНайти (below 8.3.6),
  nor when the project's min_platform_version predates it.
- ТекущаяДата -> ТекущаяДатаСеанса: manual. The two differ by time zone (the
  computer's local time vs the session's), so the edit may change a stored or
  compared value.

InvalidCharacterInFile: replace the token's illegal characters (non-breaking
space -> space, dashes -> "-", soft hyphen removed). Safe in whitespace and
comments; manual in string literals and error tokens, where the program text or
value changes.

ServerSideExportFormMethod: remove "Экспорт" from the header, manual (a call
through ЭтаФорма./ЭтотОбъект. compiles but fails at run time without it).

The compatibility mode reaches diagnostics through a new
AnalysisProvider::compatibility_mode (default None) and
AnalysisContext::compatibility_mode.

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

itrous commented Oct 15, 2026

Copy link
Copy Markdown
Owner

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

Елишев Кирилл added 6 commits October 15, 2026 18:32
Перенос головы e252140
(flamber-dev/bsl-analyzer pr/diagnostic-quick-fixes) поверх origin/develop.
ТекущаяДатаСеанса нет на тонком и веб-клиенте, поэтому переименование
ТекущаяДата не предлагается, если вызов компилируется в такую среду.
Одноимённый метод модуля владеет голым вызовом — его не переименовываем.
…рять среду перехватчика

Имя замены тоже может принадлежать методу модуля: после правки голый вызов
уйдёт в него, а не в платформенную функцию. Перехватчик без своей директивы
компилируется в базовую среду модуля, её нельзя подменять неизвестной.
…не терять среду директивы

Строка // между частями многострочного литерала — текст строки, а не
комментарий: замена символа в ней ручная. Неразобранный модульный #Если
не должен затирать уже известную среду директивы.
…нировать серию //

Неразрывный пробел в разделителе «Имя - Тип» под «Параметры:» прячет тип;
безопасная замена его создаёт. Длинная серия комментариев не требует
повторного прохода до границы строки.
@itrous
itrous merged commit b4986a1 into itrous:develop Oct 15, 2026
4 checks passed
@itrous

itrous commented Oct 15, 2026

Copy link
Copy Markdown
Owner

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

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