Repository navigation
fix(hir-ty): вызов метода через экспортную переменную модуля приложения - #423
Open
flamber-dev wants to merge 1 commit into
Open
flamber-dev wants to merge 1 commit into
flamber-dev wants to merge 1 commit into
Conversation
`глПеременная.Метод()`, where `глПеременная` is declared `Перем глПеременная Экспорт;` in the application module, was reported as UnresolvedMethodCall «Не удалось разрешить получателя вызова» in client common modules and client form procedures, although the platform compiles it: an exported application-module variable is a global of every client module of the configuration. The bare-name read path already knew these variables (an untyped user global, ranked below a common module of the same name and above platform globals, with its availability checked). The bare-receiver dispatch of a call did not consult that surface and fell through to the unresolved receiver. It now does, in the same rank, and leaves the call to the ordinary path for an untyped receiver. Server code keeps its verdict: the read of the variable is reported as UnavailableInEnvironment there, and a misspelled receiver is still an unresolved receiver. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Проблема
Переменная, объявленная в модуле управляемого (или обычного) приложения как
Перем глМояПеременная Экспорт;,по документации платформы - глобальная переменная клиентского контекста:
(Руководство разработчика 8.3.27, глава 4 «Встроенный язык», https://its.1c.eu/db/v8327doc/content/49/hdoc)
Анализатор это уже знает на пути чтения имени:
Значение = глМояПеременная;в клиентском модуле молчит, на сервередаёт
UnavailableInEnvironment. Но вызов метода через такую переменную идёт другим путём - через разбор «голого»получателя вызова, - и там эта поверхность не спрашивается. Получатель проваливается до конца каскада, и develop
сообщает ложную ошибку:
Код компилируется и работает: так устроено хранение клиентских параметров сеанса в библиотеке стандартных подсистем
(экспортная переменная модуля приложения с соответствием внутри) и в подключаемых клиентских компонентах типовых
конфигураций. Находка severity Major, и на рабочих конфигурациях она составляет заметную долю всех
UnresolvedMethodCall(867 из 1260 на одной, 238 из 511 на другой).Что меняется
crates/hir-ty/src/infer.rs,dispatch_bare_ident_field_call: перед проверкой платформенных глобальных контейнеровспрашивается та же поверхность экспортов модулей приложения (
global_read_export), что и на пути чтения имени. Еслиимя - экспортная переменная модуля приложения, разбор отдаётся обычному пути вызова на нетипизированном получателе
(
BareReceiverDispatch::Unhandled), как для локальной переменной или переменной модуля.Порядок тот же, что у
resolve_bare_name: общий модуль с тем же именем побеждает (проверка стоит послеuser_common_module_exists), реквизит формы тоже (проверка послеresolve_form_attribute), платформенные глобальныеимена - нет (переменная пользователя их затеняет). Доступность по окружениям не проверяется второй раз: получатель
уже прочитан
infer_exprдо этого разбора, и чтение имени проверило, где переменная видна. Поэтому в серверном модулевызов по-прежнему не молчит: вместо «не удалось разрешить получателя» остаётся
UnavailableInEnvironmentна самойпеременной - точная причина, по которой платформа такой модуль не скомпилирует.
Опечатка в имени переменной не экспорт модуля приложения и по-прежнему даёт
UnresolvedMethodCall; вызовнесуществующей процедуры без квалификатора по-прежнему даёт
UnresolvedBareCall.Вызов через свойство переменной (
глНастройки.Свойство.Метод()) develop и раньше не трогал: получатель там -выражение, а не имя.
Доказательство
Тесты -
crates/ide/tests/infer_application_module_variable_receiver.rs, на фикстуреbsl-metadata/fixtures/designer: модуль управляемого приложения подменяется текстом с двумя экспортными переменнымии одной экспортной процедурой, вызывающий модуль кладётся на место существующего общего модуля фикстуры с нужными
свойствами (клиентский / серверный).
a_call_through_an_application_variable_is_silent_in_a_client_common_module- клиентский общий модуль: ни одногоUnresolvedMethodCall, ни одногоUnavailableInEnvironment;a_call_through_an_application_variable_is_silent_in_a_client_form_procedure- процедура&НаКлиентемодуляформы: ни одного
UnresolvedMethodCall;an_application_variable_is_unavailable_in_a_server_common_module- серверный общий модуль:UnresolvedMethodCallнет, каждое чтение переменной даёт
UnavailableInEnvironment;a_misspelled_receiver_and_an_undeclared_bare_call_are_still_reported- контроль:глМояПеремення.Метод()остаётся
UnresolvedMethodCall,ПроцедураПрилжения()-UnresolvedBareCall, а верныйПроцедураПриложения()молчит. Проходит и на develop, и на ветке - правка не глушит находку шире своего случая.develop (
f63a2ebf):ветка:
Рабочие конфигурации
Дифференциальный прогон
bsl-analyzer-app analyze --format jsonl, release-сборки develop и ветки, на трёх рабочихконфигурациях (две - управляемое приложение, одна - обычное). Сравнение по ключу «файл, строка, колонка, код,
сообщение»:
UnresolvedMethodCallUnresolvedMethodCallUnresolvedMethodCallТри рабочие конфигурации, ложных находок ушло 1111, новых 0; других кодов разница не затронула. Ушедшие находки - в
модулях управляемых форм (в основном формы отчётов), клиентских общих модулях, модулях команд, а в конфигурации на
обычном приложении - в общем модуле (4) и модулях объектов (2), исполняемых толстым клиентом.
Ни на одной из этих строк ветка не выдаёт
UnavailableInEnvironment, и общее числоUnavailableInEnvironmentнеизменилось - ни одна снятая находка не оказалась в коде, где переменная не видна.
Прочее
hir-tyиideна develop и на ветке: списки упавших совпадают (9 тестов, одинаково на обеих сторонах:infer_three_level- 6 тестов,graph::tests::method_graph_id_*- 2,name_lookup::tests::the_address_phases_observe_a_cancelled_request), кроме трёх новых тестов, которые падаюттолько на develop.
cargo fmt --check- чисто;cargo clippy -p hir-ty -p ide --all-targets- вывод совпадает с develop.Вне рамок
тот же (
global_read_exportучитывает их окружение), отдельного сценария на рабочих конфигурациях не нашлось.проверяются вовсе, как и через любую нетипизированную переменную.