mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-14 00:47:18 +00:00
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)
This commit is contained in:
commit
17cc78f169
8 changed files with 217 additions and 2 deletions
|
@ -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,
|
||||
|
@ -51,6 +53,13 @@ pub enum ClosureReturnTypeHints {
|
|||
Never,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum DiscriminantHints {
|
||||
Always,
|
||||
Never,
|
||||
Fieldless,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum LifetimeElisionHints {
|
||||
Always,
|
||||
|
@ -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,
|
||||
|
|
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},
|
||||
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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -1742,6 +1750,17 @@ enum AdjustmentHintsDef {
|
|||
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)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
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."
|
||||
]
|
||||
},
|
||||
"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": [
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"`)::
|
||||
+
|
||||
--
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in a new issue