Commit graph

92 commits

Author SHA1 Message Date
Micha Reiser
e18b4e42d3
[red-knot] Upgrade to the *new* *new* salsa (#12406) 2024-07-29 07:21:24 +00:00
Dhruv Manilawala
6f4db8675b
[red-knot] Add support for untitled files (#12492)
## Summary

This PR adds support for untitled files in the Red Knot project.

Refer to the [design
discussion](https://github.com/astral-sh/ruff/discussions/12336) for
more details.

### Changes
* The `parsed_module` always assumes that the `SystemVirtual` path is of
`PySourceType::Python`.
* For the module resolver, as suggested, I went ahead by adding a new
`SystemOrVendoredPath` enum and renamed `FilePathRef` to
`SystemOrVendoredPathRef` (happy to consider better names here).
* The `file_to_module` query would return if it's a
`FilePath::SystemVirtual` variant because a virtual file doesn't belong
to any module.
* The sync implementation for the system virtual path is basically the
same as that of system path except that it uses the
`virtual_path_metadata`. The reason for this is that the system
(language server) would provide the metadata on whether it still exists
or not and if it exists, the corresponding metadata.

For point (1), VS Code would use `Untitled-1` for Python files and
`Untitled-1.ipynb` for Jupyter Notebooks. We could use this distinction
to determine whether the source type is `Python` or `Ipynb`.

## Test Plan

Added test cases in #12526
2024-07-26 18:13:31 +05:30
Alex Waygood
5ce80827d2
[red-knot] Refactor path.rs in the module resolver (#12494) 2024-07-25 19:29:28 +01:00
Micha Reiser
eac965ecaf
[red-knot] Watch search paths (#12407) 2024-07-24 07:38:50 +00:00
Micha Reiser
f0fc6a95fe
[red-knot] Lazy package file discovery (#12452)
Co-authored-by: Carl Meyer <carl@astral.sh>
2024-07-23 08:47:15 +00:00
Micha Reiser
40d9324f5a
[red-knot] Improved file watching (#12382) 2024-07-23 08:18:59 +02:00
Carl Meyer
f22c8ab811
[red-knot] add maybe-undefined lint rule (#12414)
Add a lint rule to detect if a name is definitely or possibly undefined
at a given usage.

If I create the file `undef/main.py` with contents:

```python
x = int
def foo():
    z
    return x
if flag:
    y = x
y
```

And then run `cargo run --bin red_knot -- --current-directory
../ruff-examples/undef`, I get the output:

```
Name 'z' used when not defined.
Name 'flag' used when not defined.
Name 'y' used when possibly not defined.
```

If I modify the file to add `y = 0` at the top, red-knot re-checks it
and I get the new output:

```
Name 'z' used when not defined.
Name 'flag' used when not defined.
```

Note that `int` is not flagged, since it's a builtin, and `return x` in
the function scope is not flagged, since it refers to the global `x`.
2024-07-22 13:53:59 -07:00
Alex Waygood
2a8f95c437
[red-knot] Use a distinct type for module search paths in the module resolver (#12379) 2024-07-22 19:44:27 +00:00
Micha Reiser
ad19b3fd0e
[red-knot] Add verbosity argument to CLI (#12404) 2024-07-19 11:38:24 +00:00
Micha Reiser
79b535587b
[red-knot] Reload notebook on file change (#12361) 2024-07-17 12:23:48 +00:00
Micha Reiser
91338ae902
[red-knot] Add basic workspace support (#12318) 2024-07-17 11:34:21 +02:00
Micha Reiser
0c72577b5d
[red-knot] Add notebook support (#12338) 2024-07-17 08:26:33 +00:00
Alex Waygood
9a2dafb43d
[red-knot] Add support for editable installs to the module resolver (#12307)
Co-authored-by: Micha Reiser <micha@reiser.io>
Co-authored-by: Carl Meyer <carl@astral.sh>
2024-07-16 18:17:47 +00:00
Carl Meyer
595b1aa4a1
[red-knot] per-definition inference, use-def maps (#12269)
Implements definition-level type inference, with basic control flow
(only if statements and if expressions so far) in Salsa.

There are a couple key ideas here:

1) We can do type inference queries at any of three region
granularities: an entire scope, a single definition, or a single
expression. These are represented by the `InferenceRegion` enum, and the
entry points are the salsa queries `infer_scope_types`,
`infer_definition_types`, and `infer_expression_types`. Generally
per-scope will be used for scopes that we are directly checking and
per-definition will be used anytime we are looking up symbol types from
another module/scope. Per-expression should be uncommon: used only for
the RHS of an unpacking or multi-target assignment (to avoid
re-inferring the RHS once per symbol defined in the assignment) and for
test nodes in type narrowing (e.g. the `test` of an `If` node). All
three queries return a `TypeInference` with a map of types for all
definitions and expressions within their region. If you do e.g.
scope-level inference, when it hits a definition, or an
independently-inferable expression, it should use the relevant query
(which may already be cached) to get all types within the smaller
region. This avoids double-inferring smaller regions, even though larger
regions encompass smaller ones.

2) Instead of building a control-flow graph and lazily traversing it to
find definitions which reach a use of a name (which is O(n^2) in the
worst case), instead semantic indexing builds a use-def map, where every
use of a name knows which definitions can reach that use. We also no
longer track all definitions of a symbol in the symbol itself; instead
the use-def map also records which defs remain visible at the end of the
scope, and considers these the publicly-visible definitions of the
symbol (see below).

Major items left as TODOs in this PR, to be done in follow-up PRs:

1) Free/global references aren't supported yet (only lookup based on
definitions in current scope), which means the override-check example
doesn't currently work. This is the first thing I'll fix as follow-up to
this PR.

2) Control flow outside of if statements and expressions.

3) Type narrowing.

There are also some smaller relevant changes here:

1) Eliminate `Option` in the return type of member lookups; instead
always return `Type::Unbound` for a name we can't find. Also use
`Type::Unbound` for modules we can't resolve (not 100% sure about this
one yet.)

2) Eliminate the use of the terms "public" and "root" to refer to
module-global scope or symbols. Instead consistently use the term
"module-global". It's longer, but it's the clearest, and the most
consistent with typical Python terminology. In particular I don't like
"public" for this use because it has other implications around author
intent (is an underscore-prefixed module-global symbol "public"?). And
"root" is just not commonly used for this in Python.

3) Eliminate the `PublicSymbol` Salsa ingredient. Many non-module-global
symbols can also be seen from other scopes (e.g. by a free var in a
nested scope, or by class attribute access), and thus need to have a
"public type" (that is, the type not as seen from a particular use in
the control flow of the same scope, but the type as seen from some other
scope.) So all symbols need to have a "public type" (here I want to keep
the use of the term "public", unless someone has a better term to
suggest -- since it's "public type of a symbol" and not "public symbol"
the confusion with e.g. initial underscores is less of an issue.) At
least initially, I would like to try not having special handling for
module-global symbols vs other symbols.

4) Switch to using "definitions that reach end of scope" rather than
"all definitions" in determining the public type of a symbol. I'm
convinced that in general this is the right way to go. We may want to
refine this further in future for some free-variable cases, but it can
be changed purely by making changes to the building of the use-def map
(the `public_definitions` index in it), without affecting any other
code. One consequence of combining this with no control-flow support
(just last-definition-wins) is that some inference tests now give more
wrong-looking results; I left TODO comments on these tests to fix them
when control flow is added.

And some potential areas for consideration in the future:

1) Should `symbol_ty` be a Salsa query? This would require making all
symbols a Salsa ingredient, and tracking even more dependencies. But it
would save some repeated reconstruction of unions, for symbols with
multiple public definitions. For now I'm not making it a query, but open
to changing this in future with actual perf evidence that it's better.
2024-07-16 11:02:30 -07:00
Micha Reiser
85ae02d62e
[red-knot] Add walk_directories to System (#12297) 2024-07-16 06:40:10 +00:00
Alex Waygood
6febd96dfe
[red-knot] Add a read_directory() method to the ruff_db::system::System trait (#12289) 2024-07-12 12:31:05 +00:00
Alex Waygood
5b21922420
[red-knot] Add more stress tests for module resolver invalidation (#12272) 2024-07-10 14:34:06 +00:00
Micha Reiser
abcf07c8c5
Change File::touch_path to only take a SystemPath (#12273) 2024-07-10 12:15:14 +00:00
Alex Waygood
6fa4e32ad3
[red-knot] Use vendored typeshed stubs for stdlib module resolution (#12224) 2024-07-09 09:21:52 +00:00
Micha Reiser
b5834d57af
[red-knot] Only store absolute paths in Files (#12215) 2024-07-09 09:52:13 +02:00
Micha Reiser
ac04380f36
[red-knot] Rename FileSystem to System (#12214) 2024-07-09 07:20:51 +00:00
Alex Waygood
0f6f73ecf3
[red-knot] Require that FileSystem objects implement Debug (#12204) 2024-07-05 12:53:30 +01:00
Micha Reiser
e2e0889a30
[red-knot] Add very basic benchmark (#12182) 2024-07-04 15:29:00 +00:00
Micha Reiser
4d385b60c8
[red-knot] Migrate CLI to Salsa (#11972) 2024-07-04 07:23:45 +00:00
Micha Reiser
b950a6c389
Replace Mutex<RefCell> with Mutex in vendored file system" (#12170) 2024-07-03 15:12:13 +02:00
Micha Reiser
37f260b5af
Introduce HasTy trait and SemanticModel facade (#11963) 2024-07-01 14:48:27 +02:00
Alex Waygood
cd2af3be73
[red-knot] Reduce allocations when normalizing VendoredPaths (#11992) 2024-06-24 13:08:01 +01:00
Alex Waygood
375d2c87b2
[red-knot] Simplify conversions from std::path::Path to VendoredPath(Buf) (#11988) 2024-06-23 15:52:26 +01:00
Alex Waygood
92b145e56a
[red-knot] Manually implement Debug for VendoredFileSystem (#11983) 2024-06-23 14:25:56 +01:00
Micha Reiser
519a278899
[red-knot] Remove itertools dependency from ruff_db (#11984) 2024-06-22 18:37:51 +00:00
Micha Reiser
927069c12f
[red-knot] Upgrade to Salsa 3.0 (#11952) 2024-06-20 20:19:16 +01:00
Micha Reiser
b456051be8
[red-knot] Add tracing to Salsa queries (#11949) 2024-06-20 13:33:41 +02:00
Alex Waygood
1d73d60bd3
[red-knot]: Add a VendoredFileSystem implementation (#11863)
Co-authored-by: Micha Reiser <micha@reiser.io>
2024-06-18 15:43:39 +00:00
Micha Reiser
f666d79cd7
red-knot: Symbol table (#11860) 2024-06-18 13:10:45 +00:00
Micha Reiser
26ac805e6d
red-knot: Port module resolver to salsa (#11835) 2024-06-18 12:11:58 +00:00
Micha Reiser
98b13b9844
red-knot: Add a method to resolve a file for an arbitrary VfsPath (#11826)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2024-06-18 12:03:30 +00:00
Micha Reiser
c5bc368e43
[red-knot] Improve Vfs and FileSystem documentation (#11856) 2024-06-13 11:49:27 +00:00
Micha Reiser
73370fe798
Use starts_with('/') instead of is_absolute to avoid platform specific API (#11855) 2024-06-13 12:35:31 +01:00
Micha Reiser
22b6488550
red-knot: Add directory support to MemoryFileSystem (#11825) 2024-06-13 07:48:28 +00:00
Micha Reiser
d4dd96d1f4
red-knot: source_text, line_index, and parsed_module queries (#11822) 2024-06-13 07:37:02 +00:00
Micha Reiser
efbf7b14b5
red-knot[salsa part 2]: Setup semantic DB and Jar (#11837)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2024-06-13 08:00:51 +01:00
Micha Reiser
93973b96cb
red-knot: VfsFile input ingredient and a Vfs (#11802) 2024-06-12 07:06:15 +00:00