@@ -8,10 +8,12 @@ use ide_db::{RootDatabase, famous_defs::FamousDefs};
88
99use itertools:: Itertools ;
1010use syntax:: {
11+ TextRange ,
1112 ast:: { self , AstNode , HasGenericArgs , HasName } ,
1213 match_ast,
1314} ;
1415
16+ use super :: TypeHintsPlacement ;
1517use 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 (
0 commit comments