fix autocomplete endpoints in web framework #2224#2299
fix autocomplete endpoints in web framework #2224#2299asukaminato0721 wants to merge 3 commits intofacebook:mainfrom
Conversation
|
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
There was a problem hiding this comment.
Pull request overview
Adds LSP support for FastAPI-style endpoints by offering URL path completions at HTTP client call sites and enabling go-to-definition from request path literals to the corresponding route handler.
Changes:
- Introduces
endpoint_supportmodule to collect route definitions from decorators and match them against client request literals. - Wires endpoint completions into the completion pipeline and endpoint literal resolution into go-to-definition.
- Adds regression tests covering endpoint completion and endpoint go-to-definition.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
pyrefly/lib/state/lsp/endpoint_support.rs |
New endpoint discovery/matching logic for completions + definition lookup. |
pyrefly/lib/lsp/wasm/completion.rs |
Calls add_endpoint_completions during completion generation. |
pyrefly/lib/state/lsp.rs |
Registers the new module and hooks endpoint literal definition lookup into go-to-definition. |
pyrefly/lib/test/lsp/completion.rs |
Adds a completion test asserting endpoint paths are suggested for client.get/post(""). |
pyrefly/lib/test/lsp/definition.rs |
Adds a definition test asserting go-to-definition from client.get("/users") lands on the route function. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let nodes = pyrefly_python::ast::Ast::locate_node(module, position); | ||
| let mut best: Option<(u8, TextSize, EndpointCallContext)> = None; | ||
| for node in nodes { | ||
| let AnyNodeRef::ExprCall(call) = node else { | ||
| continue; | ||
| }; | ||
| let method = EndpointMethod::from_attr(call_callee_name(call)?)?; | ||
| let literal = endpoint_literal_in_call(call, position)?; | ||
| let range = literal.range(); |
There was a problem hiding this comment.
endpoint_call_context treats any call whose callee attribute/name is get/post/etc as an HTTP request. This will also fire for unrelated APIs like dict.get("k") or custom .get() methods, producing incorrect endpoint completions and potentially wrong go-to-definition results. Restrict this logic to known HTTP client call sites (e.g., detect TestClient(...)-constructed variables in the module AST, or validate the receiver type/name before treating the call as an endpoint request).
| impl<'a> Transaction<'a> { | ||
| fn collect_endpoint_definitions(&self) -> Vec<EndpointDefinition> { | ||
| let mut endpoints = Vec::new(); | ||
| for handle in self.handles() { | ||
| let Some(module) = self.get_module_info(&handle) else { | ||
| continue; | ||
| }; | ||
| if module.path().style() == ModuleStyle::Interface { | ||
| continue; | ||
| } | ||
| match module.path().details() { | ||
| ModulePathDetails::FileSystem(_) | ||
| | ModulePathDetails::Memory(_) | ||
| | ModulePathDetails::Namespace(_) => {} | ||
| _ => continue, | ||
| } | ||
| let Some(ast) = self.get_ast(&handle) else { | ||
| continue; | ||
| }; | ||
| let mut collector = EndpointCollector::new(module); | ||
| for stmt in &ast.body { | ||
| collector.visit_stmt(stmt); | ||
| } | ||
| endpoints.extend(collector.endpoints); | ||
| } | ||
| endpoints |
There was a problem hiding this comment.
collect_endpoint_definitions walks every handle, loads module info/AST, and scans all statements on each completion/definition request. In larger workspaces this can make completions/definitions noticeably slower. Consider caching endpoint definitions per transaction/state (with invalidation on file changes), or narrowing the scan to a smaller set of relevant modules (e.g., only modules that contain FastAPI route decorators / only the current module plus its imports).
Summary
part of #2224
Test Plan