@@ -2,6 +2,7 @@ use either::Either;
2
2
use hir:: { known, Callable , HasVisibility , HirDisplay , Semantics , TypeInfo } ;
3
3
use ide_db:: RootDatabase ;
4
4
use ide_db:: { base_db:: FileRange , helpers:: FamousDefs } ;
5
+ use itertools:: Itertools ;
5
6
use stdx:: to_lower_snake_case;
6
7
use syntax:: {
7
8
ast:: { self , AstNode , HasArgList , HasName } ,
@@ -198,28 +199,99 @@ fn get_bind_pat_hints(
198
199
199
200
let descended = sema. descend_node_into_attributes ( pat. clone ( ) ) . pop ( ) ;
200
201
let desc_pat = descended. as_ref ( ) . unwrap_or ( pat) ;
201
- let krate = sema. scope ( desc_pat. syntax ( ) ) . module ( ) . map ( |it| it. krate ( ) ) ;
202
- let famous_defs = FamousDefs ( sema, krate) ;
203
-
204
202
let ty = sema. type_of_pat ( & desc_pat. clone ( ) . into ( ) ) ?. original ;
205
203
206
204
if should_not_display_type_hint ( sema, & pat, & ty) {
207
205
return None ;
208
206
}
209
207
208
+ let krate = sema. scope ( desc_pat. syntax ( ) ) . module ( ) . map ( |it| it. krate ( ) ) ;
209
+ let famous_defs = FamousDefs ( sema, krate) ;
210
+ let label = hint_iterator ( sema, & famous_defs, config, & ty) ;
211
+
212
+ let label = match label {
213
+ Some ( label) => label,
214
+ None => {
215
+ let ty_name = ty. display_truncated ( sema. db , config. max_length ) . to_string ( ) ;
216
+ if is_named_constructor ( sema, pat, & ty_name) . is_some ( ) {
217
+ return None ;
218
+ }
219
+ ty_name. into ( )
220
+ }
221
+ } ;
222
+
210
223
acc. push ( InlayHint {
211
224
range : match pat. name ( ) {
212
225
Some ( name) => name. syntax ( ) . text_range ( ) ,
213
226
None => pat. syntax ( ) . text_range ( ) ,
214
227
} ,
215
228
kind : InlayKind :: TypeHint ,
216
- label : hint_iterator ( sema, & famous_defs, config, & ty)
217
- . unwrap_or_else ( || ty. display_truncated ( sema. db , config. max_length ) . to_string ( ) . into ( ) ) ,
229
+ label,
218
230
} ) ;
219
231
220
232
Some ( ( ) )
221
233
}
222
234
235
+ fn is_named_constructor (
236
+ sema : & Semantics < RootDatabase > ,
237
+ pat : & ast:: IdentPat ,
238
+ ty_name : & str ,
239
+ ) -> Option < ( ) > {
240
+ let it = pat. syntax ( ) . parent ( ) ?;
241
+ let expr = match_ast ! {
242
+ match it {
243
+ ast:: LetStmt ( it) => it. initializer( ) ,
244
+ ast:: Condition ( it) => it. expr( ) ,
245
+ _ => None ,
246
+ }
247
+ } ;
248
+
249
+ if let Some ( expr) = expr {
250
+ let expr = sema. descend_node_into_attributes ( expr. clone ( ) ) . pop ( ) . unwrap_or ( expr) ;
251
+ let expr = match expr {
252
+ ast:: Expr :: TryExpr ( it) => it. expr ( ) ,
253
+ ast:: Expr :: AwaitExpr ( it) => it. expr ( ) ,
254
+ expr => Some ( expr) ,
255
+ } ?;
256
+ let expr = match expr {
257
+ ast:: Expr :: CallExpr ( call) => match call. expr ( ) ? {
258
+ ast:: Expr :: PathExpr ( p) => p,
259
+ _ => return None ,
260
+ } ,
261
+ _ => return None ,
262
+ } ;
263
+ let path = expr. path ( ) ?;
264
+
265
+ let callable = sema. type_of_expr ( & ast:: Expr :: PathExpr ( expr) ) ?. original . as_callable ( sema. db ) ;
266
+ let callable_kind = callable. map ( |it| it. kind ( ) ) ;
267
+ if let Some ( hir:: CallableKind :: TupleStruct ( _) | hir:: CallableKind :: TupleEnumVariant ( _) ) =
268
+ callable_kind
269
+ {
270
+ if let Some ( seg) = path. segment ( ) {
271
+ if & seg. to_string ( ) == ty_name {
272
+ return Some ( ( ) ) ;
273
+ }
274
+ }
275
+ }
276
+
277
+ let qual_seg = path. qualifier ( ) ?. segment ( ) ?;
278
+ let name = match qual_seg. kind ( ) ? {
279
+ ast:: PathSegmentKind :: Name ( name_ref) => {
280
+ match qual_seg. generic_arg_list ( ) . map ( |it| it. generic_args ( ) ) {
281
+ Some ( generics) => format ! ( "{}<{}>" , name_ref, generics. format( ", " ) ) ,
282
+ None => name_ref. to_string ( ) ,
283
+ }
284
+ }
285
+ ast:: PathSegmentKind :: Type { type_ref : Some ( ty) , trait_ref : None } => ty. to_string ( ) ,
286
+ _ => return None ,
287
+ } ;
288
+ if & name == ty_name {
289
+ return Some ( ( ) ) ;
290
+ }
291
+ }
292
+ None
293
+ }
294
+
223
295
/// Checks if the type is an Iterator from std::iter and replaces its hint with an `impl Iterator<Item = Ty>`.
224
296
fn hint_iterator (
225
297
sema : & Semantics < RootDatabase > ,
@@ -470,10 +542,12 @@ mod tests {
470
542
max_length : None ,
471
543
} ;
472
544
545
+ #[ track_caller]
473
546
fn check ( ra_fixture : & str ) {
474
547
check_with_config ( TEST_CONFIG , ra_fixture) ;
475
548
}
476
549
550
+ #[ track_caller]
477
551
fn check_params ( ra_fixture : & str ) {
478
552
check_with_config (
479
553
InlayHintsConfig {
@@ -486,6 +560,7 @@ mod tests {
486
560
) ;
487
561
}
488
562
563
+ #[ track_caller]
489
564
fn check_types ( ra_fixture : & str ) {
490
565
check_with_config (
491
566
InlayHintsConfig {
@@ -498,6 +573,7 @@ mod tests {
498
573
) ;
499
574
}
500
575
576
+ #[ track_caller]
501
577
fn check_chains ( ra_fixture : & str ) {
502
578
check_with_config (
503
579
InlayHintsConfig {
@@ -510,6 +586,7 @@ mod tests {
510
586
) ;
511
587
}
512
588
589
+ #[ track_caller]
513
590
fn check_with_config ( config : InlayHintsConfig , ra_fixture : & str ) {
514
591
let ( analysis, file_id) = fixture:: file ( & ra_fixture) ;
515
592
let expected = extract_annotations ( & * analysis. file_text ( file_id) . unwrap ( ) ) ;
@@ -519,6 +596,7 @@ mod tests {
519
596
assert_eq ! ( expected, actual, "\n Expected:\n {:#?}\n \n Actual:\n {:#?}" , expected, actual) ;
520
597
}
521
598
599
+ #[ track_caller]
522
600
fn check_expect ( config : InlayHintsConfig , ra_fixture : & str , expect : Expect ) {
523
601
let ( analysis, file_id) = fixture:: file ( & ra_fixture) ;
524
602
let inlay_hints = analysis. inlay_hints ( & config, file_id) . unwrap ( ) ;
@@ -1191,11 +1269,12 @@ trait Display {}
1191
1269
trait Sync {}
1192
1270
1193
1271
fn main() {
1194
- let _v = Vec::<Box<&(dyn Display + Sync)>>::new();
1272
+ // The block expression wrapping disables the constructor hint hiding logic
1273
+ let _v = { Vec::<Box<&(dyn Display + Sync)>>::new() };
1195
1274
//^^ Vec<Box<&(dyn Display + Sync)>>
1196
- let _v = Vec::<Box<*const (dyn Display + Sync)>>::new();
1275
+ let _v = { Vec::<Box<*const (dyn Display + Sync)>>::new() } ;
1197
1276
//^^ Vec<Box<*const (dyn Display + Sync)>>
1198
- let _v = Vec::<Box<dyn Display + Sync>>::new();
1277
+ let _v = { Vec::<Box<dyn Display + Sync>>::new() } ;
1199
1278
//^^ Vec<Box<dyn Display + Sync>>
1200
1279
}
1201
1280
"# ,
@@ -1234,6 +1313,48 @@ fn main() {
1234
1313
) ;
1235
1314
}
1236
1315
1316
+ #[ test]
1317
+ fn skip_constructor_type_hints ( ) {
1318
+ check_types (
1319
+ r#"
1320
+ //- minicore: try
1321
+ use core::ops::ControlFlow;
1322
+
1323
+ struct Struct;
1324
+ struct TupleStruct();
1325
+
1326
+ impl Struct {
1327
+ fn new() -> Self {
1328
+ Struct
1329
+ }
1330
+ fn try_new() -> ControlFlow<(), Self> {
1331
+ ControlFlow::Continue(Struct)
1332
+ }
1333
+ }
1334
+
1335
+ struct Generic<T>(T);
1336
+ impl Generic<i32> {
1337
+ fn new() -> Self {
1338
+ Generic(0)
1339
+ }
1340
+ }
1341
+
1342
+ fn main() {
1343
+ let strukt = Struct::new();
1344
+ let tuple_struct = TupleStruct();
1345
+ let generic0 = Generic::new();
1346
+ // ^^^^^^^^ Generic<i32>
1347
+ let generic1 = Generic::<i32>::new();
1348
+ let generic2 = <Generic<i32>>::new();
1349
+ }
1350
+
1351
+ fn fallible() -> ControlFlow<()> {
1352
+ let strukt = Struct::try_new()?;
1353
+ }
1354
+ "# ,
1355
+ ) ;
1356
+ }
1357
+
1237
1358
#[ test]
1238
1359
fn closures ( ) {
1239
1360
check (
0 commit comments