@@ -239,16 +239,22 @@ fn substitute_type_params<N: AstNode>(
239
239
240
240
use hir:: PathResolution ;
241
241
242
- // TODO handle partial paths, with generic args
242
+ // TODO handle generic args
243
+ // TODO handle associated item paths
243
244
// TODO handle value ns?
244
245
246
+ // FIXME extract this to a general utility as well
245
247
fn qualify_paths < N : AstNode > ( db : & impl HirDatabase , node : hir:: InFile < N > , from : hir:: Module ) -> N {
246
248
let path_replacements = node
247
249
. value
248
250
. syntax ( )
249
251
. descendants ( )
250
252
. filter_map ( ast:: Path :: cast)
251
253
. filter_map ( |p| {
254
+ if p. segment ( ) . and_then ( |s| s. param_list ( ) ) . is_some ( ) {
255
+ // don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway
256
+ return None ;
257
+ }
252
258
let analyzer = hir:: SourceAnalyzer :: new ( db, node. with_value ( p. syntax ( ) ) , None ) ;
253
259
let resolution = analyzer. resolve_path ( db, & p) ?;
254
260
match resolution {
@@ -468,6 +474,125 @@ impl foo::Foo for S {
468
474
) ;
469
475
}
470
476
477
+ #[ test]
478
+ fn test_qualify_path_generic ( ) {
479
+ check_assist (
480
+ add_missing_impl_members,
481
+ "
482
+ mod foo {
483
+ pub struct Bar<T>;
484
+ trait Foo { fn foo(&self, bar: Bar<u32>); }
485
+ }
486
+ struct S;
487
+ impl foo::Foo for S { <|> }" ,
488
+ "
489
+ mod foo {
490
+ pub struct Bar<T>;
491
+ trait Foo { fn foo(&self, bar: Bar<u32>); }
492
+ }
493
+ struct S;
494
+ impl foo::Foo for S {
495
+ <|>fn foo(&self, bar: foo::Bar<u32>) { unimplemented!() }
496
+ }" ,
497
+ ) ;
498
+ }
499
+
500
+ #[ test]
501
+ fn test_qualify_path_and_substitute_param ( ) {
502
+ check_assist (
503
+ add_missing_impl_members,
504
+ "
505
+ mod foo {
506
+ pub struct Bar<T>;
507
+ trait Foo<T> { fn foo(&self, bar: Bar<T>); }
508
+ }
509
+ struct S;
510
+ impl foo::Foo<u32> for S { <|> }" ,
511
+ "
512
+ mod foo {
513
+ pub struct Bar<T>;
514
+ trait Foo<T> { fn foo(&self, bar: Bar<T>); }
515
+ }
516
+ struct S;
517
+ impl foo::Foo<u32> for S {
518
+ <|>fn foo(&self, bar: foo::Bar<u32>) { unimplemented!() }
519
+ }" ,
520
+ ) ;
521
+ }
522
+
523
+ #[ test]
524
+ fn test_qualify_path_associated_item ( ) {
525
+ check_assist (
526
+ add_missing_impl_members,
527
+ "
528
+ mod foo {
529
+ pub struct Bar<T>;
530
+ impl Bar<T> { type Assoc = u32; }
531
+ trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }
532
+ }
533
+ struct S;
534
+ impl foo::Foo for S { <|> }" ,
535
+ "
536
+ mod foo {
537
+ pub struct Bar<T>;
538
+ impl Bar { type Assoc = u32; }
539
+ trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }
540
+ }
541
+ struct S;
542
+ impl foo::Foo for S {
543
+ <|>fn foo(&self, bar: foo::Bar<u32>::Assoc) { unimplemented!() }
544
+ }" ,
545
+ ) ;
546
+ }
547
+
548
+ #[ test]
549
+ fn test_qualify_path_nested ( ) {
550
+ check_assist (
551
+ add_missing_impl_members,
552
+ "
553
+ mod foo {
554
+ pub struct Bar<T>;
555
+ pub struct Baz;
556
+ trait Foo { fn foo(&self, bar: Bar<Baz>); }
557
+ }
558
+ struct S;
559
+ impl foo::Foo for S { <|> }" ,
560
+ "
561
+ mod foo {
562
+ pub struct Bar<T>;
563
+ pub struct Baz;
564
+ trait Foo { fn foo(&self, bar: Bar<Baz>); }
565
+ }
566
+ struct S;
567
+ impl foo::Foo for S {
568
+ <|>fn foo(&self, bar: foo::Bar<foo::Baz>) { unimplemented!() }
569
+ }" ,
570
+ ) ;
571
+ }
572
+
573
+ #[ test]
574
+ fn test_qualify_path_fn_trait_notation ( ) {
575
+ check_assist (
576
+ add_missing_impl_members,
577
+ "
578
+ mod foo {
579
+ pub trait Fn<Args> { type Output; }
580
+ trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
581
+ }
582
+ struct S;
583
+ impl foo::Foo for S { <|> }" ,
584
+ "
585
+ mod foo {
586
+ pub trait Fn<Args> { type Output; }
587
+ trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
588
+ }
589
+ struct S;
590
+ impl foo::Foo for S {
591
+ <|>fn foo(&self, bar: dyn Fn(u32) -> i32) { unimplemented!() }
592
+ }" ,
593
+ ) ;
594
+ }
595
+
471
596
#[ test]
472
597
fn test_empty_trait ( ) {
473
598
check_assist_not_applicable (
0 commit comments