Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/inlay_hints/discriminant.rs')
| -rw-r--r-- | crates/ide/src/inlay_hints/discriminant.rs | 144 |
1 files changed, 77 insertions, 67 deletions
diff --git a/crates/ide/src/inlay_hints/discriminant.rs b/crates/ide/src/inlay_hints/discriminant.rs index 67eaa553ad..c4d2ac75cf 100644 --- a/crates/ide/src/inlay_hints/discriminant.rs +++ b/crates/ide/src/inlay_hints/discriminant.rs @@ -9,7 +9,8 @@ use ide_db::{base_db::FileId, famous_defs::FamousDefs, RootDatabase}; use syntax::ast::{self, AstNode, HasName}; use crate::{ - DiscriminantHints, InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind, InlayTooltip, + DiscriminantHints, InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind, + InlayTooltip, }; pub(super) fn enum_hints( @@ -19,21 +20,23 @@ pub(super) fn enum_hints( _: FileId, enum_: ast::Enum, ) -> Option<()> { - let enabled = match config.discriminant_hints { - DiscriminantHints::Always => true, - DiscriminantHints::Fieldless => { - !sema.to_def(&enum_)?.is_data_carrying(sema.db) - || enum_.variant_list()?.variants().any(|v| v.expr().is_some()) - } - DiscriminantHints::Never => false, - }; - if !enabled { + if let DiscriminantHints::Never = config.discriminant_hints { + return None; + } + + let def = sema.to_def(&enum_)?; + let data_carrying = def.is_data_carrying(sema.db); + if matches!(config.discriminant_hints, DiscriminantHints::Fieldless) && data_carrying { + return None; + } + // data carrying enums without a primitive repr have no stable discriminants + if data_carrying && def.repr(sema.db).map_or(true, |r| r.int.is_none()) { return None; } for variant in enum_.variant_list()?.variants() { variant_hints(acc, sema, &variant); } - None + Some(()) } fn variant_hints( @@ -41,10 +44,11 @@ fn variant_hints( sema: &Semantics<'_, RootDatabase>, variant: &ast::Variant, ) -> Option<()> { - if variant.eq_token().is_some() { + if variant.expr().is_some() { return None; } + let eq_token = variant.eq_token(); let name = variant.name()?; let descended = sema.descend_node_into_attributes(variant.clone()).pop(); @@ -52,34 +56,43 @@ fn variant_hints( let v = sema.to_def(desc_pat)?; let d = v.eval(sema.db); + let range = match variant.field_list() { + Some(field_list) => name.syntax().text_range().cover(field_list.syntax().text_range()), + None => name.syntax().text_range(), + }; + let eq_ = if eq_token.is_none() { " =" } else { "" }; + let label = InlayHintLabel::simple( + match d { + Ok(x) => { + if x >= 10 { + format!("{eq_} {x} ({x:#X})") + } else { + format!("{eq_} {x}") + } + } + Err(_) => format!("{eq_} ?"), + }, + Some(InlayTooltip::String(match &d { + Ok(_) => "enum variant discriminant".into(), + Err(e) => format!("{e:?}").into(), + })), + None, + ); acc.push(InlayHint { - range: match variant.field_list() { - Some(field_list) => name.syntax().text_range().cover(field_list.syntax().text_range()), - None => name.syntax().text_range(), + range: match eq_token { + Some(t) => range.cover(t.text_range()), + _ => range, }, kind: InlayKind::Discriminant, - label: InlayHintLabel::simple( - match d { - Ok(x) => { - if x >= 10 { - format!("{x} ({x:#X})") - } else { - format!("{x}") - } - } - Err(_) => "?".into(), - }, - Some(InlayTooltip::String(match &d { - Ok(_) => "enum variant discriminant".into(), - Err(e) => format!("{e:?}").into(), - })), - None, - ), + label, + text_edit: None, + position: InlayHintPosition::After, + pad_left: false, + pad_right: false, }); Some(()) } - #[cfg(test)] mod tests { use crate::inlay_hints::{ @@ -111,30 +124,30 @@ mod tests { check_discriminants( r#" enum Enum { - Variant, -//^^^^^^^0 - Variant1, -//^^^^^^^^1 - Variant2, -//^^^^^^^^2 - Variant5 = 5, - Variant6, -//^^^^^^^^6 + Variant, +// ^^^^^^^ = 0$ + Variant1, +// ^^^^^^^^ = 1$ + Variant2, +// ^^^^^^^^ = 2$ + Variant5 = 5, + Variant6, +// ^^^^^^^^ = 6$ } "#, ); check_discriminants_fieldless( r#" enum Enum { - Variant, -//^^^^^^^0 - Variant1, -//^^^^^^^^1 - Variant2, -//^^^^^^^^2 - Variant5 = 5, - Variant6, -//^^^^^^^^6 + Variant, +// ^^^^^^^ = 0 + Variant1, +// ^^^^^^^^ = 1 + Variant2, +// ^^^^^^^^ = 2 + Variant5 = 5, + Variant6, +// ^^^^^^^^ = 6 } "#, ); @@ -144,26 +157,23 @@ enum Enum { fn datacarrying_mixed() { check_discriminants( r#" +#[repr(u8)] enum Enum { Variant(), - //^^^^^^^^^0 +// ^^^^^^^^^ = 0 Variant1, - //^^^^^^^^1 +// ^^^^^^^^ = 1 Variant2 {}, - //^^^^^^^^^^^2 +// ^^^^^^^^^^^ = 2 Variant3, - //^^^^^^^^3 +// ^^^^^^^^ = 3 Variant5 = 5, Variant6, - //^^^^^^^^6 +// ^^^^^^^^ = 6 } "#, ); - } - - #[test] - fn datacarrying_mixed_fieldless_set() { - check_discriminants_fieldless( + check_discriminants( r#" enum Enum { Variant(), @@ -175,20 +185,20 @@ enum Enum { } "#, ); + } + + #[test] + fn datacarrying_mixed_fieldless_set() { check_discriminants_fieldless( r#" +#[repr(u8)] enum Enum { Variant(), - //^^^^^^^^^0 Variant1, - //^^^^^^^^1 Variant2 {}, - //^^^^^^^^^^^2 Variant3, - //^^^^^^^^3 - Variant5 = 5, + Variant5, Variant6, - //^^^^^^^^6 } "#, ); |