From ec731e19df6444b2113c273fc740fd3d5c866b18 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 20 Mar 2021 23:55:16 +0200 Subject: [PATCH 1/3] Use smart case in flyimport items lookup --- .../src/completions/flyimport.rs | 61 ++++++++++++++++++- crates/ide_db/src/items_locator.rs | 9 ++- crates/ide_db/src/symbol_index.rs | 16 ++++- 3 files changed, 80 insertions(+), 6 deletions(-) diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs index eb2cba6319..1ad0171982 100644 --- a/crates/ide_completion/src/completions/flyimport.rs +++ b/crates/ide_completion/src/completions/flyimport.rs @@ -1,8 +1,10 @@ //! Feature: completion with imports-on-the-fly //! //! When completing names in the current scope, proposes additional imports from other modules or crates, -//! if they can be qualified in the scope and their name contains all symbols from the completion input -//! (case-insensitive, in any order or places). +//! if they can be qualified in the scope and their name contains all symbols from the completion input. +//! +//! To be considered applicable, the name must contain all input symbols in the given order, not necessarily adjacent. +//! If any input symbol is not lowercased, the name must contain all symbols in exact case; otherwise the contaning is checked case-insensitively. //! //! ``` //! fn main() { @@ -942,7 +944,7 @@ mod foo { } fn main() { - bar::Ass$0 + bar::ASS$0 }"#, expect![[]], ) @@ -979,4 +981,57 @@ fn main() { expect![[]], ) } + + #[test] + fn case_matters() { + check( + r#" +mod foo { + pub const TEST_CONST: usize = 3; + pub fn test_function() -> i32 { + 4 + } +} + +fn main() { + TE$0 +}"#, + expect![[r#" + ct foo::TEST_CONST + "#]], + ); + + check( + r#" +mod foo { + pub const TEST_CONST: usize = 3; + pub fn test_function() -> i32 { + 4 + } +} + +fn main() { + te$0 +}"#, + expect![[r#" + ct foo::TEST_CONST + fn test_function() (foo::test_function) fn() -> i32 + "#]], + ); + + check( + r#" +mod foo { + pub const TEST_CONST: usize = 3; + pub fn test_function() -> i32 { + 4 + } +} + +fn main() { + Te$0 +}"#, + expect![[]], + ); + } } diff --git a/crates/ide_db/src/items_locator.rs b/crates/ide_db/src/items_locator.rs index 518cddd740..b9d5852e2b 100644 --- a/crates/ide_db/src/items_locator.rs +++ b/crates/ide_db/src/items_locator.rs @@ -62,6 +62,8 @@ pub fn items_with_name( (local_query, external_query) } NameToImport::Fuzzy(fuzzy_search_string) => { + let mut local_query = symbol_index::Query::new(fuzzy_search_string.clone()); + let mut external_query = import_map::Query::new(fuzzy_search_string.clone()) .search_mode(import_map::SearchMode::Fuzzy) .name_only(); @@ -75,7 +77,12 @@ pub fn items_with_name( } } - (symbol_index::Query::new(fuzzy_search_string), external_query) + if fuzzy_search_string.to_lowercase() != fuzzy_search_string { + local_query.case_sensitive(); + external_query = external_query.case_sensitive(); + } + + (local_query, external_query) } }; diff --git a/crates/ide_db/src/symbol_index.rs b/crates/ide_db/src/symbol_index.rs index 9ed9568ce8..35e382b5cd 100644 --- a/crates/ide_db/src/symbol_index.rs +++ b/crates/ide_db/src/symbol_index.rs @@ -52,6 +52,7 @@ pub struct Query { only_types: bool, libs: bool, exact: bool, + case_sensitive: bool, limit: usize, } @@ -64,6 +65,7 @@ impl Query { only_types: false, libs: false, exact: false, + case_sensitive: false, limit: usize::max_value(), } } @@ -80,6 +82,10 @@ impl Query { self.exact = true; } + pub fn case_sensitive(&mut self) { + self.case_sensitive = true; + } + pub fn limit(&mut self, limit: usize) { self.limit = limit } @@ -326,8 +332,14 @@ impl Query { if self.only_types && !symbol.kind.is_type() { continue; } - if self.exact && symbol.name != self.query { - continue; + if self.exact { + if symbol.name != self.query { + continue; + } + } else if self.case_sensitive { + if self.query.chars().any(|c| !symbol.name.contains(c)) { + continue; + } } res.push(symbol.clone()); From eaa4fcbbdea69c8fcf5b6cdc1ff3c259be3e09cb Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 21 Mar 2021 00:17:09 +0200 Subject: [PATCH 2/3] Less reallocations --- .../replace_derive_with_manual_impl.rs | 1 - crates/ide_completion/src/lib.rs | 1 - crates/ide_db/src/helpers/import_assets.rs | 3 -- crates/ide_db/src/items_locator.rs | 28 ++++++++----------- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs index 2608b56da6..4f0ef52ca0 100644 --- a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs @@ -72,7 +72,6 @@ pub(crate) fn replace_derive_with_manual_impl( items_locator::AssocItemSearch::Exclude, Some(items_locator::DEFAULT_QUERY_SEARCH_LIMIT), ) - .into_iter() .filter_map(|item| match ModuleDef::from(item.as_module_def_id()?) { ModuleDef::Trait(trait_) => Some(trait_), _ => None, diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs index 87cddb98ee..5ac1cb48d4 100644 --- a/crates/ide_completion/src/lib.rs +++ b/crates/ide_completion/src/lib.rs @@ -161,7 +161,6 @@ pub fn resolve_completion_edits( items_locator::AssocItemSearch::Include, Some(items_locator::DEFAULT_QUERY_SEARCH_LIMIT), ) - .into_iter() .filter_map(|candidate| { current_module .find_use_path_prefixed(db, candidate, config.insert_use.prefix_kind) diff --git a/crates/ide_db/src/helpers/import_assets.rs b/crates/ide_db/src/helpers/import_assets.rs index 0da7a1a9d5..1881c746f6 100644 --- a/crates/ide_db/src/helpers/import_assets.rs +++ b/crates/ide_db/src/helpers/import_assets.rs @@ -267,7 +267,6 @@ fn path_applicable_imports( AssocItemSearch::Exclude, Some(DEFAULT_QUERY_SEARCH_LIMIT), ) - .into_iter() .filter_map(|item| { let mod_path = mod_path(item)?; Some(LocatedImport::new(mod_path.clone(), item, item, Some(mod_path))) @@ -285,7 +284,6 @@ fn path_applicable_imports( AssocItemSearch::Include, Some(DEFAULT_QUERY_SEARCH_LIMIT), ) - .into_iter() .filter_map(|item| { import_for_item( sema.db, @@ -430,7 +428,6 @@ fn trait_applicable_items( AssocItemSearch::AssocItemsOnly, Some(DEFAULT_QUERY_SEARCH_LIMIT), ) - .into_iter() .filter_map(|input| item_as_assoc(db, input)) .filter_map(|assoc| { let assoc_item_trait = assoc.containing_trait(db)?; diff --git a/crates/ide_db/src/items_locator.rs b/crates/ide_db/src/items_locator.rs index b9d5852e2b..9af94b86c2 100644 --- a/crates/ide_db/src/items_locator.rs +++ b/crates/ide_db/src/items_locator.rs @@ -15,7 +15,6 @@ use crate::{ symbol_index::{self, FileSymbol}, RootDatabase, }; -use rustc_hash::FxHashSet; /// A value to use, when uncertain which limit to pick. pub const DEFAULT_QUERY_SEARCH_LIMIT: usize = 40; @@ -32,13 +31,13 @@ pub enum AssocItemSearch { } /// Searches for importable items with the given name in the crate and its dependencies. -pub fn items_with_name( - sema: &Semantics<'_, RootDatabase>, +pub fn items_with_name<'a>( + sema: &'a Semantics<'_, RootDatabase>, krate: Crate, name: NameToImport, assoc_item_search: AssocItemSearch, limit: Option, -) -> FxHashSet { +) -> impl Iterator + 'a { let _p = profile::span("items_with_name").detail(|| { format!( "Name: {} ({:?}), crate: {:?}, limit: {:?}", @@ -94,13 +93,13 @@ pub fn items_with_name( find_items(sema, krate, assoc_item_search, local_query, external_query) } -fn find_items( - sema: &Semantics<'_, RootDatabase>, +fn find_items<'a>( + sema: &'a Semantics<'_, RootDatabase>, krate: Crate, assoc_item_search: AssocItemSearch, local_query: symbol_index::Query, external_query: import_map::Query, -) -> FxHashSet { +) -> impl Iterator + 'a { let _p = profile::span("find_items"); let db = sema.db; @@ -115,21 +114,18 @@ fn find_items( // Query the local crate using the symbol index. let local_results = symbol_index::crate_symbols(db, krate.into(), local_query) .into_iter() - .filter_map(|local_candidate| get_name_definition(sema, &local_candidate)) + .filter_map(move |local_candidate| get_name_definition(sema, &local_candidate)) .filter_map(|name_definition_to_import| match name_definition_to_import { Definition::ModuleDef(module_def) => Some(ItemInNs::from(module_def)), Definition::Macro(macro_def) => Some(ItemInNs::from(macro_def)), _ => None, }); - external_importables - .chain(local_results) - .filter(move |&item| match assoc_item_search { - AssocItemSearch::Include => true, - AssocItemSearch::Exclude => !is_assoc_item(item, sema.db), - AssocItemSearch::AssocItemsOnly => is_assoc_item(item, sema.db), - }) - .collect() + external_importables.chain(local_results).filter(move |&item| match assoc_item_search { + AssocItemSearch::Include => true, + AssocItemSearch::Exclude => !is_assoc_item(item, sema.db), + AssocItemSearch::AssocItemsOnly => is_assoc_item(item, sema.db), + }) } fn get_name_definition( From b17d99c0706674c7549aca4670f915aa0b0e2f4e Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 21 Mar 2021 00:50:59 +0200 Subject: [PATCH 3/3] Fix the profile string --- crates/ide_db/src/items_locator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ide_db/src/items_locator.rs b/crates/ide_db/src/items_locator.rs index 9af94b86c2..ef796b6f77 100644 --- a/crates/ide_db/src/items_locator.rs +++ b/crates/ide_db/src/items_locator.rs @@ -40,7 +40,7 @@ pub fn items_with_name<'a>( ) -> impl Iterator + 'a { let _p = profile::span("items_with_name").detail(|| { format!( - "Name: {} ({:?}), crate: {:?}, limit: {:?}", + "Name: {}, crate: {:?}, assoc items: {:?}, limit: {:?}", name.text(), assoc_item_search, krate.display_name(sema.db).map(|name| name.to_string()),