mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-16 01:25:22 +00:00
![]() ## Summary Implement basic *Goto type definition* support for Red Knot's LSP. This PR also builds the foundation for other LSP operations. E.g., Goto definition, hover, etc., should be able to reuse some, if not most, logic introduced in this PR. The basic steps of resolving the type definitions are: 1. Find the closest token for the cursor offset. This is a bit more subtle than I first anticipated because the cursor could be positioned right between the callee and the `(` in `call(test)`, in which case we want to resolve the type for `call`. 2. Find the node with the minimal range that fully encloses the token found in 1. I somewhat suspect that 1 and 2 could be done at the same time but it complicated things because we also need to compute the spine (ancestor chain) for the node and there's no guarantee that the found nodes have the same ancestors 3. Reduce the node found in 2. to a node that is a valid goto target. This may require traversing upwards to e.g. find the closest expression. 4. Resolve the type for the goto target 5. Resolve the location for the type, return it to the LSP ## Design decisions The current implementation navigates to the inferred type. I think this is what we want because it means that it correctly accounts for narrowing (in which case we want to go to the narrowed type because that's the value's type at the given position). However, it does have the downside that Goto type definition doesn't work whenever we infer `T & Unknown` because intersection types aren't supported. I'm not sure what to do about this specific case, other than maybe ignoring `Unkown` in Goto type definition if the type is an intersection? ## Known limitations * Types defined in the vendored typeshed aren't supported because the client can't open files from the red knot binary (we can either implement our own file protocol and handler OR extract the typeshed files and point there). See https://github.com/astral-sh/ruff/issues/17041 * Red Knot only exposes an API to get types for expressions and definitions. However, there are many other nodes with identifiers that can have a type (e.g. go to type of a globals statement, match patterns, ...). We can add support for those in separate PRs (after we figure out how to query the types from the semantic model). See https://github.com/astral-sh/ruff/issues/17113 * We should have a higher-level API for the LSP that doesn't directly call semantic queries. I intentionally decided not to design that API just yet. ## Test plan https://github.com/user-attachments/assets/fa077297-a42d-4ec8-b71f-90c0802b4edb Goto type definition on a union <img width="1215" alt="Screenshot 2025-04-01 at 13 02 55" src="https://github.com/user-attachments/assets/689cabcc-4a86-4a18-b14a-c56f56868085" /> Note: I recorded this using a custom typeshed path so that navigating to builtins works. |
||
---|---|---|
.. | ||
resources | ||
src | ||
tests | ||
Cargo.toml | ||
CONTRIBUTING.md | ||
README.md |
Ruff Python Parser
Ruff's Python parser is a hand-written recursive descent parser which can parse Python source code into an Abstract Syntax Tree (AST). It also utilizes the Pratt parsing technique to parse expressions with different precedence.
Try out the parser in the playground.
Python version support
The parser supports the latest Python syntax, which is currently Python 3.12.
It does not throw syntax errors if it encounters a syntax feature that is not
supported by the target-version
.
This will be fixed in a future release (see https://github.com/astral-sh/ruff/issues/6591).
Contributing
Refer to the contributing guidelines to get started and GitHub issues with the parser label for issues that need help.