mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-20 12:35:40 +00:00
[ty] Truncate type display for long unions in some situations (#20730)
## Summary Fixes [astral-sh/ty#1307](https://github.com/astral-sh/ty/issues/1307) Unions with length <= 5 are unaffected to minimize test churn Unions with length > 5 will only display the first 3 elements + "... omitted x union elements" Here "length" is defined as the number of elements after condensation to literals Edit: we no longer truncate in revel case. Before: > info: Attempted to call union type `(def f1() -> int) | (def f2(name: str) -> int) | (def f3(a: int, b: int) -> int) | (def f4[T](x: T@f4) -> int) | Literal[5] | (Overload[() -> None, (x: str) -> str]) | (Overload[() -> None, (x: str, y: str) -> str]) | PossiblyNotCallable` After: > info: Attempted to call union type `(def f1() -> int) | (def f2(name: str) -> int) | (def f3(a: int, b: int) -> int) | ... omitted 5 union elements` The below comparisons are outdated, but left here as a reference. Before: ```reveal_type(x) # revealed: Literal[1, 2] | A | B | C | D | E | F | G``` ```reveal_type(x) # revealed: Result1A | Result1B | Result2A | Result2B | Result3 | Result4``` After: ```reveal_type(x) # revealed: Literal[1, 2] | A | B | ... omitted 5 union elements``` ```reveal_type(x) # revealed: Result1A | Result1B | Result2A | ... omitted 3 union elements``` This formatting is consistent with `crates/ty_python_semantic/src/types/call/bind.rs` line 2992 ## Test Plan Cosmetic only, covered and verified by changes in mdtest
This commit is contained in:
parent
1f1542db51
commit
f95eb90951
3 changed files with 83 additions and 12 deletions
|
|
@ -35,6 +35,8 @@ pub struct DisplaySettings<'db> {
|
|||
/// Class names that should be displayed fully qualified
|
||||
/// (e.g., `module.ClassName` instead of just `ClassName`)
|
||||
pub qualified: Rc<FxHashSet<&'db str>>,
|
||||
/// Whether long unions are displayed in full
|
||||
pub preserve_full_unions: bool,
|
||||
}
|
||||
|
||||
impl<'db> DisplaySettings<'db> {
|
||||
|
|
@ -54,6 +56,22 @@ impl<'db> DisplaySettings<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn truncate_long_unions(self) -> Self {
|
||||
Self {
|
||||
preserve_full_unions: false,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn preserve_long_unions(self) -> Self {
|
||||
Self {
|
||||
preserve_full_unions: true,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn from_possibly_ambiguous_type_pair(
|
||||
db: &'db dyn Db,
|
||||
|
|
@ -1265,6 +1283,9 @@ struct DisplayUnionType<'db> {
|
|||
settings: DisplaySettings<'db>,
|
||||
}
|
||||
|
||||
const MAX_DISPLAYED_UNION_ITEMS: usize = 5;
|
||||
const MAX_DISPLAYED_UNION_ITEMS_WHEN_ELIDED: usize = 3;
|
||||
|
||||
impl Display for DisplayUnionType<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
fn is_condensable(ty: Type<'_>) -> bool {
|
||||
|
|
@ -1286,12 +1307,35 @@ impl Display for DisplayUnionType<'_> {
|
|||
.filter(|element| is_condensable(*element))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let total_entries =
|
||||
usize::from(!condensed_types.is_empty()) + elements.len() - condensed_types.len();
|
||||
|
||||
assert_ne!(total_entries, 0);
|
||||
|
||||
let mut join = f.join(" | ");
|
||||
|
||||
let display_limit = if self.settings.preserve_full_unions {
|
||||
total_entries
|
||||
} else {
|
||||
let limit = if total_entries > MAX_DISPLAYED_UNION_ITEMS {
|
||||
MAX_DISPLAYED_UNION_ITEMS_WHEN_ELIDED
|
||||
} else {
|
||||
MAX_DISPLAYED_UNION_ITEMS
|
||||
};
|
||||
limit.min(total_entries)
|
||||
};
|
||||
|
||||
let mut condensed_types = Some(condensed_types);
|
||||
let mut displayed_entries = 0usize;
|
||||
|
||||
for element in elements {
|
||||
if displayed_entries >= display_limit {
|
||||
break;
|
||||
}
|
||||
|
||||
if is_condensable(*element) {
|
||||
if let Some(condensed_types) = condensed_types.take() {
|
||||
displayed_entries += 1;
|
||||
join.entry(&DisplayLiteralGroup {
|
||||
literals: condensed_types,
|
||||
db: self.db,
|
||||
|
|
@ -1299,6 +1343,7 @@ impl Display for DisplayUnionType<'_> {
|
|||
});
|
||||
}
|
||||
} else {
|
||||
displayed_entries += 1;
|
||||
join.entry(&DisplayMaybeParenthesizedType {
|
||||
ty: *element,
|
||||
db: self.db,
|
||||
|
|
@ -1307,6 +1352,15 @@ impl Display for DisplayUnionType<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
if !self.settings.preserve_full_unions {
|
||||
let omitted_entries = total_entries.saturating_sub(displayed_entries);
|
||||
if omitted_entries > 0 {
|
||||
join.entry(&DisplayUnionOmitted {
|
||||
count: omitted_entries,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
join.finish()?;
|
||||
|
||||
Ok(())
|
||||
|
|
@ -1319,6 +1373,21 @@ impl fmt::Debug for DisplayUnionType<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
struct DisplayUnionOmitted {
|
||||
count: usize,
|
||||
}
|
||||
|
||||
impl Display for DisplayUnionOmitted {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
let plural = if self.count == 1 {
|
||||
"element"
|
||||
} else {
|
||||
"elements"
|
||||
};
|
||||
write!(f, "... omitted {} union {}", self.count, plural)
|
||||
}
|
||||
}
|
||||
|
||||
struct DisplayLiteralGroup<'db> {
|
||||
literals: Vec<Type<'db>>,
|
||||
db: &'db dyn Db,
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ use crate::types::diagnostic::{
|
|||
report_bad_argument_to_get_protocol_members, report_bad_argument_to_protocol_interface,
|
||||
report_runtime_check_against_non_runtime_checkable_protocol,
|
||||
};
|
||||
use crate::types::display::DisplaySettings;
|
||||
use crate::types::generics::GenericContext;
|
||||
use crate::types::narrow::ClassInfoConstraintFunction;
|
||||
use crate::types::signatures::{CallableSignature, Signature};
|
||||
|
|
@ -1386,10 +1387,11 @@ impl KnownFunction {
|
|||
{
|
||||
let mut diag = builder.into_diagnostic("Revealed type");
|
||||
let span = context.span(&call_expression.arguments.args[0]);
|
||||
diag.annotate(
|
||||
Annotation::primary(span)
|
||||
.message(format_args!("`{}`", revealed_type.display(db))),
|
||||
);
|
||||
diag.annotate(Annotation::primary(span).message(format_args!(
|
||||
"`{}`",
|
||||
revealed_type
|
||||
.display_with(db, DisplaySettings::default().preserve_long_unions())
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue