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

View File

@ -11,7 +11,7 @@ use syntax::{
ted,
};
use crate::{AdjustmentHints, InlayHint, InlayHintsConfig, InlayKind};
use crate::{AdjustmentHints, AdjustmentHintsMode, InlayHint, InlayHintsConfig, InlayKind};
pub(super) fn hints(
acc: &mut Vec<InlayHint>,
@ -40,8 +40,8 @@ pub(super) fn hints(
let desc_expr = descended.as_ref().unwrap_or(expr);
let adjustments = sema.expr_adjustments(desc_expr).filter(|it| !it.is_empty())?;
let (needs_outer_parens, needs_inner_parens) =
needs_parens_for_adjustment_hints(expr, config.adjustment_hints_postfix);
let (postfix, needs_outer_parens, needs_inner_parens) =
mode_and_needs_parens_for_adjustment_hints(expr, config.adjustment_hints_mode);
if needs_outer_parens {
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 {
range: expr.syntax().text_range(),
kind: InlayKind::OpeningParenthesis,
@ -68,7 +68,7 @@ pub(super) fn hints(
}
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();
&mut tmp0
} else {
@ -112,20 +112,16 @@ pub(super) fn hints(
};
acc.push(InlayHint {
range: expr.syntax().text_range(),
kind: if config.adjustment_hints_postfix {
kind: if postfix {
InlayKind::AdjustmentHintPostfix
} else {
InlayKind::AdjustmentHint
},
label: if config.adjustment_hints_postfix {
format!(".{}", text.trim_end()).into()
} else {
text.into()
},
label: if postfix { format!(".{}", text.trim_end()).into() } else { text.into() },
tooltip: None,
});
}
if !config.adjustment_hints_postfix && needs_inner_parens {
if !postfix && needs_inner_parens {
acc.push(InlayHint {
range: expr.syntax().text_range(),
kind: InlayKind::OpeningParenthesis,
@ -150,6 +146,41 @@ pub(super) fn hints(
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`,
/// if we are going to add (`postfix`) adjustments hints to it.
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 {
use crate::{
inlay_hints::tests::{check_with_config, DISABLED_CONFIG},
AdjustmentHints, InlayHintsConfig,
AdjustmentHints, AdjustmentHintsMode, InlayHintsConfig,
};
#[test]
@ -333,7 +364,7 @@ impl Struct {
check_with_config(
InlayHintsConfig {
adjustment_hints: AdjustmentHints::Always,
adjustment_hints_postfix: true,
adjustment_hints_mode: AdjustmentHintsMode::Postfix,
..DISABLED_CONFIG
},
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]
fn never_to_never_is_never_shown() {
check_with_config(

View File

@ -81,8 +81,8 @@ pub use crate::{
highlight_related::{HighlightRelatedConfig, HighlightedRange},
hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult},
inlay_hints::{
AdjustmentHints, ClosureReturnTypeHints, DiscriminantHints, InlayHint, InlayHintLabel,
InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints, InlayHint,
InlayHintLabel, InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
},
join_lines::JoinLinesConfig,
markup::Markup,

View File

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

View File

@ -333,8 +333,8 @@ config_data! {
inlayHints_expressionAdjustmentHints_enable: AdjustmentHintsDef = "\"never\"",
/// Whether to hide inlay hints for type adjustments outside of `unsafe` blocks.
inlayHints_expressionAdjustmentHints_hideOutsideUnsafe: bool = "false",
/// Whether to show inlay hints for type adjustments as postfix ops (`.*` instead of `*`, etc).
inlayHints_expressionAdjustmentHints_postfix: bool = "false",
/// Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc).
inlayHints_expressionAdjustmentHints_mode: AdjustmentHintsModeDef = "\"prefix\"",
/// Whether to show inlay type hints for elided lifetimes in function signatures.
inlayHints_lifetimeElisionHints_enable: LifetimeElisionDef = "\"never\"",
/// 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,
},
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
.data
.inlayHints_expressionAdjustmentHints_hideOutsideUnsafe,
@ -1771,6 +1776,15 @@ enum DiscriminantHintsDef {
Fieldless,
}
#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
enum AdjustmentHintsModeDef {
Prefix,
Postfix,
PreferPrefix,
PreferPostfix,
}
#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
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."
]
},
"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! {
"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.
--
[[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"`)::
+

View File

@ -1000,10 +1000,22 @@
"default": false,
"type": "boolean"
},
"rust-analyzer.inlayHints.expressionAdjustmentHints.postfix": {
"markdownDescription": "Whether to show inlay hints for type adjustments as postfix ops (`.*` instead of `*`, etc).",
"default": false,
"type": "boolean"
"rust-analyzer.inlayHints.expressionAdjustmentHints.mode": {
"markdownDescription": "Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc).",
"default": "prefix",
"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": {
"markdownDescription": "Whether to show inlay type hints for elided lifetimes in function signatures.",