aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_db/src/imports_locator.rs
diff options
context:
space:
mode:
authorKirill Bulatov <[email protected]>2021-03-02 23:26:53 +0000
committerKirill Bulatov <[email protected]>2021-03-08 21:59:20 +0000
commit33c83e72b9b48177a6171fd06a26676679963a4d (patch)
treeb787206319b2cf0050e4ce7c89ad4365b9a43c11 /crates/ide_db/src/imports_locator.rs
parent4d4ac1d4fa0aba107a27d3fd2d209304dfe69b9f (diff)
Work towards better import labels
Diffstat (limited to 'crates/ide_db/src/imports_locator.rs')
-rw-r--r--crates/ide_db/src/imports_locator.rs143
1 files changed, 0 insertions, 143 deletions
diff --git a/crates/ide_db/src/imports_locator.rs b/crates/ide_db/src/imports_locator.rs
deleted file mode 100644
index fd700e04f..000000000
--- a/crates/ide_db/src/imports_locator.rs
+++ /dev/null
@@ -1,143 +0,0 @@
1//! This module contains an import search functionality that is provided to the assists module.
2//! Later, this should be moved away to a separate crate that is accessible from the assists module.
3
4use hir::{
5 import_map::{self, ImportKind},
6 AsAssocItem, Crate, MacroDef, ModuleDef, Semantics,
7};
8use syntax::{ast, AstNode, SyntaxKind::NAME};
9
10use crate::{
11 defs::{Definition, NameClass},
12 symbol_index::{self, FileSymbol},
13 RootDatabase,
14};
15use either::Either;
16use rustc_hash::FxHashSet;
17
18pub(crate) const DEFAULT_QUERY_SEARCH_LIMIT: usize = 40;
19
20pub fn find_exact_imports(
21 sema: &Semantics<'_, RootDatabase>,
22 krate: Crate,
23 name_to_import: String,
24) -> Box<dyn Iterator<Item = Either<ModuleDef, MacroDef>>> {
25 let _p = profile::span("find_exact_imports");
26 Box::new(find_imports(
27 sema,
28 krate,
29 {
30 let mut local_query = symbol_index::Query::new(name_to_import.clone());
31 local_query.exact();
32 local_query.limit(DEFAULT_QUERY_SEARCH_LIMIT);
33 local_query
34 },
35 import_map::Query::new(name_to_import)
36 .limit(DEFAULT_QUERY_SEARCH_LIMIT)
37 .name_only()
38 .search_mode(import_map::SearchMode::Equals)
39 .case_sensitive(),
40 ))
41}
42
43#[derive(Debug)]
44pub enum AssocItemSearch {
45 Include,
46 Exclude,
47 AssocItemsOnly,
48}
49
50pub fn find_similar_imports<'a>(
51 sema: &'a Semantics<'a, RootDatabase>,
52 krate: Crate,
53 fuzzy_search_string: String,
54 assoc_item_search: AssocItemSearch,
55 limit: Option<usize>,
56) -> Box<dyn Iterator<Item = Either<ModuleDef, MacroDef>> + 'a> {
57 let _p = profile::span("find_similar_imports");
58
59 let mut external_query = import_map::Query::new(fuzzy_search_string.clone())
60 .search_mode(import_map::SearchMode::Fuzzy)
61 .name_only();
62
63 match assoc_item_search {
64 AssocItemSearch::Include => {}
65 AssocItemSearch::Exclude => {
66 external_query = external_query.exclude_import_kind(ImportKind::AssociatedItem);
67 }
68 AssocItemSearch::AssocItemsOnly => {
69 external_query = external_query.assoc_items_only();
70 }
71 }
72
73 let mut local_query = symbol_index::Query::new(fuzzy_search_string);
74
75 if let Some(limit) = limit {
76 external_query = external_query.limit(limit);
77 local_query.limit(limit);
78 }
79
80 Box::new(find_imports(sema, krate, local_query, external_query).filter(
81 move |import_candidate| match assoc_item_search {
82 AssocItemSearch::Include => true,
83 AssocItemSearch::Exclude => !is_assoc_item(import_candidate, sema.db),
84 AssocItemSearch::AssocItemsOnly => is_assoc_item(import_candidate, sema.db),
85 },
86 ))
87}
88
89fn is_assoc_item(import_candidate: &Either<ModuleDef, MacroDef>, db: &RootDatabase) -> bool {
90 match import_candidate {
91 Either::Left(ModuleDef::Function(function)) => function.as_assoc_item(db).is_some(),
92 Either::Left(ModuleDef::Const(const_)) => const_.as_assoc_item(db).is_some(),
93 Either::Left(ModuleDef::TypeAlias(type_alias)) => type_alias.as_assoc_item(db).is_some(),
94 _ => false,
95 }
96}
97
98fn find_imports<'a>(
99 sema: &Semantics<'a, RootDatabase>,
100 krate: Crate,
101 local_query: symbol_index::Query,
102 external_query: import_map::Query,
103) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> {
104 let _p = profile::span("find_similar_imports");
105 let db = sema.db;
106
107 // Query dependencies first.
108 let mut candidates: FxHashSet<_> =
109 krate.query_external_importables(db, external_query).collect();
110
111 // Query the local crate using the symbol index.
112 let local_results = symbol_index::crate_symbols(db, krate.into(), local_query);
113
114 candidates.extend(
115 local_results
116 .into_iter()
117 .filter_map(|import_candidate| get_name_definition(sema, &import_candidate))
118 .filter_map(|name_definition_to_import| match name_definition_to_import {
119 Definition::ModuleDef(module_def) => Some(Either::Left(module_def)),
120 Definition::Macro(macro_def) => Some(Either::Right(macro_def)),
121 _ => None,
122 }),
123 );
124
125 candidates.into_iter()
126}
127
128fn get_name_definition<'a>(
129 sema: &Semantics<'a, RootDatabase>,
130 import_candidate: &FileSymbol,
131) -> Option<Definition> {
132 let _p = profile::span("get_name_definition");
133 let file_id = import_candidate.file_id;
134
135 let candidate_node = import_candidate.ptr.to_node(sema.parse(file_id).syntax());
136 let candidate_name_node = if candidate_node.kind() != NAME {
137 candidate_node.children().find(|it| it.kind() == NAME)?
138 } else {
139 candidate_node
140 };
141 let name = ast::Name::cast(candidate_name_node)?;
142 NameClass::classify(sema, &name)?.defined(sema.db)
143}