mirror of https://github.com/astral-sh/ruff
[ty] Add type definitions for `Type::SpecialForm`s (#21544)
This commit is contained in:
parent
6e84f4fd7a
commit
c4767f5aa8
|
|
@ -213,6 +213,7 @@ impl<'db> DefinitionsOrTargets<'db> {
|
|||
| ty_python_semantic::types::TypeDefinition::Function(definition)
|
||||
| ty_python_semantic::types::TypeDefinition::TypeVar(definition)
|
||||
| ty_python_semantic::types::TypeDefinition::TypeAlias(definition)
|
||||
| ty_python_semantic::types::TypeDefinition::SpecialForm(definition)
|
||||
| ty_python_semantic::types::TypeDefinition::NewType(definition) => {
|
||||
ResolvedDefinition::Definition(definition)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,134 @@ mod tests {
|
|||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_type_of_typing_dot_literal() {
|
||||
let test = cursor_test(
|
||||
r#"
|
||||
from typing import Literal
|
||||
|
||||
a<CURSOR>b = Literal
|
||||
"#,
|
||||
);
|
||||
|
||||
assert_snapshot!(test.goto_type_definition(), @r"
|
||||
info[goto-type-definition]: Type definition
|
||||
--> stdlib/typing.pyi:351:1
|
||||
|
|
||||
349 | Final: _SpecialForm
|
||||
350 |
|
||||
351 | Literal: _SpecialForm
|
||||
| ^^^^^^^
|
||||
352 | TypedDict: _SpecialForm
|
||||
|
|
||||
info: Source
|
||||
--> main.py:4:1
|
||||
|
|
||||
2 | from typing import Literal
|
||||
3 |
|
||||
4 | ab = Literal
|
||||
| ^^
|
||||
|
|
||||
");
|
||||
}
|
||||
|
||||
// this is a slightly different case to the one above,
|
||||
// since `Any` is a class in typeshed rather than a variable
|
||||
#[test]
|
||||
fn goto_type_of_typing_dot_any() {
|
||||
let test = cursor_test(
|
||||
r#"
|
||||
from typing import Any
|
||||
|
||||
a<CURSOR>b = Any
|
||||
"#,
|
||||
);
|
||||
|
||||
assert_snapshot!(test.goto_type_definition(), @r#"
|
||||
info[goto-type-definition]: Type definition
|
||||
--> stdlib/typing.pyi:166:7
|
||||
|
|
||||
164 | # from _typeshed import AnnotationForm
|
||||
165 |
|
||||
166 | class Any:
|
||||
| ^^^
|
||||
167 | """Special type indicating an unconstrained type.
|
||||
|
|
||||
info: Source
|
||||
--> main.py:4:1
|
||||
|
|
||||
2 | from typing import Any
|
||||
3 |
|
||||
4 | ab = Any
|
||||
| ^^
|
||||
|
|
||||
"#);
|
||||
}
|
||||
|
||||
// Similarly, `Generic` is a `type[]` type in typeshed
|
||||
#[test]
|
||||
fn goto_type_of_typing_dot_generic() {
|
||||
let test = cursor_test(
|
||||
r#"
|
||||
from typing import Generic
|
||||
|
||||
a<CURSOR>b = Generic
|
||||
"#,
|
||||
);
|
||||
|
||||
assert_snapshot!(test.goto_type_definition(), @r"
|
||||
info[goto-type-definition]: Type definition
|
||||
--> stdlib/typing.pyi:770:1
|
||||
|
|
||||
768 | def __class_getitem__(cls, args: TypeVar | tuple[TypeVar, ...]) -> _Final: ...
|
||||
769 |
|
||||
770 | Generic: type[_Generic]
|
||||
| ^^^^^^^
|
||||
771 |
|
||||
772 | class _ProtocolMeta(ABCMeta):
|
||||
|
|
||||
info: Source
|
||||
--> main.py:4:1
|
||||
|
|
||||
2 | from typing import Generic
|
||||
3 |
|
||||
4 | ab = Generic
|
||||
| ^^
|
||||
|
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_type_of_ty_extensions_special_form() {
|
||||
let test = cursor_test(
|
||||
r#"
|
||||
from ty_extensions import AlwaysTruthy
|
||||
|
||||
a<CURSOR>b = AlwaysTruthy
|
||||
"#,
|
||||
);
|
||||
|
||||
assert_snapshot!(test.goto_type_definition(), @r"
|
||||
info[goto-type-definition]: Type definition
|
||||
--> stdlib/ty_extensions.pyi:21:1
|
||||
|
|
||||
19 | # Types
|
||||
20 | Unknown = object()
|
||||
21 | AlwaysTruthy = object()
|
||||
| ^^^^^^^^^^^^
|
||||
22 | AlwaysFalsy = object()
|
||||
|
|
||||
info: Source
|
||||
--> main.py:4:1
|
||||
|
|
||||
2 | from ty_extensions import AlwaysTruthy
|
||||
3 |
|
||||
4 | ab = AlwaysTruthy
|
||||
| ^^
|
||||
|
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_type_of_expression_with_function_type() {
|
||||
let test = cursor_test(
|
||||
|
|
|
|||
|
|
@ -601,6 +601,25 @@ mod tests {
|
|||
w[: int] = z
|
||||
|
||||
---------------------------------------------
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/typing.pyi:351:1
|
||||
|
|
||||
349 | Final: _SpecialForm
|
||||
350 |
|
||||
351 | Literal: _SpecialForm
|
||||
| ^^^^^^^
|
||||
352 | TypedDict: _SpecialForm
|
||||
|
|
||||
info: Source
|
||||
--> main2.py:6:5
|
||||
|
|
||||
5 | x = 1
|
||||
6 | y[: Literal[1]] = x
|
||||
| ^^^^^^^
|
||||
7 | z[: int] = i(1)
|
||||
8 | w[: int] = z
|
||||
|
|
||||
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/builtins.pyi:348:7
|
||||
|
|
||||
|
|
@ -668,6 +687,44 @@ mod tests {
|
|||
x4[: int], y4[: str] = (x3, y3)
|
||||
|
||||
---------------------------------------------
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/typing.pyi:351:1
|
||||
|
|
||||
349 | Final: _SpecialForm
|
||||
350 |
|
||||
351 | Literal: _SpecialForm
|
||||
| ^^^^^^^
|
||||
352 | TypedDict: _SpecialForm
|
||||
|
|
||||
info: Source
|
||||
--> main2.py:8:6
|
||||
|
|
||||
7 | x1, y1 = (1, 'abc')
|
||||
8 | x2[: Literal[1]], y2[: Literal["abc"]] = (x1, y1)
|
||||
| ^^^^^^^
|
||||
9 | x3[: int], y3[: str] = (i(1), s('abc'))
|
||||
10 | x4[: int], y4[: str] = (x3, y3)
|
||||
|
|
||||
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/typing.pyi:351:1
|
||||
|
|
||||
349 | Final: _SpecialForm
|
||||
350 |
|
||||
351 | Literal: _SpecialForm
|
||||
| ^^^^^^^
|
||||
352 | TypedDict: _SpecialForm
|
||||
|
|
||||
info: Source
|
||||
--> main2.py:8:24
|
||||
|
|
||||
7 | x1, y1 = (1, 'abc')
|
||||
8 | x2[: Literal[1]], y2[: Literal["abc"]] = (x1, y1)
|
||||
| ^^^^^^^
|
||||
9 | x3[: int], y3[: str] = (i(1), s('abc'))
|
||||
10 | x4[: int], y4[: str] = (x3, y3)
|
||||
|
|
||||
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/builtins.pyi:348:7
|
||||
|
|
||||
|
|
@ -772,6 +829,44 @@ mod tests {
|
|||
x4[: int], y4[: str] = x3, y3
|
||||
|
||||
---------------------------------------------
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/typing.pyi:351:1
|
||||
|
|
||||
349 | Final: _SpecialForm
|
||||
350 |
|
||||
351 | Literal: _SpecialForm
|
||||
| ^^^^^^^
|
||||
352 | TypedDict: _SpecialForm
|
||||
|
|
||||
info: Source
|
||||
--> main2.py:8:6
|
||||
|
|
||||
7 | x1, y1 = 1, 'abc'
|
||||
8 | x2[: Literal[1]], y2[: Literal["abc"]] = x1, y1
|
||||
| ^^^^^^^
|
||||
9 | x3[: int], y3[: str] = i(1), s('abc')
|
||||
10 | x4[: int], y4[: str] = x3, y3
|
||||
|
|
||||
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/typing.pyi:351:1
|
||||
|
|
||||
349 | Final: _SpecialForm
|
||||
350 |
|
||||
351 | Literal: _SpecialForm
|
||||
| ^^^^^^^
|
||||
352 | TypedDict: _SpecialForm
|
||||
|
|
||||
info: Source
|
||||
--> main2.py:8:24
|
||||
|
|
||||
7 | x1, y1 = 1, 'abc'
|
||||
8 | x2[: Literal[1]], y2[: Literal["abc"]] = x1, y1
|
||||
| ^^^^^^^
|
||||
9 | x3[: int], y3[: str] = i(1), s('abc')
|
||||
10 | x4[: int], y4[: str] = x3, y3
|
||||
|
|
||||
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/builtins.pyi:348:7
|
||||
|
|
||||
|
|
@ -876,6 +971,44 @@ mod tests {
|
|||
w[: tuple[int, str]] = z
|
||||
|
||||
---------------------------------------------
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/typing.pyi:351:1
|
||||
|
|
||||
349 | Final: _SpecialForm
|
||||
350 |
|
||||
351 | Literal: _SpecialForm
|
||||
| ^^^^^^^
|
||||
352 | TypedDict: _SpecialForm
|
||||
|
|
||||
info: Source
|
||||
--> main2.py:8:11
|
||||
|
|
||||
7 | x = (1, 'abc')
|
||||
8 | y[: tuple[Literal[1], Literal["abc"]]] = x
|
||||
| ^^^^^^^
|
||||
9 | z[: tuple[int, str]] = (i(1), s('abc'))
|
||||
10 | w[: tuple[int, str]] = z
|
||||
|
|
||||
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/typing.pyi:351:1
|
||||
|
|
||||
349 | Final: _SpecialForm
|
||||
350 |
|
||||
351 | Literal: _SpecialForm
|
||||
| ^^^^^^^
|
||||
352 | TypedDict: _SpecialForm
|
||||
|
|
||||
info: Source
|
||||
--> main2.py:8:23
|
||||
|
|
||||
7 | x = (1, 'abc')
|
||||
8 | y[: tuple[Literal[1], Literal["abc"]]] = x
|
||||
| ^^^^^^^
|
||||
9 | z[: tuple[int, str]] = (i(1), s('abc'))
|
||||
10 | w[: tuple[int, str]] = z
|
||||
|
|
||||
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/builtins.pyi:348:7
|
||||
|
|
||||
|
|
@ -978,6 +1111,63 @@ mod tests {
|
|||
x3[: int], (y3[: str], z3[: int]) = (i(1), (s('abc'), i(2)))
|
||||
x4[: int], (y4[: str], z4[: int]) = (x3, (y3, z3))
|
||||
---------------------------------------------
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/typing.pyi:351:1
|
||||
|
|
||||
349 | Final: _SpecialForm
|
||||
350 |
|
||||
351 | Literal: _SpecialForm
|
||||
| ^^^^^^^
|
||||
352 | TypedDict: _SpecialForm
|
||||
|
|
||||
info: Source
|
||||
--> main2.py:8:6
|
||||
|
|
||||
7 | x1, (y1, z1) = (1, ('abc', 2))
|
||||
8 | x2[: Literal[1]], (y2[: Literal["abc"]], z2[: Literal[2]]) = (x1, (y1, z1))
|
||||
| ^^^^^^^
|
||||
9 | x3[: int], (y3[: str], z3[: int]) = (i(1), (s('abc'), i(2)))
|
||||
10 | x4[: int], (y4[: str], z4[: int]) = (x3, (y3, z3))
|
||||
|
|
||||
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/typing.pyi:351:1
|
||||
|
|
||||
349 | Final: _SpecialForm
|
||||
350 |
|
||||
351 | Literal: _SpecialForm
|
||||
| ^^^^^^^
|
||||
352 | TypedDict: _SpecialForm
|
||||
|
|
||||
info: Source
|
||||
--> main2.py:8:25
|
||||
|
|
||||
7 | x1, (y1, z1) = (1, ('abc', 2))
|
||||
8 | x2[: Literal[1]], (y2[: Literal["abc"]], z2[: Literal[2]]) = (x1, (y1, z1))
|
||||
| ^^^^^^^
|
||||
9 | x3[: int], (y3[: str], z3[: int]) = (i(1), (s('abc'), i(2)))
|
||||
10 | x4[: int], (y4[: str], z4[: int]) = (x3, (y3, z3))
|
||||
|
|
||||
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/typing.pyi:351:1
|
||||
|
|
||||
349 | Final: _SpecialForm
|
||||
350 |
|
||||
351 | Literal: _SpecialForm
|
||||
| ^^^^^^^
|
||||
352 | TypedDict: _SpecialForm
|
||||
|
|
||||
info: Source
|
||||
--> main2.py:8:47
|
||||
|
|
||||
7 | x1, (y1, z1) = (1, ('abc', 2))
|
||||
8 | x2[: Literal[1]], (y2[: Literal["abc"]], z2[: Literal[2]]) = (x1, (y1, z1))
|
||||
| ^^^^^^^
|
||||
9 | x3[: int], (y3[: str], z3[: int]) = (i(1), (s('abc'), i(2)))
|
||||
10 | x4[: int], (y4[: str], z4[: int]) = (x3, (y3, z3))
|
||||
|
|
||||
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/builtins.pyi:348:7
|
||||
|
|
||||
|
|
@ -1113,6 +1303,25 @@ mod tests {
|
|||
z: int = i(1)
|
||||
w[: int] = z
|
||||
---------------------------------------------
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/typing.pyi:351:1
|
||||
|
|
||||
349 | Final: _SpecialForm
|
||||
350 |
|
||||
351 | Literal: _SpecialForm
|
||||
| ^^^^^^^
|
||||
352 | TypedDict: _SpecialForm
|
||||
|
|
||||
info: Source
|
||||
--> main2.py:6:5
|
||||
|
|
||||
5 | x: int = 1
|
||||
6 | y[: Literal[1]] = x
|
||||
| ^^^^^^^
|
||||
7 | z: int = i(1)
|
||||
8 | w[: int] = z
|
||||
|
|
||||
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/builtins.pyi:348:7
|
||||
|
|
||||
|
|
|
|||
|
|
@ -1109,7 +1109,7 @@ from typing import List, Dict
|
|||
# error: [invalid-type-form] "Int literals are not allowed in this context in a type expression"
|
||||
InvalidList = List[1]
|
||||
|
||||
# error: [invalid-type-form] "`typing.typing.List` requires exactly one argument"
|
||||
# error: [invalid-type-form] "`typing.List` requires exactly one argument"
|
||||
ListTooManyArgs = List[int, str]
|
||||
|
||||
# error: [invalid-type-form] "Int literals are not allowed in this context in a type expression"
|
||||
|
|
@ -1118,10 +1118,10 @@ InvalidDict1 = Dict[1, str]
|
|||
# error: [invalid-type-form] "Int literals are not allowed in this context in a type expression"
|
||||
InvalidDict2 = Dict[str, 2]
|
||||
|
||||
# error: [invalid-type-form] "`typing.typing.Dict` requires exactly two arguments, got 1"
|
||||
# error: [invalid-type-form] "`typing.Dict` requires exactly two arguments, got 1"
|
||||
DictTooFewArgs = Dict[str]
|
||||
|
||||
# error: [invalid-type-form] "`typing.typing.Dict` requires exactly two arguments, got 3"
|
||||
# error: [invalid-type-form] "`typing.Dict` requires exactly two arguments, got 3"
|
||||
DictTooManyArgs = Dict[str, int, float]
|
||||
|
||||
def _(
|
||||
|
|
|
|||
|
|
@ -7503,7 +7503,7 @@ impl<'db> Type<'db> {
|
|||
name = enum_literal.name(db)
|
||||
),
|
||||
),
|
||||
Type::SpecialForm(special_form) => Type::string_literal(db, special_form.repr()),
|
||||
Type::SpecialForm(special_form) => Type::string_literal(db, &special_form.to_string()),
|
||||
Type::KnownInstance(known_instance) => Type::StringLiteral(StringLiteralType::new(
|
||||
db,
|
||||
known_instance.repr(db).to_compact_string(),
|
||||
|
|
@ -7525,7 +7525,7 @@ impl<'db> Type<'db> {
|
|||
Type::string_literal(db, &format!("'{}'", literal.value(db).escape_default()))
|
||||
}
|
||||
Type::LiteralString => Type::LiteralString,
|
||||
Type::SpecialForm(special_form) => Type::string_literal(db, special_form.repr()),
|
||||
Type::SpecialForm(special_form) => Type::string_literal(db, &special_form.to_string()),
|
||||
Type::KnownInstance(known_instance) => Type::StringLiteral(StringLiteralType::new(
|
||||
db,
|
||||
known_instance.repr(db).to_compact_string(),
|
||||
|
|
@ -7604,13 +7604,14 @@ impl<'db> Type<'db> {
|
|||
|
||||
Self::Union(_) | Self::Intersection(_) => None,
|
||||
|
||||
Self::SpecialForm(special_form) => special_form.definition(db),
|
||||
|
||||
// These types have no definition
|
||||
Self::Dynamic(_)
|
||||
| Self::Never
|
||||
| Self::Callable(_)
|
||||
| Self::AlwaysTruthy
|
||||
| Self::AlwaysFalsy
|
||||
| Self::SpecialForm(_)
|
||||
| Self::TypeIs(_) => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4828,7 +4828,7 @@ impl KnownClass {
|
|||
}
|
||||
|
||||
/// Return the module in which we should look up the definition for this class
|
||||
fn canonical_module(self, db: &dyn Db) -> KnownModule {
|
||||
pub(super) fn canonical_module(self, db: &dyn Db) -> KnownModule {
|
||||
match self {
|
||||
Self::Bool
|
||||
| Self::Object
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ pub enum TypeDefinition<'db> {
|
|||
TypeVar(Definition<'db>),
|
||||
TypeAlias(Definition<'db>),
|
||||
NewType(Definition<'db>),
|
||||
SpecialForm(Definition<'db>),
|
||||
}
|
||||
|
||||
impl TypeDefinition<'_> {
|
||||
|
|
@ -23,6 +24,7 @@ impl TypeDefinition<'_> {
|
|||
| Self::Function(definition)
|
||||
| Self::TypeVar(definition)
|
||||
| Self::TypeAlias(definition)
|
||||
| Self::SpecialForm(definition)
|
||||
| Self::NewType(definition) => {
|
||||
let module = parsed_module(db, definition.file(db)).load(db);
|
||||
Some(definition.focus_range(db, &module))
|
||||
|
|
@ -41,6 +43,7 @@ impl TypeDefinition<'_> {
|
|||
| Self::Function(definition)
|
||||
| Self::TypeVar(definition)
|
||||
| Self::TypeAlias(definition)
|
||||
| Self::SpecialForm(definition)
|
||||
| Self::NewType(definition) => {
|
||||
let module = parsed_module(db, definition.file(db)).load(db);
|
||||
Some(definition.full_range(db, &module))
|
||||
|
|
|
|||
|
|
@ -10872,7 +10872,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
||||
builder.into_diagnostic(format_args!(
|
||||
"`typing.{}` requires exactly one argument",
|
||||
special_form.repr()
|
||||
special_form.name()
|
||||
));
|
||||
}
|
||||
Type::unknown()
|
||||
|
|
@ -10907,7 +10907,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
{
|
||||
builder.into_diagnostic(format_args!(
|
||||
"`typing.{}` requires exactly two arguments, got {}",
|
||||
special_form.repr(),
|
||||
special_form.name(),
|
||||
arguments.len()
|
||||
));
|
||||
}
|
||||
|
|
@ -10931,7 +10931,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
||||
builder.into_diagnostic(format_args!(
|
||||
"`typing.{}` requires exactly two arguments, got 1",
|
||||
special_form.repr()
|
||||
special_form.name()
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1318,10 +1318,9 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
|
|||
self.infer_type_expression(arguments_slice);
|
||||
|
||||
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
||||
let diag = builder.into_diagnostic(format_args!(
|
||||
"Special form `{}` expected exactly one type parameter",
|
||||
special_form.repr()
|
||||
));
|
||||
let diag = builder.into_diagnostic(
|
||||
"Special form `typing.TypeIs` expected exactly one type parameter",
|
||||
);
|
||||
diagnostic::add_type_expression_reference_link(diag);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@
|
|||
use super::{ClassType, Type, class::KnownClass};
|
||||
use crate::db::Db;
|
||||
use crate::module_resolver::{KnownModule, file_to_module};
|
||||
use crate::resolve_module;
|
||||
use crate::semantic_index::place::ScopedPlaceId;
|
||||
use crate::semantic_index::{FileScopeId, place_table, use_def_map};
|
||||
use crate::types::TypeDefinition;
|
||||
use ruff_db::files::File;
|
||||
use std::str::FromStr;
|
||||
|
||||
|
|
@ -435,59 +439,132 @@ impl SpecialFormType {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return the repr of the symbol at runtime
|
||||
pub(super) const fn repr(self) -> &'static str {
|
||||
/// Return the name of the symbol at runtime
|
||||
pub(super) const fn name(self) -> &'static str {
|
||||
match self {
|
||||
SpecialFormType::Any => "typing.Any",
|
||||
SpecialFormType::Annotated => "typing.Annotated",
|
||||
SpecialFormType::Literal => "typing.Literal",
|
||||
SpecialFormType::LiteralString => "typing.LiteralString",
|
||||
SpecialFormType::Optional => "typing.Optional",
|
||||
SpecialFormType::Union => "typing.Union",
|
||||
SpecialFormType::NoReturn => "typing.NoReturn",
|
||||
SpecialFormType::Never => "typing.Never",
|
||||
SpecialFormType::Tuple => "typing.Tuple",
|
||||
SpecialFormType::Type => "typing.Type",
|
||||
SpecialFormType::TypingSelf => "typing.Self",
|
||||
SpecialFormType::Final => "typing.Final",
|
||||
SpecialFormType::ClassVar => "typing.ClassVar",
|
||||
SpecialFormType::Callable => "typing.Callable",
|
||||
SpecialFormType::Concatenate => "typing.Concatenate",
|
||||
SpecialFormType::Unpack => "typing.Unpack",
|
||||
SpecialFormType::Required => "typing.Required",
|
||||
SpecialFormType::NotRequired => "typing.NotRequired",
|
||||
SpecialFormType::TypeAlias => "typing.TypeAlias",
|
||||
SpecialFormType::TypeGuard => "typing.TypeGuard",
|
||||
SpecialFormType::TypedDict => "typing.TypedDict",
|
||||
SpecialFormType::TypeIs => "typing.TypeIs",
|
||||
SpecialFormType::List => "typing.List",
|
||||
SpecialFormType::Dict => "typing.Dict",
|
||||
SpecialFormType::DefaultDict => "typing.DefaultDict",
|
||||
SpecialFormType::Set => "typing.Set",
|
||||
SpecialFormType::FrozenSet => "typing.FrozenSet",
|
||||
SpecialFormType::Counter => "typing.Counter",
|
||||
SpecialFormType::Deque => "typing.Deque",
|
||||
SpecialFormType::ChainMap => "typing.ChainMap",
|
||||
SpecialFormType::OrderedDict => "typing.OrderedDict",
|
||||
SpecialFormType::ReadOnly => "typing.ReadOnly",
|
||||
SpecialFormType::Unknown => "ty_extensions.Unknown",
|
||||
SpecialFormType::AlwaysTruthy => "ty_extensions.AlwaysTruthy",
|
||||
SpecialFormType::AlwaysFalsy => "ty_extensions.AlwaysFalsy",
|
||||
SpecialFormType::Not => "ty_extensions.Not",
|
||||
SpecialFormType::Intersection => "ty_extensions.Intersection",
|
||||
SpecialFormType::TypeOf => "ty_extensions.TypeOf",
|
||||
SpecialFormType::CallableTypeOf => "ty_extensions.CallableTypeOf",
|
||||
SpecialFormType::Top => "ty_extensions.Top",
|
||||
SpecialFormType::Bottom => "ty_extensions.Bottom",
|
||||
SpecialFormType::Protocol => "typing.Protocol",
|
||||
SpecialFormType::Generic => "typing.Generic",
|
||||
SpecialFormType::NamedTuple => "typing.NamedTuple",
|
||||
SpecialFormType::Any => "Any",
|
||||
SpecialFormType::Annotated => "Annotated",
|
||||
SpecialFormType::Literal => "Literal",
|
||||
SpecialFormType::LiteralString => "LiteralString",
|
||||
SpecialFormType::Optional => "Optional",
|
||||
SpecialFormType::Union => "Union",
|
||||
SpecialFormType::NoReturn => "NoReturn",
|
||||
SpecialFormType::Never => "Never",
|
||||
SpecialFormType::Tuple => "Tuple",
|
||||
SpecialFormType::Type => "Type",
|
||||
SpecialFormType::TypingSelf => "Self",
|
||||
SpecialFormType::Final => "Final",
|
||||
SpecialFormType::ClassVar => "ClassVar",
|
||||
SpecialFormType::Callable => "Callable",
|
||||
SpecialFormType::Concatenate => "Concatenate",
|
||||
SpecialFormType::Unpack => "Unpack",
|
||||
SpecialFormType::Required => "Required",
|
||||
SpecialFormType::NotRequired => "NotRequired",
|
||||
SpecialFormType::TypeAlias => "TypeAlias",
|
||||
SpecialFormType::TypeGuard => "TypeGuard",
|
||||
SpecialFormType::TypedDict => "TypedDict",
|
||||
SpecialFormType::TypeIs => "TypeIs",
|
||||
SpecialFormType::List => "List",
|
||||
SpecialFormType::Dict => "Dict",
|
||||
SpecialFormType::DefaultDict => "DefaultDict",
|
||||
SpecialFormType::Set => "Set",
|
||||
SpecialFormType::FrozenSet => "FrozenSet",
|
||||
SpecialFormType::Counter => "Counter",
|
||||
SpecialFormType::Deque => "Deque",
|
||||
SpecialFormType::ChainMap => "ChainMap",
|
||||
SpecialFormType::OrderedDict => "OrderedDict",
|
||||
SpecialFormType::ReadOnly => "ReadOnly",
|
||||
SpecialFormType::Unknown => "Unknown",
|
||||
SpecialFormType::AlwaysTruthy => "AlwaysTruthy",
|
||||
SpecialFormType::AlwaysFalsy => "AlwaysFalsy",
|
||||
SpecialFormType::Not => "Not",
|
||||
SpecialFormType::Intersection => "Intersection",
|
||||
SpecialFormType::TypeOf => "TypeOf",
|
||||
SpecialFormType::CallableTypeOf => "CallableTypeOf",
|
||||
SpecialFormType::Top => "Top",
|
||||
SpecialFormType::Bottom => "Bottom",
|
||||
SpecialFormType::Protocol => "Protocol",
|
||||
SpecialFormType::Generic => "Generic",
|
||||
SpecialFormType::NamedTuple => "NamedTuple",
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the module(s) in which this special form could be defined
|
||||
fn definition_modules(self) -> &'static [KnownModule] {
|
||||
match self {
|
||||
SpecialFormType::Any
|
||||
| SpecialFormType::Annotated
|
||||
| SpecialFormType::Literal
|
||||
| SpecialFormType::LiteralString
|
||||
| SpecialFormType::Optional
|
||||
| SpecialFormType::Union
|
||||
| SpecialFormType::NoReturn
|
||||
| SpecialFormType::Never
|
||||
| SpecialFormType::Tuple
|
||||
| SpecialFormType::Type
|
||||
| SpecialFormType::TypingSelf
|
||||
| SpecialFormType::Final
|
||||
| SpecialFormType::ClassVar
|
||||
| SpecialFormType::Callable
|
||||
| SpecialFormType::Concatenate
|
||||
| SpecialFormType::Unpack
|
||||
| SpecialFormType::Required
|
||||
| SpecialFormType::NotRequired
|
||||
| SpecialFormType::TypeAlias
|
||||
| SpecialFormType::TypeGuard
|
||||
| SpecialFormType::TypedDict
|
||||
| SpecialFormType::TypeIs
|
||||
| SpecialFormType::ReadOnly
|
||||
| SpecialFormType::Protocol
|
||||
| SpecialFormType::Generic
|
||||
| SpecialFormType::NamedTuple
|
||||
| SpecialFormType::List
|
||||
| SpecialFormType::Dict
|
||||
| SpecialFormType::DefaultDict
|
||||
| SpecialFormType::Set
|
||||
| SpecialFormType::FrozenSet
|
||||
| SpecialFormType::Counter
|
||||
| SpecialFormType::Deque
|
||||
| SpecialFormType::ChainMap
|
||||
| SpecialFormType::OrderedDict => &[KnownModule::Typing, KnownModule::TypingExtensions],
|
||||
|
||||
SpecialFormType::Unknown
|
||||
| SpecialFormType::AlwaysTruthy
|
||||
| SpecialFormType::AlwaysFalsy
|
||||
| SpecialFormType::Not
|
||||
| SpecialFormType::Intersection
|
||||
| SpecialFormType::TypeOf
|
||||
| SpecialFormType::CallableTypeOf
|
||||
| SpecialFormType::Top
|
||||
| SpecialFormType::Bottom => &[KnownModule::TyExtensions],
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn definition(self, db: &dyn Db) -> Option<TypeDefinition<'_>> {
|
||||
self.definition_modules()
|
||||
.iter()
|
||||
.find_map(|module| {
|
||||
let file = resolve_module(db, &module.name())?.file(db)?;
|
||||
let scope = FileScopeId::global().to_scope_id(db, file);
|
||||
let symbol_id = place_table(db, scope).symbol_id(self.name())?;
|
||||
|
||||
use_def_map(db, scope)
|
||||
.end_of_scope_bindings(ScopedPlaceId::Symbol(symbol_id))
|
||||
.next()?
|
||||
.binding
|
||||
.definition()
|
||||
})
|
||||
.map(TypeDefinition::SpecialForm)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for SpecialFormType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(self.repr())
|
||||
write!(
|
||||
f,
|
||||
"{}.{}",
|
||||
self.definition_modules()[0].as_str(),
|
||||
self.name()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue