Skip to content

Commit 241807d

Browse files
author
Jonas Schievink
committed
Allow multi-part inlay hint labels with location links
1 parent ab068f1 commit 241807d

File tree

4 files changed

+179
-46
lines changed

4 files changed

+179
-46
lines changed

crates/ide/src/inlay_hints.rs

Lines changed: 133 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::fmt;
2+
13
use either::Either;
24
use hir::{known, Callable, HasVisibility, HirDisplay, Mutability, Semantics, TypeInfo};
35
use ide_db::{
@@ -69,7 +71,7 @@ pub enum InlayKind {
6971
pub struct InlayHint {
7072
pub range: TextRange,
7173
pub kind: InlayKind,
72-
pub label: String,
74+
pub label: InlayHintLabel,
7375
pub tooltip: Option<InlayTooltip>,
7476
}
7577

@@ -80,6 +82,78 @@ pub enum InlayTooltip {
8082
HoverOffset(FileId, TextSize),
8183
}
8284

85+
pub struct InlayHintLabel {
86+
pub parts: Vec<InlayHintLabelPart>,
87+
}
88+
89+
impl InlayHintLabel {
90+
pub fn as_simple_str(&self) -> Option<&str> {
91+
match &*self.parts {
92+
[part] => part.as_simple_str(),
93+
_ => None,
94+
}
95+
}
96+
97+
pub fn prepend_str(&mut self, s: &str) {
98+
match &mut *self.parts {
99+
[part, ..] if part.as_simple_str().is_some() => part.text = format!("{s}{}", part.text),
100+
_ => self.parts.insert(0, InlayHintLabelPart { text: s.into(), linked_location: None }),
101+
}
102+
}
103+
104+
pub fn append_str(&mut self, s: &str) {
105+
match &mut *self.parts {
106+
[.., part] if part.as_simple_str().is_some() => part.text.push_str(s),
107+
_ => self.parts.push(InlayHintLabelPart { text: s.into(), linked_location: None }),
108+
}
109+
}
110+
}
111+
112+
impl From<String> for InlayHintLabel {
113+
fn from(s: String) -> Self {
114+
Self { parts: vec![InlayHintLabelPart { text: s, linked_location: None }] }
115+
}
116+
}
117+
118+
impl fmt::Display for InlayHintLabel {
119+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120+
write!(f, "{}", self.parts.iter().map(|part| &part.text).format(""))
121+
}
122+
}
123+
124+
impl fmt::Debug for InlayHintLabel {
125+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126+
f.debug_list().entries(&self.parts).finish()
127+
}
128+
}
129+
130+
pub struct InlayHintLabelPart {
131+
pub text: String,
132+
pub linked_location: Option<FileRange>,
133+
}
134+
135+
impl InlayHintLabelPart {
136+
pub fn as_simple_str(&self) -> Option<&str> {
137+
match self {
138+
Self { text, linked_location: None } => Some(text),
139+
_ => None,
140+
}
141+
}
142+
}
143+
144+
impl fmt::Debug for InlayHintLabelPart {
145+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146+
match self.as_simple_str() {
147+
Some(string) => string.fmt(f),
148+
None => f
149+
.debug_struct("InlayHintLabelPart")
150+
.field("text", &self.text)
151+
.field("linked_location", &self.linked_location)
152+
.finish(),
153+
}
154+
}
155+
}
156+
83157
// Feature: Inlay Hints
84158
//
85159
// rust-analyzer shows additional information inline with the source code.
@@ -281,7 +355,7 @@ fn closing_brace_hints(
281355
acc.push(InlayHint {
282356
range: closing_token.text_range(),
283357
kind: InlayKind::ClosingBraceHint,
284-
label,
358+
label: label.into(),
285359
tooltip: name_offset.map(|it| InlayTooltip::HoverOffset(file_id, it)),
286360
});
287361

@@ -311,7 +385,7 @@ fn implicit_static_hints(
311385
acc.push(InlayHint {
312386
range: t.text_range(),
313387
kind: InlayKind::LifetimeHint,
314-
label: "'static".to_owned(),
388+
label: "'static".to_owned().into(),
315389
tooltip: Some(InlayTooltip::String("Elided static lifetime".into())),
316390
});
317391
}
@@ -329,10 +403,10 @@ fn fn_lifetime_fn_hints(
329403
return None;
330404
}
331405

332-
let mk_lt_hint = |t: SyntaxToken, label| InlayHint {
406+
let mk_lt_hint = |t: SyntaxToken, label: String| InlayHint {
333407
range: t.text_range(),
334408
kind: InlayKind::LifetimeHint,
335-
label,
409+
label: label.into(),
336410
tooltip: Some(InlayTooltip::String("Elided lifetime".into())),
337411
};
338412

@@ -486,7 +560,8 @@ fn fn_lifetime_fn_hints(
486560
"{}{}",
487561
allocated_lifetimes.iter().format(", "),
488562
if is_empty { "" } else { ", " }
489-
),
563+
)
564+
.into(),
490565
tooltip: Some(InlayTooltip::String("Elided lifetimes".into())),
491566
});
492567
}
@@ -535,7 +610,8 @@ fn closure_ret_hints(
535610
range: param_list.syntax().text_range(),
536611
kind: InlayKind::ClosureReturnTypeHint,
537612
label: hint_iterator(sema, &famous_defs, config, &ty)
538-
.unwrap_or_else(|| ty.display_truncated(sema.db, config.max_length).to_string()),
613+
.unwrap_or_else(|| ty.display_truncated(sema.db, config.max_length).to_string())
614+
.into(),
539615
tooltip: Some(InlayTooltip::HoverRanged(file_id, param_list.syntax().text_range())),
540616
});
541617
Some(())
@@ -562,7 +638,7 @@ fn reborrow_hints(
562638
acc.push(InlayHint {
563639
range: expr.syntax().text_range(),
564640
kind: InlayKind::ImplicitReborrowHint,
565-
label: label.to_string(),
641+
label: label.to_string().into(),
566642
tooltip: Some(InlayTooltip::String("Compiler inserted reborrow".into())),
567643
});
568644
Some(())
@@ -620,9 +696,9 @@ fn chaining_hints(
620696
acc.push(InlayHint {
621697
range: expr.syntax().text_range(),
622698
kind: InlayKind::ChainingHint,
623-
label: hint_iterator(sema, &famous_defs, config, &ty).unwrap_or_else(|| {
624-
ty.display_truncated(sema.db, config.max_length).to_string()
625-
}),
699+
label: hint_iterator(sema, &famous_defs, config, &ty)
700+
.unwrap_or_else(|| ty.display_truncated(sema.db, config.max_length).to_string())
701+
.into(),
626702
tooltip: Some(InlayTooltip::HoverRanged(file_id, expr.syntax().text_range())),
627703
});
628704
}
@@ -674,7 +750,7 @@ fn param_name_hints(
674750
InlayHint {
675751
range,
676752
kind: InlayKind::ParameterHint,
677-
label: param_name,
753+
label: param_name.into(),
678754
tooltip: tooltip.map(|it| InlayTooltip::HoverOffset(it.file_id, it.range.start())),
679755
}
680756
});
@@ -705,7 +781,7 @@ fn binding_mode_hints(
705781
acc.push(InlayHint {
706782
range,
707783
kind: InlayKind::BindingModeHint,
708-
label: r.to_string(),
784+
label: r.to_string().into(),
709785
tooltip: Some(InlayTooltip::String("Inferred binding mode".into())),
710786
});
711787
});
@@ -720,7 +796,7 @@ fn binding_mode_hints(
720796
acc.push(InlayHint {
721797
range,
722798
kind: InlayKind::BindingModeHint,
723-
label: bm.to_string(),
799+
label: bm.to_string().into(),
724800
tooltip: Some(InlayTooltip::String("Inferred binding mode".into())),
725801
});
726802
}
@@ -772,7 +848,7 @@ fn bind_pat_hints(
772848
None => pat.syntax().text_range(),
773849
},
774850
kind: InlayKind::TypeHint,
775-
label,
851+
label: label.into(),
776852
tooltip: pat
777853
.name()
778854
.map(|it| it.syntax().text_range())
@@ -2223,7 +2299,9 @@ fn main() {
22232299
InlayHint {
22242300
range: 147..172,
22252301
kind: ChainingHint,
2226-
label: "B",
2302+
label: [
2303+
"B",
2304+
],
22272305
tooltip: Some(
22282306
HoverRanged(
22292307
FileId(
@@ -2236,7 +2314,9 @@ fn main() {
22362314
InlayHint {
22372315
range: 147..154,
22382316
kind: ChainingHint,
2239-
label: "A",
2317+
label: [
2318+
"A",
2319+
],
22402320
tooltip: Some(
22412321
HoverRanged(
22422322
FileId(
@@ -2294,7 +2374,9 @@ fn main() {
22942374
InlayHint {
22952375
range: 143..190,
22962376
kind: ChainingHint,
2297-
label: "C",
2377+
label: [
2378+
"C",
2379+
],
22982380
tooltip: Some(
22992381
HoverRanged(
23002382
FileId(
@@ -2307,7 +2389,9 @@ fn main() {
23072389
InlayHint {
23082390
range: 143..179,
23092391
kind: ChainingHint,
2310-
label: "B",
2392+
label: [
2393+
"B",
2394+
],
23112395
tooltip: Some(
23122396
HoverRanged(
23132397
FileId(
@@ -2350,7 +2434,9 @@ fn main() {
23502434
InlayHint {
23512435
range: 246..283,
23522436
kind: ChainingHint,
2353-
label: "B<X<i32, bool>>",
2437+
label: [
2438+
"B<X<i32, bool>>",
2439+
],
23542440
tooltip: Some(
23552441
HoverRanged(
23562442
FileId(
@@ -2363,7 +2449,9 @@ fn main() {
23632449
InlayHint {
23642450
range: 246..265,
23652451
kind: ChainingHint,
2366-
label: "A<X<i32, bool>>",
2452+
label: [
2453+
"A<X<i32, bool>>",
2454+
],
23672455
tooltip: Some(
23682456
HoverRanged(
23692457
FileId(
@@ -2408,7 +2496,9 @@ fn main() {
24082496
InlayHint {
24092497
range: 174..241,
24102498
kind: ChainingHint,
2411-
label: "impl Iterator<Item = ()>",
2499+
label: [
2500+
"impl Iterator<Item = ()>",
2501+
],
24122502
tooltip: Some(
24132503
HoverRanged(
24142504
FileId(
@@ -2421,7 +2511,9 @@ fn main() {
24212511
InlayHint {
24222512
range: 174..224,
24232513
kind: ChainingHint,
2424-
label: "impl Iterator<Item = ()>",
2514+
label: [
2515+
"impl Iterator<Item = ()>",
2516+
],
24252517
tooltip: Some(
24262518
HoverRanged(
24272519
FileId(
@@ -2434,7 +2526,9 @@ fn main() {
24342526
InlayHint {
24352527
range: 174..206,
24362528
kind: ChainingHint,
2437-
label: "impl Iterator<Item = ()>",
2529+
label: [
2530+
"impl Iterator<Item = ()>",
2531+
],
24382532
tooltip: Some(
24392533
HoverRanged(
24402534
FileId(
@@ -2447,7 +2541,9 @@ fn main() {
24472541
InlayHint {
24482542
range: 174..189,
24492543
kind: ChainingHint,
2450-
label: "&mut MyIter",
2544+
label: [
2545+
"&mut MyIter",
2546+
],
24512547
tooltip: Some(
24522548
HoverRanged(
24532549
FileId(
@@ -2489,7 +2585,9 @@ fn main() {
24892585
InlayHint {
24902586
range: 124..130,
24912587
kind: TypeHint,
2492-
label: "Struct",
2588+
label: [
2589+
"Struct",
2590+
],
24932591
tooltip: Some(
24942592
HoverRanged(
24952593
FileId(
@@ -2502,7 +2600,9 @@ fn main() {
25022600
InlayHint {
25032601
range: 145..185,
25042602
kind: ChainingHint,
2505-
label: "Struct",
2603+
label: [
2604+
"Struct",
2605+
],
25062606
tooltip: Some(
25072607
HoverRanged(
25082608
FileId(
@@ -2515,7 +2615,9 @@ fn main() {
25152615
InlayHint {
25162616
range: 145..168,
25172617
kind: ChainingHint,
2518-
label: "Struct",
2618+
label: [
2619+
"Struct",
2620+
],
25192621
tooltip: Some(
25202622
HoverRanged(
25212623
FileId(
@@ -2528,7 +2630,9 @@ fn main() {
25282630
InlayHint {
25292631
range: 222..228,
25302632
kind: ParameterHint,
2531-
label: "self",
2633+
label: [
2634+
"self",
2635+
],
25322636
tooltip: Some(
25332637
HoverOffset(
25342638
FileId(

crates/ide/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ pub use crate::{
8282
highlight_related::{HighlightRelatedConfig, HighlightedRange},
8383
hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult},
8484
inlay_hints::{
85-
ClosureReturnTypeHints, InlayHint, InlayHintsConfig, InlayKind, InlayTooltip,
86-
LifetimeElisionHints, ReborrowHints,
85+
ClosureReturnTypeHints, InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind,
86+
InlayTooltip, LifetimeElisionHints, ReborrowHints,
8787
},
8888
join_lines::JoinLinesConfig,
8989
markup::Markup,

crates/rust-analyzer/src/handlers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1362,7 +1362,7 @@ pub(crate) fn handle_inlay_hints(
13621362
.map(|it| {
13631363
to_proto::inlay_hint(&snap, &line_index, inlay_hints_config.render_colons, it)
13641364
})
1365-
.collect(),
1365+
.collect::<Result<Vec<_>>>()?,
13661366
))
13671367
}
13681368

0 commit comments

Comments
 (0)