diff options
Diffstat (limited to 'crates/hir_def')
-rw-r--r-- | crates/hir_def/src/import_map.rs | 82 |
1 files changed, 77 insertions, 5 deletions
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs index 1e24f29a8..c0f108848 100644 --- a/crates/hir_def/src/import_map.rs +++ b/crates/hir_def/src/import_map.rs | |||
@@ -7,7 +7,7 @@ use fst::{self, Streamer}; | |||
7 | use hir_expand::name::Name; | 7 | use hir_expand::name::Name; |
8 | use indexmap::{map::Entry, IndexMap}; | 8 | use indexmap::{map::Entry, IndexMap}; |
9 | use itertools::Itertools; | 9 | use itertools::Itertools; |
10 | use rustc_hash::{FxHashMap, FxHasher}; | 10 | use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; |
11 | use smallvec::SmallVec; | 11 | use smallvec::SmallVec; |
12 | use syntax::SmolStr; | 12 | use syntax::SmolStr; |
13 | 13 | ||
@@ -225,6 +225,19 @@ fn cmp((_, lhs): &(&ItemInNs, &ImportInfo), (_, rhs): &(&ItemInNs, &ImportInfo)) | |||
225 | lhs_str.cmp(&rhs_str) | 225 | lhs_str.cmp(&rhs_str) |
226 | } | 226 | } |
227 | 227 | ||
228 | #[derive(Debug, Eq, PartialEq, Hash)] | ||
229 | pub enum ImportKind { | ||
230 | Module, | ||
231 | Function, | ||
232 | Adt, | ||
233 | EnumVariant, | ||
234 | Const, | ||
235 | Static, | ||
236 | Trait, | ||
237 | TypeAlias, | ||
238 | BuiltinType, | ||
239 | } | ||
240 | |||
228 | #[derive(Debug)] | 241 | #[derive(Debug)] |
229 | pub struct Query { | 242 | pub struct Query { |
230 | query: String, | 243 | query: String, |
@@ -232,6 +245,7 @@ pub struct Query { | |||
232 | anchor_end: bool, | 245 | anchor_end: bool, |
233 | case_sensitive: bool, | 246 | case_sensitive: bool, |
234 | limit: usize, | 247 | limit: usize, |
248 | exclude_import_kinds: FxHashSet<ImportKind>, | ||
235 | } | 249 | } |
236 | 250 | ||
237 | impl Query { | 251 | impl Query { |
@@ -242,6 +256,7 @@ impl Query { | |||
242 | anchor_end: false, | 256 | anchor_end: false, |
243 | case_sensitive: false, | 257 | case_sensitive: false, |
244 | limit: usize::max_value(), | 258 | limit: usize::max_value(), |
259 | exclude_import_kinds: FxHashSet::default(), | ||
245 | } | 260 | } |
246 | } | 261 | } |
247 | 262 | ||
@@ -260,6 +275,12 @@ impl Query { | |||
260 | pub fn case_sensitive(self) -> Self { | 275 | pub fn case_sensitive(self) -> Self { |
261 | Self { case_sensitive: true, ..self } | 276 | Self { case_sensitive: true, ..self } |
262 | } | 277 | } |
278 | |||
279 | /// Do not include imports of the specified kind in the search results. | ||
280 | pub fn exclude_import_kind(mut self, import_kind: ImportKind) -> Self { | ||
281 | self.exclude_import_kinds.insert(import_kind); | ||
282 | self | ||
283 | } | ||
263 | } | 284 | } |
264 | 285 | ||
265 | /// Searches dependencies of `krate` for an importable path matching `query`. | 286 | /// Searches dependencies of `krate` for an importable path matching `query`. |
@@ -303,10 +324,17 @@ pub fn search_dependencies<'a>( | |||
303 | 324 | ||
304 | // Add the items from this `ModPath` group. Those are all subsequent items in | 325 | // Add the items from this `ModPath` group. Those are all subsequent items in |
305 | // `importables` whose paths match `path`. | 326 | // `importables` whose paths match `path`. |
306 | let iter = importables.iter().copied().take_while(|item| { | 327 | let iter = importables |
307 | let item_path = &import_map.map[item].path; | 328 | .iter() |
308 | fst_path(item_path) == fst_path(path) | 329 | .copied() |
309 | }); | 330 | .take_while(|item| { |
331 | let item_path = &import_map.map[item].path; | ||
332 | fst_path(item_path) == fst_path(path) | ||
333 | }) | ||
334 | .filter(|&item| match item_import_kind(item) { | ||
335 | Some(import_kind) => !query.exclude_import_kinds.contains(&import_kind), | ||
336 | None => true, | ||
337 | }); | ||
310 | 338 | ||
311 | if query.case_sensitive { | 339 | if query.case_sensitive { |
312 | // FIXME: This does not do a subsequence match. | 340 | // FIXME: This does not do a subsequence match. |
@@ -341,6 +369,20 @@ pub fn search_dependencies<'a>( | |||
341 | res | 369 | res |
342 | } | 370 | } |
343 | 371 | ||
372 | fn item_import_kind(item: ItemInNs) -> Option<ImportKind> { | ||
373 | Some(match item.as_module_def_id()? { | ||
374 | ModuleDefId::ModuleId(_) => ImportKind::Module, | ||
375 | ModuleDefId::FunctionId(_) => ImportKind::Function, | ||
376 | ModuleDefId::AdtId(_) => ImportKind::Adt, | ||
377 | ModuleDefId::EnumVariantId(_) => ImportKind::EnumVariant, | ||
378 | ModuleDefId::ConstId(_) => ImportKind::Const, | ||
379 | ModuleDefId::StaticId(_) => ImportKind::Static, | ||
380 | ModuleDefId::TraitId(_) => ImportKind::Trait, | ||
381 | ModuleDefId::TypeAliasId(_) => ImportKind::TypeAlias, | ||
382 | ModuleDefId::BuiltinType(_) => ImportKind::BuiltinType, | ||
383 | }) | ||
384 | } | ||
385 | |||
344 | #[cfg(test)] | 386 | #[cfg(test)] |
345 | mod tests { | 387 | mod tests { |
346 | use base_db::{fixture::WithFixture, SourceDatabase, Upcast}; | 388 | use base_db::{fixture::WithFixture, SourceDatabase, Upcast}; |
@@ -758,4 +800,34 @@ mod tests { | |||
758 | "#]], | 800 | "#]], |
759 | ); | 801 | ); |
760 | } | 802 | } |
803 | |||
804 | #[test] | ||
805 | fn search_exclusions() { | ||
806 | let ra_fixture = r#" | ||
807 | //- /main.rs crate:main deps:dep | ||
808 | //- /dep.rs crate:dep | ||
809 | |||
810 | pub struct fmt; | ||
811 | pub struct FMT; | ||
812 | "#; | ||
813 | |||
814 | check_search( | ||
815 | ra_fixture, | ||
816 | "main", | ||
817 | Query::new("FMT"), | ||
818 | expect![[r#" | ||
819 | dep::fmt (t) | ||
820 | dep::fmt (v) | ||
821 | dep::FMT (t) | ||
822 | dep::FMT (v) | ||
823 | "#]], | ||
824 | ); | ||
825 | |||
826 | check_search( | ||
827 | ra_fixture, | ||
828 | "main", | ||
829 | Query::new("FMT").exclude_import_kind(ImportKind::Adt), | ||
830 | expect![[r#""#]], | ||
831 | ); | ||
832 | } | ||
761 | } | 833 | } |