diff options
Diffstat (limited to 'crates/completion/src/completions/unqualified_path.rs')
-rw-r--r-- | crates/completion/src/completions/unqualified_path.rs | 172 |
1 files changed, 110 insertions, 62 deletions
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs index 93869f92e..099ffb4d4 100644 --- a/crates/completion/src/completions/unqualified_path.rs +++ b/crates/completion/src/completions/unqualified_path.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! Completion of names from the current scope, e.g. locals and imported items. | 1 | //! Completion of names from the current scope, e.g. locals and imported items. |
2 | 2 | ||
3 | use either::Either; | 3 | use either::Either; |
4 | use hir::{Adt, ModuleDef, ScopeDef, Type}; | 4 | use hir::{Adt, ModPath, ModuleDef, ScopeDef, Type}; |
5 | use ide_db::helpers::insert_use::ImportScope; | 5 | use ide_db::helpers::insert_use::ImportScope; |
6 | use ide_db::imports_locator; | 6 | use ide_db::imports_locator; |
7 | use syntax::AstNode; | 7 | use syntax::AstNode; |
@@ -146,13 +146,9 @@ fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<() | |||
146 | .filter(|(mod_path, _)| mod_path.len() > 1) | 146 | .filter(|(mod_path, _)| mod_path.len() > 1) |
147 | .collect::<Vec<_>>(); | 147 | .collect::<Vec<_>>(); |
148 | 148 | ||
149 | let user_input_lowercased = potential_import_name.to_lowercase(); | ||
149 | all_mod_paths.sort_by_cached_key(|(mod_path, _)| { | 150 | all_mod_paths.sort_by_cached_key(|(mod_path, _)| { |
150 | if let Some(name) = mod_path.segments.last().map(|name| name.to_string().to_lowercase()) { | 151 | compute_fuzzy_completion_order_key(mod_path, &user_input_lowercased) |
151 | if name.contains(&potential_import_name.to_lowercase()) { | ||
152 | return 0; | ||
153 | } | ||
154 | } | ||
155 | 1 | ||
156 | }); | 152 | }); |
157 | 153 | ||
158 | acc.add_all(all_mod_paths.into_iter().filter_map(|(import_path, definition)| { | 154 | acc.add_all(all_mod_paths.into_iter().filter_map(|(import_path, definition)| { |
@@ -165,21 +161,48 @@ fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<() | |||
165 | Some(()) | 161 | Some(()) |
166 | } | 162 | } |
167 | 163 | ||
164 | fn compute_fuzzy_completion_order_key( | ||
165 | proposed_mod_path: &ModPath, | ||
166 | user_input_lowercased: &str, | ||
167 | ) -> usize { | ||
168 | mark::hit!(certain_fuzzy_order_test); | ||
169 | let proposed_import_name = match proposed_mod_path.segments.last() { | ||
170 | Some(name) => name.to_string().to_lowercase(), | ||
171 | None => return usize::MAX, | ||
172 | }; | ||
173 | match proposed_import_name.match_indices(user_input_lowercased).next() { | ||
174 | Some((first_matching_index, _)) => first_matching_index, | ||
175 | None => usize::MAX, | ||
176 | } | ||
177 | } | ||
178 | |||
168 | #[cfg(test)] | 179 | #[cfg(test)] |
169 | mod tests { | 180 | mod tests { |
170 | use expect_test::{expect, Expect}; | 181 | use expect_test::{expect, Expect}; |
171 | use test_utils::mark; | 182 | use test_utils::mark; |
172 | 183 | ||
173 | use crate::{ | 184 | use crate::{ |
174 | test_utils::{check_edit, check_edit_with_config, completion_list}, | 185 | test_utils::{check_edit, check_edit_with_config, completion_list_with_config}, |
175 | CompletionConfig, CompletionKind, | 186 | CompletionConfig, CompletionKind, |
176 | }; | 187 | }; |
177 | 188 | ||
178 | fn check(ra_fixture: &str, expect: Expect) { | 189 | fn check(ra_fixture: &str, expect: Expect) { |
179 | let actual = completion_list(ra_fixture, CompletionKind::Reference); | 190 | check_with_config(CompletionConfig::default(), ra_fixture, expect); |
191 | } | ||
192 | |||
193 | fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) { | ||
194 | let actual = completion_list_with_config(config, ra_fixture, CompletionKind::Reference); | ||
180 | expect.assert_eq(&actual) | 195 | expect.assert_eq(&actual) |
181 | } | 196 | } |
182 | 197 | ||
198 | fn fuzzy_completion_config() -> CompletionConfig { | ||
199 | let mut completion_config = CompletionConfig::default(); | ||
200 | completion_config | ||
201 | .active_resolve_capabilities | ||
202 | .insert(crate::CompletionResolveCapability::AdditionalTextEdits); | ||
203 | completion_config | ||
204 | } | ||
205 | |||
183 | #[test] | 206 | #[test] |
184 | fn self_fulfilling_completion() { | 207 | fn self_fulfilling_completion() { |
185 | mark::check!(self_fulfilling_completion); | 208 | mark::check!(self_fulfilling_completion); |
@@ -255,9 +278,9 @@ fn quux(x: i32) { | |||
255 | } | 278 | } |
256 | "#, | 279 | "#, |
257 | expect![[r#" | 280 | expect![[r#" |
258 | fn quux(…) fn quux(x: i32) | ||
259 | bn x i32 | ||
260 | bn y i32 | 281 | bn y i32 |
282 | bn x i32 | ||
283 | fn quux(…) fn quux(x: i32) | ||
261 | "#]], | 284 | "#]], |
262 | ); | 285 | ); |
263 | } | 286 | } |
@@ -277,8 +300,8 @@ fn quux() { | |||
277 | } | 300 | } |
278 | "#, | 301 | "#, |
279 | expect![[r#" | 302 | expect![[r#" |
280 | bn a | ||
281 | bn b i32 | 303 | bn b i32 |
304 | bn a | ||
282 | fn quux() fn quux() | 305 | fn quux() fn quux() |
283 | "#]], | 306 | "#]], |
284 | ); | 307 | ); |
@@ -293,8 +316,8 @@ fn quux() { | |||
293 | } | 316 | } |
294 | "#, | 317 | "#, |
295 | expect![[r#" | 318 | expect![[r#" |
296 | fn quux() fn quux() | ||
297 | bn x | 319 | bn x |
320 | fn quux() fn quux() | ||
298 | "#]], | 321 | "#]], |
299 | ); | 322 | ); |
300 | } | 323 | } |
@@ -335,9 +358,9 @@ fn main() { | |||
335 | check( | 358 | check( |
336 | r#"struct S<T> { x: <|>}"#, | 359 | r#"struct S<T> { x: <|>}"#, |
337 | expect![[r#" | 360 | expect![[r#" |
338 | st S<…> | ||
339 | tp Self | 361 | tp Self |
340 | tp T | 362 | tp T |
363 | st S<…> | ||
341 | "#]], | 364 | "#]], |
342 | ); | 365 | ); |
343 | } | 366 | } |
@@ -362,9 +385,9 @@ enum E {} | |||
362 | fn quux() { <|> } | 385 | fn quux() { <|> } |
363 | "#, | 386 | "#, |
364 | expect![[r#" | 387 | expect![[r#" |
365 | en E | ||
366 | st S | 388 | st S |
367 | fn quux() fn quux() | 389 | fn quux() fn quux() |
390 | en E | ||
368 | "#]], | 391 | "#]], |
369 | ); | 392 | ); |
370 | } | 393 | } |
@@ -416,8 +439,8 @@ mod m { | |||
416 | } | 439 | } |
417 | "#, | 440 | "#, |
418 | expect![[r#" | 441 | expect![[r#" |
419 | st Bar | ||
420 | fn quux() fn quux() | 442 | fn quux() fn quux() |
443 | st Bar | ||
421 | "#]], | 444 | "#]], |
422 | ); | 445 | ); |
423 | } | 446 | } |
@@ -462,8 +485,8 @@ fn foo() { | |||
462 | check( | 485 | check( |
463 | r#"impl S { fn foo(&self) { <|> } }"#, | 486 | r#"impl S { fn foo(&self) { <|> } }"#, |
464 | expect![[r#" | 487 | expect![[r#" |
465 | tp Self | ||
466 | bn self &{unknown} | 488 | bn self &{unknown} |
489 | tp Self | ||
467 | "#]], | 490 | "#]], |
468 | ); | 491 | ); |
469 | } | 492 | } |
@@ -482,9 +505,9 @@ use prelude::*; | |||
482 | mod prelude { struct Option; } | 505 | mod prelude { struct Option; } |
483 | "#, | 506 | "#, |
484 | expect![[r#" | 507 | expect![[r#" |
485 | st Option | ||
486 | fn foo() fn foo() | 508 | fn foo() fn foo() |
487 | md std | 509 | md std |
510 | st Option | ||
488 | "#]], | 511 | "#]], |
489 | ); | 512 | ); |
490 | } | 513 | } |
@@ -509,10 +532,10 @@ use prelude::*; | |||
509 | mod prelude { struct String; } | 532 | mod prelude { struct String; } |
510 | "#, | 533 | "#, |
511 | expect![[r#" | 534 | expect![[r#" |
512 | st String | ||
513 | md core | ||
514 | fn foo() fn foo() | 535 | fn foo() fn foo() |
515 | md std | 536 | md std |
537 | md core | ||
538 | st String | ||
516 | "#]], | 539 | "#]], |
517 | ); | 540 | ); |
518 | } | 541 | } |
@@ -538,13 +561,13 @@ mod m2 { | |||
538 | fn main() { let v = <|> } | 561 | fn main() { let v = <|> } |
539 | "#, | 562 | "#, |
540 | expect![[r##" | 563 | expect![[r##" |
541 | ma bar!(…) macro_rules! bar | 564 | md m1 |
542 | ma baz!(…) #[macro_export] | 565 | ma baz!(…) #[macro_export] |
543 | macro_rules! baz | 566 | macro_rules! baz |
544 | ma foo!(…) macro_rules! foo | ||
545 | md m1 | ||
546 | md m2 | ||
547 | fn main() fn main() | 567 | fn main() fn main() |
568 | md m2 | ||
569 | ma bar!(…) macro_rules! bar | ||
570 | ma foo!(…) macro_rules! foo | ||
548 | "##]], | 571 | "##]], |
549 | ); | 572 | ); |
550 | } | 573 | } |
@@ -557,8 +580,8 @@ macro_rules! foo { () => {} } | |||
557 | fn foo() { <|> } | 580 | fn foo() { <|> } |
558 | "#, | 581 | "#, |
559 | expect![[r#" | 582 | expect![[r#" |
560 | ma foo!(…) macro_rules! foo | ||
561 | fn foo() fn foo() | 583 | fn foo() fn foo() |
584 | ma foo!(…) macro_rules! foo | ||
562 | "#]], | 585 | "#]], |
563 | ); | 586 | ); |
564 | } | 587 | } |
@@ -571,8 +594,8 @@ macro_rules! foo { () => {} } | |||
571 | fn main() { let x: <|> } | 594 | fn main() { let x: <|> } |
572 | "#, | 595 | "#, |
573 | expect![[r#" | 596 | expect![[r#" |
574 | ma foo!(…) macro_rules! foo | ||
575 | fn main() fn main() | 597 | fn main() fn main() |
598 | ma foo!(…) macro_rules! foo | ||
576 | "#]], | 599 | "#]], |
577 | ); | 600 | ); |
578 | } | 601 | } |
@@ -585,8 +608,8 @@ macro_rules! foo { () => {} } | |||
585 | fn main() { <|> } | 608 | fn main() { <|> } |
586 | "#, | 609 | "#, |
587 | expect![[r#" | 610 | expect![[r#" |
588 | ma foo!(…) macro_rules! foo | ||
589 | fn main() fn main() | 611 | fn main() fn main() |
612 | ma foo!(…) macro_rules! foo | ||
590 | "#]], | 613 | "#]], |
591 | ); | 614 | ); |
592 | } | 615 | } |
@@ -618,10 +641,10 @@ fn quux(x: i32) { | |||
618 | } | 641 | } |
619 | "#, | 642 | "#, |
620 | expect![[r#" | 643 | expect![[r#" |
621 | ma m!(…) macro_rules! m | ||
622 | fn quux(…) fn quux(x: i32) | ||
623 | bn x i32 | ||
624 | bn y i32 | 644 | bn y i32 |
645 | bn x i32 | ||
646 | fn quux(…) fn quux(x: i32) | ||
647 | ma m!(…) macro_rules! m | ||
625 | "#]], | 648 | "#]], |
626 | ); | 649 | ); |
627 | } | 650 | } |
@@ -637,10 +660,10 @@ fn quux(x: i32) { | |||
637 | } | 660 | } |
638 | ", | 661 | ", |
639 | expect![[r#" | 662 | expect![[r#" |
640 | ma m!(…) macro_rules! m | ||
641 | fn quux(…) fn quux(x: i32) | ||
642 | bn x i32 | ||
643 | bn y i32 | 663 | bn y i32 |
664 | bn x i32 | ||
665 | fn quux(…) fn quux(x: i32) | ||
666 | ma m!(…) macro_rules! m | ||
644 | "#]], | 667 | "#]], |
645 | ); | 668 | ); |
646 | } | 669 | } |
@@ -656,10 +679,10 @@ fn quux(x: i32) { | |||
656 | } | 679 | } |
657 | "#, | 680 | "#, |
658 | expect![[r#" | 681 | expect![[r#" |
659 | ma m!(…) macro_rules! m | ||
660 | fn quux(…) fn quux(x: i32) | ||
661 | bn x i32 | ||
662 | bn y i32 | 682 | bn y i32 |
683 | bn x i32 | ||
684 | fn quux(…) fn quux(x: i32) | ||
685 | ma m!(…) macro_rules! m | ||
663 | "#]], | 686 | "#]], |
664 | ); | 687 | ); |
665 | } | 688 | } |
@@ -673,8 +696,8 @@ use spam::Quux; | |||
673 | fn main() { <|> } | 696 | fn main() { <|> } |
674 | "#, | 697 | "#, |
675 | expect![[r#" | 698 | expect![[r#" |
676 | ?? Quux | ||
677 | fn main() fn main() | 699 | fn main() fn main() |
700 | ?? Quux | ||
678 | "#]], | 701 | "#]], |
679 | ); | 702 | ); |
680 | } | 703 | } |
@@ -690,10 +713,10 @@ fn main() { | |||
690 | } | 713 | } |
691 | "#, | 714 | "#, |
692 | expect![[r#" | 715 | expect![[r#" |
693 | en Foo | ||
694 | ev Foo::Bar () | 716 | ev Foo::Bar () |
695 | ev Foo::Baz () | 717 | ev Foo::Baz () |
696 | ev Foo::Quux () | 718 | ev Foo::Quux () |
719 | en Foo | ||
697 | "#]], | 720 | "#]], |
698 | ) | 721 | ) |
699 | } | 722 | } |
@@ -710,10 +733,10 @@ fn main() { | |||
710 | } | 733 | } |
711 | "#, | 734 | "#, |
712 | expect![[r#" | 735 | expect![[r#" |
713 | en Foo | ||
714 | ev Foo::Bar () | 736 | ev Foo::Bar () |
715 | ev Foo::Baz () | 737 | ev Foo::Baz () |
716 | ev Foo::Quux () | 738 | ev Foo::Quux () |
739 | en Foo | ||
717 | "#]], | 740 | "#]], |
718 | ) | 741 | ) |
719 | } | 742 | } |
@@ -726,10 +749,10 @@ enum Foo { Bar, Baz, Quux } | |||
726 | fn main() { let foo: Foo = Q<|> } | 749 | fn main() { let foo: Foo = Q<|> } |
727 | "#, | 750 | "#, |
728 | expect![[r#" | 751 | expect![[r#" |
729 | en Foo | ||
730 | ev Foo::Bar () | 752 | ev Foo::Bar () |
731 | ev Foo::Baz () | 753 | ev Foo::Baz () |
732 | ev Foo::Quux () | 754 | ev Foo::Quux () |
755 | en Foo | ||
733 | fn main() fn main() | 756 | fn main() fn main() |
734 | "#]], | 757 | "#]], |
735 | ) | 758 | ) |
@@ -743,9 +766,9 @@ mod m { pub enum E { V } } | |||
743 | fn f() -> m::E { V<|> } | 766 | fn f() -> m::E { V<|> } |
744 | "#, | 767 | "#, |
745 | expect![[r#" | 768 | expect![[r#" |
746 | fn f() fn f() -> m::E | ||
747 | md m | ||
748 | ev m::E::V () | 769 | ev m::E::V () |
770 | md m | ||
771 | fn f() fn f() -> m::E | ||
749 | "#]], | 772 | "#]], |
750 | ) | 773 | ) |
751 | } | 774 | } |
@@ -772,22 +795,17 @@ struct MyStruct {} | |||
772 | impl My<|> | 795 | impl My<|> |
773 | "#, | 796 | "#, |
774 | expect![[r#" | 797 | expect![[r#" |
775 | st MyStruct | ||
776 | tt MyTrait | ||
777 | tp Self | 798 | tp Self |
799 | tt MyTrait | ||
800 | st MyStruct | ||
778 | "#]], | 801 | "#]], |
779 | ) | 802 | ) |
780 | } | 803 | } |
781 | 804 | ||
782 | #[test] | 805 | #[test] |
783 | fn function_fuzzy_completion() { | 806 | fn function_fuzzy_completion() { |
784 | let mut completion_config = CompletionConfig::default(); | ||
785 | completion_config | ||
786 | .active_resolve_capabilities | ||
787 | .insert(crate::CompletionResolveCapability::AdditionalTextEdits); | ||
788 | |||
789 | check_edit_with_config( | 807 | check_edit_with_config( |
790 | completion_config, | 808 | fuzzy_completion_config(), |
791 | "stdin", | 809 | "stdin", |
792 | r#" | 810 | r#" |
793 | //- /lib.rs crate:dep | 811 | //- /lib.rs crate:dep |
@@ -812,13 +830,8 @@ fn main() { | |||
812 | 830 | ||
813 | #[test] | 831 | #[test] |
814 | fn macro_fuzzy_completion() { | 832 | fn macro_fuzzy_completion() { |
815 | let mut completion_config = CompletionConfig::default(); | ||
816 | completion_config | ||
817 | .active_resolve_capabilities | ||
818 | .insert(crate::CompletionResolveCapability::AdditionalTextEdits); | ||
819 | |||
820 | check_edit_with_config( | 833 | check_edit_with_config( |
821 | completion_config, | 834 | fuzzy_completion_config(), |
822 | "macro_with_curlies!", | 835 | "macro_with_curlies!", |
823 | r#" | 836 | r#" |
824 | //- /lib.rs crate:dep | 837 | //- /lib.rs crate:dep |
@@ -845,13 +858,8 @@ fn main() { | |||
845 | 858 | ||
846 | #[test] | 859 | #[test] |
847 | fn struct_fuzzy_completion() { | 860 | fn struct_fuzzy_completion() { |
848 | let mut completion_config = CompletionConfig::default(); | ||
849 | completion_config | ||
850 | .active_resolve_capabilities | ||
851 | .insert(crate::CompletionResolveCapability::AdditionalTextEdits); | ||
852 | |||
853 | check_edit_with_config( | 861 | check_edit_with_config( |
854 | completion_config, | 862 | fuzzy_completion_config(), |
855 | "ThirdStruct", | 863 | "ThirdStruct", |
856 | r#" | 864 | r#" |
857 | //- /lib.rs crate:dep | 865 | //- /lib.rs crate:dep |
@@ -877,4 +885,44 @@ fn main() { | |||
877 | "#, | 885 | "#, |
878 | ); | 886 | ); |
879 | } | 887 | } |
888 | |||
889 | #[test] | ||
890 | fn fuzzy_completions_come_in_specific_order() { | ||
891 | mark::check!(certain_fuzzy_order_test); | ||
892 | check_with_config( | ||
893 | fuzzy_completion_config(), | ||
894 | r#" | ||
895 | //- /lib.rs crate:dep | ||
896 | pub struct FirstStruct; | ||
897 | pub mod some_module { | ||
898 | // already imported, omitted | ||
899 | pub struct SecondStruct; | ||
900 | // does not contain all letters from the query, omitted | ||
901 | pub struct UnrelatedOne; | ||
902 | // contains all letters from the query, but not in sequence, displayed last | ||
903 | pub struct ThiiiiiirdStruct; | ||
904 | // contains all letters from the query, but not in the beginning, displayed second | ||
905 | pub struct AfterThirdStruct; | ||
906 | // contains all letters from the query in the begginning, displayed first | ||
907 | pub struct ThirdStruct; | ||
908 | } | ||
909 | |||
910 | //- /main.rs crate:main deps:dep | ||
911 | use dep::{FirstStruct, some_module::SecondStruct}; | ||
912 | |||
913 | fn main() { | ||
914 | hir<|> | ||
915 | } | ||
916 | "#, | ||
917 | expect![[r#" | ||
918 | fn main() fn main() | ||
919 | st SecondStruct | ||
920 | st FirstStruct | ||
921 | md dep | ||
922 | st dep::some_module::ThirdStruct | ||
923 | st dep::some_module::AfterThirdStruct | ||
924 | st dep::some_module::ThiiiiiirdStruct | ||
925 | "#]], | ||
926 | ); | ||
927 | } | ||
880 | } | 928 | } |