1
Fork 0

Add an option to minimize parentheses for adjustment hints

This commit is contained in:
Maybe Waffle 2022-12-21 15:00:05 +00:00
parent b89c4f0a05
commit 12b7f9f7bf
7 changed files with 162 additions and 29 deletions

View file

@ -35,7 +35,7 @@ pub struct InlayHintsConfig {
pub parameter_hints: bool, pub parameter_hints: bool,
pub chaining_hints: bool, pub chaining_hints: bool,
pub adjustment_hints: AdjustmentHints, pub adjustment_hints: AdjustmentHints,
pub adjustment_hints_postfix: bool, pub adjustment_hints_mode: AdjustmentHintsMode,
pub adjustment_hints_hide_outside_unsafe: bool, pub adjustment_hints_hide_outside_unsafe: bool,
pub closure_return_type_hints: ClosureReturnTypeHints, pub closure_return_type_hints: ClosureReturnTypeHints,
pub binding_mode_hints: bool, pub binding_mode_hints: bool,
@ -75,6 +75,14 @@ pub enum AdjustmentHints {
Never, Never,
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum AdjustmentHintsMode {
Prefix,
Postfix,
PreferPrefix,
PreferPostfix,
}
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub enum InlayKind { pub enum InlayKind {
BindingModeHint, BindingModeHint,
@ -432,7 +440,7 @@ mod tests {
use itertools::Itertools; use itertools::Itertools;
use test_utils::extract_annotations; use test_utils::extract_annotations;
use crate::inlay_hints::AdjustmentHints; use crate::inlay_hints::{AdjustmentHints, AdjustmentHintsMode};
use crate::DiscriminantHints; use crate::DiscriminantHints;
use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints}; use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints};
@ -448,7 +456,7 @@ mod tests {
lifetime_elision_hints: LifetimeElisionHints::Never, lifetime_elision_hints: LifetimeElisionHints::Never,
closure_return_type_hints: ClosureReturnTypeHints::Never, closure_return_type_hints: ClosureReturnTypeHints::Never,
adjustment_hints: AdjustmentHints::Never, adjustment_hints: AdjustmentHints::Never,
adjustment_hints_postfix: false, adjustment_hints_mode: AdjustmentHintsMode::Prefix,
adjustment_hints_hide_outside_unsafe: false, adjustment_hints_hide_outside_unsafe: false,
binding_mode_hints: false, binding_mode_hints: false,
hide_named_constructor_hints: false, hide_named_constructor_hints: false,

View file

@ -11,7 +11,7 @@ use syntax::{
ted, ted,
}; };
use crate::{AdjustmentHints, InlayHint, InlayHintsConfig, InlayKind}; use crate::{AdjustmentHints, AdjustmentHintsMode, InlayHint, InlayHintsConfig, InlayKind};
pub(super) fn hints( pub(super) fn hints(
acc: &mut Vec<InlayHint>, acc: &mut Vec<InlayHint>,
@ -40,8 +40,8 @@ pub(super) fn hints(
let desc_expr = descended.as_ref().unwrap_or(expr); let desc_expr = descended.as_ref().unwrap_or(expr);
let adjustments = sema.expr_adjustments(desc_expr).filter(|it| !it.is_empty())?; let adjustments = sema.expr_adjustments(desc_expr).filter(|it| !it.is_empty())?;
let (needs_outer_parens, needs_inner_parens) = let (postfix, needs_outer_parens, needs_inner_parens) =
needs_parens_for_adjustment_hints(expr, config.adjustment_hints_postfix); mode_and_needs_parens_for_adjustment_hints(expr, config.adjustment_hints_mode);
if needs_outer_parens { if needs_outer_parens {
acc.push(InlayHint { acc.push(InlayHint {
@ -52,7 +52,7 @@ pub(super) fn hints(
}); });
} }
if config.adjustment_hints_postfix && needs_inner_parens { if postfix && needs_inner_parens {
acc.push(InlayHint { acc.push(InlayHint {
range: expr.syntax().text_range(), range: expr.syntax().text_range(),
kind: InlayKind::OpeningParenthesis, kind: InlayKind::OpeningParenthesis,
@ -68,7 +68,7 @@ pub(super) fn hints(
} }
let (mut tmp0, mut tmp1); let (mut tmp0, mut tmp1);
let iter: &mut dyn Iterator<Item = _> = if config.adjustment_hints_postfix { let iter: &mut dyn Iterator<Item = _> = if postfix {
tmp0 = adjustments.into_iter(); tmp0 = adjustments.into_iter();
&mut tmp0 &mut tmp0
} else { } else {
@ -112,20 +112,16 @@ pub(super) fn hints(
}; };
acc.push(InlayHint { acc.push(InlayHint {
range: expr.syntax().text_range(), range: expr.syntax().text_range(),
kind: if config.adjustment_hints_postfix { kind: if postfix {
InlayKind::AdjustmentHintPostfix InlayKind::AdjustmentHintPostfix
} else { } else {
InlayKind::AdjustmentHint InlayKind::AdjustmentHint
}, },
label: if config.adjustment_hints_postfix { label: if postfix { format!(".{}", text.trim_end()).into() } else { text.into() },
format!(".{}", text.trim_end()).into()
} else {
text.into()
},
tooltip: None, tooltip: None,
}); });
} }
if !config.adjustment_hints_postfix && needs_inner_parens { if !postfix && needs_inner_parens {
acc.push(InlayHint { acc.push(InlayHint {
range: expr.syntax().text_range(), range: expr.syntax().text_range(),
kind: InlayKind::OpeningParenthesis, kind: InlayKind::OpeningParenthesis,
@ -150,6 +146,41 @@ pub(super) fn hints(
Some(()) Some(())
} }
/// Returns whatever the hint should be postfix and if we need to add paretheses on the inside and/or outside of `expr`,
/// if we are going to add (`postfix`) adjustments hints to it.
fn mode_and_needs_parens_for_adjustment_hints(
expr: &ast::Expr,
mode: AdjustmentHintsMode,
) -> (bool, bool, bool) {
use {std::cmp::Ordering::*, AdjustmentHintsMode::*};
match mode {
Prefix | Postfix => {
let postfix = matches!(mode, Postfix);
let (inside, outside) = needs_parens_for_adjustment_hints(expr, postfix);
(postfix, inside, outside)
}
PreferPrefix | PreferPostfix => {
let prefer_postfix = matches!(mode, PreferPostfix);
let (pre_inside, pre_outside) = needs_parens_for_adjustment_hints(expr, false);
let prefix = (false, pre_inside, pre_outside);
let pre_count = pre_inside as u8 + pre_outside as u8;
let (post_inside, post_outside) = needs_parens_for_adjustment_hints(expr, true);
let postfix = (true, post_inside, post_outside);
let post_count = post_inside as u8 + post_outside as u8;
match pre_count.cmp(&post_count) {
Less => prefix,
Greater => postfix,
Equal if prefer_postfix => postfix,
Equal => prefix,
}
}
}
}
/// Returns whatever we need to add paretheses on the inside and/or outside of `expr`, /// Returns whatever we need to add paretheses on the inside and/or outside of `expr`,
/// if we are going to add (`postfix`) adjustments hints to it. /// if we are going to add (`postfix`) adjustments hints to it.
fn needs_parens_for_adjustment_hints(expr: &ast::Expr, postfix: bool) -> (bool, bool) { 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,
mod tests { mod tests {
use crate::{ use crate::{
inlay_hints::tests::{check_with_config, DISABLED_CONFIG}, inlay_hints::tests::{check_with_config, DISABLED_CONFIG},
AdjustmentHints, InlayHintsConfig, AdjustmentHints, AdjustmentHintsMode, InlayHintsConfig,
}; };
#[test] #[test]
@ -333,7 +364,7 @@ impl Struct {
check_with_config( check_with_config(
InlayHintsConfig { InlayHintsConfig {
adjustment_hints: AdjustmentHints::Always, adjustment_hints: AdjustmentHints::Always,
adjustment_hints_postfix: true, adjustment_hints_mode: AdjustmentHintsMode::Postfix,
..DISABLED_CONFIG ..DISABLED_CONFIG
}, },
r#" r#"
@ -419,6 +450,58 @@ impl Struct {
); );
} }
#[test]
fn adjustment_hints_prefer_prefix() {
check_with_config(
InlayHintsConfig {
adjustment_hints: AdjustmentHints::Always,
adjustment_hints_mode: AdjustmentHintsMode::PreferPrefix,
..DISABLED_CONFIG
},
r#"
fn main() {
let _: u32 = loop {};
//^^^^^^^<never-to-any>
Struct.by_ref();
//^^^^^^.&
let (): () = return ();
//^^^^^^^^^<never-to-any>
struct Struct;
impl Struct { fn by_ref(&self) {} }
}
"#,
)
}
#[test]
fn adjustment_hints_prefer_postfix() {
check_with_config(
InlayHintsConfig {
adjustment_hints: AdjustmentHints::Always,
adjustment_hints_mode: AdjustmentHintsMode::PreferPostfix,
..DISABLED_CONFIG
},
r#"
fn main() {
let _: u32 = loop {};
//^^^^^^^.<never-to-any>
Struct.by_ref();
//^^^^^^.&
let (): () = return ();
//^^^^^^^^^<never-to-any>
struct Struct;
impl Struct { fn by_ref(&self) {} }
}
"#,
)
}
#[test] #[test]
fn never_to_never_is_never_shown() { fn never_to_never_is_never_shown() {
check_with_config( check_with_config(

View file

@ -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, DiscriminantHints, InlayHint, InlayHintLabel, AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints, InlayHint,
InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints, InlayHintLabel, InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
}, },
join_lines::JoinLinesConfig, join_lines::JoinLinesConfig,
markup::Markup, markup::Markup,

View file

@ -13,6 +13,7 @@ use syntax::{AstNode, SyntaxKind::*, SyntaxToken, TextRange, T};
use crate::{ use crate::{
hover::hover_for_definition, hover::hover_for_definition,
inlay_hints::AdjustmentHintsMode,
moniker::{def_to_moniker, MonikerResult}, moniker::{def_to_moniker, MonikerResult},
parent_module::crates_for, parent_module::crates_for,
Analysis, Fold, HoverConfig, HoverDocFormat, HoverResult, InlayHint, InlayHintsConfig, Analysis, Fold, HoverConfig, HoverDocFormat, HoverResult, InlayHint, InlayHintsConfig,
@ -115,7 +116,7 @@ impl StaticIndex<'_> {
closure_return_type_hints: crate::ClosureReturnTypeHints::WithBlock, closure_return_type_hints: crate::ClosureReturnTypeHints::WithBlock,
lifetime_elision_hints: crate::LifetimeElisionHints::Never, lifetime_elision_hints: crate::LifetimeElisionHints::Never,
adjustment_hints: crate::AdjustmentHints::Never, adjustment_hints: crate::AdjustmentHints::Never,
adjustment_hints_postfix: false, adjustment_hints_mode: AdjustmentHintsMode::Prefix,
adjustment_hints_hide_outside_unsafe: false, adjustment_hints_hide_outside_unsafe: false,
hide_named_constructor_hints: false, hide_named_constructor_hints: false,
hide_closure_initialization_hints: false, hide_closure_initialization_hints: false,

View file

@ -333,8 +333,8 @@ config_data! {
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.
inlayHints_expressionAdjustmentHints_hideOutsideUnsafe: bool = "false", inlayHints_expressionAdjustmentHints_hideOutsideUnsafe: bool = "false",
/// Whether to show inlay hints for type adjustments as postfix ops (`.*` instead of `*`, etc). /// Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc).
inlayHints_expressionAdjustmentHints_postfix: bool = "false", inlayHints_expressionAdjustmentHints_mode: AdjustmentHintsModeDef = "\"prefix\"",
/// Whether to show inlay type hints for elided lifetimes in function signatures. /// Whether to show inlay type hints for elided lifetimes in function signatures.
inlayHints_lifetimeElisionHints_enable: LifetimeElisionDef = "\"never\"", inlayHints_lifetimeElisionHints_enable: LifetimeElisionDef = "\"never\"",
/// Whether to prefer using parameter names as the name for elided lifetime hints if possible. /// Whether to prefer using parameter names as the name for elided lifetime hints if possible.
@ -1254,7 +1254,12 @@ impl Config {
}, },
AdjustmentHintsDef::Reborrow => ide::AdjustmentHints::ReborrowOnly, AdjustmentHintsDef::Reborrow => ide::AdjustmentHints::ReborrowOnly,
}, },
adjustment_hints_postfix: self.data.inlayHints_expressionAdjustmentHints_postfix, adjustment_hints_mode: match self.data.inlayHints_expressionAdjustmentHints_mode {
AdjustmentHintsModeDef::Prefix => ide::AdjustmentHintsMode::Prefix,
AdjustmentHintsModeDef::Postfix => ide::AdjustmentHintsMode::Postfix,
AdjustmentHintsModeDef::PreferPrefix => ide::AdjustmentHintsMode::PreferPrefix,
AdjustmentHintsModeDef::PreferPostfix => ide::AdjustmentHintsMode::PreferPostfix,
},
adjustment_hints_hide_outside_unsafe: self adjustment_hints_hide_outside_unsafe: self
.data .data
.inlayHints_expressionAdjustmentHints_hideOutsideUnsafe, .inlayHints_expressionAdjustmentHints_hideOutsideUnsafe,
@ -1771,6 +1776,15 @@ enum DiscriminantHintsDef {
Fieldless, Fieldless,
} }
#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
enum AdjustmentHintsModeDef {
Prefix,
Postfix,
PreferPrefix,
PreferPostfix,
}
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
enum FilesWatcherDef { enum FilesWatcherDef {
@ -2104,6 +2118,21 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
"Only show discriminant hints on fieldless enum variants." "Only show discriminant hints on fieldless enum variants."
] ]
}, },
"AdjustmentHintsModeDef" => set! {
"type": "string",
"enum": [
"prefix",
"postfix",
"prefer_prefix",
"prefer_postfix",
],
"enumDescriptions": [
"Always show adjustment hints as prefix (`*expr`).",
"Always show adjustment hints as postfix (`expr.*`).",
"Show prefix or postfix depending on which uses less parenthesis, prefering prefix.",
"Show prefix or postfix depending on which uses less parenthesis, prefering postfix.",
]
},
"CargoFeaturesDef" => set! { "CargoFeaturesDef" => set! {
"anyOf": [ "anyOf": [
{ {

View file

@ -469,10 +469,10 @@ Whether to show inlay hints for type adjustments.
-- --
Whether to hide inlay hints for type adjustments outside of `unsafe` blocks. Whether to hide inlay hints for type adjustments outside of `unsafe` blocks.
-- --
[[rust-analyzer.inlayHints.expressionAdjustmentHints.postfix]]rust-analyzer.inlayHints.expressionAdjustmentHints.postfix (default: `false`):: [[rust-analyzer.inlayHints.expressionAdjustmentHints.mode]]rust-analyzer.inlayHints.expressionAdjustmentHints.mode (default: `"prefix"`)::
+ +
-- --
Whether to show inlay hints for type adjustments as postfix ops (`.*` instead of `*`, etc). Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc).
-- --
[[rust-analyzer.inlayHints.lifetimeElisionHints.enable]]rust-analyzer.inlayHints.lifetimeElisionHints.enable (default: `"never"`):: [[rust-analyzer.inlayHints.lifetimeElisionHints.enable]]rust-analyzer.inlayHints.lifetimeElisionHints.enable (default: `"never"`)::
+ +

View file

@ -1000,10 +1000,22 @@
"default": false, "default": false,
"type": "boolean" "type": "boolean"
}, },
"rust-analyzer.inlayHints.expressionAdjustmentHints.postfix": { "rust-analyzer.inlayHints.expressionAdjustmentHints.mode": {
"markdownDescription": "Whether to show inlay hints for type adjustments as postfix ops (`.*` instead of `*`, etc).", "markdownDescription": "Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc).",
"default": false, "default": "prefix",
"type": "boolean" "type": "string",
"enum": [
"prefix",
"postfix",
"prefer_prefix",
"prefer_postfix"
],
"enumDescriptions": [
"Always show adjustment hints as prefix (`*expr`).",
"Always show adjustment hints as postfix (`expr.*`).",
"Show prefix or postfix depending on which uses less parenthesis, prefering prefix.",
"Show prefix or postfix depending on which uses less parenthesis, prefering postfix."
]
}, },
"rust-analyzer.inlayHints.lifetimeElisionHints.enable": { "rust-analyzer.inlayHints.lifetimeElisionHints.enable": {
"markdownDescription": "Whether to show inlay type hints for elided lifetimes in function signatures.", "markdownDescription": "Whether to show inlay type hints for elided lifetimes in function signatures.",