Skip to content

Commit 36d28e4

Browse files
impl
1 parent 624761a commit 36d28e4

File tree

9 files changed

+252
-19
lines changed

9 files changed

+252
-19
lines changed

crates/ide/src/inlay_hints.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ fn hints(
302302
pub struct InlayHintsConfig<'a> {
303303
pub render_colons: bool,
304304
pub type_hints: bool,
305+
pub type_hints_placement: TypeHintsPlacement,
305306
pub sized_bound: bool,
306307
pub discriminant_hints: DiscriminantHints,
307308
pub parameter_hints: bool,
@@ -331,6 +332,12 @@ pub struct InlayHintsConfig<'a> {
331332
pub minicore: MiniCore<'a>,
332333
}
333334

335+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
336+
pub enum TypeHintsPlacement {
337+
Inline,
338+
EndOfLine,
339+
}
340+
334341
impl InlayHintsConfig<'_> {
335342
fn lazy_text_edit(&self, finish: impl FnOnce() -> TextEdit) -> LazyProperty<TextEdit> {
336343
if self.fields_to_resolve.resolve_text_edits {
@@ -876,12 +883,15 @@ mod tests {
876883
use crate::inlay_hints::{AdjustmentHints, AdjustmentHintsMode};
877884
use crate::{LifetimeElisionHints, fixture, inlay_hints::InlayHintsConfig};
878885

879-
use super::{ClosureReturnTypeHints, GenericParameterHints, InlayFieldsToResolve};
886+
use super::{
887+
ClosureReturnTypeHints, GenericParameterHints, InlayFieldsToResolve, TypeHintsPlacement,
888+
};
880889

881890
pub(super) const DISABLED_CONFIG: InlayHintsConfig<'_> = InlayHintsConfig {
882891
discriminant_hints: DiscriminantHints::Never,
883892
render_colons: false,
884893
type_hints: false,
894+
type_hints_placement: TypeHintsPlacement::Inline,
885895
parameter_hints: false,
886896
parameter_hints_for_missing_arguments: false,
887897
sized_bound: false,
@@ -915,6 +925,7 @@ mod tests {
915925
};
916926
pub(super) const TEST_CONFIG: InlayHintsConfig<'_> = InlayHintsConfig {
917927
type_hints: true,
928+
type_hints_placement: TypeHintsPlacement::Inline,
918929
parameter_hints: true,
919930
chaining_hints: true,
920931
closure_return_type_hints: ClosureReturnTypeHints::WithBlock,

crates/ide/src/inlay_hints/bind_pat.rs

Lines changed: 92 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ use ide_db::{RootDatabase, famous_defs::FamousDefs};
88

99
use itertools::Itertools;
1010
use syntax::{
11+
TextRange,
1112
ast::{self, AstNode, HasGenericArgs, HasName},
1213
match_ast,
1314
};
1415

16+
use super::TypeHintsPlacement;
1517
use crate::{
1618
InlayHint, InlayHintPosition, InlayHintsConfig, InlayKind,
1719
inlay_hints::{closure_has_block_body, label_of_ty, ty_to_text_edit},
@@ -29,6 +31,7 @@ pub(super) fn hints(
2931
}
3032

3133
let parent = pat.syntax().parent()?;
34+
let mut enclosing_let_stmt = None;
3235
let type_ascriptable = match_ast! {
3336
match parent {
3437
ast::Param(it) => {
@@ -41,6 +44,7 @@ pub(super) fn hints(
4144
Some(it.colon_token())
4245
},
4346
ast::LetStmt(it) => {
47+
enclosing_let_stmt = Some(it.clone());
4448
if config.hide_closure_initialization_hints
4549
&& let Some(ast::Expr::ClosureExpr(closure)) = it.initializer()
4650
&& closure_has_block_body(&closure) {
@@ -101,16 +105,26 @@ pub(super) fn hints(
101105
Some(name) => name.syntax().text_range(),
102106
None => pat.syntax().text_range(),
103107
};
108+
let mut range = match type_ascriptable {
109+
Some(Some(t)) => text_range.cover(t.text_range()),
110+
_ => text_range,
111+
};
112+
113+
let mut pad_left = !render_colons;
114+
if matches!(config.type_hints_placement, TypeHintsPlacement::EndOfLine) {
115+
if let Some(let_stmt) = enclosing_let_stmt {
116+
let stmt_range = let_stmt.syntax().text_range();
117+
range = TextRange::new(range.start(), stmt_range.end());
118+
pad_left = true;
119+
}
120+
}
104121
acc.push(InlayHint {
105-
range: match type_ascriptable {
106-
Some(Some(t)) => text_range.cover(t.text_range()),
107-
_ => text_range,
108-
},
122+
range,
109123
kind: InlayKind::Type,
110124
label,
111125
text_edit,
112126
position: InlayHintPosition::After,
113-
pad_left: !render_colons,
127+
pad_left,
114128
pad_right: false,
115129
resolve_parent: Some(pat.syntax().text_range()),
116130
});
@@ -182,8 +196,10 @@ mod tests {
182196

183197
use crate::{ClosureReturnTypeHints, fixture, inlay_hints::InlayHintsConfig};
184198

199+
use super::TypeHintsPlacement;
185200
use crate::inlay_hints::tests::{
186-
DISABLED_CONFIG, TEST_CONFIG, check, check_edit, check_no_edit, check_with_config,
201+
DISABLED_CONFIG, TEST_CONFIG, check, check_edit, check_expect, check_no_edit,
202+
check_with_config,
187203
};
188204

189205
#[track_caller]
@@ -203,6 +219,76 @@ fn main() {
203219
);
204220
}
205221

222+
#[test]
223+
fn type_hints_end_of_line_placement() {
224+
let mut config = InlayHintsConfig { type_hints: true, ..DISABLED_CONFIG };
225+
config.type_hints_placement = TypeHintsPlacement::EndOfLine;
226+
check_expect(
227+
config,
228+
r#"
229+
fn main() {
230+
let foo = 92_i32;
231+
}
232+
"#,
233+
expect![[r#"
234+
[
235+
(
236+
20..33,
237+
[
238+
"i32",
239+
],
240+
),
241+
]
242+
"#]],
243+
);
244+
}
245+
246+
#[test]
247+
fn type_hints_end_of_line_placement_chain_expr() {
248+
let mut config = InlayHintsConfig { type_hints: true, ..DISABLED_CONFIG };
249+
config.type_hints_placement = TypeHintsPlacement::EndOfLine;
250+
check_expect(
251+
config,
252+
r#"
253+
fn main() {
254+
struct Builder;
255+
impl Builder {
256+
fn iter(self) -> Builder { Builder }
257+
fn map(self) -> Builder { Builder }
258+
}
259+
fn make() -> Builder { Builder }
260+
261+
let foo = make()
262+
.iter()
263+
.map();
264+
}
265+
"#,
266+
expect![[r#"
267+
[
268+
(
269+
192..236,
270+
[
271+
InlayHintLabelPart {
272+
text: "Builder",
273+
linked_location: Some(
274+
Computed(
275+
FileRangeWrapper {
276+
file_id: FileId(
277+
0,
278+
),
279+
range: 23..30,
280+
},
281+
),
282+
),
283+
tooltip: "",
284+
},
285+
],
286+
),
287+
]
288+
"#]],
289+
);
290+
}
291+
206292
#[test]
207293
fn type_hints_bindings_after_at() {
208294
check_types(

crates/ide/src/inlay_hints/chaining.rs

Lines changed: 97 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
use hir::DisplayTarget;
33
use ide_db::famous_defs::FamousDefs;
44
use syntax::{
5-
Direction, NodeOrToken, SyntaxKind, T,
5+
Direction, NodeOrToken, SyntaxKind, T, TextRange,
66
ast::{self, AstNode},
77
};
88

99
use crate::{InlayHint, InlayHintPosition, InlayHintsConfig, InlayKind};
1010

11-
use super::label_of_ty;
11+
use super::{TypeHintsPlacement, label_of_ty};
1212

1313
pub(super) fn hints(
1414
acc: &mut Vec<InlayHint>,
@@ -40,13 +40,14 @@ pub(super) fn hints(
4040

4141
// Chaining can be defined as an expression whose next sibling tokens are newline and dot
4242
// Ignoring extra whitespace and comments
43-
let next = tokens.next()?.kind();
44-
if next == SyntaxKind::WHITESPACE {
45-
let mut next_next = tokens.next()?.kind();
46-
while next_next == SyntaxKind::WHITESPACE {
47-
next_next = tokens.next()?.kind();
43+
let next_token = tokens.next()?;
44+
if next_token.kind() == SyntaxKind::WHITESPACE {
45+
let newline_token = next_token;
46+
let mut next_next = tokens.next()?;
47+
while next_next.kind() == SyntaxKind::WHITESPACE {
48+
next_next = tokens.next()?;
4849
}
49-
if next_next == T![.] {
50+
if next_next.kind() == T![.] {
5051
let ty = sema.type_of_expr(desc_expr)?.original;
5152
if ty.is_unknown() {
5253
return None;
@@ -58,8 +59,18 @@ pub(super) fn hints(
5859
return None;
5960
}
6061
let label = label_of_ty(famous_defs, config, &ty, display_target)?;
62+
let range = {
63+
let mut range = expr.syntax().text_range();
64+
if config.type_hints_placement == TypeHintsPlacement::EndOfLine {
65+
range = TextRange::new(
66+
range.start(),
67+
newline_token.text_range().start().max(range.end()),
68+
);
69+
}
70+
range
71+
};
6172
acc.push(InlayHint {
62-
range: expr.syntax().text_range(),
73+
range,
6374
kind: InlayKind::Chaining,
6475
label,
6576
text_edit: None,
@@ -79,7 +90,7 @@ mod tests {
7990
use ide_db::text_edit::{TextRange, TextSize};
8091

8192
use crate::{
82-
InlayHintsConfig, fixture,
93+
InlayHintsConfig, TypeHintsPlacement, fixture,
8394
inlay_hints::{
8495
LazyProperty,
8596
tests::{DISABLED_CONFIG, TEST_CONFIG, check_expect, check_with_config},
@@ -686,4 +697,80 @@ fn main() {
686697
"#]],
687698
);
688699
}
700+
701+
#[test]
702+
fn chaining_hints_end_of_line_placement() {
703+
check_expect(
704+
InlayHintsConfig {
705+
chaining_hints: true,
706+
type_hints_placement: TypeHintsPlacement::EndOfLine,
707+
..DISABLED_CONFIG
708+
},
709+
r#"
710+
fn main() {
711+
let baz = make()
712+
.into_bar()
713+
.into_baz();
714+
}
715+
716+
struct Foo;
717+
struct Bar;
718+
struct Baz;
719+
720+
impl Foo {
721+
fn into_bar(self) -> Bar { Bar }
722+
}
723+
724+
impl Bar {
725+
fn into_baz(self) -> Baz { Baz }
726+
}
727+
728+
fn make() -> Foo {
729+
Foo
730+
}
731+
"#,
732+
expect![[r#"
733+
[
734+
(
735+
26..52,
736+
[
737+
InlayHintLabelPart {
738+
text: "Bar",
739+
linked_location: Some(
740+
Computed(
741+
FileRangeWrapper {
742+
file_id: FileId(
743+
0,
744+
),
745+
range: 96..99,
746+
},
747+
),
748+
),
749+
tooltip: "",
750+
},
751+
],
752+
),
753+
(
754+
26..32,
755+
[
756+
InlayHintLabelPart {
757+
text: "Foo",
758+
linked_location: Some(
759+
Computed(
760+
FileRangeWrapper {
761+
file_id: FileId(
762+
0,
763+
),
764+
range: 84..87,
765+
},
766+
),
767+
),
768+
tooltip: "",
769+
},
770+
],
771+
),
772+
]
773+
"#]],
774+
);
775+
}
689776
}

crates/ide/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ pub use crate::{
9696
AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints,
9797
GenericParameterHints, InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart,
9898
InlayHintPosition, InlayHintsConfig, InlayKind, InlayTooltip, LazyProperty,
99-
LifetimeElisionHints,
99+
LifetimeElisionHints, TypeHintsPlacement,
100100
},
101101
join_lines::JoinLinesConfig,
102102
markup::Markup,

crates/ide/src/static_index.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::navigation_target::UpmappingResult;
1616
use crate::{
1717
Analysis, Fold, HoverConfig, HoverResult, InlayHint, InlayHintsConfig, TryToNav,
1818
hover::{SubstTyLen, hover_for_definition},
19-
inlay_hints::{AdjustmentHintsMode, InlayFieldsToResolve},
19+
inlay_hints::{AdjustmentHintsMode, InlayFieldsToResolve, TypeHintsPlacement},
2020
moniker::{MonikerResult, SymbolInformationKind, def_to_kind, def_to_moniker},
2121
parent_module::crates_for,
2222
};
@@ -167,6 +167,7 @@ impl StaticIndex<'_> {
167167
render_colons: true,
168168
discriminant_hints: crate::DiscriminantHints::Fieldless,
169169
type_hints: true,
170+
type_hints_placement: TypeHintsPlacement::Inline,
170171
sized_bound: false,
171172
parameter_hints: true,
172173
parameter_hints_for_missing_arguments: false,

crates/rust-analyzer/src/cli/analysis_stats.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,6 +1204,7 @@ impl flags::AnalysisStats {
12041204
&InlayHintsConfig {
12051205
render_colons: false,
12061206
type_hints: true,
1207+
type_hints_placement: ide::TypeHintsPlacement::Inline,
12071208
sized_bound: false,
12081209
discriminant_hints: ide::DiscriminantHints::Always,
12091210
parameter_hints: true,

0 commit comments

Comments
 (0)