ruff/crates/ty_python_semantic/resources/mdtest/hover.md

3.1 KiB

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.)

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:

#       ↓ 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

def _(param: bool) -> None:
    #        ↓ hover: bool
    #         ↓ hover: bool
    #          ↓ hover: bool
    #           ↓ hover: bool
    #            ↓ hover: bool
    result = param

Hovering with unicode characters

def _(café: str) -> None:
    #        ↓ hover: str
    #         ↓ hover: str
    #          ↓ hover: str
    #           ↓ hover: str
    result = café

Different results for reveal_type and hover

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

#           ↓ hover: Literal[42]
int_value = 42

#              ↓ hover: Literal["test"]
string_value = "test"

#            ↓ hover: Literal[True]
bool_value = True

Names and attributes

class MyClass:
    value: int

def test_attributes(instance: MyClass) -> None:
    # ↓ hover: MyClass
    instance

    #        ↓ hover: int
    instance.value

Function definitions

def f(x: int) -> None: ...

#        ↓ hover: def f(x: int) -> None
result = f

Binary operations

#        ↓ hover: Literal[10]
#             ↓ hover: Literal[20]
result = 10 + 20

Comprehensions

# List comprehension
#        ↓ hover: list[@Todo(list comprehension element type)]
result = [x for x in range(5)]