Skip to content

Commit d741cd3

Browse files
committed
feat: show full type in tooltips for hints
1 parent ed737b5 commit d741cd3

File tree

5 files changed

+558
-337
lines changed

5 files changed

+558
-337
lines changed

crates/ide/src/inlay_hints.rs

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -524,9 +524,17 @@ pub enum InlayTooltip {
524524
Markdown(String),
525525
}
526526

527-
#[derive(Default, Hash)]
527+
#[derive(Default)]
528528
pub struct InlayHintLabel {
529529
pub parts: SmallVec<[InlayHintLabelPart; 1]>,
530+
pub tooltip: Option<LazyProperty<String>>,
531+
}
532+
533+
impl std::hash::Hash for InlayHintLabel {
534+
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
535+
self.parts.hash(state);
536+
self.tooltip.is_some().hash(state);
537+
}
530538
}
531539

532540
impl InlayHintLabel {
@@ -537,6 +545,7 @@ impl InlayHintLabel {
537545
) -> InlayHintLabel {
538546
InlayHintLabel {
539547
parts: smallvec![InlayHintLabelPart { text: s.into(), linked_location, tooltip }],
548+
tooltip: None,
540549
}
541550
}
542551

@@ -582,6 +591,7 @@ impl From<String> for InlayHintLabel {
582591
fn from(s: String) -> Self {
583592
Self {
584593
parts: smallvec![InlayHintLabelPart { text: s, linked_location: None, tooltip: None }],
594+
tooltip: None,
585595
}
586596
}
587597
}
@@ -592,8 +602,9 @@ impl From<&str> for InlayHintLabel {
592602
parts: smallvec![InlayHintLabelPart {
593603
text: s.into(),
594604
linked_location: None,
595-
tooltip: None
605+
tooltip: None,
596606
}],
607+
tooltip: None,
597608
}
598609
}
599610
}
@@ -606,7 +617,10 @@ impl fmt::Display for InlayHintLabel {
606617

607618
impl fmt::Debug for InlayHintLabel {
608619
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
609-
f.debug_list().entries(&self.parts).finish()
620+
f.debug_struct("InlayHintLabel")
621+
.field("parts", &self.parts)
622+
.field("tooltip", &self.tooltip)
623+
.finish()
610624
}
611625
}
612626

@@ -703,6 +717,13 @@ impl InlayHintLabelBuilder<'_> {
703717
}
704718
}
705719

720+
fn write_to_label_and_tooltip(&mut self, s: &str) -> fmt::Result {
721+
if let Some(LazyProperty::Computed(ref mut tooltip)) = self.result.tooltip {
722+
tooltip.push_str(s);
723+
}
724+
self.write_str(s)
725+
}
726+
706727
fn finish(mut self) -> InlayHintLabel {
707728
self.make_new_part();
708729
self.result
@@ -744,31 +765,44 @@ fn label_of_ty(
744765
)
745766
});
746767

747-
label_builder.write_str(LABEL_START)?;
768+
label_builder.write_to_label_and_tooltip(LABEL_START)?;
748769
label_builder.start_location_link(ModuleDef::from(iter_trait).into());
749-
label_builder.write_str(LABEL_ITERATOR)?;
770+
label_builder.write_to_label_and_tooltip(LABEL_ITERATOR)?;
750771
label_builder.end_location_link();
751-
label_builder.write_str(LABEL_MIDDLE)?;
772+
label_builder.write_to_label_and_tooltip(LABEL_MIDDLE)?;
752773
label_builder.start_location_link(ModuleDef::from(item).into());
753-
label_builder.write_str(LABEL_ITEM)?;
774+
label_builder.write_to_label_and_tooltip(LABEL_ITEM)?;
754775
label_builder.end_location_link();
755-
label_builder.write_str(LABEL_MIDDLE2)?;
776+
label_builder.write_to_label_and_tooltip(LABEL_MIDDLE2)?;
756777
rec(sema, famous_defs, max_length, &ty, label_builder, config, display_target)?;
757-
label_builder.write_str(LABEL_END)?;
778+
label_builder.write_to_label_and_tooltip(LABEL_END)?;
758779
Ok(())
759780
}
760-
None => ty
761-
.display_truncated(sema.db, max_length, display_target)
762-
.with_closure_style(config.closure_style)
763-
.write_to(label_builder),
781+
None => {
782+
if let Some(LazyProperty::Computed(ref mut tooltip)) = label_builder.result.tooltip
783+
{
784+
ty.display(sema.db, display_target)
785+
.with_closure_style(config.closure_style)
786+
.write_to(tooltip)?;
787+
}
788+
789+
ty.display_truncated(sema.db, max_length, display_target)
790+
.with_closure_style(config.closure_style)
791+
.write_to(label_builder)
792+
}
764793
}
765794
}
766795

796+
let tooltip = if config.fields_to_resolve.resolve_label_tooltip {
797+
Some(LazyProperty::Lazy)
798+
} else {
799+
Some(LazyProperty::Computed(String::new()))
800+
};
767801
let mut label_builder = InlayHintLabelBuilder {
768802
db: sema.db,
769803
last_part: String::new(),
770804
location: None,
771-
result: InlayHintLabel::default(),
805+
result: InlayHintLabel { tooltip, ..Default::default() },
772806
resolve: config.fields_to_resolve.resolve_label_location,
773807
};
774808
let _ =
@@ -966,6 +1000,22 @@ mod tests {
9661000
assert!(edits.is_empty(), "unexpected edits: {edits:?}");
9671001
}
9681002

1003+
#[track_caller]
1004+
pub(super) fn check_tooltip(
1005+
config: InlayHintsConfig,
1006+
#[rust_analyzer::rust_fixture] ra_fixture: &str,
1007+
expect: Expect,
1008+
) {
1009+
let (analysis, file_id) = fixture::file(ra_fixture);
1010+
let inlay_hints = analysis.inlay_hints(&config, file_id, None).unwrap();
1011+
1012+
let tooltips = inlay_hints
1013+
.into_iter()
1014+
.filter_map(|hint| hint.label.tooltip?.computed())
1015+
.collect::<Vec<_>>();
1016+
expect.assert_debug_eq(&tooltips);
1017+
}
1018+
9691019
#[test]
9701020
fn hints_disabled() {
9711021
check_with_config(

crates/ide/src/inlay_hints/bind_pat.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,14 +184,23 @@ mod tests {
184184
use crate::{ClosureReturnTypeHints, fixture, inlay_hints::InlayHintsConfig};
185185

186186
use crate::inlay_hints::tests::{
187-
DISABLED_CONFIG, TEST_CONFIG, check, check_edit, check_no_edit, check_with_config,
187+
DISABLED_CONFIG, TEST_CONFIG, check, check_edit, check_no_edit, check_tooltip,
188+
check_with_config,
188189
};
189190

190191
#[track_caller]
191192
fn check_types(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
192193
check_with_config(InlayHintsConfig { type_hints: true, ..DISABLED_CONFIG }, ra_fixture);
193194
}
194195

196+
#[track_caller]
197+
fn check_types_tooltip(
198+
#[rust_analyzer::rust_fixture] ra_fixture: &str,
199+
expect: expect_test::Expect,
200+
) {
201+
check_tooltip(InlayHintsConfig { type_hints: true, ..DISABLED_CONFIG }, ra_fixture, expect);
202+
}
203+
195204
#[test]
196205
fn type_hints_only() {
197206
check_types(
@@ -1256,4 +1265,42 @@ where
12561265
"#,
12571266
);
12581267
}
1268+
1269+
#[test]
1270+
fn tooltip_for_bind_pat() {
1271+
check_types_tooltip(
1272+
r#"
1273+
struct Struct<T, T2> {
1274+
a: T,
1275+
b: T2,
1276+
}
1277+
1278+
pub fn main() {
1279+
let x = Struct { a: Struct { a: Struct { a: 1, b: 2 }, b: 2 }, b: Struct { a: 1, b: 2 } };
1280+
}
1281+
"#,
1282+
expect![[r#"
1283+
[
1284+
"Struct<Struct<Struct<i32, i32>, i32>, Struct<i32, i32>>",
1285+
]
1286+
"#]],
1287+
);
1288+
}
1289+
1290+
#[test]
1291+
fn tooltip_for_bind_pat_with_type_alias() {
1292+
check_types_tooltip(
1293+
r#"
1294+
//- minicore: option
1295+
pub fn main() {
1296+
let x = Some(1);
1297+
}
1298+
"#,
1299+
expect![[r#"
1300+
[
1301+
"Option<i32>",
1302+
]
1303+
"#]],
1304+
);
1305+
}
12591306
}

crates/ide/src/inlay_hints/bounds.rs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -135,23 +135,26 @@ fn foo<T>() {}
135135
[
136136
(
137137
7..8,
138-
[
139-
": ",
140-
InlayHintLabelPart {
141-
text: "Sized",
142-
linked_location: Some(
143-
Computed(
144-
FileRangeWrapper {
145-
file_id: FileId(
146-
1,
147-
),
148-
range: 135..140,
149-
},
138+
InlayHintLabel {
139+
parts: [
140+
": ",
141+
InlayHintLabelPart {
142+
text: "Sized",
143+
linked_location: Some(
144+
Computed(
145+
FileRangeWrapper {
146+
file_id: FileId(
147+
1,
148+
),
149+
range: 135..140,
150+
},
151+
),
150152
),
151-
),
152-
tooltip: "",
153-
},
154-
],
153+
tooltip: "",
154+
},
155+
],
156+
tooltip: None,
157+
},
155158
),
156159
]
157160
"#]],

0 commit comments

Comments
 (0)