aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/auto_import.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists/src/auto_import.rs')
-rw-r--r--crates/ra_assists/src/auto_import.rs85
1 files changed, 67 insertions, 18 deletions
diff --git a/crates/ra_assists/src/auto_import.rs b/crates/ra_assists/src/auto_import.rs
index 52c2a0b2b..105c888d5 100644
--- a/crates/ra_assists/src/auto_import.rs
+++ b/crates/ra_assists/src/auto_import.rs
@@ -1,4 +1,5 @@
1use hir::db::HirDatabase; 1use hir::db::HirDatabase;
2
2use ra_syntax::{ 3use ra_syntax::{
3 ast::{ self, NameOwner }, AstNode, SyntaxNode, Direction, TextRange, 4 ast::{ self, NameOwner }, AstNode, SyntaxNode, Direction, TextRange,
4 SyntaxKind::{ PATH, PATH_SEGMENT, COLONCOLON, COMMA } 5 SyntaxKind::{ PATH, PATH_SEGMENT, COLONCOLON, COMMA }
@@ -267,7 +268,7 @@ fn walk_use_tree_for_best_action<'a>(
267 false, 268 false,
268 ) 269 )
269 } 270 }
270 common if left.len() > right.len() => { 271 common if common == right.len() && left.len() > right.len() => {
271 // e.g: target is std::fmt and we can have 272 // e.g: target is std::fmt and we can have
272 // 1- use std; 273 // 1- use std;
273 // 2- use std::{ ... }; 274 // 2- use std::{ ... };
@@ -294,12 +295,12 @@ fn walk_use_tree_for_best_action<'a>(
294 } 295 }
295 } 296 }
296 } else { 297 } else {
297 // Case 1, split 298 // Case 1, split adding self
298 better_action = ImportAction::add_nested_import(prev_len + common, path, None, true) 299 better_action = ImportAction::add_nested_import(prev_len + common, path, None, true)
299 } 300 }
300 better_action 301 better_action
301 } 302 }
302 common if left.len() < right.len() => { 303 common if common == left.len() && left.len() < right.len() => {
303 // e.g: target is std::fmt and we can have 304 // e.g: target is std::fmt and we can have
304 // use std::fmt::Debug; 305 // use std::fmt::Debug;
305 let segments_to_split = current_path_segments.split_at(prev_len + common).1; 306 let segments_to_split = current_path_segments.split_at(prev_len + common).1;
@@ -310,6 +311,17 @@ fn walk_use_tree_for_best_action<'a>(
310 true, 311 true,
311 ) 312 )
312 } 313 }
314 common if common < left.len() && common < right.len() => {
315 // e.g: target is std::fmt::nested::Debug
316 // use std::fmt::Display
317 let segments_to_split = current_path_segments.split_at(prev_len + common).1;
318 ImportAction::add_nested_import(
319 prev_len + common,
320 path,
321 Some(segments_to_split[0]),
322 false,
323 )
324 }
313 _ => unreachable!(), 325 _ => unreachable!(),
314 }; 326 };
315 327
@@ -500,8 +512,6 @@ fn apply_auto_import<'a>(
500 512
501pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 513pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
502 let node = ctx.covering_node(); 514 let node = ctx.covering_node();
503 let current_file = node.ancestors().find_map(ast::SourceFile::cast)?;
504
505 let path = node.ancestors().find_map(ast::Path::cast)?; 515 let path = node.ancestors().find_map(ast::Path::cast)?;
506 // We don't want to mess with use statements 516 // We don't want to mess with use statements
507 if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() { 517 if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() {
@@ -523,6 +533,7 @@ pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist
523 ); 533 );
524 } 534 }
525 } else { 535 } else {
536 let current_file = node.ancestors().find_map(ast::SourceFile::cast)?;
526 ctx.add_action(format!("import {} in the current file", fmt_segments(&segments)), |edit| { 537 ctx.add_action(format!("import {} in the current file", fmt_segments(&segments)), |edit| {
527 apply_auto_import(current_file.syntax(), path, &segments, edit); 538 apply_auto_import(current_file.syntax(), path, &segments, edit);
528 }); 539 });
@@ -537,7 +548,7 @@ mod tests {
537 use crate::helpers::{ check_assist, check_assist_not_applicable }; 548 use crate::helpers::{ check_assist, check_assist_not_applicable };
538 549
539 #[test] 550 #[test]
540 fn test_auto_import_file_add_use_no_anchor() { 551 fn test_auto_import_add_use_no_anchor() {
541 check_assist( 552 check_assist(
542 auto_import, 553 auto_import,
543 " 554 "
@@ -552,7 +563,7 @@ Debug<|>
552 } 563 }
553 564
554 #[test] 565 #[test]
555 fn test_auto_import_file_add_use_no_anchor_2seg() { 566 fn test_auto_import_add_use_no_anchor_2seg() {
556 check_assist( 567 check_assist(
557 auto_import, 568 auto_import,
558 " 569 "
@@ -567,7 +578,7 @@ fmt<|>::Debug
567 } 578 }
568 579
569 #[test] 580 #[test]
570 fn test_auto_import_file_add_use() { 581 fn test_auto_import_add_use() {
571 check_assist( 582 check_assist(
572 auto_import, 583 auto_import,
573 " 584 "
@@ -587,7 +598,7 @@ impl Debug<|> for Foo {
587 } 598 }
588 599
589 #[test] 600 #[test]
590 fn test_auto_import_file_add_use_other_anchor() { 601 fn test_auto_import_file_use_other_anchor() {
591 check_assist( 602 check_assist(
592 auto_import, 603 auto_import,
593 " 604 "
@@ -604,7 +615,7 @@ impl Debug<|> for Foo {
604 } 615 }
605 616
606 #[test] 617 #[test]
607 fn test_auto_import_file_add_use_other_anchor_indent() { 618 fn test_auto_import_add_use_other_anchor_indent() {
608 check_assist( 619 check_assist(
609 auto_import, 620 auto_import,
610 " 621 "
@@ -621,7 +632,7 @@ impl Debug<|> for Foo {
621 } 632 }
622 633
623 #[test] 634 #[test]
624 fn test_auto_import_file_split_different() { 635 fn test_auto_import_split_different() {
625 check_assist( 636 check_assist(
626 auto_import, 637 auto_import,
627 " 638 "
@@ -640,7 +651,7 @@ impl io<|> for Foo {
640 } 651 }
641 652
642 #[test] 653 #[test]
643 fn test_auto_import_file_split_self_for_use() { 654 fn test_auto_import_split_self_for_use() {
644 check_assist( 655 check_assist(
645 auto_import, 656 auto_import,
646 " 657 "
@@ -659,7 +670,7 @@ impl Debug<|> for Foo {
659 } 670 }
660 671
661 #[test] 672 #[test]
662 fn test_auto_import_file_split_self_for_target() { 673 fn test_auto_import_split_self_for_target() {
663 check_assist( 674 check_assist(
664 auto_import, 675 auto_import,
665 " 676 "
@@ -678,7 +689,7 @@ impl fmt<|> for Foo {
678 } 689 }
679 690
680 #[test] 691 #[test]
681 fn test_auto_import_file_add_to_nested_self_nested() { 692 fn test_auto_import_add_to_nested_self_nested() {
682 check_assist( 693 check_assist(
683 auto_import, 694 auto_import,
684 " 695 "
@@ -697,7 +708,7 @@ impl nested<|> for Foo {
697 } 708 }
698 709
699 #[test] 710 #[test]
700 fn test_auto_import_file_add_to_nested_self_already_included() { 711 fn test_auto_import_add_to_nested_self_already_included() {
701 check_assist( 712 check_assist(
702 auto_import, 713 auto_import,
703 " 714 "
@@ -716,7 +727,7 @@ impl nested<|> for Foo {
716 } 727 }
717 728
718 #[test] 729 #[test]
719 fn test_auto_import_file_add_to_nested_nested() { 730 fn test_auto_import_add_to_nested_nested() {
720 check_assist( 731 check_assist(
721 auto_import, 732 auto_import,
722 " 733 "
@@ -735,7 +746,45 @@ impl Debug<|> for Foo {
735 } 746 }
736 747
737 #[test] 748 #[test]
738 fn test_auto_import_file_alias() { 749 fn test_auto_import_split_common_target_longer() {
750 check_assist(
751 auto_import,
752 "
753use std::fmt::Debug;
754
755impl std::fmt::nested::Display<|> for Foo {
756}
757",
758 "
759use std::fmt::{ nested::Display, Debug};
760
761impl Display<|> for Foo {
762}
763",
764 );
765 }
766
767 #[test]
768 fn test_auto_import_split_common_use_longer() {
769 check_assist(
770 auto_import,
771 "
772use std::fmt::nested::Debug;
773
774impl std::fmt::Display<|> for Foo {
775}
776",
777 "
778use std::fmt::{ Display, nested::Debug};
779
780impl Display<|> for Foo {
781}
782",
783 );
784 }
785
786 #[test]
787 fn test_auto_import_alias() {
739 check_assist( 788 check_assist(
740 auto_import, 789 auto_import,
741 " 790 "
@@ -775,7 +824,7 @@ use std::fmt<|>;
775 } 824 }
776 825
777 #[test] 826 #[test]
778 fn test_auto_import_file_add_use_no_anchor_in_mod_mod() { 827 fn test_auto_import_add_use_no_anchor_in_mod_mod() {
779 check_assist( 828 check_assist(
780 auto_import, 829 auto_import,
781 " 830 "