mirror of https://github.com/astral-sh/ruff
[ty] Add more TypeDetails to the display code (#21541)
As far as I know this change is largely non-functional, largely because of https://github.com/astral-sh/ty/issues/1601 It's possible some of these like `Type::KnownInstance` produce something useful sometimes. `LiteralString` is a new introduction, although its goto-type jumps to `str` which is a bit sad (considering that part of the SpecialForm discourse for now). Also wrt the generics testing followup: turns out the snapshot tests were full of those already.
This commit is contained in:
parent
0761ea42d9
commit
78ce17ce8f
|
|
@ -4143,6 +4143,43 @@ mod tests {
|
|||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_literal_string() {
|
||||
let mut test = inlay_hint_test(
|
||||
r#"
|
||||
from typing import LiteralString
|
||||
def my_func(x: LiteralString):
|
||||
y = x
|
||||
my_func(x="hello")"#,
|
||||
);
|
||||
|
||||
assert_snapshot!(test.inlay_hints(), @r#"
|
||||
from typing import LiteralString
|
||||
def my_func(x: LiteralString):
|
||||
y[: LiteralString] = x
|
||||
my_func(x="hello")
|
||||
---------------------------------------------
|
||||
info[inlay-hint-location]: Inlay Hint Target
|
||||
--> stdlib/builtins.pyi:915:7
|
||||
|
|
||||
914 | @disjoint_base
|
||||
915 | class str(Sequence[str]):
|
||||
| ^^^
|
||||
916 | """str(object='') -> str
|
||||
917 | str(bytes_or_buffer[, encoding[, errors]]) -> str
|
||||
|
|
||||
info: Source
|
||||
--> main2.py:4:9
|
||||
|
|
||||
2 | from typing import LiteralString
|
||||
3 | def my_func(x: LiteralString):
|
||||
4 | y[: LiteralString] = x
|
||||
| ^^^^^^^^^^^^^
|
||||
5 | my_func(x="hello")
|
||||
|
|
||||
"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_complex_parameter_combinations() {
|
||||
let mut test = inlay_hint_test(
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ use crate::types::signatures::{CallableSignature, Parameter, Parameters, Signatu
|
|||
use crate::types::tuple::TupleSpec;
|
||||
use crate::types::visitor::TypeVisitor;
|
||||
use crate::types::{
|
||||
BoundTypeVarIdentity, CallableType, IntersectionType, KnownBoundMethodType, KnownClass,
|
||||
MaterializationKind, Protocol, ProtocolInstanceType, StringLiteralType, SubclassOfInner, Type,
|
||||
UnionType, WrapperDescriptorKind, visitor,
|
||||
BoundTypeVarIdentity, CallableType, DynamicType, IntersectionType, KnownBoundMethodType,
|
||||
KnownClass, MaterializationKind, Protocol, ProtocolInstanceType, SpecialFormType,
|
||||
StringLiteralType, SubclassOfInner, Type, UnionType, WrapperDescriptorKind, visitor,
|
||||
};
|
||||
use ruff_db::parsed::parsed_module;
|
||||
|
||||
|
|
@ -470,7 +470,11 @@ impl<'db> FmtDetailed<'db> for DisplayType<'db> {
|
|||
| Type::StringLiteral(_)
|
||||
| Type::BytesLiteral(_)
|
||||
| Type::EnumLiteral(_) => {
|
||||
f.write_str("Literal[")?;
|
||||
f.with_detail(TypeDetail::Type(Type::SpecialForm(
|
||||
SpecialFormType::Literal,
|
||||
)))
|
||||
.write_str("Literal")?;
|
||||
f.write_char('[')?;
|
||||
representation.fmt_detailed(f)?;
|
||||
f.write_str("]")
|
||||
}
|
||||
|
|
@ -608,7 +612,16 @@ impl Display for DisplayRepresentation<'_> {
|
|||
impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
|
||||
fn fmt_detailed(&self, f: &mut TypeWriter<'_, '_, 'db>) -> fmt::Result {
|
||||
match self.ty {
|
||||
Type::Dynamic(dynamic) => write!(f, "{dynamic}"),
|
||||
Type::Dynamic(dynamic) => {
|
||||
if let DynamicType::Any = dynamic {
|
||||
write!(
|
||||
f.with_detail(TypeDetail::Type(Type::SpecialForm(SpecialFormType::Any))),
|
||||
"{dynamic}"
|
||||
)
|
||||
} else {
|
||||
write!(f, "{dynamic}")
|
||||
}
|
||||
}
|
||||
Type::Never => f.with_detail(TypeDetail::Type(self.ty)).write_str("Never"),
|
||||
Type::NominalInstance(instance) => {
|
||||
let class = instance.class(self.db);
|
||||
|
|
@ -638,7 +651,12 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
|
|||
.fmt_detailed(f),
|
||||
},
|
||||
Protocol::Synthesized(synthetic) => {
|
||||
f.write_str("<Protocol with members ")?;
|
||||
f.write_char('<')?;
|
||||
f.with_detail(TypeDetail::Type(Type::SpecialForm(
|
||||
SpecialFormType::Protocol,
|
||||
)))
|
||||
.write_str("Protocol")?;
|
||||
f.write_str(" with members ")?;
|
||||
let interface = synthetic.interface();
|
||||
let member_list = interface.members(self.db);
|
||||
let num_members = member_list.len();
|
||||
|
|
@ -687,8 +705,14 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
|
|||
}
|
||||
SubclassOfInner::Dynamic(dynamic) => write!(f, "type[{dynamic}]"),
|
||||
},
|
||||
Type::SpecialForm(special_form) => write!(f, "{special_form}"),
|
||||
Type::KnownInstance(known_instance) => write!(f, "{}", known_instance.repr(self.db)),
|
||||
Type::SpecialForm(special_form) => {
|
||||
write!(f.with_detail(TypeDetail::Type(self.ty)), "{special_form}")
|
||||
}
|
||||
Type::KnownInstance(known_instance) => write!(
|
||||
f.with_detail(TypeDetail::Type(self.ty)),
|
||||
"{}",
|
||||
known_instance.repr(self.db)
|
||||
),
|
||||
Type::FunctionLiteral(function) => function
|
||||
.display_with(self.db, self.settings.clone())
|
||||
.fmt_detailed(f),
|
||||
|
|
@ -724,7 +748,10 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
|
|||
signatures => {
|
||||
// TODO: How to display overloads?
|
||||
if !self.settings.multiline {
|
||||
f.write_str("Overload[")?;
|
||||
// TODO: This should ideally have a TypeDetail but we actually
|
||||
// don't have a type for @overload (we just detect the decorator)
|
||||
f.write_str("Overload")?;
|
||||
f.write_char('[')?;
|
||||
}
|
||||
let separator = if self.settings.multiline { "\n" } else { ", " };
|
||||
let mut join = f.join(separator);
|
||||
|
|
@ -815,7 +842,9 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
|
|||
Type::StringLiteral(string) => {
|
||||
write!(f, "{}", string.display_with(self.db, self.settings.clone()))
|
||||
}
|
||||
Type::LiteralString => f.write_str("LiteralString"),
|
||||
Type::LiteralString => f
|
||||
.with_detail(TypeDetail::Type(self.ty))
|
||||
.write_str("LiteralString"),
|
||||
Type::BytesLiteral(bytes) => {
|
||||
let escape = AsciiEscape::with_preferred_quote(bytes.value(self.db), Quote::Double);
|
||||
|
||||
|
|
@ -831,8 +860,12 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
|
|||
Type::TypeVar(bound_typevar) => {
|
||||
write!(f, "{}", bound_typevar.identity(self.db).display(self.db))
|
||||
}
|
||||
Type::AlwaysTruthy => f.write_str("AlwaysTruthy"),
|
||||
Type::AlwaysFalsy => f.write_str("AlwaysFalsy"),
|
||||
Type::AlwaysTruthy => f
|
||||
.with_detail(TypeDetail::Type(self.ty))
|
||||
.write_str("AlwaysTruthy"),
|
||||
Type::AlwaysFalsy => f
|
||||
.with_detail(TypeDetail::Type(self.ty))
|
||||
.write_str("AlwaysFalsy"),
|
||||
Type::BoundSuper(bound_super) => {
|
||||
f.write_str("<super: ")?;
|
||||
Type::from(bound_super.pivot_class(self.db))
|
||||
|
|
@ -845,7 +878,9 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
|
|||
f.write_str(">")
|
||||
}
|
||||
Type::TypeIs(type_is) => {
|
||||
f.write_str("TypeIs[")?;
|
||||
f.with_detail(TypeDetail::Type(Type::SpecialForm(SpecialFormType::TypeIs)))
|
||||
.write_str("TypeIs")?;
|
||||
f.write_char('[')?;
|
||||
type_is
|
||||
.return_type(self.db)
|
||||
.display_with(self.db, self.settings.singleline())
|
||||
|
|
|
|||
Loading…
Reference in New Issue