Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/inlay_hints/binding_mode.rs')
-rw-r--r--crates/ide/src/inlay_hints/binding_mode.rs106
1 files changed, 65 insertions, 41 deletions
diff --git a/crates/ide/src/inlay_hints/binding_mode.rs b/crates/ide/src/inlay_hints/binding_mode.rs
index d1c0677863..cfe8657fd0 100644
--- a/crates/ide/src/inlay_hints/binding_mode.rs
+++ b/crates/ide/src/inlay_hints/binding_mode.rs
@@ -2,13 +2,16 @@
//! ```no_run
//! let /* & */ (/* ref */ x,) = &(0,);
//! ```
+use std::mem;
+
use hir::Mutability;
use ide_db::famous_defs::FamousDefs;
+use ide_db::text_edit::TextEditBuilder;
use span::EditionedFileId;
use syntax::ast::{self, AstNode};
-use crate::{InlayHint, InlayHintPosition, InlayHintsConfig, InlayKind};
+use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind};
pub(super) fn hints(
acc: &mut Vec<InlayHint>,
@@ -21,16 +24,7 @@ pub(super) fn hints(
return None;
}
- let outer_paren_pat = pat
- .syntax()
- .ancestors()
- .skip(1)
- .map_while(ast::Pat::cast)
- .map_while(|pat| match pat {
- ast::Pat::ParenPat(pat) => Some(pat),
- _ => None,
- })
- .last();
+ let outer_paren_pat = pat.syntax().ancestors().skip(1).map_while(ast::ParenPat::cast).last();
let range = outer_paren_pat.as_ref().map_or_else(
|| match pat {
// for ident patterns that @ bind a name, render the un-ref patterns in front of the inner pattern
@@ -42,7 +36,18 @@ pub(super) fn hints(
},
|it| it.syntax().text_range(),
);
+ let mut hint = InlayHint {
+ range,
+ kind: InlayKind::BindingMode,
+ label: InlayHintLabel::default(),
+ text_edit: None,
+ position: InlayHintPosition::Before,
+ pad_left: false,
+ pad_right: false,
+ resolve_parent: Some(pat.syntax().text_range()),
+ };
let pattern_adjustments = sema.pattern_adjustments(pat);
+ let mut was_mut_last = false;
pattern_adjustments.iter().for_each(|ty| {
let reference = ty.is_reference();
let mut_reference = ty.is_mutable_reference();
@@ -51,41 +56,36 @@ pub(super) fn hints(
(true, false) => "&",
_ => return,
};
- acc.push(InlayHint {
- range,
- kind: InlayKind::BindingMode,
- label: r.into(),
- text_edit: None,
- position: InlayHintPosition::Before,
- pad_left: false,
- pad_right: mut_reference,
- resolve_parent: Some(pat.syntax().text_range()),
- });
+ if mem::replace(&mut was_mut_last, mut_reference) {
+ hint.label.append_str(" ");
+ }
+ hint.label.append_str(r);
});
+ hint.pad_right = was_mut_last;
+ let acc_base = acc.len();
match pat {
ast::Pat::IdentPat(pat) if pat.ref_token().is_none() && pat.mut_token().is_none() => {
let bm = sema.binding_mode_of_pat(pat)?;
let bm = match bm {
- hir::BindingMode::Move => return None,
- hir::BindingMode::Ref(Mutability::Mut) => "ref mut",
- hir::BindingMode::Ref(Mutability::Shared) => "ref",
+ hir::BindingMode::Move => None,
+ hir::BindingMode::Ref(Mutability::Mut) => Some("ref mut"),
+ hir::BindingMode::Ref(Mutability::Shared) => Some("ref"),
};
- acc.push(InlayHint {
- range: pat.syntax().text_range(),
- kind: InlayKind::BindingMode,
- label: bm.into(),
- text_edit: None,
- position: InlayHintPosition::Before,
- pad_left: false,
- pad_right: true,
- resolve_parent: Some(pat.syntax().text_range()),
- });
+ if let Some(bm) = bm {
+ acc.push(InlayHint {
+ range: pat.syntax().text_range(),
+ kind: InlayKind::BindingMode,
+ label: bm.into(),
+ text_edit: None,
+ position: InlayHintPosition::Before,
+ pad_left: false,
+ pad_right: true,
+ resolve_parent: Some(pat.syntax().text_range()),
+ });
+ }
}
ast::Pat::OrPat(pat) if !pattern_adjustments.is_empty() && outer_paren_pat.is_none() => {
- acc.push(InlayHint::opening_paren_before(
- InlayKind::BindingMode,
- pat.syntax().text_range(),
- ));
+ hint.label.append_str("(");
acc.push(InlayHint::closing_paren_after(
InlayKind::BindingMode,
pat.syntax().text_range(),
@@ -93,6 +93,24 @@ pub(super) fn hints(
}
_ => (),
}
+ if !hint.label.parts.is_empty() {
+ acc.push(hint);
+ }
+
+ if let hints @ [_, ..] = &mut acc[acc_base..] {
+ let mut edit = TextEditBuilder::default();
+ for h in &mut *hints {
+ edit.insert(
+ match h.position {
+ InlayHintPosition::Before => h.range.start(),
+ InlayHintPosition::After => h.range.end(),
+ },
+ h.label.parts.iter().map(|p| &*p.text).collect(),
+ );
+ }
+ let edit = edit.finish();
+ hints.iter_mut().for_each(|h| h.text_edit = Some(edit.clone()));
+ }
Some(())
}
@@ -117,6 +135,13 @@ fn __(
(x,): &mut (u32,)
//^^^^&mut
//^ ref mut
+ (x,): &mut &mut (u32,)
+ //^^^^&mut &mut
+ //^ ref mut
+ (x,): &&(u32,)
+ //^^^^&&
+ //^ ref
+
) {
let (x,) = (0,);
let (x,) = &(0,);
@@ -136,11 +161,10 @@ fn __(
}
match &(0,) {
(x,) | (x,) => (),
- //^^^^^^^^^^^&
+ //^^^^^^^^^^^)
+ //^^^^^^^^^^^&(
//^ ref
//^ ref
- //^^^^^^^^^^^(
- //^^^^^^^^^^^)
((x,) | (x,)) => (),
//^^^^^^^^^^^^^&
//^ ref