Repository navigation
impl Class Hierarchy #2207 - #2687
asukaminato0721 wants to merge 4 commits into
Conversation
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
This PR adds an overrides/implementations CodeLens experience for Python in the VS Code extension and extends the backend go-to-declaration behavior so overriding members can navigate to the overridden parent declaration (supporting class hierarchy/navigation work tracked in #2207).
Changes:
- Added a new VS Code
OverrideCodeLensProviderthat shows “Overrides …” and “Implemented by …” lenses based on declaration/implementation providers. - Registered the provider and navigation/quick-pick commands in the extension activation flow.
- Updated backend
goto_declarationto redirect overriding members to parent declarations, and added regression tests for method + class attribute overrides.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| pyrefly/lib/test/lsp/definition.rs | Adds tests validating go-to-declaration jumps from overrides to parent declarations. |
| pyrefly/lib/state/lsp.rs | Adds override-parent lookup logic to goto_declaration plus a helper for resolving module info from a ModulePath. |
| lsp/src/overrideCodeLens.ts | Implements the CodeLens provider and navigation commands for override/implementation targets. |
| lsp/src/extension.ts | Registers the CodeLens provider, hooks refreshes, and registers navigation commands. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| context.subscriptions.push( | ||
| workspace.onDidChangeTextDocument(event => { | ||
| if (event.document.languageId === 'python') { | ||
| overrideCodeLensProvider.refresh(); | ||
| } | ||
| }), | ||
| ); |
There was a problem hiding this comment.
Refreshing CodeLenses on every onDidChangeTextDocument for Python means this provider will re-run (and potentially issue many LSP requests) on every keystroke. Consider debouncing this refresh (timer-based) and/or refreshing only on saves / when the edited document is the active editor to reduce churn.
| fn parent_declarations_for_definition( | ||
| &self, | ||
| handle: &Handle, | ||
| definition: &TextRangeWithModule, | ||
| ) -> Vec<TextRangeWithModule> { | ||
| let Some(index) = self | ||
| .get_solutions(handle) | ||
| .and_then(|solutions| solutions.get_index()) | ||
| else { | ||
| return Vec::new(); | ||
| }; | ||
| let Some(parent_methods) = index | ||
| .lock() | ||
| .parent_methods_map | ||
| .get(&definition.range) |
There was a problem hiding this comment.
parent_declarations_for_definition always reads the solutions index for the current handle, but it looks up overrides by definition.range (a TextRange without module identity). If find_definition returns a definition in another module (e.g. imports/stubs), this can either miss the override info or accidentally match an unrelated range in the current module and return incorrect parent declarations. Consider only applying this override-redirect when definition.module.path() matches the current module, or resolve the correct handle/index for definition.module before consulting parent_methods_map.
This comment has been minimized.
This comment has been minimized.
5ffd72b to
3b624e4
Compare
This comment has been minimized.
This comment has been minimized.
3b624e4 to
7caf02c
Compare
This comment has been minimized.
This comment has been minimized.
7caf02c to
dd3e847
Compare
This comment has been minimized.
This comment has been minimized.
dd3e847 to
8777e0b
Compare
This comment has been minimized.
This comment has been minimized.
8777e0b to
a23e70b
Compare
This comment has been minimized.
This comment has been minimized.
a23e70b to
b0d9b11
Compare
This comment has been minimized.
This comment has been minimized.
49b9981 to
b1839bd
Compare
This comment has been minimized.
This comment has been minimized.
b1839bd to
64a316f
Compare
This comment has been minimized.
This comment has been minimized.
stroxler
left a comment
There was a problem hiding this comment.
Thanks! I think there are at least four sets of concerns we need to address before we can merge this:
-
Design concern: the reused references index excludes library parents and several special methods. I confirmed that
Sized.__len__and a project-local__init__override resolve to themselves. A dedicated ancestor lookup would avoid those limitations and avoid repurposing Go to Declaration for every LSP client. -
Parent navigation can use offsets from the wrong document snapshot.
[lsp.rs:5420–5431](https://github.com/meta/pyrefly/blob/64a316f1f08451e4a45d257c7aec7a35884746b7/pyrefly/lib/state/lsp.rs#L5420-L5431)selects whichever memory/filesystem counterpart appears first in an unordered handle list, then retains the original byte range. With CRLF disk contents and LF editor contents, my repro navigated to thesinselfinstead offin 10/20 runs. Prefer the exact module snapshot; any counterpart fallback must reconcile the range. -
[Routine CodeLens refreshes enqueue uncancellable workspace searches.
[overrideCodeLens.ts:270–281](https://github.com/meta/pyrefly/blob/64a316f1f08451e4a45d257c7aec7a35884746b7/lsp/src/overrideCodeLens.ts#L270-L281)issues declaration and implementation requests for every method—even when none has overrides. A 200-method negative fixture generated 400 requests. Implementation searches traverse reverse dependencies on the shared heavy-task queue, and execute-provider commands do not propagate the lens cancellation token. Debouncing and the per-invocation worker limit don’t cancel obsolete work. Use a cancellable server-side CodeLens query, batching methods or resolving lazily. -
Comment-section headings suppress otherwise-working lenses.
[overrideCodeLens.ts:83–91](https://github.com/meta/pyrefly/blob/64a316f1f08451e4a45d257c7aec7a35884746b7/lsp/src/overrideCodeLens.ts#L83-L91)descends only through class symbols. Pyrefly nests classes underStringsymbols for headings such as# Models ----, so the entire subtree is skipped. The mocked-provider repro changes from one override lens to none when wrapped in a section. Traverse other container nodes while preserving class context.
64a316f to
3ec319c
Compare
This comment has been minimized.
This comment has been minimized.
stroxler
left a comment
There was a problem hiding this comment.
Looks like this needs a rebase before we can merge. The update addresses the original ancestor-lookup, snapshot-pairing, and comment-section concerns. Since we need an update anyway, here are a few more concerns worth looking into:
-
Rebase onto
mainand resolve the merge conflicts. -
Avoid eagerly querying symbols for every navigation target.
[overrideCodeLens.ts:280–301](https://github.com/meta/pyrefly/blob/3ec319ca6271b4bcdce1e9016966da26f288a7e9/lsp/src/overrideCodeLens.ts#L280-L301)requests document symbols for every implementation just to build lens labels. A mocked-provider repro generated one batch plus 500 symbol requests, all still pending after cancellation. Return display names in the batch, or defer multi-target naming until the user opens the quick-pick. -
Refresh lenses when server state changes, and handle server cancellation.
Background indexing and changes to subclass files can leave the base file’s lenses stale because they don’t trigger a refresh. Also,[overrideCodeLens.ts:255–259](https://github.com/meta/pyrefly/blob/3ec319ca6271b4bcdce1e9016966da26f288a7e9/lsp/src/overrideCodeLens.ts#L255-L259)rethrows server-initiated cancellation when the local token/version hasn’t changed, leaving lenses missing. Add server-driven invalidation and an appropriate cancellation/retry path. -
Validate notebook requests against the correct version.
[server.rs:6055–6058](https://github.com/meta/pyrefly/blob/3ec319ca6271b4bcdce1e9016966da26f288a7e9/pyrefly/lib/lsp/non_wasm/server.rs#L6055-L6058)compares the cell document’s version with the notebook’s version. A backend repro succeeds initially, then rejects the unchanged cell after a metadata-only notebook update. Track cell versions or explicitly send and validate the notebook version; add that regression test.
Optional, nonblocking optimization: cache the method lookup/remapping maps instead of rebuilding them for every reverse dependency, and skip candidates with empty parent maps.
3ec319c to
91d6977
Compare
|
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
Summary
Fixes part of #2207
ref microsoft/pylance-release#4972 (comment)
Added a client-side Python CodeLens provider that shows:
- $(arrow-up) Overrides ... on overriding methods
- $(arrow-down) Implemented by ... / implementation counts on parent methods
Registered the provider plus navigation/quick-pick commands
Implemented the provider
Test Plan
Added backend regression coverage for that parent-resolution path