summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs')
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs108
1 files changed, 78 insertions, 30 deletions
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs
index f32c4bdf2..5dd51ad11 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs
@@ -4,27 +4,43 @@
//! Bar/* = 0*/,
//! }
//! ```
-use ide_db::{base_db::FileId, famous_defs::FamousDefs};
+use hir::Semantics;
+use ide_db::{base_db::FileId, famous_defs::FamousDefs, RootDatabase};
use syntax::ast::{self, AstNode, HasName};
-use crate::{DiscriminantHints, InlayHint, InlayHintsConfig, InlayKind, InlayTooltip};
+use crate::{
+ DiscriminantHints, InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind, InlayTooltip,
+};
-pub(super) fn hints(
+pub(super) fn enum_hints(
acc: &mut Vec<InlayHint>,
FamousDefs(sema, _): &FamousDefs<'_, '_>,
config: &InlayHintsConfig,
_: FileId,
- variant: &ast::Variant,
+ enum_: ast::Enum,
) -> Option<()> {
- let field_list = match config.discriminant_hints {
- DiscriminantHints::Always => variant.field_list(),
- DiscriminantHints::Fieldless => match variant.field_list() {
- Some(_) => return None,
- None => None,
- },
- DiscriminantHints::Never => return None,
+ 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 {
+ return None;
+ }
+ for variant in enum_.variant_list()?.variants() {
+ variant_hints(acc, sema, &variant);
+ }
+ None
+}
+fn variant_hints(
+ acc: &mut Vec<InlayHint>,
+ sema: &Semantics<'_, RootDatabase>,
+ variant: &ast::Variant,
+) -> Option<()> {
if variant.eq_token().is_some() {
return None;
}
@@ -37,19 +53,22 @@ pub(super) fn hints(
let d = v.eval(sema.db);
acc.push(InlayHint {
- range: match field_list {
+ range: match variant.field_list() {
Some(field_list) => name.syntax().text_range().cover(field_list.syntax().text_range()),
None => name.syntax().text_range(),
},
- kind: InlayKind::DiscriminantHint,
- label: match &d {
- Ok(v) => format!("{}", v).into(),
- Err(_) => "?".into(),
- },
- tooltip: Some(InlayTooltip::String(match &d {
- Ok(_) => "enum variant discriminant".into(),
- Err(e) => format!("{e:?}").into(),
- })),
+ kind: InlayKind::Discriminant,
+ label: InlayHintLabel::simple(
+ match &d {
+ Ok(v) => format!("{}", v),
+ Err(_) => "?".into(),
+ },
+ Some(InlayTooltip::String(match &d {
+ Ok(_) => "enum variant discriminant".into(),
+ Err(e) => format!("{e:?}").into(),
+ })),
+ None,
+ ),
});
Some(())
@@ -86,15 +105,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
}
"#,
);
@@ -128,8 +162,22 @@ enum Enum {
enum Enum {
Variant(),
Variant1,
+ Variant2 {},
+ Variant3,
+ Variant5,
+ Variant6,
+}
+"#,
+ );
+ check_discriminants_fieldless(
+ r#"
+enum Enum {
+ Variant(),
+ //^^^^^^^^^0
+ Variant1,
//^^^^^^^^1
Variant2 {},
+ //^^^^^^^^^^^2
Variant3,
//^^^^^^^^3
Variant5 = 5,