aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/hir_def/src/find_path.rs587
-rw-r--r--crates/ide/src/move_item.rs100
-rw-r--r--crates/rust-analyzer/src/handlers.rs9
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs2
-rw-r--r--crates/rust-analyzer/src/to_proto.rs12
5 files changed, 402 insertions, 308 deletions
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs
index 109d3552f..317ca86ec 100644
--- a/crates/hir_def/src/find_path.rs
+++ b/crates/hir_def/src/find_path.rs
@@ -425,106 +425,145 @@ mod tests {
425 425
426 #[test] 426 #[test]
427 fn same_module() { 427 fn same_module() {
428 let code = r#" 428 check_found_path(
429 //- /main.rs 429 r#"
430 struct S; 430//- /main.rs
431 $0 431struct S;
432 "#; 432$0
433 check_found_path(code, "S", "S", "crate::S", "self::S"); 433 "#,
434 "S",
435 "S",
436 "crate::S",
437 "self::S",
438 );
434 } 439 }
435 440
436 #[test] 441 #[test]
437 fn enum_variant() { 442 fn enum_variant() {
438 let code = r#" 443 check_found_path(
439 //- /main.rs 444 r#"
440 enum E { A } 445//- /main.rs
441 $0 446enum E { A }
442 "#; 447$0
443 check_found_path(code, "E::A", "E::A", "E::A", "E::A"); 448 "#,
449 "E::A",
450 "E::A",
451 "E::A",
452 "E::A",
453 );
444 } 454 }
445 455
446 #[test] 456 #[test]
447 fn sub_module() { 457 fn sub_module() {
448 let code = r#" 458 check_found_path(
449 //- /main.rs 459 r#"
450 mod foo { 460//- /main.rs
451 pub struct S; 461mod foo {
452 } 462 pub struct S;
453 $0 463}
454 "#; 464$0
455 check_found_path(code, "foo::S", "foo::S", "crate::foo::S", "self::foo::S"); 465 "#,
466 "foo::S",
467 "foo::S",
468 "crate::foo::S",
469 "self::foo::S",
470 );
456 } 471 }
457 472
458 #[test] 473 #[test]
459 fn super_module() { 474 fn super_module() {
460 let code = r#" 475 check_found_path(
461 //- /main.rs 476 r#"
462 mod foo; 477//- /main.rs
463 //- /foo.rs 478mod foo;
464 mod bar; 479//- /foo.rs
465 struct S; 480mod bar;
466 //- /foo/bar.rs 481struct S;
467 $0 482//- /foo/bar.rs
468 "#; 483$0
469 check_found_path(code, "super::S", "super::S", "crate::foo::S", "super::S"); 484 "#,
485 "super::S",
486 "super::S",
487 "crate::foo::S",
488 "super::S",
489 );
470 } 490 }
471 491
472 #[test] 492 #[test]
473 fn self_module() { 493 fn self_module() {
474 let code = r#" 494 check_found_path(
475 //- /main.rs 495 r#"
476 mod foo; 496//- /main.rs
477 //- /foo.rs 497mod foo;
478 $0 498//- /foo.rs
479 "#; 499$0
480 check_found_path(code, "self", "self", "crate::foo", "self"); 500 "#,
501 "self",
502 "self",
503 "crate::foo",
504 "self",
505 );
481 } 506 }
482 507
483 #[test] 508 #[test]
484 fn crate_root() { 509 fn crate_root() {
485 let code = r#" 510 check_found_path(
486 //- /main.rs 511 r#"
487 mod foo; 512//- /main.rs
488 //- /foo.rs 513mod foo;
489 $0 514//- /foo.rs
490 "#; 515$0
491 check_found_path(code, "crate", "crate", "crate", "crate"); 516 "#,
517 "crate",
518 "crate",
519 "crate",
520 "crate",
521 );
492 } 522 }
493 523
494 #[test] 524 #[test]
495 fn same_crate() { 525 fn same_crate() {
496 let code = r#" 526 check_found_path(
497 //- /main.rs 527 r#"
498 mod foo; 528//- /main.rs
499 struct S; 529mod foo;
500 //- /foo.rs 530struct S;
501 $0 531//- /foo.rs
502 "#; 532$0
503 check_found_path(code, "crate::S", "crate::S", "crate::S", "crate::S"); 533 "#,
534 "crate::S",
535 "crate::S",
536 "crate::S",
537 "crate::S",
538 );
504 } 539 }
505 540
506 #[test] 541 #[test]
507 fn different_crate() { 542 fn different_crate() {
508 let code = r#" 543 check_found_path(
509 //- /main.rs crate:main deps:std 544 r#"
510 $0 545//- /main.rs crate:main deps:std
511 //- /std.rs crate:std 546$0
512 pub struct S; 547//- /std.rs crate:std
513 "#; 548pub struct S;
514 check_found_path(code, "std::S", "std::S", "std::S", "std::S"); 549 "#,
550 "std::S",
551 "std::S",
552 "std::S",
553 "std::S",
554 );
515 } 555 }
516 556
517 #[test] 557 #[test]
518 fn different_crate_renamed() { 558 fn different_crate_renamed() {
519 let code = r#"
520 //- /main.rs crate:main deps:std
521 extern crate std as std_renamed;
522 $0
523 //- /std.rs crate:std
524 pub struct S;
525 "#;
526 check_found_path( 559 check_found_path(
527 code, 560 r#"
561//- /main.rs crate:main deps:std
562extern crate std as std_renamed;
563$0
564//- /std.rs crate:std
565pub struct S;
566 "#,
528 "std_renamed::S", 567 "std_renamed::S",
529 "std_renamed::S", 568 "std_renamed::S",
530 "std_renamed::S", 569 "std_renamed::S",
@@ -537,41 +576,38 @@ mod tests {
537 cov_mark::check!(partially_imported); 576 cov_mark::check!(partially_imported);
538 // Tests that short paths are used even for external items, when parts of the path are 577 // Tests that short paths are used even for external items, when parts of the path are
539 // already in scope. 578 // already in scope.
540 let code = r#" 579 check_found_path(
541 //- /main.rs crate:main deps:syntax 580 r#"
581//- /main.rs crate:main deps:syntax
542 582
543 use syntax::ast; 583use syntax::ast;
544 $0 584$0
545 585
546 //- /lib.rs crate:syntax 586//- /lib.rs crate:syntax
547 pub mod ast { 587pub mod ast {
548 pub enum ModuleItem { 588 pub enum ModuleItem {
549 A, B, C, 589 A, B, C,
550 } 590 }
551 } 591}
552 "#; 592 "#,
553 check_found_path(
554 code,
555 "ast::ModuleItem", 593 "ast::ModuleItem",
556 "syntax::ast::ModuleItem", 594 "syntax::ast::ModuleItem",
557 "syntax::ast::ModuleItem", 595 "syntax::ast::ModuleItem",
558 "syntax::ast::ModuleItem", 596 "syntax::ast::ModuleItem",
559 ); 597 );
560 598
561 let code = r#"
562 //- /main.rs crate:main deps:syntax
563
564 $0
565
566 //- /lib.rs crate:syntax
567 pub mod ast {
568 pub enum ModuleItem {
569 A, B, C,
570 }
571 }
572 "#;
573 check_found_path( 599 check_found_path(
574 code, 600 r#"
601//- /main.rs crate:main deps:syntax
602$0
603
604//- /lib.rs crate:syntax
605pub mod ast {
606 pub enum ModuleItem {
607 A, B, C,
608 }
609}
610 "#,
575 "syntax::ast::ModuleItem", 611 "syntax::ast::ModuleItem",
576 "syntax::ast::ModuleItem", 612 "syntax::ast::ModuleItem",
577 "syntax::ast::ModuleItem", 613 "syntax::ast::ModuleItem",
@@ -581,68 +617,88 @@ mod tests {
581 617
582 #[test] 618 #[test]
583 fn same_crate_reexport() { 619 fn same_crate_reexport() {
584 let code = r#" 620 check_found_path(
585 //- /main.rs 621 r#"
586 mod bar { 622//- /main.rs
587 mod foo { pub(super) struct S; } 623mod bar {
588 pub(crate) use foo::*; 624 mod foo { pub(super) struct S; }
589 } 625 pub(crate) use foo::*;
590 $0 626}
591 "#; 627$0
592 check_found_path(code, "bar::S", "bar::S", "crate::bar::S", "self::bar::S"); 628 "#,
629 "bar::S",
630 "bar::S",
631 "crate::bar::S",
632 "self::bar::S",
633 );
593 } 634 }
594 635
595 #[test] 636 #[test]
596 fn same_crate_reexport_rename() { 637 fn same_crate_reexport_rename() {
597 let code = r#" 638 check_found_path(
598 //- /main.rs 639 r#"
599 mod bar { 640//- /main.rs
600 mod foo { pub(super) struct S; } 641mod bar {
601 pub(crate) use foo::S as U; 642 mod foo { pub(super) struct S; }
602 } 643 pub(crate) use foo::S as U;
603 $0 644}
604 "#; 645$0
605 check_found_path(code, "bar::U", "bar::U", "crate::bar::U", "self::bar::U"); 646 "#,
647 "bar::U",
648 "bar::U",
649 "crate::bar::U",
650 "self::bar::U",
651 );
606 } 652 }
607 653
608 #[test] 654 #[test]
609 fn different_crate_reexport() { 655 fn different_crate_reexport() {
610 let code = r#" 656 check_found_path(
611 //- /main.rs crate:main deps:std 657 r#"
612 $0 658//- /main.rs crate:main deps:std
613 //- /std.rs crate:std deps:core 659$0
614 pub use core::S; 660//- /std.rs crate:std deps:core
615 //- /core.rs crate:core 661pub use core::S;
616 pub struct S; 662//- /core.rs crate:core
617 "#; 663pub struct S;
618 check_found_path(code, "std::S", "std::S", "std::S", "std::S"); 664 "#,
665 "std::S",
666 "std::S",
667 "std::S",
668 "std::S",
669 );
619 } 670 }
620 671
621 #[test] 672 #[test]
622 fn prelude() { 673 fn prelude() {
623 let code = r#" 674 check_found_path(
624 //- /main.rs crate:main deps:std 675 r#"
625 $0 676//- /main.rs crate:main deps:std
626 //- /std.rs crate:std 677$0
627 pub mod prelude { pub struct S; } 678//- /std.rs crate:std
628 #[prelude_import] 679pub mod prelude { pub struct S; }
629 pub use prelude::*; 680#[prelude_import]
630 "#; 681pub use prelude::*;
631 check_found_path(code, "S", "S", "S", "S"); 682 "#,
683 "S",
684 "S",
685 "S",
686 "S",
687 );
632 } 688 }
633 689
634 #[test] 690 #[test]
635 fn enum_variant_from_prelude() { 691 fn enum_variant_from_prelude() {
636 let code = r#" 692 let code = r#"
637 //- /main.rs crate:main deps:std 693//- /main.rs crate:main deps:std
638 $0 694$0
639 //- /std.rs crate:std 695//- /std.rs crate:std
640 pub mod prelude { 696pub mod prelude {
641 pub enum Option<T> { Some(T), None } 697 pub enum Option<T> { Some(T), None }
642 pub use Option::*; 698 pub use Option::*;
643 } 699}
644 #[prelude_import] 700#[prelude_import]
645 pub use prelude::*; 701pub use prelude::*;
646 "#; 702 "#;
647 check_found_path(code, "None", "None", "None", "None"); 703 check_found_path(code, "None", "None", "None", "None");
648 check_found_path(code, "Some", "Some", "Some", "Some"); 704 check_found_path(code, "Some", "Some", "Some", "Some");
@@ -650,71 +706,85 @@ mod tests {
650 706
651 #[test] 707 #[test]
652 fn shortest_path() { 708 fn shortest_path() {
653 let code = r#" 709 check_found_path(
654 //- /main.rs 710 r#"
655 pub mod foo; 711//- /main.rs
656 pub mod baz; 712pub mod foo;
657 struct S; 713pub mod baz;
658 $0 714struct S;
659 //- /foo.rs 715$0
660 pub mod bar { pub struct S; } 716//- /foo.rs
661 //- /baz.rs 717pub mod bar { pub struct S; }
662 pub use crate::foo::bar::S; 718//- /baz.rs
663 "#; 719pub use crate::foo::bar::S;
664 check_found_path(code, "baz::S", "baz::S", "crate::baz::S", "self::baz::S"); 720 "#,
721 "baz::S",
722 "baz::S",
723 "crate::baz::S",
724 "self::baz::S",
725 );
665 } 726 }
666 727
667 #[test] 728 #[test]
668 fn discount_private_imports() { 729 fn discount_private_imports() {
669 let code = r#" 730 check_found_path(
670 //- /main.rs 731 r#"
671 mod foo; 732//- /main.rs
672 pub mod bar { pub struct S; } 733mod foo;
673 use bar::S; 734pub mod bar { pub struct S; }
674 //- /foo.rs 735use bar::S;
675 $0 736//- /foo.rs
676 "#; 737$0
677 // crate::S would be shorter, but using private imports seems wrong 738 "#,
678 check_found_path(code, "crate::bar::S", "crate::bar::S", "crate::bar::S", "crate::bar::S"); 739 // crate::S would be shorter, but using private imports seems wrong
740 "crate::bar::S",
741 "crate::bar::S",
742 "crate::bar::S",
743 "crate::bar::S",
744 );
679 } 745 }
680 746
681 #[test] 747 #[test]
682 fn import_cycle() { 748 fn import_cycle() {
683 let code = r#" 749 check_found_path(
684 //- /main.rs 750 r#"
685 pub mod foo; 751//- /main.rs
686 pub mod bar; 752pub mod foo;
687 pub mod baz; 753pub mod bar;
688 //- /bar.rs 754pub mod baz;
689 $0 755//- /bar.rs
690 //- /foo.rs 756$0
691 pub use super::baz; 757//- /foo.rs
692 pub struct S; 758pub use super::baz;
693 //- /baz.rs 759pub struct S;
694 pub use super::foo; 760//- /baz.rs
695 "#; 761pub use super::foo;
696 check_found_path(code, "crate::foo::S", "crate::foo::S", "crate::foo::S", "crate::foo::S"); 762 "#,
763 "crate::foo::S",
764 "crate::foo::S",
765 "crate::foo::S",
766 "crate::foo::S",
767 );
697 } 768 }
698 769
699 #[test] 770 #[test]
700 fn prefer_std_paths_over_alloc() { 771 fn prefer_std_paths_over_alloc() {
701 cov_mark::check!(prefer_std_paths); 772 cov_mark::check!(prefer_std_paths);
702 let code = r#" 773 check_found_path(
703 //- /main.rs crate:main deps:alloc,std 774 r#"
704 $0 775//- /main.rs crate:main deps:alloc,std
776$0
705 777
706 //- /std.rs crate:std deps:alloc 778//- /std.rs crate:std deps:alloc
707 pub mod sync { 779pub mod sync {
708 pub use alloc::sync::Arc; 780 pub use alloc::sync::Arc;
709 } 781}
710 782
711 //- /zzz.rs crate:alloc 783//- /zzz.rs crate:alloc
712 pub mod sync { 784pub mod sync {
713 pub struct Arc; 785 pub struct Arc;
714 } 786}
715 "#; 787 "#,
716 check_found_path(
717 code,
718 "std::sync::Arc", 788 "std::sync::Arc",
719 "std::sync::Arc", 789 "std::sync::Arc",
720 "std::sync::Arc", 790 "std::sync::Arc",
@@ -725,26 +795,25 @@ mod tests {
725 #[test] 795 #[test]
726 fn prefer_core_paths_over_std() { 796 fn prefer_core_paths_over_std() {
727 cov_mark::check!(prefer_no_std_paths); 797 cov_mark::check!(prefer_no_std_paths);
728 let code = r#" 798 check_found_path(
729 //- /main.rs crate:main deps:core,std 799 r#"
730 #![no_std] 800//- /main.rs crate:main deps:core,std
801#![no_std]
731 802
732 $0 803$0
733 804
734 //- /std.rs crate:std deps:core 805//- /std.rs crate:std deps:core
735 806
736 pub mod fmt { 807pub mod fmt {
737 pub use core::fmt::Error; 808 pub use core::fmt::Error;
738 } 809}
739 810
740 //- /zzz.rs crate:core 811//- /zzz.rs crate:core
741 812
742 pub mod fmt { 813pub mod fmt {
743 pub struct Error; 814 pub struct Error;
744 } 815}
745 "#; 816 "#,
746 check_found_path(
747 code,
748 "core::fmt::Error", 817 "core::fmt::Error",
749 "core::fmt::Error", 818 "core::fmt::Error",
750 "core::fmt::Error", 819 "core::fmt::Error",
@@ -754,26 +823,25 @@ mod tests {
754 823
755 #[test] 824 #[test]
756 fn prefer_alloc_paths_over_std() { 825 fn prefer_alloc_paths_over_std() {
757 let code = r#" 826 check_found_path(
758 //- /main.rs crate:main deps:alloc,std 827 r#"
759 #![no_std] 828//- /main.rs crate:main deps:alloc,std
829#![no_std]
760 830
761 $0 831$0
762 832
763 //- /std.rs crate:std deps:alloc 833//- /std.rs crate:std deps:alloc
764 834
765 pub mod sync { 835pub mod sync {
766 pub use alloc::sync::Arc; 836 pub use alloc::sync::Arc;
767 } 837}
768 838
769 //- /zzz.rs crate:alloc 839//- /zzz.rs crate:alloc
770 840
771 pub mod sync { 841pub mod sync {
772 pub struct Arc; 842 pub struct Arc;
773 } 843}
774 "#; 844 "#,
775 check_found_path(
776 code,
777 "alloc::sync::Arc", 845 "alloc::sync::Arc",
778 "alloc::sync::Arc", 846 "alloc::sync::Arc",
779 "alloc::sync::Arc", 847 "alloc::sync::Arc",
@@ -783,20 +851,19 @@ mod tests {
783 851
784 #[test] 852 #[test]
785 fn prefer_shorter_paths_if_not_alloc() { 853 fn prefer_shorter_paths_if_not_alloc() {
786 let code = r#" 854 check_found_path(
787 //- /main.rs crate:main deps:megaalloc,std 855 r#"
788 $0 856//- /main.rs crate:main deps:megaalloc,std
857$0
789 858
790 //- /std.rs crate:std deps:megaalloc 859//- /std.rs crate:std deps:megaalloc
791 pub mod sync { 860pub mod sync {
792 pub use megaalloc::sync::Arc; 861 pub use megaalloc::sync::Arc;
793 } 862}
794 863
795 //- /zzz.rs crate:megaalloc 864//- /zzz.rs crate:megaalloc
796 pub struct Arc; 865pub struct Arc;
797 "#; 866 "#,
798 check_found_path(
799 code,
800 "megaalloc::Arc", 867 "megaalloc::Arc",
801 "megaalloc::Arc", 868 "megaalloc::Arc",
802 "megaalloc::Arc", 869 "megaalloc::Arc",
@@ -807,12 +874,12 @@ mod tests {
807 #[test] 874 #[test]
808 fn builtins_are_in_scope() { 875 fn builtins_are_in_scope() {
809 let code = r#" 876 let code = r#"
810 //- /main.rs 877//- /main.rs
811 $0 878$0
812 879
813 pub mod primitive { 880pub mod primitive {
814 pub use u8; 881 pub use u8;
815 } 882}
816 "#; 883 "#;
817 check_found_path(code, "u8", "u8", "u8", "u8"); 884 check_found_path(code, "u8", "u8", "u8", "u8");
818 check_found_path(code, "u16", "u16", "u16", "u16"); 885 check_found_path(code, "u16", "u16", "u16", "u16");
@@ -822,10 +889,10 @@ mod tests {
822 fn inner_items() { 889 fn inner_items() {
823 check_found_path( 890 check_found_path(
824 r#" 891 r#"
825 fn main() { 892fn main() {
826 struct Inner {} 893 struct Inner {}
827 $0 894 $0
828 } 895}
829 "#, 896 "#,
830 "Inner", 897 "Inner",
831 "Inner", 898 "Inner",
@@ -838,12 +905,12 @@ mod tests {
838 fn inner_items_from_outer_scope() { 905 fn inner_items_from_outer_scope() {
839 check_found_path( 906 check_found_path(
840 r#" 907 r#"
841 fn main() { 908fn main() {
842 struct Struct {} 909 struct Struct {}
843 { 910 {
844 $0 911 $0
845 } 912 }
846 } 913}
847 "#, 914 "#,
848 "Struct", 915 "Struct",
849 "Struct", 916 "Struct",
@@ -857,14 +924,14 @@ mod tests {
857 cov_mark::check!(prefixed_in_block_expression); 924 cov_mark::check!(prefixed_in_block_expression);
858 check_found_path( 925 check_found_path(
859 r#" 926 r#"
860 fn main() { 927fn main() {
861 mod module { 928 mod module {
862 struct Struct {} 929 struct Struct {}
863 } 930 }
864 { 931 {
865 $0 932 $0
866 } 933 }
867 } 934}
868 "#, 935 "#,
869 "module::Struct", 936 "module::Struct",
870 "module::Struct", 937 "module::Struct",
@@ -877,14 +944,14 @@ mod tests {
877 fn outer_items_with_inner_items_present() { 944 fn outer_items_with_inner_items_present() {
878 check_found_path( 945 check_found_path(
879 r#" 946 r#"
880 mod module { 947mod module {
881 pub struct CompleteMe; 948 pub struct CompleteMe;
882 } 949}
883 950
884 fn main() { 951fn main() {
885 fn inner() {} 952 fn inner() {}
886 $0 953 $0
887 } 954}
888 "#, 955 "#,
889 "module::CompleteMe", 956 "module::CompleteMe",
890 "module::CompleteMe", 957 "module::CompleteMe",
diff --git a/crates/ide/src/move_item.rs b/crates/ide/src/move_item.rs
index 8d37f4f92..246f10a0a 100644
--- a/crates/ide/src/move_item.rs
+++ b/crates/ide/src/move_item.rs
@@ -1,4 +1,4 @@
1use std::iter::once; 1use std::{iter::once, mem};
2 2
3use hir::Semantics; 3use hir::Semantics;
4use ide_db::{base_db::FileRange, RootDatabase}; 4use ide_db::{base_db::FileRange, RootDatabase};
@@ -102,7 +102,7 @@ fn move_in_direction(
102 ast::GenericArgList(it) => swap_sibling_in_list(node, it.generic_args(), range, direction), 102 ast::GenericArgList(it) => swap_sibling_in_list(node, it.generic_args(), range, direction),
103 ast::VariantList(it) => swap_sibling_in_list(node, it.variants(), range, direction), 103 ast::VariantList(it) => swap_sibling_in_list(node, it.variants(), range, direction),
104 ast::TypeBoundList(it) => swap_sibling_in_list(node, it.bounds(), range, direction), 104 ast::TypeBoundList(it) => swap_sibling_in_list(node, it.bounds(), range, direction),
105 _ => Some(replace_nodes(node, &match direction { 105 _ => Some(replace_nodes(range, node, &match direction {
106 Direction::Up => node.prev_sibling(), 106 Direction::Up => node.prev_sibling(),
107 Direction::Down => node.next_sibling(), 107 Direction::Down => node.next_sibling(),
108 }?)) 108 }?))
@@ -125,7 +125,7 @@ fn swap_sibling_in_list<A: AstNode + Clone, I: Iterator<Item = A>>(
125 .next(); 125 .next();
126 126
127 if let Some((l, r)) = list_lookup { 127 if let Some((l, r)) = list_lookup {
128 Some(replace_nodes(l.syntax(), r.syntax())) 128 Some(replace_nodes(range, l.syntax(), r.syntax()))
129 } else { 129 } else {
130 // Cursor is beyond any movable list item (for example, on curly brace in enum). 130 // Cursor is beyond any movable list item (for example, on curly brace in enum).
131 // It's not necessary, that parent of list is movable (arg list's parent is not, for example), 131 // It's not necessary, that parent of list is movable (arg list's parent is not, for example),
@@ -134,11 +134,38 @@ fn swap_sibling_in_list<A: AstNode + Clone, I: Iterator<Item = A>>(
134 } 134 }
135} 135}
136 136
137fn replace_nodes(first: &SyntaxNode, second: &SyntaxNode) -> TextEdit { 137fn replace_nodes<'a>(
138 range: TextRange,
139 mut first: &'a SyntaxNode,
140 mut second: &'a SyntaxNode,
141) -> TextEdit {
142 let cursor_offset = if range.is_empty() {
143 // FIXME: `applySnippetTextEdits` does not support non-empty selection ranges
144 if first.text_range().contains_range(range) {
145 Some(range.start() - first.text_range().start())
146 } else if second.text_range().contains_range(range) {
147 mem::swap(&mut first, &mut second);
148 Some(range.start() - first.text_range().start())
149 } else {
150 None
151 }
152 } else {
153 None
154 };
155
156 let first_with_cursor = match cursor_offset {
157 Some(offset) => {
158 let mut item_text = first.text().to_string();
159 item_text.insert_str(offset.into(), "$0");
160 item_text
161 }
162 None => first.text().to_string(),
163 };
164
138 let mut edit = TextEditBuilder::default(); 165 let mut edit = TextEditBuilder::default();
139 166
140 algo::diff(first, second).into_text_edit(&mut edit); 167 algo::diff(first, second).into_text_edit(&mut edit);
141 algo::diff(second, first).into_text_edit(&mut edit); 168 edit.replace(second.text_range(), first_with_cursor);
142 169
143 edit.finish() 170 edit.finish()
144} 171}
@@ -188,7 +215,7 @@ fn main() {
188 expect![[r#" 215 expect![[r#"
189fn main() { 216fn main() {
190 match true { 217 match true {
191 false => { 218 false =>$0 {
192 println!("Test"); 219 println!("Test");
193 }, 220 },
194 true => { 221 true => {
@@ -222,7 +249,7 @@ fn main() {
222 false => { 249 false => {
223 println!("Test"); 250 println!("Test");
224 }, 251 },
225 true => { 252 true =>$0 {
226 println!("Hello, world"); 253 println!("Hello, world");
227 } 254 }
228 }; 255 };
@@ -274,7 +301,7 @@ fn main() {
274 "#, 301 "#,
275 expect![[r#" 302 expect![[r#"
276fn main() { 303fn main() {
277 let test2 = 456; 304 let test2$0 = 456;
278 let test = 123; 305 let test = 123;
279} 306}
280 "#]], 307 "#]],
@@ -293,7 +320,7 @@ fn main() {
293 "#, 320 "#,
294 expect![[r#" 321 expect![[r#"
295fn main() { 322fn main() {
296 println!("All I want to say is..."); 323 println!("All I want to say is...");$0
297 println!("Hello, world"); 324 println!("Hello, world");
298} 325}
299 "#]], 326 "#]],
@@ -313,7 +340,7 @@ fn main() {
313fn main() { 340fn main() {
314 if true { 341 if true {
315 println!("Test"); 342 println!("Test");
316 } 343 }$0
317 344
318 println!("Hello, world"); 345 println!("Hello, world");
319} 346}
@@ -334,7 +361,7 @@ fn main() {
334fn main() { 361fn main() {
335 for i in 0..10 { 362 for i in 0..10 {
336 println!("Test"); 363 println!("Test");
337 } 364 }$0
338 365
339 println!("Hello, world"); 366 println!("Hello, world");
340} 367}
@@ -355,7 +382,7 @@ fn main() {
355fn main() { 382fn main() {
356 loop { 383 loop {
357 println!("Test"); 384 println!("Test");
358 } 385 }$0
359 386
360 println!("Hello, world"); 387 println!("Hello, world");
361} 388}
@@ -376,7 +403,7 @@ fn main() {
376fn main() { 403fn main() {
377 while true { 404 while true {
378 println!("Test"); 405 println!("Test");
379 } 406 }$0
380 407
381 println!("Hello, world"); 408 println!("Hello, world");
382} 409}
@@ -393,7 +420,7 @@ fn main() {
393 "#, 420 "#,
394 expect![[r#" 421 expect![[r#"
395fn main() { 422fn main() {
396 return 123; 423 return 123;$0
397 424
398 println!("Hello, world"); 425 println!("Hello, world");
399} 426}
@@ -430,7 +457,7 @@ fn main() {}
430fn foo() {}$0$0 457fn foo() {}$0$0
431 "#, 458 "#,
432 expect![[r#" 459 expect![[r#"
433fn foo() {} 460fn foo() {}$0
434 461
435fn main() {} 462fn main() {}
436 "#]], 463 "#]],
@@ -451,7 +478,7 @@ impl Wow for Yay $0$0{}
451 expect![[r#" 478 expect![[r#"
452struct Yay; 479struct Yay;
453 480
454impl Wow for Yay {} 481impl Wow for Yay $0{}
455 482
456trait Wow {} 483trait Wow {}
457 "#]], 484 "#]],
@@ -467,7 +494,7 @@ use std::vec::Vec;
467use std::collections::HashMap$0$0; 494use std::collections::HashMap$0$0;
468 "#, 495 "#,
469 expect![[r#" 496 expect![[r#"
470use std::collections::HashMap; 497use std::collections::HashMap$0;
471use std::vec::Vec; 498use std::vec::Vec;
472 "#]], 499 "#]],
473 Direction::Up, 500 Direction::Up,
@@ -502,7 +529,7 @@ fn main() {
502 } 529 }
503 530
504 #[test] 531 #[test]
505 fn test_moves_param_up() { 532 fn test_moves_param() {
506 check( 533 check(
507 r#" 534 r#"
508fn test(one: i32, two$0$0: u32) {} 535fn test(one: i32, two$0$0: u32) {}
@@ -512,7 +539,7 @@ fn main() {
512} 539}
513 "#, 540 "#,
514 expect![[r#" 541 expect![[r#"
515fn test(two: u32, one: i32) {} 542fn test(two$0: u32, one: i32) {}
516 543
517fn main() { 544fn main() {
518 test(123, 456); 545 test(123, 456);
@@ -520,6 +547,15 @@ fn main() {
520 "#]], 547 "#]],
521 Direction::Up, 548 Direction::Up,
522 ); 549 );
550 check(
551 r#"
552fn f($0$0arg: u8, arg2: u16) {}
553 "#,
554 expect![[r#"
555fn f(arg2: u16, $0arg: u8) {}
556 "#]],
557 Direction::Down,
558 );
523 } 559 }
524 560
525 #[test] 561 #[test]
@@ -536,7 +572,7 @@ fn main() {
536fn test(one: i32, two: u32) {} 572fn test(one: i32, two: u32) {}
537 573
538fn main() { 574fn main() {
539 test(456, 123); 575 test(456$0, 123);
540} 576}
541 "#]], 577 "#]],
542 Direction::Up, 578 Direction::Up,
@@ -557,7 +593,7 @@ fn main() {
557fn test(one: i32, two: u32) {} 593fn test(one: i32, two: u32) {}
558 594
559fn main() { 595fn main() {
560 test(456, 123); 596 test(456, 123$0);
561} 597}
562 "#]], 598 "#]],
563 Direction::Down, 599 Direction::Down,
@@ -594,7 +630,7 @@ struct Test<A, B$0$0>(A, B);
594fn main() {} 630fn main() {}
595 "#, 631 "#,
596 expect![[r#" 632 expect![[r#"
597struct Test<B, A>(A, B); 633struct Test<B$0, A>(A, B);
598 634
599fn main() {} 635fn main() {}
600 "#]], 636 "#]],
@@ -616,7 +652,7 @@ fn main() {
616struct Test<A, B>(A, B); 652struct Test<A, B>(A, B);
617 653
618fn main() { 654fn main() {
619 let t = Test::<&str, i32>(123, "yay"); 655 let t = Test::<&str$0, i32>(123, "yay");
620} 656}
621 "#]], 657 "#]],
622 Direction::Up, 658 Direction::Up,
@@ -636,7 +672,7 @@ fn main() {}
636 "#, 672 "#,
637 expect![[r#" 673 expect![[r#"
638enum Hello { 674enum Hello {
639 Two, 675 Two$0,
640 One 676 One
641} 677}
642 678
@@ -663,7 +699,7 @@ trait One {}
663 699
664trait Two {} 700trait Two {}
665 701
666fn test<T: Two + One>(t: T) {} 702fn test<T: Two$0 + One>(t: T) {}
667 703
668fn main() {} 704fn main() {}
669 "#]], 705 "#]],
@@ -709,7 +745,7 @@ trait Yay {
709impl Yay for Test { 745impl Yay for Test {
710 type One = i32; 746 type One = i32;
711 747
712 fn inner() { 748 fn inner() {$0
713 println!("Mmmm"); 749 println!("Mmmm");
714 } 750 }
715 751
@@ -736,7 +772,7 @@ fn test() {
736 "#, 772 "#,
737 expect![[r#" 773 expect![[r#"
738fn test() { 774fn test() {
739 mod hi { 775 mod hi {$0
740 fn inner() {} 776 fn inner() {}
741 } 777 }
742 778
@@ -764,7 +800,7 @@ fn main() {}
764 expect![[r#" 800 expect![[r#"
765fn main() {} 801fn main() {}
766 802
767#[derive(Debug)] 803$0#[derive(Debug)]
768enum FooBar { 804enum FooBar {
769 Foo, 805 Foo,
770 Bar, 806 Bar,
@@ -784,7 +820,7 @@ fn main() {}
784 expect![[r#" 820 expect![[r#"
785fn main() {} 821fn main() {}
786 822
787enum FooBar { 823$0enum FooBar {
788 Foo, 824 Foo,
789 Bar, 825 Bar,
790} 826}
@@ -804,7 +840,7 @@ fn main() {}
804 expect![[r#" 840 expect![[r#"
805struct Test; 841struct Test;
806 842
807impl SomeTrait for Test {} 843$0impl SomeTrait for Test {}
808 844
809trait SomeTrait {} 845trait SomeTrait {}
810 846
@@ -831,7 +867,7 @@ fn main() {}
831enum FooBar { 867enum FooBar {
832 Foo, 868 Foo,
833 Bar, 869 Bar,
834} 870}$0
835 "#]], 871 "#]],
836 Direction::Down, 872 Direction::Down,
837 ); 873 );
@@ -848,7 +884,7 @@ fn main() {}
848 expect![[r#" 884 expect![[r#"
849struct Test; 885struct Test;
850 886
851impl SomeTrait for Test {} 887impl SomeTrait for Test {}$0
852 888
853trait SomeTrait {} 889trait SomeTrait {}
854 890
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 4f0c9d23c..1f59402e5 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -1410,7 +1410,7 @@ pub(crate) fn handle_open_cargo_toml(
1410pub(crate) fn handle_move_item( 1410pub(crate) fn handle_move_item(
1411 snap: GlobalStateSnapshot, 1411 snap: GlobalStateSnapshot,
1412 params: lsp_ext::MoveItemParams, 1412 params: lsp_ext::MoveItemParams,
1413) -> Result<Option<lsp_types::TextDocumentEdit>> { 1413) -> Result<Vec<lsp_ext::SnippetTextEdit>> {
1414 let _p = profile::span("handle_move_item"); 1414 let _p = profile::span("handle_move_item");
1415 let file_id = from_proto::file_id(&snap, &params.text_document.uri)?; 1415 let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
1416 let range = from_proto::file_range(&snap, params.text_document, params.range)?; 1416 let range = from_proto::file_range(&snap, params.text_document, params.range)?;
@@ -1421,8 +1421,11 @@ pub(crate) fn handle_move_item(
1421 }; 1421 };
1422 1422
1423 match snap.analysis.move_item(range, direction)? { 1423 match snap.analysis.move_item(range, direction)? {
1424 Some(text_edit) => Ok(Some(to_proto::text_document_edit(&snap, file_id, text_edit)?)), 1424 Some(text_edit) => {
1425 None => Ok(None), 1425 let line_index = snap.file_line_index(file_id)?;
1426 Ok(to_proto::snippet_text_edit_vec(&line_index, true, text_edit))
1427 }
1428 None => Ok(vec![]),
1426 } 1429 }
1427} 1430}
1428 1431
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index 81a6f22f1..d648cda32 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -407,7 +407,7 @@ pub enum MoveItem {}
407 407
408impl Request for MoveItem { 408impl Request for MoveItem {
409 type Params = MoveItemParams; 409 type Params = MoveItemParams;
410 type Result = Option<lsp_types::TextDocumentEdit>; 410 type Result = Vec<SnippetTextEdit>;
411 const METHOD: &'static str = "experimental/moveItem"; 411 const METHOD: &'static str = "experimental/moveItem";
412} 412}
413 413
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 8d7cb9b74..1a1f65f3b 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -688,18 +688,6 @@ pub(crate) fn goto_definition_response(
688 } 688 }
689} 689}
690 690
691pub(crate) fn text_document_edit(
692 snap: &GlobalStateSnapshot,
693 file_id: FileId,
694 edit: TextEdit,
695) -> Result<lsp_types::TextDocumentEdit> {
696 let text_document = optional_versioned_text_document_identifier(snap, file_id);
697 let line_index = snap.file_line_index(file_id)?;
698 let edits =
699 edit.into_iter().map(|it| lsp_types::OneOf::Left(text_edit(&line_index, it))).collect();
700 Ok(lsp_types::TextDocumentEdit { text_document, edits })
701}
702
703pub(crate) fn snippet_text_document_edit( 691pub(crate) fn snippet_text_document_edit(
704 snap: &GlobalStateSnapshot, 692 snap: &GlobalStateSnapshot,
705 is_snippet: bool, 693 is_snippet: bool,