mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Enum variant discriminants hints
This commit is contained in:
parent
b48a1ae004
commit
df8fc78ece
8 changed files with 217 additions and 2 deletions
|
@ -24,12 +24,14 @@ mod chaining;
|
||||||
mod param_name;
|
mod param_name;
|
||||||
mod binding_mode;
|
mod binding_mode;
|
||||||
mod bind_pat;
|
mod bind_pat;
|
||||||
|
mod discrimant;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct InlayHintsConfig {
|
pub struct InlayHintsConfig {
|
||||||
pub location_links: bool,
|
pub location_links: bool,
|
||||||
pub render_colons: bool,
|
pub render_colons: bool,
|
||||||
pub type_hints: bool,
|
pub type_hints: bool,
|
||||||
|
pub discriminant_hints: DiscriminantHints,
|
||||||
pub parameter_hints: bool,
|
pub parameter_hints: bool,
|
||||||
pub chaining_hints: bool,
|
pub chaining_hints: bool,
|
||||||
pub adjustment_hints: AdjustmentHints,
|
pub adjustment_hints: AdjustmentHints,
|
||||||
|
@ -51,6 +53,13 @@ pub enum ClosureReturnTypeHints {
|
||||||
Never,
|
Never,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum DiscriminantHints {
|
||||||
|
Always,
|
||||||
|
Never,
|
||||||
|
Fieldless,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum LifetimeElisionHints {
|
pub enum LifetimeElisionHints {
|
||||||
Always,
|
Always,
|
||||||
|
@ -76,6 +85,7 @@ pub enum InlayKind {
|
||||||
LifetimeHint,
|
LifetimeHint,
|
||||||
ParameterHint,
|
ParameterHint,
|
||||||
TypeHint,
|
TypeHint,
|
||||||
|
DiscriminantHint,
|
||||||
OpeningParenthesis,
|
OpeningParenthesis,
|
||||||
ClosingParenthesis,
|
ClosingParenthesis,
|
||||||
}
|
}
|
||||||
|
@ -365,6 +375,9 @@ fn hints(
|
||||||
ast::Item::Const(it) => implicit_static::hints(hints, config, Either::Right(it)),
|
ast::Item::Const(it) => implicit_static::hints(hints, config, Either::Right(it)),
|
||||||
_ => None,
|
_ => 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
|
// FIXME: fn-ptr type, dyn fn type, and trait object type elisions
|
||||||
ast::Type(_) => None,
|
ast::Type(_) => None,
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -418,12 +431,14 @@ mod tests {
|
||||||
use test_utils::extract_annotations;
|
use test_utils::extract_annotations;
|
||||||
|
|
||||||
use crate::inlay_hints::AdjustmentHints;
|
use crate::inlay_hints::AdjustmentHints;
|
||||||
|
use crate::DiscriminantHints;
|
||||||
use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints};
|
use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints};
|
||||||
|
|
||||||
use super::ClosureReturnTypeHints;
|
use super::ClosureReturnTypeHints;
|
||||||
|
|
||||||
pub(super) const DISABLED_CONFIG: InlayHintsConfig = InlayHintsConfig {
|
pub(super) const DISABLED_CONFIG: InlayHintsConfig = InlayHintsConfig {
|
||||||
location_links: false,
|
location_links: false,
|
||||||
|
discriminant_hints: DiscriminantHints::Never,
|
||||||
render_colons: false,
|
render_colons: false,
|
||||||
type_hints: false,
|
type_hints: false,
|
||||||
parameter_hints: false,
|
parameter_hints: false,
|
||||||
|
|
142
crates/ide/src/inlay_hints/discrimant.rs
Normal file
142
crates/ide/src/inlay_hints/discrimant.rs
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -81,8 +81,8 @@ pub use crate::{
|
||||||
highlight_related::{HighlightRelatedConfig, HighlightedRange},
|
highlight_related::{HighlightRelatedConfig, HighlightedRange},
|
||||||
hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult},
|
hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult},
|
||||||
inlay_hints::{
|
inlay_hints::{
|
||||||
AdjustmentHints, ClosureReturnTypeHints, InlayHint, InlayHintLabel, InlayHintsConfig,
|
AdjustmentHints, ClosureReturnTypeHints, DiscriminantHints, InlayHint, InlayHintLabel,
|
||||||
InlayKind, InlayTooltip, LifetimeElisionHints,
|
InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
|
||||||
},
|
},
|
||||||
join_lines::JoinLinesConfig,
|
join_lines::JoinLinesConfig,
|
||||||
markup::Markup,
|
markup::Markup,
|
||||||
|
|
|
@ -108,6 +108,7 @@ impl StaticIndex<'_> {
|
||||||
&InlayHintsConfig {
|
&InlayHintsConfig {
|
||||||
location_links: true,
|
location_links: true,
|
||||||
render_colons: true,
|
render_colons: true,
|
||||||
|
discriminant_hints: crate::DiscriminantHints::Fieldless,
|
||||||
type_hints: true,
|
type_hints: true,
|
||||||
parameter_hints: true,
|
parameter_hints: true,
|
||||||
chaining_hints: true,
|
chaining_hints: true,
|
||||||
|
|
|
@ -327,6 +327,8 @@ config_data! {
|
||||||
inlayHints_closingBraceHints_minLines: usize = "25",
|
inlayHints_closingBraceHints_minLines: usize = "25",
|
||||||
/// Whether to show inlay type hints for return types of closures.
|
/// Whether to show inlay type hints for return types of closures.
|
||||||
inlayHints_closureReturnTypeHints_enable: ClosureReturnTypeHintsDef = "\"never\"",
|
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.
|
/// Whether to show inlay hints for type adjustments.
|
||||||
inlayHints_expressionAdjustmentHints_enable: AdjustmentHintsDef = "\"never\"",
|
inlayHints_expressionAdjustmentHints_enable: AdjustmentHintsDef = "\"never\"",
|
||||||
/// Whether to hide inlay hints for type adjustments outside of `unsafe` blocks.
|
/// 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,
|
type_hints: self.data.inlayHints_typeHints_enable,
|
||||||
parameter_hints: self.data.inlayHints_parameterHints_enable,
|
parameter_hints: self.data.inlayHints_parameterHints_enable,
|
||||||
chaining_hints: self.data.inlayHints_chainingHints_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 {
|
closure_return_type_hints: match self.data.inlayHints_closureReturnTypeHints_enable {
|
||||||
ClosureReturnTypeHintsDef::Always => ide::ClosureReturnTypeHints::Always,
|
ClosureReturnTypeHintsDef::Always => ide::ClosureReturnTypeHints::Always,
|
||||||
ClosureReturnTypeHintsDef::Never => ide::ClosureReturnTypeHints::Never,
|
ClosureReturnTypeHintsDef::Never => ide::ClosureReturnTypeHints::Never,
|
||||||
|
@ -1579,6 +1586,7 @@ mod de_unit_v {
|
||||||
named_unit_variant!(skip_trivial);
|
named_unit_variant!(skip_trivial);
|
||||||
named_unit_variant!(mutable);
|
named_unit_variant!(mutable);
|
||||||
named_unit_variant!(reborrow);
|
named_unit_variant!(reborrow);
|
||||||
|
named_unit_variant!(fieldless);
|
||||||
named_unit_variant!(with_block);
|
named_unit_variant!(with_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1742,6 +1750,17 @@ enum AdjustmentHintsDef {
|
||||||
Reborrow,
|
Reborrow,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
enum FilesWatcherDef {
|
enum FilesWatcherDef {
|
||||||
|
@ -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."
|
"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! {
|
"CargoFeaturesDef" => set! {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -434,6 +434,7 @@ pub(crate) fn inlay_hint(
|
||||||
InlayKind::ParameterHint if render_colons => inlay_hint.label.append_str(":"),
|
InlayKind::ParameterHint if render_colons => inlay_hint.label.append_str(":"),
|
||||||
InlayKind::TypeHint if render_colons => inlay_hint.label.prepend_str(": "),
|
InlayKind::TypeHint if render_colons => inlay_hint.label.prepend_str(": "),
|
||||||
InlayKind::ClosureReturnTypeHint => 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
|
// after annotated thing
|
||||||
InlayKind::ClosureReturnTypeHint
|
InlayKind::ClosureReturnTypeHint
|
||||||
| InlayKind::TypeHint
|
| InlayKind::TypeHint
|
||||||
|
| InlayKind::DiscriminantHint
|
||||||
| InlayKind::ChainingHint
|
| InlayKind::ChainingHint
|
||||||
| InlayKind::GenericParamListHint
|
| InlayKind::GenericParamListHint
|
||||||
| InlayKind::ClosingParenthesis
|
| InlayKind::ClosingParenthesis
|
||||||
|
@ -457,6 +459,7 @@ pub(crate) fn inlay_hint(
|
||||||
InlayKind::TypeHint => !render_colons,
|
InlayKind::TypeHint => !render_colons,
|
||||||
InlayKind::ChainingHint | InlayKind::ClosingBraceHint => true,
|
InlayKind::ChainingHint | InlayKind::ClosingBraceHint => true,
|
||||||
InlayKind::ClosingParenthesis
|
InlayKind::ClosingParenthesis
|
||||||
|
| InlayKind::DiscriminantHint
|
||||||
| InlayKind::OpeningParenthesis
|
| InlayKind::OpeningParenthesis
|
||||||
| InlayKind::BindingModeHint
|
| InlayKind::BindingModeHint
|
||||||
| InlayKind::ClosureReturnTypeHint
|
| InlayKind::ClosureReturnTypeHint
|
||||||
|
@ -473,6 +476,7 @@ pub(crate) fn inlay_hint(
|
||||||
| InlayKind::GenericParamListHint
|
| InlayKind::GenericParamListHint
|
||||||
| InlayKind::AdjustmentHint
|
| InlayKind::AdjustmentHint
|
||||||
| InlayKind::TypeHint
|
| InlayKind::TypeHint
|
||||||
|
| InlayKind::DiscriminantHint
|
||||||
| InlayKind::ClosingBraceHint => false,
|
| InlayKind::ClosingBraceHint => false,
|
||||||
InlayKind::BindingModeHint => inlay_hint.label.as_simple_str() != Some("&"),
|
InlayKind::BindingModeHint => inlay_hint.label.as_simple_str() != Some("&"),
|
||||||
InlayKind::ParameterHint | InlayKind::LifetimeHint => true,
|
InlayKind::ParameterHint | InlayKind::LifetimeHint => true,
|
||||||
|
@ -483,6 +487,7 @@ pub(crate) fn inlay_hint(
|
||||||
Some(lsp_types::InlayHintKind::TYPE)
|
Some(lsp_types::InlayHintKind::TYPE)
|
||||||
}
|
}
|
||||||
InlayKind::ClosingParenthesis
|
InlayKind::ClosingParenthesis
|
||||||
|
| InlayKind::DiscriminantHint
|
||||||
| InlayKind::OpeningParenthesis
|
| InlayKind::OpeningParenthesis
|
||||||
| InlayKind::BindingModeHint
|
| InlayKind::BindingModeHint
|
||||||
| InlayKind::GenericParamListHint
|
| InlayKind::GenericParamListHint
|
||||||
|
|
|
@ -454,6 +454,11 @@ to always show them).
|
||||||
--
|
--
|
||||||
Whether to show inlay type hints for return types of closures.
|
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"`)::
|
[[rust-analyzer.inlayHints.expressionAdjustmentHints.enable]]rust-analyzer.inlayHints.expressionAdjustmentHints.enable (default: `"never"`)::
|
||||||
+
|
+
|
||||||
--
|
--
|
||||||
|
|
|
@ -960,6 +960,21 @@
|
||||||
"Only show type hints for return types of closures with blocks."
|
"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": {
|
"rust-analyzer.inlayHints.expressionAdjustmentHints.enable": {
|
||||||
"markdownDescription": "Whether to show inlay hints for type adjustments.",
|
"markdownDescription": "Whether to show inlay hints for type adjustments.",
|
||||||
"default": "never",
|
"default": "never",
|
||||||
|
|
Loading…
Reference in a new issue