141 lines
3.1 KiB
Markdown
141 lines
3.1 KiB
Markdown
# Hover type assertions
|
|
|
|
You can use the `hover` assertion to test the inferred type of an expression. This exercises the
|
|
same logic as the hover LSP action.
|
|
|
|
Typically, you will not need to use the `hover` action to test the behavior of our type inference
|
|
code, since you can also use `reveal_type` to display the inferred type of an expression. Since
|
|
`reveal_type` is part of the standard library, we prefer to use it when possible.
|
|
|
|
However, there are certain situations where `reveal_type` and `hover` will give different results.
|
|
In particular, `reveal_type` is not transparent to bidirectional type checking, as seen in the
|
|
"Different results" section below.
|
|
|
|
## Syntax
|
|
|
|
### Basic syntax
|
|
|
|
The `hover` assertion operates on a specific location in the source text. We find the "inner-most"
|
|
expression at that position, and then query the inferred type of that expression. The row to query
|
|
is identified just like any other mdtest assertion. The column to query is identified by a down
|
|
arrow (↓) in the assertion. (Note that the down arrow should always appear immediately before the
|
|
`hover` keyword in the assertion.)
|
|
|
|
```py
|
|
def test_basic_types(parameter: int) -> None:
|
|
# ↓ hover: int
|
|
parameter
|
|
|
|
# ↓ hover: Literal[10]
|
|
number = 10
|
|
|
|
# ↓ hover: Literal["hello"]
|
|
text = "hello"
|
|
```
|
|
|
|
### Multiple hovers on the same line
|
|
|
|
We can have multiple hover assertions for different positions on the same line:
|
|
|
|
```py
|
|
# ↓ hover: Literal[1]
|
|
# ↓ hover: Literal[2]
|
|
# ↓ hover: Literal[3]
|
|
total = 1 + 2 + 3
|
|
|
|
# ↓ hover: Literal[5]
|
|
# ↓ hover: Literal[3]
|
|
result = max(5, 3)
|
|
```
|
|
|
|
### Hovering works on every character in an expression
|
|
|
|
```py
|
|
def _(param: bool) -> None:
|
|
# ↓ hover: bool
|
|
# ↓ hover: bool
|
|
# ↓ hover: bool
|
|
# ↓ hover: bool
|
|
# ↓ hover: bool
|
|
result = param
|
|
```
|
|
|
|
### Hovering with unicode characters
|
|
|
|
```py
|
|
def _(café: str) -> None:
|
|
# ↓ hover: str
|
|
# ↓ hover: str
|
|
# ↓ hover: str
|
|
# ↓ hover: str
|
|
result = café
|
|
```
|
|
|
|
## Different results for `reveal_type` and `hover`
|
|
|
|
```py
|
|
from typing import overload
|
|
|
|
def f(x: dict[str, int]) -> None: ...
|
|
|
|
# revealed: dict[Unknown, Unknown]
|
|
f(reveal_type({}))
|
|
|
|
# ↓ hover: dict[str, int]
|
|
f({})
|
|
```
|
|
|
|
## Hovering on different expression types
|
|
|
|
### Literals
|
|
|
|
```py
|
|
# ↓ hover: Literal[42]
|
|
int_value = 42
|
|
|
|
# ↓ hover: Literal["test"]
|
|
string_value = "test"
|
|
|
|
# ↓ hover: Literal[True]
|
|
bool_value = True
|
|
```
|
|
|
|
### Names and attributes
|
|
|
|
```py
|
|
class MyClass:
|
|
value: int
|
|
|
|
def test_attributes(instance: MyClass) -> None:
|
|
# ↓ hover: MyClass
|
|
instance
|
|
|
|
# ↓ hover: int
|
|
instance.value
|
|
```
|
|
|
|
### Function definitions
|
|
|
|
```py
|
|
def f(x: int) -> None: ...
|
|
|
|
# ↓ hover: def f(x: int) -> None
|
|
result = f
|
|
```
|
|
|
|
### Binary operations
|
|
|
|
```py
|
|
# ↓ hover: Literal[10]
|
|
# ↓ hover: Literal[20]
|
|
result = 10 + 20
|
|
```
|
|
|
|
### Comprehensions
|
|
|
|
```py
|
|
# List comprehension
|
|
# ↓ hover: list[@Todo(list comprehension element type)]
|
|
result = [x for x in range(5)]
|
|
```
|