feat: Allow reborrow inlay hints to be restricted to mutable reborrows only

This commit is contained in:
Lukas Wirth 2022-05-12 13:39:32 +02:00
parent 4b505ce0f9
commit c2190ad87c
6 changed files with 76 additions and 27 deletions

View file

@ -19,7 +19,7 @@ pub struct InlayHintsConfig {
pub type_hints: bool, pub type_hints: bool,
pub parameter_hints: bool, pub parameter_hints: bool,
pub chaining_hints: bool, pub chaining_hints: bool,
pub reborrow_hints: bool, pub reborrow_hints: ReborrowHints,
pub closure_return_type_hints: bool, pub closure_return_type_hints: bool,
pub lifetime_elision_hints: LifetimeElisionHints, pub lifetime_elision_hints: LifetimeElisionHints,
pub param_names_for_lifetime_elision_hints: bool, pub param_names_for_lifetime_elision_hints: bool,
@ -34,6 +34,13 @@ pub enum LifetimeElisionHints {
Never, Never,
} }
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ReborrowHints {
Always,
MutableOnly,
Never,
}
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub enum InlayKind { pub enum InlayKind {
ChainingHint, ChainingHint,
@ -372,18 +379,20 @@ fn reborrow_hints(
config: &InlayHintsConfig, config: &InlayHintsConfig,
expr: &ast::Expr, expr: &ast::Expr,
) -> Option<()> { ) -> Option<()> {
if !config.reborrow_hints { if config.reborrow_hints == ReborrowHints::Never {
return None; return None;
} }
let mutability = sema.is_implicit_reborrow(expr)?; let mutability = sema.is_implicit_reborrow(expr)?;
let label = match mutability {
hir::Mutability::Shared if config.reborrow_hints != ReborrowHints::MutableOnly => "&*",
hir::Mutability::Mut => "&mut *",
_ => return None,
};
acc.push(InlayHint { acc.push(InlayHint {
range: expr.syntax().text_range(), range: expr.syntax().text_range(),
kind: InlayKind::ImplicitReborrow, kind: InlayKind::ImplicitReborrow,
label: match mutability { label: SmolStr::new_inline(label),
hir::Mutability::Shared => SmolStr::new_inline("&*"),
hir::Mutability::Mut => SmolStr::new_inline("&mut *"),
},
}); });
Some(()) Some(())
} }
@ -848,6 +857,7 @@ mod tests {
use syntax::{TextRange, TextSize}; use syntax::{TextRange, TextSize};
use test_utils::extract_annotations; use test_utils::extract_annotations;
use crate::inlay_hints::ReborrowHints;
use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints}; use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints};
const DISABLED_CONFIG: InlayHintsConfig = InlayHintsConfig { const DISABLED_CONFIG: InlayHintsConfig = InlayHintsConfig {
@ -858,7 +868,7 @@ mod tests {
lifetime_elision_hints: LifetimeElisionHints::Never, lifetime_elision_hints: LifetimeElisionHints::Never,
hide_named_constructor_hints: false, hide_named_constructor_hints: false,
closure_return_type_hints: false, closure_return_type_hints: false,
reborrow_hints: false, reborrow_hints: ReborrowHints::Always,
param_names_for_lifetime_elision_hints: false, param_names_for_lifetime_elision_hints: false,
max_length: None, max_length: None,
}; };
@ -866,7 +876,7 @@ mod tests {
type_hints: true, type_hints: true,
parameter_hints: true, parameter_hints: true,
chaining_hints: true, chaining_hints: true,
reborrow_hints: true, reborrow_hints: ReborrowHints::Always,
closure_return_type_hints: true, closure_return_type_hints: true,
lifetime_elision_hints: LifetimeElisionHints::Always, lifetime_elision_hints: LifetimeElisionHints::Always,
..DISABLED_CONFIG ..DISABLED_CONFIG
@ -2146,7 +2156,11 @@ impl () {
#[test] #[test]
fn hints_implicit_reborrow() { fn hints_implicit_reborrow() {
check_with_config( check_with_config(
InlayHintsConfig { reborrow_hints: true, parameter_hints: true, ..DISABLED_CONFIG }, InlayHintsConfig {
reborrow_hints: ReborrowHints::Always,
parameter_hints: true,
..DISABLED_CONFIG
},
r#" r#"
fn __() { fn __() {
let unique = &mut (); let unique = &mut ();

View file

@ -80,7 +80,7 @@ pub use crate::{
folding_ranges::{Fold, FoldKind}, folding_ranges::{Fold, FoldKind},
highlight_related::{HighlightRelatedConfig, HighlightedRange}, highlight_related::{HighlightRelatedConfig, HighlightedRange},
hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult}, hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult},
inlay_hints::{InlayHint, InlayHintsConfig, InlayKind, LifetimeElisionHints}, inlay_hints::{InlayHint, InlayHintsConfig, InlayKind, LifetimeElisionHints, ReborrowHints},
join_lines::JoinLinesConfig, join_lines::JoinLinesConfig,
markup::Markup, markup::Markup,
moniker::{MonikerKind, MonikerResult, PackageInformation}, moniker::{MonikerKind, MonikerResult, PackageInformation},

View file

@ -12,12 +12,10 @@ use ide_db::{
use syntax::{AstNode, SyntaxKind::*, SyntaxToken, TextRange, T}; use syntax::{AstNode, SyntaxKind::*, SyntaxToken, TextRange, T};
use crate::{ use crate::{
hover::hover_for_definition, Analysis, Fold, HoverConfig, HoverDocFormat, HoverResult, hover::hover_for_definition,
InlayHint, InlayHintsConfig, TryToNav,
};
use crate::{
moniker::{crate_for_file, def_to_moniker, MonikerResult}, moniker::{crate_for_file, def_to_moniker, MonikerResult},
LifetimeElisionHints, Analysis, Fold, HoverConfig, HoverDocFormat, HoverResult, InlayHint, InlayHintsConfig,
TryToNav,
}; };
/// A static representation of fully analyzed source code. /// A static representation of fully analyzed source code.
@ -112,8 +110,8 @@ impl StaticIndex<'_> {
parameter_hints: true, parameter_hints: true,
chaining_hints: true, chaining_hints: true,
closure_return_type_hints: true, closure_return_type_hints: true,
lifetime_elision_hints: LifetimeElisionHints::Never, lifetime_elision_hints: crate::LifetimeElisionHints::Never,
reborrow_hints: false, reborrow_hints: crate::ReborrowHints::Never,
hide_named_constructor_hints: false, hide_named_constructor_hints: false,
param_names_for_lifetime_elision_hints: false, param_names_for_lifetime_elision_hints: false,
max_length: Some(25), max_length: Some(25),

View file

@ -12,8 +12,7 @@ use std::{ffi::OsString, fmt, iter, path::PathBuf};
use flycheck::FlycheckConfig; use flycheck::FlycheckConfig;
use ide::{ use ide::{
AssistConfig, CompletionConfig, DiagnosticsConfig, ExprFillDefaultMode, HighlightRelatedConfig, AssistConfig, CompletionConfig, DiagnosticsConfig, ExprFillDefaultMode, HighlightRelatedConfig,
HoverConfig, HoverDocFormat, InlayHintsConfig, JoinLinesConfig, LifetimeElisionHints, Snippet, HoverConfig, HoverDocFormat, InlayHintsConfig, JoinLinesConfig, Snippet, SnippetScope,
SnippetScope,
}; };
use ide_db::{ use ide_db::{
imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind}, imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
@ -263,7 +262,7 @@ config_data! {
/// site. /// site.
inlayHints_parameterHints_enable: bool = "true", inlayHints_parameterHints_enable: bool = "true",
/// Whether to show inlay type hints for compiler inserted reborrows. /// Whether to show inlay type hints for compiler inserted reborrows.
inlayHints_reborrowHints_enable: bool = "false", inlayHints_reborrowHints_enable: ReborrowHintsDef = "\"never\"",
/// Whether to render leading colons for type hints, and trailing colons for parameter hints. /// Whether to render leading colons for type hints, and trailing colons for parameter hints.
inlayHints_renderColons: bool = "true", inlayHints_renderColons: bool = "true",
/// Whether to show inlay type hints for variables. /// Whether to show inlay type hints for variables.
@ -986,12 +985,16 @@ impl Config {
chaining_hints: self.data.inlayHints_chainingHints_enable, chaining_hints: self.data.inlayHints_chainingHints_enable,
closure_return_type_hints: self.data.inlayHints_closureReturnTypeHints_enable, closure_return_type_hints: self.data.inlayHints_closureReturnTypeHints_enable,
lifetime_elision_hints: match self.data.inlayHints_lifetimeElisionHints_enable { lifetime_elision_hints: match self.data.inlayHints_lifetimeElisionHints_enable {
LifetimeElisionDef::Always => LifetimeElisionHints::Always, LifetimeElisionDef::Always => ide::LifetimeElisionHints::Always,
LifetimeElisionDef::Never => LifetimeElisionHints::Never, LifetimeElisionDef::Never => ide::LifetimeElisionHints::Never,
LifetimeElisionDef::SkipTrivial => LifetimeElisionHints::SkipTrivial, LifetimeElisionDef::SkipTrivial => ide::LifetimeElisionHints::SkipTrivial,
}, },
hide_named_constructor_hints: self.data.inlayHints_typeHints_hideNamedConstructor, hide_named_constructor_hints: self.data.inlayHints_typeHints_hideNamedConstructor,
reborrow_hints: self.data.inlayHints_reborrowHints_enable, reborrow_hints: match self.data.inlayHints_reborrowHints_enable {
ReborrowHintsDef::Always => ide::ReborrowHints::Always,
ReborrowHintsDef::Never => ide::ReborrowHints::Never,
ReborrowHintsDef::Mutable => ide::ReborrowHints::MutableOnly,
},
param_names_for_lifetime_elision_hints: self param_names_for_lifetime_elision_hints: self
.data .data
.inlayHints_lifetimeElisionHints_useParameterNames, .inlayHints_lifetimeElisionHints_useParameterNames,
@ -1293,6 +1296,7 @@ macro_rules! named_unit_variant {
mod de_unit_v { mod de_unit_v {
named_unit_variant!(all); named_unit_variant!(all);
named_unit_variant!(skip_trivial); named_unit_variant!(skip_trivial);
named_unit_variant!(mutable);
} }
#[derive(Deserialize, Debug, Clone, Copy)] #[derive(Deserialize, Debug, Clone, Copy)]
@ -1404,6 +1408,17 @@ enum LifetimeElisionDef {
SkipTrivial, SkipTrivial,
} }
#[derive(Deserialize, Debug, Clone)]
#[serde(untagged)]
enum ReborrowHintsDef {
#[serde(deserialize_with = "true_or_always")]
Always,
#[serde(deserialize_with = "false_or_never")]
Never,
#[serde(deserialize_with = "de_unit_v::mutable")]
Mutable,
}
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
enum ImportPrefixDef { enum ImportPrefixDef {
@ -1675,6 +1690,15 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
"Only show lifetime elision hints if a return type is involved." "Only show lifetime elision hints if a return type is involved."
], ],
}, },
"ReborrowHintsDef" => set! {
"type": ["string", "boolean"],
"enum": ["always", "never", "mutable"],
"enumDescriptions": [
"Always show reborrow hints.",
"Never show reborrow hints.",
"Only show mutable reborrow hints."
],
},
"CargoFeatures" => set! { "CargoFeatures" => set! {
"type": ["string", "array"], "type": ["string", "array"],
"items": { "type": "string" }, "items": { "type": "string" },

View file

@ -365,7 +365,7 @@ Maximum length for inlay hints. Set to null to have an unlimited length.
Whether to show function parameter name inlay hints at the call Whether to show function parameter name inlay hints at the call
site. site.
-- --
[[rust-analyzer.inlayHints.reborrowHints.enable]]rust-analyzer.inlayHints.reborrowHints.enable (default: `false`):: [[rust-analyzer.inlayHints.reborrowHints.enable]]rust-analyzer.inlayHints.reborrowHints.enable (default: `"never"`)::
+ +
-- --
Whether to show inlay type hints for compiler inserted reborrows. Whether to show inlay type hints for compiler inserted reborrows.

View file

@ -810,8 +810,21 @@
}, },
"rust-analyzer.inlayHints.reborrowHints.enable": { "rust-analyzer.inlayHints.reborrowHints.enable": {
"markdownDescription": "Whether to show inlay type hints for compiler inserted reborrows.", "markdownDescription": "Whether to show inlay type hints for compiler inserted reborrows.",
"default": false, "default": "never",
"type": "boolean" "type": [
"string",
"boolean"
],
"enum": [
"always",
"never",
"mutable"
],
"enumDescriptions": [
"Always show reborrow hints.",
"Never show reborrow hints.",
"Only show mutable reborrow hints."
]
}, },
"rust-analyzer.inlayHints.renderColons": { "rust-analyzer.inlayHints.renderColons": {
"markdownDescription": "Whether to render leading colons for type hints, and trailing colons for parameter hints.", "markdownDescription": "Whether to render leading colons for type hints, and trailing colons for parameter hints.",