Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #18373 from Veykril/veykril/push-mzumrrvynxqu
internal: Merge separate inlay hints targeting same range
Lukas Wirth 2024-10-22
parent 1b00f08 · parent 3ae93bc · commit b35d93c
-rw-r--r--crates/ide/src/inlay_hints.rs12
-rw-r--r--crates/ide/src/inlay_hints/adjustment.rs228
-rw-r--r--crates/ide/src/inlay_hints/binding_mode.rs40
-rw-r--r--crates/ide/src/inlay_hints/closure_captures.rs119
4 files changed, 153 insertions, 246 deletions
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 97e712356b..fcf262877d 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -475,6 +475,18 @@ impl InlayHintLabel {
}
}
+ pub fn append_part(&mut self, part: InlayHintLabelPart) {
+ if part.linked_location.is_none() && part.tooltip.is_none() {
+ if let Some(InlayHintLabelPart { text, linked_location: None, tooltip: None }) =
+ self.parts.last_mut()
+ {
+ text.push_str(&part.text);
+ return;
+ }
+ }
+ self.parts.push(part);
+ }
+
pub fn needs_resolve(&self) -> bool {
self.parts.iter().any(|part| part.linked_location.is_some() || part.tooltip.is_some())
}
diff --git a/crates/ide/src/inlay_hints/adjustment.rs b/crates/ide/src/inlay_hints/adjustment.rs
index c37c469dff..ab44d8c3b5 100644
--- a/crates/ide/src/inlay_hints/adjustment.rs
+++ b/crates/ide/src/inlay_hints/adjustment.rs
@@ -17,8 +17,8 @@ use syntax::{
};
use crate::{
- AdjustmentHints, AdjustmentHintsMode, InlayHint, InlayHintLabel, InlayHintPosition,
- InlayHintsConfig, InlayKind, InlayTooltip,
+ AdjustmentHints, AdjustmentHintsMode, InlayHint, InlayHintLabel, InlayHintLabelPart,
+ InlayHintPosition, InlayHintsConfig, InlayKind, InlayTooltip,
};
pub(super) fn hints(
@@ -64,19 +64,34 @@ pub(super) fn hints(
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::opening_paren_before(
- InlayKind::Adjustment,
- expr.syntax().text_range(),
- ));
+ let range = expr.syntax().text_range();
+ let mut pre = InlayHint {
+ range,
+ position: InlayHintPosition::Before,
+ pad_left: false,
+ pad_right: false,
+ kind: InlayKind::Adjustment,
+ label: InlayHintLabel::default(),
+ text_edit: None,
+ resolve_parent: Some(range),
+ };
+ let mut post = InlayHint {
+ range,
+ position: InlayHintPosition::After,
+ pad_left: false,
+ pad_right: false,
+ kind: InlayKind::Adjustment,
+ label: InlayHintLabel::default(),
+ text_edit: None,
+ resolve_parent: Some(range),
+ };
+
+ if needs_outer_parens || (postfix && needs_inner_parens) {
+ pre.label.append_str("(");
}
if postfix && needs_inner_parens {
- acc.push(InlayHint::opening_paren_before(
- InlayKind::Adjustment,
- expr.syntax().text_range(),
- ));
- acc.push(InlayHint::closing_paren_after(InlayKind::Adjustment, expr.syntax().text_range()));
+ post.label.append_str(")");
}
let mut iter = if postfix {
@@ -138,35 +153,28 @@ pub(super) fn hints(
}
_ => continue,
};
- let label = InlayHintLabel::simple(
- if postfix { format!(".{}", text.trim_end()) } else { text.to_owned() },
- Some(InlayTooltip::Markdown(format!(
+ let label = InlayHintLabelPart {
+ text: if postfix { format!(".{}", text.trim_end()) } else { text.to_owned() },
+ linked_location: None,
+ tooltip: Some(InlayTooltip::Markdown(format!(
"`{}` → `{}` ({coercion} coercion)",
source.display(sema.db, file_id.edition()),
target.display(sema.db, file_id.edition()),
))),
- None,
- );
- acc.push(InlayHint {
- range: expr.syntax().text_range(),
- pad_left: false,
- pad_right: false,
- position: if postfix { InlayHintPosition::After } else { InlayHintPosition::Before },
- kind: InlayKind::Adjustment,
- label,
- text_edit: None,
- resolve_parent: Some(expr.syntax().text_range()),
- });
+ };
+ if postfix { &mut post } else { &mut pre }.label.append_part(label);
}
if !postfix && needs_inner_parens {
- acc.push(InlayHint::opening_paren_before(
- InlayKind::Adjustment,
- expr.syntax().text_range(),
- ));
- acc.push(InlayHint::closing_paren_after(InlayKind::Adjustment, expr.syntax().text_range()));
+ pre.label.append_str("(");
+ }
+ if needs_outer_parens || (!postfix && needs_inner_parens) {
+ post.label.append_str(")");
}
- if needs_outer_parens {
- acc.push(InlayHint::closing_paren_after(InlayKind::Adjustment, expr.syntax().text_range()));
+ if !pre.label.parts.is_empty() {
+ acc.push(pre);
+ }
+ if !post.label.parts.is_empty() {
+ acc.push(post);
}
Some(())
}
@@ -293,25 +301,19 @@ fn main() {
let _: u32 = loop {};
//^^^^^^^<never-to-any>
let _: &u32 = &mut 0;
- //^^^^^^&
- //^^^^^^*
+ //^^^^^^&*
let _: &mut u32 = &mut 0;
- //^^^^^^&mut $
- //^^^^^^*
+ //^^^^^^&mut *
let _: *const u32 = &mut 0;
- //^^^^^^&raw const $
- //^^^^^^*
+ //^^^^^^&raw const *
let _: *mut u32 = &mut 0;
- //^^^^^^&raw mut $
- //^^^^^^*
+ //^^^^^^&raw mut *
let _: fn() = main;
//^^^^<fn-item-to-fn-pointer>
let _: unsafe fn() = main;
- //^^^^<safe-fn-pointer-to-unsafe-fn-pointer>
- //^^^^<fn-item-to-fn-pointer>
+ //^^^^<safe-fn-pointer-to-unsafe-fn-pointer><fn-item-to-fn-pointer>
let _: unsafe fn() = main as fn();
- //^^^^^^^^^^^^<safe-fn-pointer-to-unsafe-fn-pointer>
- //^^^^^^^^^^^^(
+ //^^^^^^^^^^^^<safe-fn-pointer-to-unsafe-fn-pointer>(
//^^^^^^^^^^^^)
//^^^^<fn-item-to-fn-pointer>
let _: fn() = || {};
@@ -319,72 +321,51 @@ fn main() {
let _: unsafe fn() = || {};
//^^^^^<closure-to-unsafe-fn-pointer>
let _: *const u32 = &mut 0u32 as *mut u32;
- //^^^^^^^^^^^^^^^^^^^^^<mut-ptr-to-const-ptr>
- //^^^^^^^^^^^^^^^^^^^^^(
+ //^^^^^^^^^^^^^^^^^^^^^<mut-ptr-to-const-ptr>(
//^^^^^^^^^^^^^^^^^^^^^)
- //^^^^^^^^^&raw mut $
- //^^^^^^^^^*
+ //^^^^^^^^^&raw mut *
let _: &mut [_] = &mut [0; 0];
- //^^^^^^^^^^^<unsize>
- //^^^^^^^^^^^&mut $
- //^^^^^^^^^^^*
+ //^^^^^^^^^^^<unsize>&mut *
Struct.consume();
Struct.by_ref();
- //^^^^^^(
- //^^^^^^&
+ //^^^^^^(&
//^^^^^^)
Struct.by_ref_mut();
- //^^^^^^(
- //^^^^^^&mut $
+ //^^^^^^(&mut $
//^^^^^^)
(&Struct).consume();
//^^^^^^^*
(&Struct).by_ref();
- //^^^^^^^&
- //^^^^^^^*
+ //^^^^^^^&*
(&mut Struct).consume();
//^^^^^^^^^^^*
(&mut Struct).by_ref();
- //^^^^^^^^^^^&
- //^^^^^^^^^^^*
+ //^^^^^^^^^^^&*
(&mut Struct).by_ref_mut();
- //^^^^^^^^^^^&mut $
- //^^^^^^^^^^^*
+ //^^^^^^^^^^^&mut *
// Check that block-like expressions don't duplicate hints
let _: &mut [u32] = (&mut []);
- //^^^^^^^<unsize>
- //^^^^^^^&mut $
- //^^^^^^^*
+ //^^^^^^^<unsize>&mut *
let _: &mut [u32] = { &mut [] };
- //^^^^^^^<unsize>
- //^^^^^^^&mut $
- //^^^^^^^*
+ //^^^^^^^<unsize>&mut *
let _: &mut [u32] = unsafe { &mut [] };
- //^^^^^^^<unsize>
- //^^^^^^^&mut $
- //^^^^^^^*
+ //^^^^^^^<unsize>&mut *
let _: &mut [u32] = if true {
&mut []
- //^^^^^^^<unsize>
- //^^^^^^^&mut $
- //^^^^^^^*
+ //^^^^^^^<unsize>&mut *
} else {
loop {}
//^^^^^^^<never-to-any>
};
let _: &mut [u32] = match () { () => &mut [] };
- //^^^^^^^<unsize>
- //^^^^^^^&mut $
- //^^^^^^^*
+ //^^^^^^^<unsize>&mut *
let _: &mut dyn Fn() = &mut || ();
- //^^^^^^^^^^<unsize>
- //^^^^^^^^^^&mut $
- //^^^^^^^^^^*
+ //^^^^^^^^^^<unsize>&mut *
() == ();
// ^^&
// ^^&
@@ -393,16 +374,13 @@ fn main() {
// ^^^^&
let closure: dyn Fn = || ();
closure();
- //^^^^^^^(
- //^^^^^^^&
+ //^^^^^^^(&
//^^^^^^^)
Struct[0];
- //^^^^^^(
- //^^^^^^&
+ //^^^^^^(&
//^^^^^^)
&mut Struct[0];
- //^^^^^^(
- //^^^^^^&mut $
+ //^^^^^^(&mut $
//^^^^^^)
}
@@ -442,72 +420,46 @@ fn main() {
(&Struct).consume();
//^^^^^^^(
- //^^^^^^^)
- //^^^^^^^.*
+ //^^^^^^^).*
(&Struct).by_ref();
//^^^^^^^(
- //^^^^^^^)
- //^^^^^^^.*
- //^^^^^^^.&
+ //^^^^^^^).*.&
(&mut Struct).consume();
//^^^^^^^^^^^(
- //^^^^^^^^^^^)
- //^^^^^^^^^^^.*
+ //^^^^^^^^^^^).*
(&mut Struct).by_ref();
//^^^^^^^^^^^(
- //^^^^^^^^^^^)
- //^^^^^^^^^^^.*
- //^^^^^^^^^^^.&
+ //^^^^^^^^^^^).*.&
(&mut Struct).by_ref_mut();
//^^^^^^^^^^^(
- //^^^^^^^^^^^)
- //^^^^^^^^^^^.*
- //^^^^^^^^^^^.&mut
+ //^^^^^^^^^^^).*.&mut
// Check that block-like expressions don't duplicate hints
let _: &mut [u32] = (&mut []);
//^^^^^^^(
- //^^^^^^^)
- //^^^^^^^.*
- //^^^^^^^.&mut
- //^^^^^^^.<unsize>
+ //^^^^^^^).*.&mut.<unsize>
let _: &mut [u32] = { &mut [] };
//^^^^^^^(
- //^^^^^^^)
- //^^^^^^^.*
- //^^^^^^^.&mut
- //^^^^^^^.<unsize>
+ //^^^^^^^).*.&mut.<unsize>
let _: &mut [u32] = unsafe { &mut [] };
//^^^^^^^(
- //^^^^^^^)
- //^^^^^^^.*
- //^^^^^^^.&mut
- //^^^^^^^.<unsize>
+ //^^^^^^^).*.&mut.<unsize>
let _: &mut [u32] = if true {
&mut []
//^^^^^^^(
- //^^^^^^^)
- //^^^^^^^.*
- //^^^^^^^.&mut
- //^^^^^^^.<unsize>
+ //^^^^^^^).*.&mut.<unsize>
} else {
loop {}
//^^^^^^^.<never-to-any>
};
let _: &mut [u32] = match () { () => &mut [] };
//^^^^^^^(
- //^^^^^^^)
- //^^^^^^^.*
- //^^^^^^^.&mut
- //^^^^^^^.<unsize>
+ //^^^^^^^).*.&mut.<unsize>
let _: &mut dyn Fn() = &mut || ();
//^^^^^^^^^^(
- //^^^^^^^^^^)
- //^^^^^^^^^^.*
- //^^^^^^^^^^.&mut
- //^^^^^^^^^^.<unsize>
+ //^^^^^^^^^^).*.&mut.<unsize>
() == ();
// ^^.&
// ^^.&
@@ -619,9 +571,7 @@ fn or_else() {
r#"
unsafe fn enabled() {
f(&&());
- //^^^^&
- //^^^^*
- //^^^^*
+ //^^^^&**
}
fn disabled() {
@@ -633,9 +583,7 @@ fn mixed() {
unsafe {
f(&&());
- //^^^^&
- //^^^^*
- //^^^^*
+ //^^^^&**
}
}
@@ -644,9 +592,7 @@ const _: () = {
unsafe {
f(&&());
- //^^^^&
- //^^^^*
- //^^^^*
+ //^^^^&**
}
};
@@ -655,18 +601,14 @@ static STATIC: () = {
unsafe {
f(&&());
- //^^^^&
- //^^^^*
- //^^^^*
+ //^^^^&**
}
};
enum E {
Disable = { f(&&()); 0 },
Enable = unsafe { f(&&()); 1 },
- //^^^^&
- //^^^^*
- //^^^^*
+ //^^^^&**
}
const fn f(_: &()) {}
@@ -692,8 +634,7 @@ fn a() {
_ = Struct.by_ref();
_ = unsafe { Struct.by_ref() };
- //^^^^^^(
- //^^^^^^&
+ //^^^^^^(&
//^^^^^^)
}
"#,
@@ -726,10 +667,7 @@ trait T<RHS = Self> {}
fn hello(it: &&[impl T]) {
it.len();
- //^^(
- //^^&
- //^^*
- //^^*
+ //^^(&**
//^^)
}
"#,
diff --git a/crates/ide/src/inlay_hints/binding_mode.rs b/crates/ide/src/inlay_hints/binding_mode.rs
index d1c0677863..beba2ad748 100644
--- a/crates/ide/src/inlay_hints/binding_mode.rs
+++ b/crates/ide/src/inlay_hints/binding_mode.rs
@@ -2,13 +2,15 @@
//! ```no_run
//! let /* & */ (/* ref */ x,) = &(0,);
//! ```
+use std::mem;
+
use hir::Mutability;
use ide_db::famous_defs::FamousDefs;
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>,
@@ -42,7 +44,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,17 +64,15 @@ 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;
+ if !hint.label.parts.is_empty() {
+ acc.push(hint);
+ }
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)?;
@@ -117,6 +128,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,);
diff --git a/crates/ide/src/inlay_hints/closure_captures.rs b/crates/ide/src/inlay_hints/closure_captures.rs
index f399bd01d0..628ddc6154 100644
--- a/crates/ide/src/inlay_hints/closure_captures.rs
+++ b/crates/ide/src/inlay_hints/closure_captures.rs
@@ -7,7 +7,9 @@ use stdx::{never, TupleExt};
use syntax::ast::{self, AstNode};
use text_edit::{TextRange, TextSize};
-use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind};
+use crate::{
+ InlayHint, InlayHintLabel, InlayHintLabelPart, InlayHintPosition, InlayHintsConfig, InlayKind,
+};
pub(super) fn hints(
acc: &mut Vec<InlayHint>,
@@ -27,34 +29,27 @@ pub(super) fn hints(
return None;
}
- let move_kw_range = match closure.move_token() {
- Some(t) => t.text_range(),
+ let (range, label) = match closure.move_token() {
+ Some(t) => (t.text_range(), InlayHintLabel::default()),
None => {
- let range = closure.syntax().first_token()?.prev_token()?.text_range();
- let range = TextRange::new(range.end() - TextSize::from(1), range.end());
- acc.push(InlayHint {
- range,
- kind: InlayKind::ClosureCapture,
- label: InlayHintLabel::from("move"),
- text_edit: None,
- position: InlayHintPosition::After,
- pad_left: false,
- pad_right: false,
- resolve_parent: Some(closure.syntax().text_range()),
- });
- range
+ let prev_token = closure.syntax().first_token()?.prev_token()?.text_range();
+ (
+ TextRange::new(prev_token.end() - TextSize::from(1), prev_token.end()),
+ InlayHintLabel::from("move"),
+ )
}
};
- acc.push(InlayHint {
- range: move_kw_range,
+ let mut hint = InlayHint {
+ range,
kind: InlayKind::ClosureCapture,
- label: InlayHintLabel::from("("),
+ label,
text_edit: None,
position: InlayHintPosition::After,
pad_left: false,
- pad_right: false,
- resolve_parent: None,
- });
+ pad_right: true,
+ resolve_parent: Some(closure.syntax().text_range()),
+ };
+ hint.label.append_str("(");
let last = captures.len() - 1;
for (idx, capture) in captures.into_iter().enumerate() {
let local = capture.local();
@@ -76,48 +71,20 @@ pub(super) fn hints(
if never!(label.is_empty()) {
continue;
}
- let label = InlayHintLabel::simple(
- label,
- None,
- source.name().and_then(|name| {
+ hint.label.append_part(InlayHintLabelPart {
+ text: label,
+ linked_location: source.name().and_then(|name| {
name.syntax().original_file_range_opt(sema.db).map(TupleExt::head).map(Into::into)
}),
- );
- acc.push(InlayHint {
- range: move_kw_range,
- kind: InlayKind::ClosureCapture,
- label,
- text_edit: None,
- position: InlayHintPosition::After,
- pad_left: false,
- pad_right: false,
- resolve_parent: Some(closure.syntax().text_range()),
+ tooltip: None,
});
if idx != last {
- acc.push(InlayHint {
- range: move_kw_range,
- kind: InlayKind::ClosureCapture,
- label: InlayHintLabel::from(", "),
- text_edit: None,
- position: InlayHintPosition::After,
- pad_left: false,
- pad_right: false,
- resolve_parent: None,
- });
+ hint.label.append_str(", ");
}
}
- acc.push(InlayHint {
- range: move_kw_range,
- kind: InlayKind::ClosureCapture,
- label: InlayHintLabel::from(")"),
- text_edit: None,
- position: InlayHintPosition::After,
- pad_left: false,
- pad_right: true,
- resolve_parent: None,
- });
-
+ hint.label.append_str(")");
+ acc.push(hint);
Some(())
}
@@ -147,51 +114,25 @@ fn main() {
let mut baz = NonCopy;
let qux = &mut NonCopy;
|| {
-// ^ move
-// ^ (
-// ^ &foo
-// ^ , $
-// ^ bar
-// ^ , $
-// ^ baz
-// ^ , $
-// ^ qux
-// ^ )
+// ^ move(&foo, bar, baz, qux)
foo;
bar;
baz;
qux;
};
|| {
-// ^ move
-// ^ (
-// ^ &foo
-// ^ , $
-// ^ &bar
-// ^ , $
-// ^ &baz
-// ^ , $
-// ^ &qux
-// ^ )
+// ^ move(&foo, &bar, &baz, &qux)
&foo;
&bar;
&baz;
&qux;
};
|| {
-// ^ move
-// ^ (
-// ^ &mut baz
-// ^ )
+// ^ move(&mut baz)
&mut baz;
};
|| {
-// ^ move
-// ^ (
-// ^ &mut baz
-// ^ , $
-// ^ &mut *qux
-// ^ )
+// ^ move(&mut baz, &mut *qux)
baz = NonCopy;
*qux = NonCopy;
};
@@ -209,9 +150,7 @@ fn main() {
fn main() {
let foo = u32;
move || {
-// ^^^^ (
-// ^^^^ foo
-// ^^^^ )
+// ^^^^ (foo)
foo;
};
}