1
1
use hir:: db:: HirDatabase ;
2
2
use ra_syntax:: {
3
- ast, AstNode , SyntaxNode , Direction , TextRange ,
3
+ ast:: { self , NameOwner } , AstNode , SyntaxNode , Direction , TextRange ,
4
4
SyntaxKind :: { PATH , PATH_SEGMENT , COLONCOLON , COMMA }
5
5
} ;
6
6
use crate :: assist_ctx:: { AssistCtx , Assist , AssistBuilder } ;
@@ -345,9 +345,9 @@ fn best_action_for_target<'b, 'a: 'b>(
345
345
match best_action {
346
346
Some ( action) => return action,
347
347
None => {
348
- // We have no action we no use item was found in container so we find
348
+ // We have no action and no UseItem was found in container so we find
349
349
// another item and we use it as anchor.
350
- // If there are not items, we choose the target path itself as anchor.
350
+ // If there are no items, we choose the target path itself as anchor.
351
351
let anchor = container
352
352
. children ( )
353
353
. find_map ( ast:: ModuleItem :: cast)
@@ -480,6 +480,24 @@ fn make_assist_add_nested_import(
480
480
}
481
481
}
482
482
483
+ fn apply_auto_import < ' a > (
484
+ container : & SyntaxNode ,
485
+ path : & ast:: Path ,
486
+ target : & [ & ' a ast:: PathSegment ] ,
487
+ edit : & mut AssistBuilder ,
488
+ ) {
489
+ let action = best_action_for_target ( container, path, target) ;
490
+ make_assist ( & action, target, edit) ;
491
+ if let ( Some ( first) , Some ( last) ) = ( target. first ( ) , target. last ( ) ) {
492
+ // Here we are assuming the assist will provide a correct use statement
493
+ // so we can delete the path qualifier
494
+ edit. delete ( TextRange :: from_to (
495
+ first. syntax ( ) . range ( ) . start ( ) ,
496
+ last. syntax ( ) . range ( ) . start ( ) ,
497
+ ) ) ;
498
+ }
499
+ }
500
+
483
501
pub ( crate ) fn auto_import ( mut ctx : AssistCtx < impl HirDatabase > ) -> Option < Assist > {
484
502
let node = ctx. covering_node ( ) ;
485
503
let current_file = node. ancestors ( ) . find_map ( ast:: SourceFile :: cast) ?;
@@ -495,18 +513,20 @@ pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist
495
513
return None ;
496
514
}
497
515
498
- ctx. add_action ( format ! ( "import {} in the current file" , fmt_segments( & segments) ) , |edit| {
499
- let action = best_action_for_target ( current_file. syntax ( ) , path, & segments) ;
500
- make_assist ( & action, segments. as_slice ( ) , edit) ;
501
- if let Some ( last_segment) = path. segment ( ) {
502
- // Here we are assuming the assist will provide a correct use statement
503
- // so we can delete the path qualifier
504
- edit. delete ( TextRange :: from_to (
505
- path. syntax ( ) . range ( ) . start ( ) ,
506
- last_segment. syntax ( ) . range ( ) . start ( ) ,
507
- ) ) ;
516
+ if let Some ( module) = path. syntax ( ) . ancestors ( ) . find_map ( ast:: Module :: cast) {
517
+ if let ( Some ( item_list) , Some ( name) ) = ( module. item_list ( ) , module. name ( ) ) {
518
+ ctx. add_action (
519
+ format ! ( "import {} in mod {}" , fmt_segments( & segments) , name. text( ) ) ,
520
+ |edit| {
521
+ apply_auto_import ( item_list. syntax ( ) , path, & segments, edit) ;
522
+ } ,
523
+ ) ;
508
524
}
509
- } ) ;
525
+ } else {
526
+ ctx. add_action ( format ! ( "import {} in the current file" , fmt_segments( & segments) ) , |edit| {
527
+ apply_auto_import ( current_file. syntax ( ) , path, & segments, edit) ;
528
+ } ) ;
529
+ }
510
530
511
531
ctx. build ( )
512
532
}
@@ -531,6 +551,21 @@ Debug<|>
531
551
) ;
532
552
}
533
553
554
+ #[ test]
555
+ fn test_auto_import_file_add_use_no_anchor_2seg ( ) {
556
+ check_assist (
557
+ auto_import,
558
+ "
559
+ std::fmt<|>::Debug
560
+ " ,
561
+ "
562
+ use std::fmt;
563
+
564
+ fmt<|>::Debug
565
+ " ,
566
+ ) ;
567
+ }
568
+
534
569
#[ test]
535
570
fn test_auto_import_file_add_use ( ) {
536
571
check_assist (
@@ -728,4 +763,37 @@ impl foo<|> for Foo {
728
763
" ,
729
764
) ;
730
765
}
766
+
767
+ #[ test]
768
+ fn test_auto_import_not_applicable_in_use ( ) {
769
+ check_assist_not_applicable (
770
+ auto_import,
771
+ "
772
+ use std::fmt<|>;
773
+ " ,
774
+ ) ;
775
+ }
776
+
777
+ #[ test]
778
+ fn test_auto_import_file_add_use_no_anchor_in_mod_mod ( ) {
779
+ check_assist (
780
+ auto_import,
781
+ "
782
+ mod foo {
783
+ mod bar {
784
+ std::fmt::Debug<|>
785
+ }
786
+ }
787
+ " ,
788
+ "
789
+ mod foo {
790
+ mod bar {
791
+ use std::fmt::Debug;
792
+
793
+ Debug<|>
794
+ }
795
+ }
796
+ " ,
797
+ ) ;
798
+ }
731
799
}
0 commit comments