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.rs144
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
}
"#,
);