Commit Graph

142 Commits

Author SHA1 Message Date
Aria Desires e5818d89fd
[ty] Add "import ..." code-action for unresolved references (#21629)
## Summary

Originally I planned to feed this in as a `fix` but I realized that we
probably don't want to be trying to resolve import suggestions while
we're doing type inference. Thus I implemented this as a fallback when
there's no fixes on a diagnostic, which can use the full lsp machinery.

Fixes https://github.com/astral-sh/ty/issues/1552

## Test Plan

Works in the IDE, added some e2e tests.
2025-11-27 10:06:38 -05:00
Dhruv Manilawala c7107a5a90
[ty] Use `zip` to perform explicit specialization (#21635)
## Summary

This PR updates the explicit specialization logic to avoid using the
call machinery.

Previously, the logic would use the call machinery by converting the
list of type variables into a `Binding` with a single `Signature` where
all the type variables are positional-only parameters with bounds and
constraints as the annotated type and the default type as the default
parameter value. This has the advantage that it doesn't need to
implement any specific logic but the disadvantages are subpar diagnostic
messages as it would use the ones specific to a function call. But, an
important disadvantage is that the kind of type variable is lost in this
translation which becomes important in #21445 where a `ParamSpec` can
specialize into a list of types which is provided using list literal.
For example,

```py
class Foo[T, **P]: ...

Foo[int, [int, str]]
```

This PR converts the logic to use a simple loop using `zip_longest` as
all type variables and their corresponding type argument maps on a 1-1
basis. They cannot be specified using keyword argument either e.g.,
`dict[_VT=str, _KT=int]` is invalid.

This PR also makes an initial attempt to improve the diagnostic message
to specifically target the specialization part by using words like "type
argument" instead of just "argument" and including information like the
type variable, bounds, and constraints. Further improvements can be made
by highlighting the type variable definition or the bounds / constraints
as a sub-diagnostic but I'm going to leave that as a follow-up.

## Test Plan

Update messages in existing test cases.
2025-11-27 03:52:22 +00:00
Shunsuke Shibayama 2c0c5ff4e7
[ty] handle recursive type inference properly (#20566)
## Summary

Derived from #17371

Fixes astral-sh/ty#256
Fixes https://github.com/astral-sh/ty/issues/1415
Fixes https://github.com/astral-sh/ty/issues/1433
Fixes https://github.com/astral-sh/ty/issues/1524

Properly handles any kind of recursive inference and prevents panics.

---

Let me explain techniques for converging fixed-point iterations during
recursive type inference.
There are two types of type inference that naively don't converge
(causing salsa to panic): divergent type inference and oscillating type
inference.

### Divergent type inference

Divergent type inference occurs when eagerly expanding a recursive type.
A typical example is this:

```python
class C:
    def f(self, other: "C"):
        self.x = (other.x, 1)

reveal_type(C().x) # revealed: Unknown | tuple[Unknown | tuple[Unknown | tuple[..., Literal[1]], Literal[1]], Literal[1]]
```

To solve this problem, we have already introduced `Divergent` types
(https://github.com/astral-sh/ruff/pull/20312). `Divergent` types are
treated as a kind of dynamic type [^1].

```python
Unknown | tuple[Unknown | tuple[Unknown | tuple[..., Literal[1]], Literal[1]], Literal[1]]
=> Unknown | tuple[Divergent, Literal[1]]
```

When a query function that returns a type enters a cycle, it sets
`Divergent` as the cycle initial value (instead of `Never`). Then, in
the cycle recovery function, it reduces the nesting of types containing
`Divergent` to converge.

```python
0th: Divergent
1st: Unknown | tuple[Divergent, Literal[1]]
2nd: Unknown | tuple[Unknown | tuple[Divergent, Literal[1]], Literal[1]]
=> Unknown | tuple[Divergent, Literal[1]]
```

Each cycle recovery function for each query should operate only on the
`Divergent` type originating from that query.
For this reason, while `Divergent` appears the same as `Any` to the
user, it internally carries some information: the location where the
cycle occurred. Previously, we roughly identified this by having the
scope where the cycle occurred, but with the update to salsa, functions
that create cycle initial values ​​can now receive a `salsa::Id`
(https://github.com/salsa-rs/salsa/pull/1012). This is an opaque ID that
uniquely identifies the cycle head (the query that is the starting point
for the fixed-point iteration). `Divergent` now has this `salsa::Id`.

### Oscillating type inference

Now, another thing to consider is oscillating type inference.
Oscillating type inference arises from the fact that monotonicity is
broken. Monotonicity here means that for a query function, if it enters
a cycle, the calculation must start from a "bottom value" and progress
towards the final result with each cycle. Monotonicity breaks down in
type systems that have features like overloading and overriding.

```python
class Base:
    def flip(self) -> "Sub":
        return Sub()

class Sub(Base):
    def flip(self) -> "Base":
        return Base()

class C:
    def __init__(self, x: Sub):
        self.x = x

    def replace_with(self, other: "C"):
        self.x = other.x.flip()

reveal_type(C(Sub()).x)
```

Naive fixed-point iteration results in `Divergent -> Sub -> Base -> Sub
-> ...`, which oscillates forever without diverging or converging. To
address this, the salsa API has been modified so that the cycle recovery
function receives the value of the previous cycle
(https://github.com/salsa-rs/salsa/pull/1012).
The cycle recovery function returns the union type of the current cycle
and the previous cycle. In the above example, the result type for each
cycle is `Divergent -> Sub -> Base (= Sub | Base) -> Base`, which
converges.

The final result of oscillating type inference does not contain
`Divergent` because `Divergent` that appears in a union type can be
removed, as is clear from the expansion. This simplification is
performed at the same time as nesting reduction.

```
T | Divergent = T | (T | (T | ...)) = T
```

[^1]: In theory, it may be possible to strictly treat types containing
`Divergent` types as recursive types, but we probably shouldn't go that
deep yet. (AFAIK, there are no PEPs that specify how to handle
implicitly recursive types that aren't named by type aliases)

## Performance analysis

A happy side effect of this PR is that we've observed widespread
performance improvements!
This is likely due to the removal of the `ITERATIONS_BEFORE_FALLBACK`
and max-specialization depth trick
(https://github.com/astral-sh/ty/issues/1433,
https://github.com/astral-sh/ty/issues/1415), which means we reach a
fixed point much sooner.

## Ecosystem analysis

The changes look good overall.
You may notice changes in the converged values ​​for recursive types,
this is because the way recursive types are normalized has been changed.
Previously, types containing `Divergent` types were normalized by
replacing them with the `Divergent` type itself, but in this PR, types
with a nesting level of 2 or more that contain `Divergent` types are
normalized by replacing them with a type with a nesting level of 1. This
means that information about the non-divergent parts of recursive types
is no longer lost.

```python
# previous
tuple[tuple[Divergent, int], int] => Divergent
# now
tuple[tuple[Divergent, int], int] => tuple[Divergent, int]
```

The false positive error introduced in this PR occurs in class
definitions with self-referential base classes, such as the one below.

```python
from typing_extensions import Generic, TypeVar

T = TypeVar("T")
U = TypeVar("U")

class Base2(Generic[T, U]): ...

# TODO: no error
# error: [unsupported-base] "Unsupported class base with type `<class 'Base2[Sub2, U@Sub2]'> | <class 'Base2[Sub2[Unknown], U@Sub2]'>`"
class Sub2(Base2["Sub2", U]): ...
```

This is due to the lack of support for unions of MROs, or because cyclic
legacy generic types are not inferred as generic types early in the
query cycle.

## Test Plan

All samples listed in astral-sh/ty#256 are tested and passed without any
panic!

## Acknowledgments

Thanks to @MichaReiser for working on bug fixes and improvements to
salsa for this PR. @carljm also contributed early on to the discussion
of the query convergence mechanism proposed in this PR.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-11-26 08:50:26 -08:00
Alex Waygood 81c97e9e94
[ty] Implement `typing.override` (#21627)
## Summary

Part of https://github.com/astral-sh/ty/issues/155. This implements the
basic check (`@override`-decorated methods should override things!), but
not the strict check specified in
https://typing.python.org/en/latest/spec/class-compat.html#strict-enforcement-per-project,
which should be a separate error code.

## Test Plan

mdtests and snapshots

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-11-25 10:42:40 -08:00
Micha Reiser 15cb41c1f9
[ty] Add 'remove unused ignore comment' code action (#21582)
## Summary

This PR adds a code action to remove unused ignore comments.

This PR also includes some infrastructure boilerplate to set up code
actions in the editor:

* Extend `snapshot-diagnostics` to render fixes
* Render fixes when using `--output-format=full`
* Hook up edits and the code action request in the LSP
* Add the `Unnecessary` tag to `unused-ignore-comment` diagnostics
* Group multiple unused codes into a single diagnostic

The same fix can be used on the CLI once we add `ty fix` 

Note: `unused-ignore-comment` is currently disabled by default.


https://github.com/user-attachments/assets/f9e21087-3513-4156-85d7-a90b1a7a3489
2025-11-25 08:08:21 -05:00
Matthew Mckee 6f9265d78d
[ty] Double click to insert inlay hint (#21600)
<!--
Thank you for contributing to Ruff/ty! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

Resolves
https://github.com/astral-sh/ty/issues/317#issuecomment-3567398107.

I can't get the auto import working great.

I haven't added many places where we specify that the type display is
invalid syntax.

## Test Plan

Nothing yet
2025-11-24 19:48:30 +00:00
Dhruv Manilawala 3b23d3c041
Fix cargo shear in CI (#21609)
Tested using `cargo build` and `cargo build --release`.
2025-11-24 05:35:34 +00:00
Alex Waygood e642874cf1
[ty] Check method definitions on subclasses for Liskov violations (#21436) 2025-11-23 18:08:15 +00:00
Aria Desires 416e2267da
[ty] Implement goto-type for inlay type hints (#21533)
This PR generalizes the signature_help system's SignatureWriter which
could get the subspans of function parameters.
We now have TypeDetailsWriter which is threaded between type's display
implementations via a new `fmt_detailed` method that many of the Display
types now have.

With this information we can properly add goto-type targets to our inlay
hints. This also lays groundwork for any future "I want to render a type
but get spans" work.

Also a ton of lifetimes are introduced to avoid things getting conflated
with `'db`.

This PR is broken up into a series of commits:

* Generalizing `SignatureWriter` to `TypeDetailsWriter`, but not using
it anywhere else. This commit was confirmed to be a non-functional
change (no test results changed)
* Introducing `fmt_detailed` everywhere to thread through
`TypeDetailsWriter` and annotate various spans as "being" a given Type
-- this is also where I had to reckon with a ton of erroneous `&'db
self`. This commit was also confirmed to be a non-functional change.
* Finally, actually using the results for goto-type on inlay hints!
* Regenerating snapshots, fixups, etc.
2025-11-20 09:40:40 -05:00
Luca Chiodini 18a14bfaf1
[ty] Semantic tokens: consistently add the `DEFINITION` modifier (#21521) 2025-11-19 12:45:39 +01:00
Micha Reiser 7043d51df0
[ty] Add hyperlinks to rule codes in CLI (#21502) 2025-11-18 16:36:59 +01:00
Matthew Mckee 901e9cdf49
[ty] Inlay hint call argument location (#20349)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-11-17 11:33:09 +01:00
Micha Reiser 58fa1d71b6
[ty] Use `CompactStr` for `StringLiteralType` (#21497) 2025-11-17 10:01:21 +01:00
github-actions[bot] efa2b5167f
[ty] Sync vendored typeshed stubs (#21466)
Co-authored-by: typeshedbot <>
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-11-15 17:12:32 +00:00
Micha Reiser 008e9d06e1
[ty] Add panic-by-default await methods to `TestServer` (#21451) 2025-11-14 19:47:39 +01:00
Micha Reiser d0314131fb
[ty] Increase default receive timeout in tests to 10s (#21448) 2025-11-14 13:15:22 +01:00
Micha Reiser f9cc26aa12
[ty] Respect notebook cell boundaries when adding an auto import (#21322) 2025-11-13 18:58:08 +01:00
Micha Reiser e70fccbf25
[ty] Improve LSP test server logging (#21432) 2025-11-13 18:29:54 +01:00
Micha Reiser 12e74ae894
[ty] Support for notebooks in VS Code (#21175) 2025-11-13 13:23:19 +01:00
Jack O'Connor 5f3e086ee4 [ty] implement `typing.NewType` by adding `Type::NewTypeInstance` 2025-11-10 14:55:47 -08:00
Aria Desires d258302b08
[ty] supress some trivial expr inlay hints (#21367)
I'm not 100% sold on this implementation, but it's a strict improvement
and it adds a ton of snapshot tests for future iteration.

Part of https://github.com/astral-sh/ty/issues/494
2025-11-10 19:51:14 +00:00
Micha Reiser 6cc3393ccd
[ty] Make range/position conversions fallible (#21297)
Co-authored-by: Aria Desires <aria.desires@gmail.com>
2025-11-07 14:44:23 +00:00
Dhruv Manilawala cb2e277482
[ty] Understand legacy and PEP 695 `ParamSpec` (#21139)
## Summary

This PR adds support for understanding the legacy definition and PEP 695
definition for `ParamSpec`.

This is still very initial and doesn't really implement any of the
semantics.

Part of https://github.com/astral-sh/ty/issues/157

## Test Plan

Add mdtest cases.

## Ecosystem analysis

Most of the diagnostics in `starlette` are due to the fact that ty now
understands `ParamSpec` is not a `Todo` type, so the assignability check
fails. The code looks something like:

```py
class _MiddlewareFactory(Protocol[P]):
    def __call__(self, app: ASGIApp, /, *args: P.args, **kwargs: P.kwargs) -> ASGIApp: ...  # pragma: no cover

class Middleware:
    def __init__(
        self,
        cls: _MiddlewareFactory[P],
        *args: P.args,
        **kwargs: P.kwargs,
    ) -> None:
        self.cls = cls
        self.args = args
        self.kwargs = kwargs

# ty complains that `ServerErrorMiddleware` is not assignable to `_MiddlewareFactory[P]`
Middleware(ServerErrorMiddleware, handler=error_handler, debug=debug)
```

There are multiple diagnostics where there's an attribute access on the
`Wrapped` object of `functools` which Pyright also raises:
```py
from functools import wraps

def my_decorator(f):
    @wraps(f)
    def wrapper(*args, **kwds):
        return f(*args, **kwds)

	# Pyright: Cannot access attribute "__signature__" for class "_Wrapped[..., Unknown, ..., Unknown]"
      Attribute "__signature__" is unknown [reportAttributeAccessIssue]
	# ty: Object of type `_Wrapped[Unknown, Unknown, Unknown, Unknown]` has no attribute `__signature__` [unresolved-attribute]
    wrapper.__signature__
    return wrapper
```

There are additional diagnostics that is due to the assignability checks
failing because ty now infers the `ParamSpec` instead of using the
`Todo` type which would always succeed. This results in a few
`no-matching-overload` diagnostics because the assignability checks
fail.

There are a few diagnostics related to
https://github.com/astral-sh/ty/issues/491 where there's a variable
which is either a bound method or a variable that's annotated with
`Callable` that doesn't contain the instance as the first parameter.

Another set of (valid) diagnostics are where the code hasn't provided
all the type variables. ty is now raising diagnostics for these because
we include `ParamSpec` type variable in the signature. For example,
`staticmethod[Any]` which contains two type variables.
2025-11-06 11:14:40 -05:00
Micha Reiser 7569b09bdd
[ty] Add `ty_server::Db` trait (#21241) 2025-11-05 13:40:07 +00:00
Micha Reiser 7009d60260
[ty] Refactor `Range` to/from `TextRange` conversion as prep for notebook support (#21230) 2025-11-05 13:24:03 +00:00
Matthew Mckee e2e83acd2f
[ty] Remove mentions of VS Code from server logs (#21155)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-11-03 14:49:58 +00:00
Micha Reiser 6337e22f0c
[ty] Smaller refactors to server API in prep for notebook support (#21095) 2025-10-31 20:00:04 +00:00
Andrew Gallant 196a68e4c8 [ty] Render `import <...>` in completions when "label details" isn't supported
This fixes a bug where the `import module` part of a completion for
unimported candidates would be missing. This makes it especially
confusing because the user can't tell where the symbol is coming from,
and there is no hint that an `import` statement will be inserted.

Previously, we were using [`CompletionItemLabelDetails`] to render the
`import module` part of the suggestion. But this is only supported in
clients that support version 3.17 (or newer) of the LSP specification.
It turns out that this support isn't widespread yet. In particular,
Heliex doesn't seem to support "label details."

To fix this, we take a [cue from rust-analyzer][rust-analyzer-details].
We detect if the client supports "label details," and if so, use it.
Otherwise, we push the `import module` text into the completion label
itself.

Fixes https://github.com/astral-sh/ruff/pull/20439#issuecomment-3313689568

[`CompletionItemLabelDetails`]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#completionItemLabelDetails
[rust-analyzer-details]: 5d905576d4/crates/rust-analyzer/src/lsp/to_proto.rs (L391-L404)
2025-10-29 08:50:41 -04:00
Micha Reiser be5a62f7e5
[ty] Timeout based workspace diagnostic progress reports (#21019) 2025-10-24 09:06:19 +02:00
Aria Desires 2e13b13012
[ty] Support goto-definition on vendored typeshed stubs (#21020)
This is an alternative to #21012 that more narrowly handles this logic
in the stub-mapping machinery rather than pervasively allowing us to
identify cached files as typeshed stubs. Much of the logic is the same
(pulling the logic out of ty_server so it can be reused).

I don't have a good sense for if one approach is "better" or "worse" in
terms of like, semantics and Weird Bugs that this can cause. This one is
just "less spooky in its broad consequences" and "less muddying of
separation of concerns" and puts the extra logic on a much colder path.
I won't be surprised if one day the previous implementation needs to be
revisited for its more sweeping effects but for now this is good.

Fixes https://github.com/astral-sh/ty/issues/1054
2025-10-21 13:38:40 -04:00
Takayuki Maeda 1197035c02
[`ty`] Add capabilities check for `clear_diagnostics` (#20989) 2025-10-20 19:31:01 +02:00
Micha Reiser 7532155c9b
[ty] Add suggestion to unknown rule diagnostics, rename `unknown-rule` lint to `ignore-comment-unknown-rule` (#20948) 2025-10-18 12:44:21 +02:00
Andrew Gallant 651f7963a7
[ty] Add some completion ranking improvements (#20807)
Co-authored-by: Micha Reiser <micha@reiser.io>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-10-15 08:59:33 +00:00
Alex Waygood ff386b4797
[ty] Improve diagnostics for bad `@overload` definitions (#20745) 2025-10-07 21:52:57 +00:00
Renkai Ge bf38e69870
[ty] Rename "possibly unbound" diagnostics to "possibly missing" (#20492)
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-09-23 14:26:55 +00:00
fgiacome 4ed8c65d29
[ty] Add positional-only-parameter-as-kwarg error (#20495) 2025-09-23 15:10:45 +01:00
renovate[bot] 61bb2a8245
Update Rust crate anyhow to v1.0.100 (#20499)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-09-22 09:51:52 +02:00
GF eb354608d2
[ty] Add LSP debug information command (#20379)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-09-20 11:15:13 +00:00
Micha Reiser 1758f26d94
Update rust toolchain to 1.90 (#20469) 2025-09-18 16:54:49 +02:00
Andrew Gallant 1ebbe73a1d [ty] Swap `detail` and `description` fields for `CompletionItemLabelDetails`
This seems to be more consistent with how other LSPs work (like
`rust-analyzer`), and also I think is more consistent with how
`CompletionItem.detail` is itself rendered. Namely, in VS Code, it
is right-aligned. And it's also where we put the type signature.
But `CompletionItemLabelDetails.detail` is left-aligned where as
`CompletionItemLabelDetails.description` is right-aligned. So let's
swap them such that type signatures go in the latter and not the
former.

This also adds a space before the module name and contextualizes
it with `(import <name>)` to help aide the end user in figuring out
selecting the completion will do.

Fixes #1200
2025-09-18 09:11:17 -04:00
Andrew Gallant bcc8d6910b [ty] Refactor to handle unimported completions
This rejiggers some stuff in the main completions entrypoint
in `ty_ide`. A more refined `Completion` type is defined
with more information. In particular, to support auto-import,
we now include a module name and an "edit" for inserting an
import.

This also rolls the old "detailed completion" into the new
completion type. Previously, we were relying on the completion
type for `ty_python_semantic`. But `ty_ide` is really the code
that owns completions.

Note that this code doesn't build as-is. The next commit will
add the importer used here in `add_unimported_completions`.
2025-09-17 13:59:28 -04:00
Andrew Gallant 25853e2377 Allow the `if_not_else` Clippy lint
Specifically, the [`if_not_else`] lint will sometimes flag
code to change the order of `if` and `else` bodies if this
would allow a `!` to be removed. While perhaps tasteful in
some cases, there are many cases in my experience where this
bows to other competing concerns that impact readability.
(Such as the relative sizes of the `if` and `else` bodies,
or perhaps an ordering that just makes the code flow in a
more natural way.)

[`if_not_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#/if_not_else
2025-09-09 08:49:25 -04:00
Andrew Gallant c402bf8ae2 [ty] Correct default value for experimental rename setting
Ref https://github.com/astral-sh/ruff/pull/20207#discussion_r2318336964
2025-09-03 09:57:26 -04:00
Andrew Gallant 0a0eaf5a9b [ty] Make auto-import completions opt-in via an experimental option
Instead of waiting to land auto-import until it is "ready
for users," it'd be nicer to get incremental progress merged
to `main`. By making it an experimental opt-in, we avoid making
the default completion experience worse but permit developers
and motivated users to try it.
2025-09-03 09:57:26 -04:00
Andrew Gallant 8e52027a88 [ty] Add naive implementation of completions for unimported symbols
This re-works the `all_symbols` based added previously to work across
all modules available, and not just what is directly in the workspace.

Note that we always pass an empty string as a query, which makes the
results always empty. We'll fix this in a subsequent commit.
2025-09-03 09:57:26 -04:00
Matthew Mckee 8d6dc7d3a3
[ty] Refactor inlay hints structure to use separate parts (#20052)
## Summary

Our internal inlay hints structure (`ty_ide::InlayHint`) now more
closely resembles `lsp_types::InlayHint`.

This mainly allows us to convert to `lsp_types::InlayHint` with less
hassle, but it also allows us to manage the different parts of the inlay
hint better, which in the future will allow us to implement features
like goto on the type part of the type inlay hint.

It also really isn't important to store a specific `Type` instance in
the `InlayHintContent`. So we remove this and use `InlayHintLabel`
instead which just shows the representation of the type (along with
other information).

We see a similar structure used in rust-analyzer too.
2025-08-26 10:21:31 +05:30
Andrew Gallant 205eae14d2 [ty] Rejigger workspace symbols for more efficient caching
In effect, we make the Salsa query aspect keyed only on whether we want
global symbols. We move everything else (hierarchical and querying) to
an aggregate step *after* the query.

This was a somewhat involved change since we want to return a flattened
list from visiting the source while also preserving enough information
to reform the symbols into a hierarchical structure that the LSP
expects. But I think overall the API has gotten simpler and we encode
more invariants into the type system. (For example, previously you got a
runtime assertion if you tried to provide a query string while enabling
hierarchical mode. But now that's prevented by construction.)
2025-08-23 12:53:41 -04:00
Andrew Gallant 06dbec8479 [ty] Add debug trace for workspace symbol elapsed time
Useful for ad hoc debugging, but it's also useful to have permanently to
enable serendipitous discovery of performance problems.
2025-08-23 12:53:41 -04:00
Micha Reiser 796819e7a0
[ty] Disallow std::env and io methods in most ty crates (#20046)
## Summary

We use the `System` abstraction in ty to abstract away the host/system
on which ty runs.
This has a few benefits:

* Tests can run in full isolation using a memory system (that uses an
in-memory file system)
* The LSP has a custom implementation where `read_to_string` returns the
content as seen by the editor (e.g. unsaved changes) instead of always
returning the content as it is stored on disk
* We don't require any file system polyfills for wasm in the browser


However, it does require extra care that we don't accidentally use
`std::fs` or `std::env` (etc.) methods in ty's code base (which is very
easy).

This PR sets up Clippy and disallows the most common methods, instead
pointing users towards the corresponding `System` methods.

The setup is a bit awkward because clippy doesn't support inheriting
configurations. That means, a crate can only override the entire
workspace configuration or not at all.
The approach taken in this PR is:

* Configure the disallowed methods at the workspace level
* Allow `disallowed_methods` at the workspace level
* Enable the lint at the crate level using the warn attribute (in code)


The obvious downside is that it won't work if we ever want to disallow
other methods, but we can figure that out once we reach that point.

What about false positives: Just add an `allow` and move on with your
life :) This isn't something that we have to enforce strictly; the goal
is to catch accidental misuse.

## Test Plan

Clippy found a place where we incorrectly used `std::fs::read_to_string`
2025-08-22 11:13:47 -07:00
Micha Reiser 5d217b7f46
[ty] Add type as detail to completion items (#20047)
## Summary

@BurntSushi was so kind as to find me an easy task to do some coding
before I'm off to PTO.

This PR adds the type to completion items (see the gray little text at
the end of a completion item).



https://github.com/user-attachments/assets/c0a86061-fa12-47b4-b43c-3c646771a69d
2025-08-22 12:32:53 -04:00