Skip to content

Commit 12b7f9f

Browse files
committed
Add an option to minimize parentheses for adjustment hints
1 parent b89c4f0 commit 12b7f9f

File tree

7 files changed

+162
-29
lines changed

7 files changed

+162
-29
lines changed

crates/ide/src/inlay_hints.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub struct InlayHintsConfig {
3535
pub parameter_hints: bool,
3636
pub chaining_hints: bool,
3737
pub adjustment_hints: AdjustmentHints,
38-
pub adjustment_hints_postfix: bool,
38+
pub adjustment_hints_mode: AdjustmentHintsMode,
3939
pub adjustment_hints_hide_outside_unsafe: bool,
4040
pub closure_return_type_hints: ClosureReturnTypeHints,
4141
pub binding_mode_hints: bool,
@@ -75,6 +75,14 @@ pub enum AdjustmentHints {
7575
Never,
7676
}
7777

78+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
79+
pub enum AdjustmentHintsMode {
80+
Prefix,
81+
Postfix,
82+
PreferPrefix,
83+
PreferPostfix,
84+
}
85+
7886
#[derive(Clone, Debug, PartialEq, Eq)]
7987
pub enum InlayKind {
8088
BindingModeHint,
@@ -432,7 +440,7 @@ mod tests {
432440
use itertools::Itertools;
433441
use test_utils::extract_annotations;
434442

435-
use crate::inlay_hints::AdjustmentHints;
443+
use crate::inlay_hints::{AdjustmentHints, AdjustmentHintsMode};
436444
use crate::DiscriminantHints;
437445
use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints};
438446

@@ -448,7 +456,7 @@ mod tests {
448456
lifetime_elision_hints: LifetimeElisionHints::Never,
449457
closure_return_type_hints: ClosureReturnTypeHints::Never,
450458
adjustment_hints: AdjustmentHints::Never,
451-
adjustment_hints_postfix: false,
459+
adjustment_hints_mode: AdjustmentHintsMode::Prefix,
452460
adjustment_hints_hide_outside_unsafe: false,
453461
binding_mode_hints: false,
454462
hide_named_constructor_hints: false,

crates/ide/src/inlay_hints/adjustment.rs

Lines changed: 97 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use syntax::{
1111
ted,
1212
};
1313

14-
use crate::{AdjustmentHints, InlayHint, InlayHintsConfig, InlayKind};
14+
use crate::{AdjustmentHints, AdjustmentHintsMode, InlayHint, InlayHintsConfig, InlayKind};
1515

1616
pub(super) fn hints(
1717
acc: &mut Vec<InlayHint>,
@@ -40,8 +40,8 @@ pub(super) fn hints(
4040
let desc_expr = descended.as_ref().unwrap_or(expr);
4141
let adjustments = sema.expr_adjustments(desc_expr).filter(|it| !it.is_empty())?;
4242

43-
let (needs_outer_parens, needs_inner_parens) =
44-
needs_parens_for_adjustment_hints(expr, config.adjustment_hints_postfix);
43+
let (postfix, needs_outer_parens, needs_inner_parens) =
44+
mode_and_needs_parens_for_adjustment_hints(expr, config.adjustment_hints_mode);
4545

4646
if needs_outer_parens {
4747
acc.push(InlayHint {
@@ -52,7 +52,7 @@ pub(super) fn hints(
5252
});
5353
}
5454

55-
if config.adjustment_hints_postfix && needs_inner_parens {
55+
if postfix && needs_inner_parens {
5656
acc.push(InlayHint {
5757
range: expr.syntax().text_range(),
5858
kind: InlayKind::OpeningParenthesis,
@@ -68,7 +68,7 @@ pub(super) fn hints(
6868
}
6969

7070
let (mut tmp0, mut tmp1);
71-
let iter: &mut dyn Iterator<Item = _> = if config.adjustment_hints_postfix {
71+
let iter: &mut dyn Iterator<Item = _> = if postfix {
7272
tmp0 = adjustments.into_iter();
7373
&mut tmp0
7474
} else {
@@ -112,20 +112,16 @@ pub(super) fn hints(
112112
};
113113
acc.push(InlayHint {
114114
range: expr.syntax().text_range(),
115-
kind: if config.adjustment_hints_postfix {
115+
kind: if postfix {
116116
InlayKind::AdjustmentHintPostfix
117117
} else {
118118
InlayKind::AdjustmentHint
119119
},
120-
label: if config.adjustment_hints_postfix {
121-
format!(".{}", text.trim_end()).into()
122-
} else {
123-
text.into()
124-
},
120+
label: if postfix { format!(".{}", text.trim_end()).into() } else { text.into() },
125121
tooltip: None,
126122
});
127123
}
128-
if !config.adjustment_hints_postfix && needs_inner_parens {
124+
if !postfix && needs_inner_parens {
129125
acc.push(InlayHint {
130126
range: expr.syntax().text_range(),
131127
kind: InlayKind::OpeningParenthesis,
@@ -150,6 +146,41 @@ pub(super) fn hints(
150146
Some(())
151147
}
152148

149+
/// Returns whatever the hint should be postfix and if we need to add paretheses on the inside and/or outside of `expr`,
150+
/// if we are going to add (`postfix`) adjustments hints to it.
151+
fn mode_and_needs_parens_for_adjustment_hints(
152+
expr: &ast::Expr,
153+
mode: AdjustmentHintsMode,
154+
) -> (bool, bool, bool) {
155+
use {std::cmp::Ordering::*, AdjustmentHintsMode::*};
156+
157+
match mode {
158+
Prefix | Postfix => {
159+
let postfix = matches!(mode, Postfix);
160+
let (inside, outside) = needs_parens_for_adjustment_hints(expr, postfix);
161+
(postfix, inside, outside)
162+
}
163+
PreferPrefix | PreferPostfix => {
164+
let prefer_postfix = matches!(mode, PreferPostfix);
165+
166+
let (pre_inside, pre_outside) = needs_parens_for_adjustment_hints(expr, false);
167+
let prefix = (false, pre_inside, pre_outside);
168+
let pre_count = pre_inside as u8 + pre_outside as u8;
169+
170+
let (post_inside, post_outside) = needs_parens_for_adjustment_hints(expr, true);
171+
let postfix = (true, post_inside, post_outside);
172+
let post_count = post_inside as u8 + post_outside as u8;
173+
174+
match pre_count.cmp(&post_count) {
175+
Less => prefix,
176+
Greater => postfix,
177+
Equal if prefer_postfix => postfix,
178+
Equal => prefix,
179+
}
180+
}
181+
}
182+
}
183+
153184
/// Returns whatever we need to add paretheses on the inside and/or outside of `expr`,
154185
/// if we are going to add (`postfix`) adjustments hints to it.
155186
fn needs_parens_for_adjustment_hints(expr: &ast::Expr, postfix: bool) -> (bool, bool) {
@@ -217,7 +248,7 @@ fn needs_parens_for_adjustment_hints(expr: &ast::Expr, postfix: bool) -> (bool,
217248
mod tests {
218249
use crate::{
219250
inlay_hints::tests::{check_with_config, DISABLED_CONFIG},
220-
AdjustmentHints, InlayHintsConfig,
251+
AdjustmentHints, AdjustmentHintsMode, InlayHintsConfig,
221252
};
222253

223254
#[test]
@@ -333,7 +364,7 @@ impl Struct {
333364
check_with_config(
334365
InlayHintsConfig {
335366
adjustment_hints: AdjustmentHints::Always,
336-
adjustment_hints_postfix: true,
367+
adjustment_hints_mode: AdjustmentHintsMode::Postfix,
337368
..DISABLED_CONFIG
338369
},
339370
r#"
@@ -419,6 +450,58 @@ impl Struct {
419450
);
420451
}
421452

453+
#[test]
454+
fn adjustment_hints_prefer_prefix() {
455+
check_with_config(
456+
InlayHintsConfig {
457+
adjustment_hints: AdjustmentHints::Always,
458+
adjustment_hints_mode: AdjustmentHintsMode::PreferPrefix,
459+
..DISABLED_CONFIG
460+
},
461+
r#"
462+
fn main() {
463+
let _: u32 = loop {};
464+
//^^^^^^^<never-to-any>
465+
466+
Struct.by_ref();
467+
//^^^^^^.&
468+
469+
let (): () = return ();
470+
//^^^^^^^^^<never-to-any>
471+
472+
struct Struct;
473+
impl Struct { fn by_ref(&self) {} }
474+
}
475+
"#,
476+
)
477+
}
478+
479+
#[test]
480+
fn adjustment_hints_prefer_postfix() {
481+
check_with_config(
482+
InlayHintsConfig {
483+
adjustment_hints: AdjustmentHints::Always,
484+
adjustment_hints_mode: AdjustmentHintsMode::PreferPostfix,
485+
..DISABLED_CONFIG
486+
},
487+
r#"
488+
fn main() {
489+
let _: u32 = loop {};
490+
//^^^^^^^.<never-to-any>
491+
492+
Struct.by_ref();
493+
//^^^^^^.&
494+
495+
let (): () = return ();
496+
//^^^^^^^^^<never-to-any>
497+
498+
struct Struct;
499+
impl Struct { fn by_ref(&self) {} }
500+
}
501+
"#,
502+
)
503+
}
504+
422505
#[test]
423506
fn never_to_never_is_never_shown() {
424507
check_with_config(

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, DiscriminantHints, InlayHint, InlayHintLabel,
85-
InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
84+
AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints, InlayHint,
85+
InlayHintLabel, InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
8686
},
8787
join_lines::JoinLinesConfig,
8888
markup::Markup,

crates/ide/src/static_index.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use syntax::{AstNode, SyntaxKind::*, SyntaxToken, TextRange, T};
1313

1414
use crate::{
1515
hover::hover_for_definition,
16+
inlay_hints::AdjustmentHintsMode,
1617
moniker::{def_to_moniker, MonikerResult},
1718
parent_module::crates_for,
1819
Analysis, Fold, HoverConfig, HoverDocFormat, HoverResult, InlayHint, InlayHintsConfig,
@@ -115,7 +116,7 @@ impl StaticIndex<'_> {
115116
closure_return_type_hints: crate::ClosureReturnTypeHints::WithBlock,
116117
lifetime_elision_hints: crate::LifetimeElisionHints::Never,
117118
adjustment_hints: crate::AdjustmentHints::Never,
118-
adjustment_hints_postfix: false,
119+
adjustment_hints_mode: AdjustmentHintsMode::Prefix,
119120
adjustment_hints_hide_outside_unsafe: false,
120121
hide_named_constructor_hints: false,
121122
hide_closure_initialization_hints: false,

crates/rust-analyzer/src/config.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,8 +333,8 @@ config_data! {
333333
inlayHints_expressionAdjustmentHints_enable: AdjustmentHintsDef = "\"never\"",
334334
/// Whether to hide inlay hints for type adjustments outside of `unsafe` blocks.
335335
inlayHints_expressionAdjustmentHints_hideOutsideUnsafe: bool = "false",
336-
/// Whether to show inlay hints for type adjustments as postfix ops (`.*` instead of `*`, etc).
337-
inlayHints_expressionAdjustmentHints_postfix: bool = "false",
336+
/// Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc).
337+
inlayHints_expressionAdjustmentHints_mode: AdjustmentHintsModeDef = "\"prefix\"",
338338
/// Whether to show inlay type hints for elided lifetimes in function signatures.
339339
inlayHints_lifetimeElisionHints_enable: LifetimeElisionDef = "\"never\"",
340340
/// Whether to prefer using parameter names as the name for elided lifetime hints if possible.
@@ -1254,7 +1254,12 @@ impl Config {
12541254
},
12551255
AdjustmentHintsDef::Reborrow => ide::AdjustmentHints::ReborrowOnly,
12561256
},
1257-
adjustment_hints_postfix: self.data.inlayHints_expressionAdjustmentHints_postfix,
1257+
adjustment_hints_mode: match self.data.inlayHints_expressionAdjustmentHints_mode {
1258+
AdjustmentHintsModeDef::Prefix => ide::AdjustmentHintsMode::Prefix,
1259+
AdjustmentHintsModeDef::Postfix => ide::AdjustmentHintsMode::Postfix,
1260+
AdjustmentHintsModeDef::PreferPrefix => ide::AdjustmentHintsMode::PreferPrefix,
1261+
AdjustmentHintsModeDef::PreferPostfix => ide::AdjustmentHintsMode::PreferPostfix,
1262+
},
12581263
adjustment_hints_hide_outside_unsafe: self
12591264
.data
12601265
.inlayHints_expressionAdjustmentHints_hideOutsideUnsafe,
@@ -1771,6 +1776,15 @@ enum DiscriminantHintsDef {
17711776
Fieldless,
17721777
}
17731778

1779+
#[derive(Deserialize, Debug, Clone)]
1780+
#[serde(rename_all = "snake_case")]
1781+
enum AdjustmentHintsModeDef {
1782+
Prefix,
1783+
Postfix,
1784+
PreferPrefix,
1785+
PreferPostfix,
1786+
}
1787+
17741788
#[derive(Deserialize, Debug, Clone)]
17751789
#[serde(rename_all = "snake_case")]
17761790
enum FilesWatcherDef {
@@ -2104,6 +2118,21 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
21042118
"Only show discriminant hints on fieldless enum variants."
21052119
]
21062120
},
2121+
"AdjustmentHintsModeDef" => set! {
2122+
"type": "string",
2123+
"enum": [
2124+
"prefix",
2125+
"postfix",
2126+
"prefer_prefix",
2127+
"prefer_postfix",
2128+
],
2129+
"enumDescriptions": [
2130+
"Always show adjustment hints as prefix (`*expr`).",
2131+
"Always show adjustment hints as postfix (`expr.*`).",
2132+
"Show prefix or postfix depending on which uses less parenthesis, prefering prefix.",
2133+
"Show prefix or postfix depending on which uses less parenthesis, prefering postfix.",
2134+
]
2135+
},
21072136
"CargoFeaturesDef" => set! {
21082137
"anyOf": [
21092138
{

docs/user/generated_config.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -469,10 +469,10 @@ Whether to show inlay hints for type adjustments.
469469
--
470470
Whether to hide inlay hints for type adjustments outside of `unsafe` blocks.
471471
--
472-
[[rust-analyzer.inlayHints.expressionAdjustmentHints.postfix]]rust-analyzer.inlayHints.expressionAdjustmentHints.postfix (default: `false`)::
472+
[[rust-analyzer.inlayHints.expressionAdjustmentHints.mode]]rust-analyzer.inlayHints.expressionAdjustmentHints.mode (default: `"prefix"`)::
473473
+
474474
--
475-
Whether to show inlay hints for type adjustments as postfix ops (`.*` instead of `*`, etc).
475+
Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc).
476476
--
477477
[[rust-analyzer.inlayHints.lifetimeElisionHints.enable]]rust-analyzer.inlayHints.lifetimeElisionHints.enable (default: `"never"`)::
478478
+

editors/code/package.json

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,10 +1000,22 @@
10001000
"default": false,
10011001
"type": "boolean"
10021002
},
1003-
"rust-analyzer.inlayHints.expressionAdjustmentHints.postfix": {
1004-
"markdownDescription": "Whether to show inlay hints for type adjustments as postfix ops (`.*` instead of `*`, etc).",
1005-
"default": false,
1006-
"type": "boolean"
1003+
"rust-analyzer.inlayHints.expressionAdjustmentHints.mode": {
1004+
"markdownDescription": "Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc).",
1005+
"default": "prefix",
1006+
"type": "string",
1007+
"enum": [
1008+
"prefix",
1009+
"postfix",
1010+
"prefer_prefix",
1011+
"prefer_postfix"
1012+
],
1013+
"enumDescriptions": [
1014+
"Always show adjustment hints as prefix (`*expr`).",
1015+
"Always show adjustment hints as postfix (`expr.*`).",
1016+
"Show prefix or postfix depending on which uses less parenthesis, prefering prefix.",
1017+
"Show prefix or postfix depending on which uses less parenthesis, prefering postfix."
1018+
]
10071019
},
10081020
"rust-analyzer.inlayHints.lifetimeElisionHints.enable": {
10091021
"markdownDescription": "Whether to show inlay type hints for elided lifetimes in function signatures.",

0 commit comments

Comments
 (0)