summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs142
1 files changed, 142 insertions, 0 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
new file mode 100644
index 000000000..f32c4bdf2
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs
@@ -0,0 +1,142 @@
+//! Implementation of "enum variant discriminant" inlay hints:
+//! ```no_run
+//! enum Foo {
+//! Bar/* = 0*/,
+//! }
+//! ```
+use ide_db::{base_db::FileId, famous_defs::FamousDefs};
+use syntax::ast::{self, AstNode, HasName};
+
+use crate::{DiscriminantHints, InlayHint, InlayHintsConfig, InlayKind, InlayTooltip};
+
+pub(super) fn hints(
+ acc: &mut Vec<InlayHint>,
+ FamousDefs(sema, _): &FamousDefs<'_, '_>,
+ config: &InlayHintsConfig,
+ _: FileId,
+ variant: &ast::Variant,
+) -> 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,
+ };
+
+ if variant.eq_token().is_some() {
+ return None;
+ }
+
+ let name = variant.name()?;
+
+ let descended = sema.descend_node_into_attributes(variant.clone()).pop();
+ let desc_pat = descended.as_ref().unwrap_or(variant);
+ let v = sema.to_def(desc_pat)?;
+ let d = v.eval(sema.db);
+
+ acc.push(InlayHint {
+ range: match 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(),
+ })),
+ });
+
+ Some(())
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::inlay_hints::{
+ tests::{check_with_config, DISABLED_CONFIG},
+ DiscriminantHints, InlayHintsConfig,
+ };
+
+ #[track_caller]
+ fn check_discriminants(ra_fixture: &str) {
+ check_with_config(
+ InlayHintsConfig { discriminant_hints: DiscriminantHints::Always, ..DISABLED_CONFIG },
+ ra_fixture,
+ );
+ }
+
+ #[track_caller]
+ fn check_discriminants_fieldless(ra_fixture: &str) {
+ check_with_config(
+ InlayHintsConfig {
+ discriminant_hints: DiscriminantHints::Fieldless,
+ ..DISABLED_CONFIG
+ },
+ ra_fixture,
+ );
+ }
+
+ #[test]
+ fn fieldless() {
+ check_discriminants(
+ r#"
+enum Enum {
+ Variant,
+ //^^^^^^^0
+ Variant1,
+ //^^^^^^^^1
+ Variant2,
+ //^^^^^^^^2
+ Variant5 = 5,
+ Variant6,
+ //^^^^^^^^6
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn datacarrying_mixed() {
+ check_discriminants(
+ r#"
+enum Enum {
+ Variant(),
+ //^^^^^^^^^0
+ Variant1,
+ //^^^^^^^^1
+ Variant2 {},
+ //^^^^^^^^^^^2
+ Variant3,
+ //^^^^^^^^3
+ Variant5 = 5,
+ Variant6,
+ //^^^^^^^^6
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn datacarrying_mixed_fieldless_set() {
+ check_discriminants_fieldless(
+ r#"
+enum Enum {
+ Variant(),
+ Variant1,
+ //^^^^^^^^1
+ Variant2 {},
+ Variant3,
+ //^^^^^^^^3
+ Variant5 = 5,
+ Variant6,
+ //^^^^^^^^6
+}
+"#,
+ );
+ }
+}