Skip to content

Commit 17cc78f

Browse files
committed
Auto merge of rust-lang#13832 - Veykril:discriminant-hints, r=Veykril
Enum variant discriminants hints ![image](https://user-images.githubusercontent.com/3757771/209320042-eced617a-9a47-4808-ac23-916f469dc90c.png)
2 parents 790759f + df8fc78 commit 17cc78f

File tree

8 files changed

+217
-2
lines changed

8 files changed

+217
-2
lines changed

crates/ide/src/inlay_hints.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@ mod chaining;
2424
mod param_name;
2525
mod binding_mode;
2626
mod bind_pat;
27+
mod discrimant;
2728

2829
#[derive(Clone, Debug, PartialEq, Eq)]
2930
pub struct InlayHintsConfig {
3031
pub location_links: bool,
3132
pub render_colons: bool,
3233
pub type_hints: bool,
34+
pub discriminant_hints: DiscriminantHints,
3335
pub parameter_hints: bool,
3436
pub chaining_hints: bool,
3537
pub adjustment_hints: AdjustmentHints,
@@ -51,6 +53,13 @@ pub enum ClosureReturnTypeHints {
5153
Never,
5254
}
5355

56+
#[derive(Clone, Debug, PartialEq, Eq)]
57+
pub enum DiscriminantHints {
58+
Always,
59+
Never,
60+
Fieldless,
61+
}
62+
5463
#[derive(Clone, Debug, PartialEq, Eq)]
5564
pub enum LifetimeElisionHints {
5665
Always,
@@ -76,6 +85,7 @@ pub enum InlayKind {
7685
LifetimeHint,
7786
ParameterHint,
7887
TypeHint,
88+
DiscriminantHint,
7989
OpeningParenthesis,
8090
ClosingParenthesis,
8191
}
@@ -365,6 +375,9 @@ fn hints(
365375
ast::Item::Const(it) => implicit_static::hints(hints, config, Either::Right(it)),
366376
_ => None,
367377
},
378+
ast::Variant(v) => {
379+
discrimant::hints(hints, famous_defs, config, file_id, &v)
380+
},
368381
// FIXME: fn-ptr type, dyn fn type, and trait object type elisions
369382
ast::Type(_) => None,
370383
_ => None,
@@ -418,12 +431,14 @@ mod tests {
418431
use test_utils::extract_annotations;
419432

420433
use crate::inlay_hints::AdjustmentHints;
434+
use crate::DiscriminantHints;
421435
use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints};
422436

423437
use super::ClosureReturnTypeHints;
424438

425439
pub(super) const DISABLED_CONFIG: InlayHintsConfig = InlayHintsConfig {
426440
location_links: false,
441+
discriminant_hints: DiscriminantHints::Never,
427442
render_colons: false,
428443
type_hints: false,
429444
parameter_hints: false,
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
//! Implementation of "enum variant discriminant" inlay hints:
2+
//! ```no_run
3+
//! enum Foo {
4+
//! Bar/* = 0*/,
5+
//! }
6+
//! ```
7+
use ide_db::{base_db::FileId, famous_defs::FamousDefs};
8+
use syntax::ast::{self, AstNode, HasName};
9+
10+
use crate::{DiscriminantHints, InlayHint, InlayHintsConfig, InlayKind, InlayTooltip};
11+
12+
pub(super) fn hints(
13+
acc: &mut Vec<InlayHint>,
14+
FamousDefs(sema, _): &FamousDefs<'_, '_>,
15+
config: &InlayHintsConfig,
16+
_: FileId,
17+
variant: &ast::Variant,
18+
) -> Option<()> {
19+
let field_list = match config.discriminant_hints {
20+
DiscriminantHints::Always => variant.field_list(),
21+
DiscriminantHints::Fieldless => match variant.field_list() {
22+
Some(_) => return None,
23+
None => None,
24+
},
25+
DiscriminantHints::Never => return None,
26+
};
27+
28+
if variant.eq_token().is_some() {
29+
return None;
30+
}
31+
32+
let name = variant.name()?;
33+
34+
let descended = sema.descend_node_into_attributes(variant.clone()).pop();
35+
let desc_pat = descended.as_ref().unwrap_or(variant);
36+
let v = sema.to_def(desc_pat)?;
37+
let d = v.eval(sema.db);
38+
39+
acc.push(InlayHint {
40+
range: match field_list {
41+
Some(field_list) => name.syntax().text_range().cover(field_list.syntax().text_range()),
42+
None => name.syntax().text_range(),
43+
},
44+
kind: InlayKind::DiscriminantHint,
45+
label: match &d {
46+
Ok(v) => format!("{}", v).into(),
47+
Err(_) => "?".into(),
48+
},
49+
tooltip: Some(InlayTooltip::String(match &d {
50+
Ok(_) => "enum variant discriminant".into(),
51+
Err(e) => format!("{e:?}").into(),
52+
})),
53+
});
54+
55+
Some(())
56+
}
57+
58+
#[cfg(test)]
59+
mod tests {
60+
use crate::inlay_hints::{
61+
tests::{check_with_config, DISABLED_CONFIG},
62+
DiscriminantHints, InlayHintsConfig,
63+
};
64+
65+
#[track_caller]
66+
fn check_discriminants(ra_fixture: &str) {
67+
check_with_config(
68+
InlayHintsConfig { discriminant_hints: DiscriminantHints::Always, ..DISABLED_CONFIG },
69+
ra_fixture,
70+
);
71+
}
72+
73+
#[track_caller]
74+
fn check_discriminants_fieldless(ra_fixture: &str) {
75+
check_with_config(
76+
InlayHintsConfig {
77+
discriminant_hints: DiscriminantHints::Fieldless,
78+
..DISABLED_CONFIG
79+
},
80+
ra_fixture,
81+
);
82+
}
83+
84+
#[test]
85+
fn fieldless() {
86+
check_discriminants(
87+
r#"
88+
enum Enum {
89+
Variant,
90+
//^^^^^^^0
91+
Variant1,
92+
//^^^^^^^^1
93+
Variant2,
94+
//^^^^^^^^2
95+
Variant5 = 5,
96+
Variant6,
97+
//^^^^^^^^6
98+
}
99+
"#,
100+
);
101+
}
102+
103+
#[test]
104+
fn datacarrying_mixed() {
105+
check_discriminants(
106+
r#"
107+
enum Enum {
108+
Variant(),
109+
//^^^^^^^^^0
110+
Variant1,
111+
//^^^^^^^^1
112+
Variant2 {},
113+
//^^^^^^^^^^^2
114+
Variant3,
115+
//^^^^^^^^3
116+
Variant5 = 5,
117+
Variant6,
118+
//^^^^^^^^6
119+
}
120+
"#,
121+
);
122+
}
123+
124+
#[test]
125+
fn datacarrying_mixed_fieldless_set() {
126+
check_discriminants_fieldless(
127+
r#"
128+
enum Enum {
129+
Variant(),
130+
Variant1,
131+
//^^^^^^^^1
132+
Variant2 {},
133+
Variant3,
134+
//^^^^^^^^3
135+
Variant5 = 5,
136+
Variant6,
137+
//^^^^^^^^6
138+
}
139+
"#,
140+
);
141+
}
142+
}

crates/ide/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ pub use crate::{
8181
highlight_related::{HighlightRelatedConfig, HighlightedRange},
8282
hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult},
8383
inlay_hints::{
84-
AdjustmentHints, ClosureReturnTypeHints, InlayHint, InlayHintLabel, InlayHintsConfig,
85-
InlayKind, InlayTooltip, LifetimeElisionHints,
84+
AdjustmentHints, ClosureReturnTypeHints, DiscriminantHints, InlayHint, InlayHintLabel,
85+
InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
8686
},
8787
join_lines::JoinLinesConfig,
8888
markup::Markup,

crates/ide/src/static_index.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ impl StaticIndex<'_> {
108108
&InlayHintsConfig {
109109
location_links: true,
110110
render_colons: true,
111+
discriminant_hints: crate::DiscriminantHints::Fieldless,
111112
type_hints: true,
112113
parameter_hints: true,
113114
chaining_hints: true,

crates/rust-analyzer/src/config.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,8 @@ config_data! {
327327
inlayHints_closingBraceHints_minLines: usize = "25",
328328
/// Whether to show inlay type hints for return types of closures.
329329
inlayHints_closureReturnTypeHints_enable: ClosureReturnTypeHintsDef = "\"never\"",
330+
/// Whether to show enum variant discriminant hints.
331+
inlayHints_discriminantHints_enable: DiscriminantHintsDef = "\"never\"",
330332
/// Whether to show inlay hints for type adjustments.
331333
inlayHints_expressionAdjustmentHints_enable: AdjustmentHintsDef = "\"never\"",
332334
/// Whether to hide inlay hints for type adjustments outside of `unsafe` blocks.
@@ -1218,6 +1220,11 @@ impl Config {
12181220
type_hints: self.data.inlayHints_typeHints_enable,
12191221
parameter_hints: self.data.inlayHints_parameterHints_enable,
12201222
chaining_hints: self.data.inlayHints_chainingHints_enable,
1223+
discriminant_hints: match self.data.inlayHints_discriminantHints_enable {
1224+
DiscriminantHintsDef::Always => ide::DiscriminantHints::Always,
1225+
DiscriminantHintsDef::Never => ide::DiscriminantHints::Never,
1226+
DiscriminantHintsDef::Fieldless => ide::DiscriminantHints::Fieldless,
1227+
},
12211228
closure_return_type_hints: match self.data.inlayHints_closureReturnTypeHints_enable {
12221229
ClosureReturnTypeHintsDef::Always => ide::ClosureReturnTypeHints::Always,
12231230
ClosureReturnTypeHintsDef::Never => ide::ClosureReturnTypeHints::Never,
@@ -1579,6 +1586,7 @@ mod de_unit_v {
15791586
named_unit_variant!(skip_trivial);
15801587
named_unit_variant!(mutable);
15811588
named_unit_variant!(reborrow);
1589+
named_unit_variant!(fieldless);
15821590
named_unit_variant!(with_block);
15831591
}
15841592

@@ -1742,6 +1750,17 @@ enum AdjustmentHintsDef {
17421750
Reborrow,
17431751
}
17441752

1753+
#[derive(Deserialize, Debug, Clone)]
1754+
#[serde(untagged)]
1755+
enum DiscriminantHintsDef {
1756+
#[serde(deserialize_with = "true_or_always")]
1757+
Always,
1758+
#[serde(deserialize_with = "false_or_never")]
1759+
Never,
1760+
#[serde(deserialize_with = "de_unit_v::fieldless")]
1761+
Fieldless,
1762+
}
1763+
17451764
#[derive(Deserialize, Debug, Clone)]
17461765
#[serde(rename_all = "snake_case")]
17471766
enum FilesWatcherDef {
@@ -2064,6 +2083,19 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
20642083
"Only show auto borrow and dereference adjustment hints."
20652084
]
20662085
},
2086+
"DiscriminantHintsDef" => set! {
2087+
"type": "string",
2088+
"enum": [
2089+
"always",
2090+
"never",
2091+
"fieldless"
2092+
],
2093+
"enumDescriptions": [
2094+
"Always show all discriminant hints.",
2095+
"Never show discriminant hints.",
2096+
"Only show discriminant hints on fieldless enum variants."
2097+
]
2098+
},
20672099
"CargoFeaturesDef" => set! {
20682100
"anyOf": [
20692101
{

crates/rust-analyzer/src/to_proto.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@ pub(crate) fn inlay_hint(
434434
InlayKind::ParameterHint if render_colons => inlay_hint.label.append_str(":"),
435435
InlayKind::TypeHint if render_colons => inlay_hint.label.prepend_str(": "),
436436
InlayKind::ClosureReturnTypeHint => inlay_hint.label.prepend_str(" -> "),
437+
InlayKind::DiscriminantHint => inlay_hint.label.prepend_str(" = "),
437438
_ => {}
438439
}
439440

@@ -447,6 +448,7 @@ pub(crate) fn inlay_hint(
447448
// after annotated thing
448449
InlayKind::ClosureReturnTypeHint
449450
| InlayKind::TypeHint
451+
| InlayKind::DiscriminantHint
450452
| InlayKind::ChainingHint
451453
| InlayKind::GenericParamListHint
452454
| InlayKind::ClosingParenthesis
@@ -457,6 +459,7 @@ pub(crate) fn inlay_hint(
457459
InlayKind::TypeHint => !render_colons,
458460
InlayKind::ChainingHint | InlayKind::ClosingBraceHint => true,
459461
InlayKind::ClosingParenthesis
462+
| InlayKind::DiscriminantHint
460463
| InlayKind::OpeningParenthesis
461464
| InlayKind::BindingModeHint
462465
| InlayKind::ClosureReturnTypeHint
@@ -473,6 +476,7 @@ pub(crate) fn inlay_hint(
473476
| InlayKind::GenericParamListHint
474477
| InlayKind::AdjustmentHint
475478
| InlayKind::TypeHint
479+
| InlayKind::DiscriminantHint
476480
| InlayKind::ClosingBraceHint => false,
477481
InlayKind::BindingModeHint => inlay_hint.label.as_simple_str() != Some("&"),
478482
InlayKind::ParameterHint | InlayKind::LifetimeHint => true,
@@ -483,6 +487,7 @@ pub(crate) fn inlay_hint(
483487
Some(lsp_types::InlayHintKind::TYPE)
484488
}
485489
InlayKind::ClosingParenthesis
490+
| InlayKind::DiscriminantHint
486491
| InlayKind::OpeningParenthesis
487492
| InlayKind::BindingModeHint
488493
| InlayKind::GenericParamListHint

docs/user/generated_config.adoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,11 @@ to always show them).
454454
--
455455
Whether to show inlay type hints for return types of closures.
456456
--
457+
[[rust-analyzer.inlayHints.discriminantHints.enable]]rust-analyzer.inlayHints.discriminantHints.enable (default: `"never"`)::
458+
+
459+
--
460+
Whether to show enum variant discriminant hints.
461+
--
457462
[[rust-analyzer.inlayHints.expressionAdjustmentHints.enable]]rust-analyzer.inlayHints.expressionAdjustmentHints.enable (default: `"never"`)::
458463
+
459464
--

editors/code/package.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,21 @@
960960
"Only show type hints for return types of closures with blocks."
961961
]
962962
},
963+
"rust-analyzer.inlayHints.discriminantHints.enable": {
964+
"markdownDescription": "Whether to show enum variant discriminant hints.",
965+
"default": "never",
966+
"type": "string",
967+
"enum": [
968+
"always",
969+
"never",
970+
"fieldless"
971+
],
972+
"enumDescriptions": [
973+
"Always show all discriminant hints.",
974+
"Never show discriminant hints.",
975+
"Only show discriminant hints on fieldless enum variants."
976+
]
977+
},
963978
"rust-analyzer.inlayHints.expressionAdjustmentHints.enable": {
964979
"markdownDescription": "Whether to show inlay hints for type adjustments.",
965980
"default": "never",

0 commit comments

Comments
 (0)