aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Bulatov <[email protected]>2020-12-19 10:54:17 +0000
committerKirill Bulatov <[email protected]>2020-12-19 10:54:17 +0000
commit5fa078f26fed1d951e949df09da82567e9e12404 (patch)
tree746a7cfa285577927f1c4f3a6a4235232227eab4
parentbd270cbc024f56596c315061d10732ebbe16eef9 (diff)
Add a slightly better fuzzy search heuristics
-rw-r--r--crates/completion/src/completions/unqualified_path.rs72
1 files changed, 62 insertions, 10 deletions
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs
index 93869f92e..5a7a6e83d 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
3use either::Either; 3use either::Either;
4use hir::{Adt, ModuleDef, ScopeDef, Type}; 4use hir::{Adt, ModPath, ModuleDef, ScopeDef, Type};
5use ide_db::helpers::insert_use::ImportScope; 5use ide_db::helpers::insert_use::ImportScope;
6use ide_db::imports_locator; 6use ide_db::imports_locator;
7use syntax::AstNode; 7use syntax::AstNode;
@@ -147,36 +147,49 @@ fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<()
147 .collect::<Vec<_>>(); 147 .collect::<Vec<_>>();
148 148
149 all_mod_paths.sort_by_cached_key(|(mod_path, _)| { 149 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()) { 150 compute_fuzzy_completion_order_key(mod_path, &potential_import_name)
151 if name.contains(&potential_import_name.to_lowercase()) {
152 return 0;
153 }
154 }
155 1
156 }); 151 });
157 152
158 acc.add_all(all_mod_paths.into_iter().filter_map(|(import_path, definition)| { 153 acc.add_all(all_mod_paths.into_iter().filter_map(|(import_path, definition)| {
159 render_resolution_with_import( 154 render_resolution_with_import(
160 RenderContext::new(ctx), 155 RenderContext::new(ctx),
161 ImportEdit { import_path, import_scope: import_scope.clone() }, 156 ImportEdit { import_path: import_path, import_scope: import_scope.clone() },
162 &definition, 157 &definition,
163 ) 158 )
164 })); 159 }));
165 Some(()) 160 Some(())
166} 161}
167 162
163// todo kb add tet marks for the completion order test + the sotring description
164fn compute_fuzzy_completion_order_key(proposed_mod_path: &ModPath, user_input: &str) -> usize {
165 let proposed_import_name = match proposed_mod_path.segments.last() {
166 Some(name) => name.to_string().to_lowercase(),
167 None => return usize::MAX,
168 };
169 let user_input = user_input.to_lowercase();
170
171 match proposed_import_name.match_indices(&user_input).next() {
172 Some((first_matching_index, _)) => first_matching_index,
173 None => usize::MAX,
174 }
175}
176
168#[cfg(test)] 177#[cfg(test)]
169mod tests { 178mod tests {
170 use expect_test::{expect, Expect}; 179 use expect_test::{expect, Expect};
171 use test_utils::mark; 180 use test_utils::mark;
172 181
173 use crate::{ 182 use crate::{
174 test_utils::{check_edit, check_edit_with_config, completion_list}, 183 test_utils::{check_edit, check_edit_with_config, completion_list_with_config},
175 CompletionConfig, CompletionKind, 184 CompletionConfig, CompletionKind,
176 }; 185 };
177 186
178 fn check(ra_fixture: &str, expect: Expect) { 187 fn check(ra_fixture: &str, expect: Expect) {
179 let actual = completion_list(ra_fixture, CompletionKind::Reference); 188 check_with_config(CompletionConfig::default(), ra_fixture, expect);
189 }
190
191 fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) {
192 let actual = completion_list_with_config(config, ra_fixture, CompletionKind::Reference);
180 expect.assert_eq(&actual) 193 expect.assert_eq(&actual)
181 } 194 }
182 195
@@ -877,4 +890,43 @@ fn main() {
877"#, 890"#,
878 ); 891 );
879 } 892 }
893
894 #[test]
895 fn fuzzy_completions_come_in_specific_order() {
896 let mut completion_config = CompletionConfig::default();
897 completion_config
898 .active_resolve_capabilities
899 .insert(crate::CompletionResolveCapability::AdditionalTextEdits);
900
901 check_with_config(
902 completion_config,
903 r#"
904//- /lib.rs crate:dep
905pub struct FirstStruct;
906pub mod some_module {
907 pub struct SecondStruct;
908
909 pub struct ThiiiiiirdStruct;
910 pub struct AfterThirdStruct;
911 pub struct ThirdStruct;
912}
913
914//- /main.rs crate:main deps:dep
915use dep::{FirstStruct, some_module::SecondStruct};
916
917fn main() {
918 hir<|>
919}
920"#,
921 expect![[r#"
922 st FirstStruct
923 st SecondStruct
924 md dep
925 st dep::some_module::ThirdStruct
926 st dep::some_module::AfterThirdStruct
927 st dep::some_module::ThiiiiiirdStruct
928 fn main() fn main()
929 "#]],
930 );
931 }
880} 932}