@@ -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 } ,
@@ -211,11 +212,11 @@ fn get_bind_pat_hints(
211
212
let label = match label {
212
213
Some ( label) => label,
213
214
None => {
214
- let ty = ty. display_truncated ( sema. db , config. max_length ) . to_string ( ) ;
215
- if Some ( & * ty ) == get_constructor_name ( sema, pat) . as_deref ( ) {
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 ( ) {
216
217
return None ;
217
218
}
218
- ty . into ( )
219
+ ty_name . into ( )
219
220
}
220
221
} ;
221
222
@@ -231,34 +232,60 @@ fn get_bind_pat_hints(
231
232
Some ( ( ) )
232
233
}
233
234
234
- fn get_constructor_name ( sema : & Semantics < RootDatabase > , pat : & ast:: IdentPat ) -> Option < String > {
235
- let it = pat. syntax ( ) . parent ( ) ?;
235
+ fn is_named_constructor (
236
+ sema : & Semantics < RootDatabase > ,
237
+ pat : & ast:: IdentPat ,
238
+ ty_name : & str ,
239
+ ) -> Option < ( ) > {
240
+ let let_node = pat. syntax ( ) . parent ( ) ?;
236
241
let expr = match_ast ! {
237
- match it {
242
+ match let_node {
238
243
ast:: LetStmt ( it) => it. initializer( ) ,
239
244
ast:: Condition ( it) => it. expr( ) ,
240
245
_ => None ,
241
246
}
247
+ } ?;
248
+
249
+ let expr = sema. descend_node_into_attributes ( expr. clone ( ) ) . pop ( ) . unwrap_or ( expr) ;
250
+ // unwrap postfix expressions
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 ,
242
262
} ;
263
+ let path = expr. path ( ) ?;
243
264
244
- if let Some ( expr) = expr {
245
- let expr = sema. descend_node_into_attributes ( expr. clone ( ) ) . pop ( ) . unwrap_or ( expr) ;
246
- let expr = match expr {
247
- ast:: Expr :: TryExpr ( it) => it. expr ( ) ,
248
- ast:: Expr :: AwaitExpr ( it) => it. expr ( ) ,
249
- expr => Some ( expr) ,
250
- } ?;
251
- let path = match expr {
252
- ast:: Expr :: CallExpr ( call) => match call. expr ( ) ? {
253
- ast:: Expr :: PathExpr ( p) => p. path ( ) ,
254
- _ => None ,
255
- } ,
256
- _ => None ,
257
- } ?;
258
- let seg = path. qualifier ( ) ?. segment ( ) ?;
259
- return Some ( seg. to_string ( ) ) ;
265
+ // Check for tuple-struct or tuple-variant in which case we can check the last segment
266
+ let callable = sema. type_of_expr ( & ast:: Expr :: PathExpr ( expr) ) ?. original . as_callable ( sema. db ) ;
267
+ let callable_kind = callable. map ( |it| it. kind ( ) ) ;
268
+ if let Some ( hir:: CallableKind :: TupleStruct ( _) | hir:: CallableKind :: TupleEnumVariant ( _) ) =
269
+ callable_kind
270
+ {
271
+ if let Some ( ctor) = path. segment ( ) {
272
+ return ( & ctor. to_string ( ) == ty_name) . then ( || ( ) ) ;
273
+ }
260
274
}
261
- None
275
+
276
+ // otherwise use the qualifying segment as the constructor name
277
+ let qual_seg = path. qualifier ( ) ?. segment ( ) ?;
278
+ let ctor_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
+ ( & ctor_name == ty_name) . then ( || ( ) )
262
289
}
263
290
264
291
/// Checks if the type is an Iterator from std::iter and replaces its hint with an `impl Iterator<Item = Ty>`.
@@ -511,10 +538,12 @@ mod tests {
511
538
max_length : None ,
512
539
} ;
513
540
541
+ #[ track_caller]
514
542
fn check ( ra_fixture : & str ) {
515
543
check_with_config ( TEST_CONFIG , ra_fixture) ;
516
544
}
517
545
546
+ #[ track_caller]
518
547
fn check_params ( ra_fixture : & str ) {
519
548
check_with_config (
520
549
InlayHintsConfig {
@@ -527,6 +556,7 @@ mod tests {
527
556
) ;
528
557
}
529
558
559
+ #[ track_caller]
530
560
fn check_types ( ra_fixture : & str ) {
531
561
check_with_config (
532
562
InlayHintsConfig {
@@ -539,6 +569,7 @@ mod tests {
539
569
) ;
540
570
}
541
571
572
+ #[ track_caller]
542
573
fn check_chains ( ra_fixture : & str ) {
543
574
check_with_config (
544
575
InlayHintsConfig {
@@ -551,6 +582,7 @@ mod tests {
551
582
) ;
552
583
}
553
584
585
+ #[ track_caller]
554
586
fn check_with_config ( config : InlayHintsConfig , ra_fixture : & str ) {
555
587
let ( analysis, file_id) = fixture:: file ( & ra_fixture) ;
556
588
let expected = extract_annotations ( & * analysis. file_text ( file_id) . unwrap ( ) ) ;
@@ -560,6 +592,7 @@ mod tests {
560
592
assert_eq ! ( expected, actual, "\n Expected:\n {:#?}\n \n Actual:\n {:#?}" , expected, actual) ;
561
593
}
562
594
595
+ #[ track_caller]
563
596
fn check_expect ( config : InlayHintsConfig , ra_fixture : & str , expect : Expect ) {
564
597
let ( analysis, file_id) = fixture:: file ( & ra_fixture) ;
565
598
let inlay_hints = analysis. inlay_hints ( & config, file_id) . unwrap ( ) ;
@@ -1232,11 +1265,12 @@ trait Display {}
1232
1265
trait Sync {}
1233
1266
1234
1267
fn main() {
1235
- let _v = Vec::<Box<&(dyn Display + Sync)>>::new();
1268
+ // The block expression wrapping disables the constructor hint hiding logic
1269
+ let _v = { Vec::<Box<&(dyn Display + Sync)>>::new() };
1236
1270
//^^ Vec<Box<&(dyn Display + Sync)>>
1237
- let _v = Vec::<Box<*const (dyn Display + Sync)>>::new();
1271
+ let _v = { Vec::<Box<*const (dyn Display + Sync)>>::new() } ;
1238
1272
//^^ Vec<Box<*const (dyn Display + Sync)>>
1239
- let _v = Vec::<Box<dyn Display + Sync>>::new();
1273
+ let _v = { Vec::<Box<dyn Display + Sync>>::new() } ;
1240
1274
//^^ Vec<Box<dyn Display + Sync>>
1241
1275
}
1242
1276
"# ,
@@ -1304,13 +1338,10 @@ impl Generic<i32> {
1304
1338
fn main() {
1305
1339
let strukt = Struct::new();
1306
1340
let tuple_struct = TupleStruct();
1307
- // ^^^^^^^^^^^^ TupleStruct
1308
1341
let generic0 = Generic::new();
1309
1342
// ^^^^^^^^ Generic<i32>
1310
1343
let generic1 = Generic::<i32>::new();
1311
- // ^^^^^^^^ Generic<i32>
1312
1344
let generic2 = <Generic<i32>>::new();
1313
- // ^^^^^^^^ Generic<i32>
1314
1345
}
1315
1346
1316
1347
fn fallible() -> ControlFlow<()> {
0 commit comments