Skip to content

fix Goto-definition on import shouldn't use a transaction #1331#3027

Open
asukaminato0721 wants to merge 1 commit intofacebook:mainfrom
asukaminato0721:1331
Open

fix Goto-definition on import shouldn't use a transaction #1331#3027
asukaminato0721 wants to merge 1 commit intofacebook:mainfrom
asukaminato0721:1331

Conversation

@asukaminato0721
Copy link
Copy Markdown
Contributor

Summary

Fixes #1331

import module names now has a server-side fast path that resolves the import directly from the current file contents and import lookup state, before creating or validating a transaction.

That means requests like import bar or from .bar import value still return the target module file even while a recheck is in flight.

Test Plan

add test

@meta-cla meta-cla bot added the cla signed label Apr 6, 2026
@github-actions github-actions bot added the size/l label Apr 6, 2026
@asukaminato0721 asukaminato0721 marked this pull request as ready for review April 6, 2026 09:13
Copilot AI review requested due to automatic review settings April 6, 2026 09:13
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a server-side fast path for go-to-definition on import module names so navigation can still succeed even when a recheck/transaction is blocked (fixes #1331).

Changes:

  • Adds a GotoDefinition pre-transaction fast path that parses the current file contents and resolves imported modules via the loader without creating/validating a transaction.
  • Factors import-module target resolution into Transaction::target_imported_module_name and exposes identifier_from_covering_nodes for reuse.
  • Adds an LSP interaction test covering go-to-definition on an import while a recheck is blocked.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
pyrefly/lib/lsp/non_wasm/server.rs Adds fast-path handling for import-module goto-definition before transaction creation.
pyrefly/lib/state/lsp.rs Exposes identifier extraction and factors module-name targeting logic into a reusable helper.
pyrefly/lib/test/lsp/lsp_interaction/definition.rs Adds a regression test for goto-definition on imports during blocked recheck.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1840 to +1848
let response = match response {
Ok(response) => response,
Err(reason) => {
telemetry_event.set_empty_response_reason(reason);
None
}
};
self.send_response(new_response(x.id, Ok(response)));
return Ok(ProcessEvent::Continue);
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fast-path short-circuits the whole GotoDefinition request whenever it detects an imported-module identifier, even if the fast-path fails (it converts the error into an empty response and returns early). That can regress existing behavior by preventing the normal transaction-backed goto-definition from running in cases where the loader/path conversion fails but the full analysis could still resolve the definition. Consider only short-circuiting on a successful fast-path resolution, and falling back to the existing transaction path on fast-path errors.

Suggested change
let response = match response {
Ok(response) => response,
Err(reason) => {
telemetry_event.set_empty_response_reason(reason);
None
}
};
self.send_response(new_response(x.id, Ok(response)));
return Ok(ProcessEvent::Continue);
if let Ok(response) = response {
self.send_response(new_response(x.id, Ok(response)));
return Ok(ProcessEvent::Continue);
}

Copilot uses AI. Check for mistakes.
Comment on lines +4014 to +4019
.state
.config_finder()
.python_file(handle.module_kind(), handle.path());
let loader = LoaderFindCache::new(config.dupe());
let Some(target_path) = loader
.find_import_prefer_executable(target_module, Some(handle.path()))
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoaderFindCache::new is constructed on every goto-definition fast-path invocation, which discards the cache and can make repeated import go-to-def requests unnecessarily expensive. Consider reusing a cached LoaderFindCache keyed by config (or exposing a shared loader cache from state) so import resolution benefits from memoization across requests.

Copilot uses AI. Check for mistakes.
Comment on lines +234 to +236
interaction
.client
.edit_file("bar.py", &bar_contents.replace("foo = 3", "foo = 4"));
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This edit relies on replace("foo = 3", "foo = 4") to change the file contents, but it doesn't assert that the replacement actually happened. If the fixture changes (or the string appears multiple times), this can become a no-op and the test may stop exercising the blocked-recheck path. Consider asserting the substring exists exactly once (or constructing the edited contents more explicitly) before calling edit_file.

Copilot uses AI. Check for mistakes.
Comment on lines +242 to +246
interaction
.client
.definition("foo.py", 5, 7)
.expect_definition_response_from_root("bar.py", 0, 0, 0, 0)
.unwrap();
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description mentions fast-path support for both import bar and from .bar import value while a recheck is in flight, but this test only covers the plain import case. Adding a companion assertion for a from ... import ... (including a relative-dots case) would help ensure the new imported-module parsing and dots/position logic stays correct.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 7, 2026

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Goto-definition on import shouldn't use a transaction

2 participants