Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #13832 - Veykril:discriminant-hints, r=Veykril
Enum variant discriminants hints ![image](https://user-images.githubusercontent.com/3757771/209320042-eced617a-9a47-4808-ac23-916f469dc90c.png)
bors 2023-01-02
parent 790759f · parent df8fc78 · commit 17cc78f
-rw-r--r--crates/ide/src/inlay_hints.rs15
-rw-r--r--crates/ide/src/inlay_hints/discrimant.rs142
-rw-r--r--crates/ide/src/lib.rs4
-rw-r--r--crates/ide/src/static_index.rs1
-rw-r--r--crates/rust-analyzer/src/config.rs32
-rw-r--r--crates/rust-analyzer/src/to_proto.rs5
-rw-r--r--docs/user/generated_config.adoc5
-rw-r--r--editors/code/package.json15
8 files changed, 217 insertions, 2 deletions
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 9fabc6bc4f..9ec3f7f29a 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -24,12 +24,14 @@ mod chaining;
mod param_name;
mod binding_mode;
mod bind_pat;
+mod discrimant;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct InlayHintsConfig {
pub location_links: bool,
pub render_colons: bool,
pub type_hints: bool,
+ pub discriminant_hints: DiscriminantHints,
pub parameter_hints: bool,
pub chaining_hints: bool,
pub adjustment_hints: AdjustmentHints,
@@ -52,6 +54,13 @@ pub enum ClosureReturnTypeHints {
}
#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum DiscriminantHints {
+ Always,
+ Never,
+ Fieldless,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
pub enum LifetimeElisionHints {
Always,
SkipTrivial,
@@ -76,6 +85,7 @@ pub enum InlayKind {
LifetimeHint,
ParameterHint,
TypeHint,
+ DiscriminantHint,
OpeningParenthesis,
ClosingParenthesis,
}
@@ -365,6 +375,9 @@ fn hints(
ast::Item::Const(it) => implicit_static::hints(hints, config, Either::Right(it)),
_ => None,
},
+ ast::Variant(v) => {
+ discrimant::hints(hints, famous_defs, config, file_id, &v)
+ },
// FIXME: fn-ptr type, dyn fn type, and trait object type elisions
ast::Type(_) => None,
_ => None,
@@ -418,12 +431,14 @@ mod tests {
use test_utils::extract_annotations;
use crate::inlay_hints::AdjustmentHints;
+ use crate::DiscriminantHints;
use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints};
use super::ClosureReturnTypeHints;
pub(super) const DISABLED_CONFIG: InlayHintsConfig = InlayHintsConfig {
location_links: false,
+ discriminant_hints: DiscriminantHints::Never,
render_colons: false,
type_hints: false,
parameter_hints: false,
diff --git a/crates/ide/src/inlay_hints/discrimant.rs b/crates/ide/src/inlay_hints/discrimant.rs
new file mode 100644
index 0000000000..f32c4bdf28
--- /dev/null
+++ b/crates/ide/src/inlay_hints/discrimant.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
+}
+"#,
+ );
+ }
+}
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 6698bf766a..200958a433 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -81,8 +81,8 @@ pub use crate::{
highlight_related::{HighlightRelatedConfig, HighlightedRange},
hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult},
inlay_hints::{
- AdjustmentHints, ClosureReturnTypeHints, InlayHint, InlayHintLabel, InlayHintsConfig,
- InlayKind, InlayTooltip, LifetimeElisionHints,
+ AdjustmentHints, ClosureReturnTypeHints, DiscriminantHints, InlayHint, InlayHintLabel,
+ InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
},
join_lines::JoinLinesConfig,
markup::Markup,
diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs
index b6a58f5ef5..6e31a1420e 100644
--- a/crates/ide/src/static_index.rs
+++ b/crates/ide/src/static_index.rs
@@ -108,6 +108,7 @@ impl StaticIndex<'_> {
&InlayHintsConfig {
location_links: true,
render_colons: true,
+ discriminant_hints: crate::DiscriminantHints::Fieldless,
type_hints: true,
parameter_hints: true,
chaining_hints: true,
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index ac496a7a9f..dc876720de 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -327,6 +327,8 @@ config_data! {
inlayHints_closingBraceHints_minLines: usize = "25",
/// Whether to show inlay type hints for return types of closures.
inlayHints_closureReturnTypeHints_enable: ClosureReturnTypeHintsDef = "\"never\"",
+ /// Whether to show enum variant discriminant hints.
+ inlayHints_discriminantHints_enable: DiscriminantHintsDef = "\"never\"",
/// Whether to show inlay hints for type adjustments.
inlayHints_expressionAdjustmentHints_enable: AdjustmentHintsDef = "\"never\"",
/// Whether to hide inlay hints for type adjustments outside of `unsafe` blocks.
@@ -1218,6 +1220,11 @@ impl Config {
type_hints: self.data.inlayHints_typeHints_enable,
parameter_hints: self.data.inlayHints_parameterHints_enable,
chaining_hints: self.data.inlayHints_chainingHints_enable,
+ discriminant_hints: match self.data.inlayHints_discriminantHints_enable {
+ DiscriminantHintsDef::Always => ide::DiscriminantHints::Always,
+ DiscriminantHintsDef::Never => ide::DiscriminantHints::Never,
+ DiscriminantHintsDef::Fieldless => ide::DiscriminantHints::Fieldless,
+ },
closure_return_type_hints: match self.data.inlayHints_closureReturnTypeHints_enable {
ClosureReturnTypeHintsDef::Always => ide::ClosureReturnTypeHints::Always,
ClosureReturnTypeHintsDef::Never => ide::ClosureReturnTypeHints::Never,
@@ -1579,6 +1586,7 @@ mod de_unit_v {
named_unit_variant!(skip_trivial);
named_unit_variant!(mutable);
named_unit_variant!(reborrow);
+ named_unit_variant!(fieldless);
named_unit_variant!(with_block);
}
@@ -1743,6 +1751,17 @@ enum AdjustmentHintsDef {
}
#[derive(Deserialize, Debug, Clone)]
+#[serde(untagged)]
+enum DiscriminantHintsDef {
+ #[serde(deserialize_with = "true_or_always")]
+ Always,
+ #[serde(deserialize_with = "false_or_never")]
+ Never,
+ #[serde(deserialize_with = "de_unit_v::fieldless")]
+ Fieldless,
+}
+
+#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
enum FilesWatcherDef {
Client,
@@ -2064,6 +2083,19 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
"Only show auto borrow and dereference adjustment hints."
]
},
+ "DiscriminantHintsDef" => set! {
+ "type": "string",
+ "enum": [
+ "always",
+ "never",
+ "fieldless"
+ ],
+ "enumDescriptions": [
+ "Always show all discriminant hints.",
+ "Never show discriminant hints.",
+ "Only show discriminant hints on fieldless enum variants."
+ ]
+ },
"CargoFeaturesDef" => set! {
"anyOf": [
{
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 35ced15de5..6773fc40e1 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -434,6 +434,7 @@ pub(crate) fn inlay_hint(
InlayKind::ParameterHint if render_colons => inlay_hint.label.append_str(":"),
InlayKind::TypeHint if render_colons => inlay_hint.label.prepend_str(": "),
InlayKind::ClosureReturnTypeHint => inlay_hint.label.prepend_str(" -> "),
+ InlayKind::DiscriminantHint => inlay_hint.label.prepend_str(" = "),
_ => {}
}
@@ -447,6 +448,7 @@ pub(crate) fn inlay_hint(
// after annotated thing
InlayKind::ClosureReturnTypeHint
| InlayKind::TypeHint
+ | InlayKind::DiscriminantHint
| InlayKind::ChainingHint
| InlayKind::GenericParamListHint
| InlayKind::ClosingParenthesis
@@ -457,6 +459,7 @@ pub(crate) fn inlay_hint(
InlayKind::TypeHint => !render_colons,
InlayKind::ChainingHint | InlayKind::ClosingBraceHint => true,
InlayKind::ClosingParenthesis
+ | InlayKind::DiscriminantHint
| InlayKind::OpeningParenthesis
| InlayKind::BindingModeHint
| InlayKind::ClosureReturnTypeHint
@@ -473,6 +476,7 @@ pub(crate) fn inlay_hint(
| InlayKind::GenericParamListHint
| InlayKind::AdjustmentHint
| InlayKind::TypeHint
+ | InlayKind::DiscriminantHint
| InlayKind::ClosingBraceHint => false,
InlayKind::BindingModeHint => inlay_hint.label.as_simple_str() != Some("&"),
InlayKind::ParameterHint | InlayKind::LifetimeHint => true,
@@ -483,6 +487,7 @@ pub(crate) fn inlay_hint(
Some(lsp_types::InlayHintKind::TYPE)
}
InlayKind::ClosingParenthesis
+ | InlayKind::DiscriminantHint
| InlayKind::OpeningParenthesis
| InlayKind::BindingModeHint
| InlayKind::GenericParamListHint
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index 867fd5620f..91f8e98449 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -454,6 +454,11 @@ to always show them).
--
Whether to show inlay type hints for return types of closures.
--
+[[rust-analyzer.inlayHints.discriminantHints.enable]]rust-analyzer.inlayHints.discriminantHints.enable (default: `"never"`)::
++
+--
+Whether to show enum variant discriminant hints.
+--
[[rust-analyzer.inlayHints.expressionAdjustmentHints.enable]]rust-analyzer.inlayHints.expressionAdjustmentHints.enable (default: `"never"`)::
+
--
diff --git a/editors/code/package.json b/editors/code/package.json
index fad67ce803..b45058a6cf 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -960,6 +960,21 @@
"Only show type hints for return types of closures with blocks."
]
},
+ "rust-analyzer.inlayHints.discriminantHints.enable": {
+ "markdownDescription": "Whether to show enum variant discriminant hints.",
+ "default": "never",
+ "type": "string",
+ "enum": [
+ "always",
+ "never",
+ "fieldless"
+ ],
+ "enumDescriptions": [
+ "Always show all discriminant hints.",
+ "Never show discriminant hints.",
+ "Only show discriminant hints on fieldless enum variants."
+ ]
+ },
"rust-analyzer.inlayHints.expressionAdjustmentHints.enable": {
"markdownDescription": "Whether to show inlay hints for type adjustments.",
"default": "never",