diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-06-11 11:07:52 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-06-11 11:07:52 +0100 |
commit | f320c38aec185de2a02e0febff133da1f6a3462b (patch) | |
tree | f22c1d5af6dcd994667d656833c3a27c568961ff /crates/ra_ide_db | |
parent | dfbd81e84a699005db4e88e9fbf8d4440525a097 (diff) | |
parent | 6766a6b0e189f47d7a405c872598bca9a2395360 (diff) |
Merge #4819
4819: Add an FST index to `ImportMap` and use it to speed up auto import r=matklad a=jonas-schievink
For the importing crate, we still use the symbol index, but I've modified it to only look at files that comprise that crate (instead of the whole workspace).
Oh, and since now the symbol query limit is respected correctly, it's possible that some results from the local crate now disappear if there are many matches.
Fixes https://github.com/rust-analyzer/rust-analyzer/issues/4763
Co-authored-by: Jonas Schievink <[email protected]>
Diffstat (limited to 'crates/ra_ide_db')
-rw-r--r-- | crates/ra_ide_db/src/imports_locator.rs | 46 | ||||
-rw-r--r-- | crates/ra_ide_db/src/symbol_index.rs | 53 |
2 files changed, 66 insertions, 33 deletions
diff --git a/crates/ra_ide_db/src/imports_locator.rs b/crates/ra_ide_db/src/imports_locator.rs index bf0d8db60..fff112e66 100644 --- a/crates/ra_ide_db/src/imports_locator.rs +++ b/crates/ra_ide_db/src/imports_locator.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! This module contains an import search funcionality that is provided to the ra_assists module. | 1 | //! This module contains an import search funcionality that is provided to the ra_assists module. |
2 | //! Later, this should be moved away to a separate crate that is accessible from the ra_assists module. | 2 | //! Later, this should be moved away to a separate crate that is accessible from the ra_assists module. |
3 | 3 | ||
4 | use hir::{MacroDef, ModuleDef, Semantics}; | 4 | use hir::{Crate, MacroDef, ModuleDef, Semantics}; |
5 | use ra_prof::profile; | 5 | use ra_prof::profile; |
6 | use ra_syntax::{ast, AstNode, SyntaxKind::NAME}; | 6 | use ra_syntax::{ast, AstNode, SyntaxKind::NAME}; |
7 | 7 | ||
@@ -11,44 +11,46 @@ use crate::{ | |||
11 | RootDatabase, | 11 | RootDatabase, |
12 | }; | 12 | }; |
13 | use either::Either; | 13 | use either::Either; |
14 | use rustc_hash::FxHashSet; | ||
14 | 15 | ||
15 | pub struct ImportsLocator<'a> { | 16 | pub struct ImportsLocator<'a> { |
16 | sema: Semantics<'a, RootDatabase>, | 17 | sema: Semantics<'a, RootDatabase>, |
18 | krate: Crate, | ||
17 | } | 19 | } |
18 | 20 | ||
19 | impl<'a> ImportsLocator<'a> { | 21 | impl<'a> ImportsLocator<'a> { |
20 | pub fn new(db: &'a RootDatabase) -> Self { | 22 | pub fn new(db: &'a RootDatabase, krate: Crate) -> Self { |
21 | Self { sema: Semantics::new(db) } | 23 | Self { sema: Semantics::new(db), krate } |
22 | } | 24 | } |
23 | 25 | ||
24 | pub fn find_imports(&mut self, name_to_import: &str) -> Vec<Either<ModuleDef, MacroDef>> { | 26 | pub fn find_imports(&mut self, name_to_import: &str) -> Vec<Either<ModuleDef, MacroDef>> { |
25 | let _p = profile("search_for_imports"); | 27 | let _p = profile("search_for_imports"); |
26 | let db = self.sema.db; | 28 | let db = self.sema.db; |
27 | 29 | ||
28 | let project_results = { | 30 | // Query dependencies first. |
29 | let mut query = Query::new(name_to_import.to_string()); | 31 | let mut candidates: FxHashSet<_> = |
30 | query.exact(); | 32 | self.krate.query_external_importables(db, name_to_import).collect(); |
31 | query.limit(40); | 33 | |
32 | symbol_index::world_symbols(db, query) | 34 | // Query the local crate using the symbol index. |
33 | }; | 35 | let local_results = { |
34 | let lib_results = { | ||
35 | let mut query = Query::new(name_to_import.to_string()); | 36 | let mut query = Query::new(name_to_import.to_string()); |
36 | query.libs(); | ||
37 | query.exact(); | 37 | query.exact(); |
38 | query.limit(40); | 38 | query.limit(40); |
39 | symbol_index::world_symbols(db, query) | 39 | symbol_index::crate_symbols(db, self.krate.into(), query) |
40 | }; | 40 | }; |
41 | 41 | ||
42 | project_results | 42 | candidates.extend( |
43 | .into_iter() | 43 | local_results |
44 | .chain(lib_results.into_iter()) | 44 | .into_iter() |
45 | .filter_map(|import_candidate| self.get_name_definition(&import_candidate)) | 45 | .filter_map(|import_candidate| self.get_name_definition(&import_candidate)) |
46 | .filter_map(|name_definition_to_import| match name_definition_to_import { | 46 | .filter_map(|name_definition_to_import| match name_definition_to_import { |
47 | Definition::ModuleDef(module_def) => Some(Either::Left(module_def)), | 47 | Definition::ModuleDef(module_def) => Some(Either::Left(module_def)), |
48 | Definition::Macro(macro_def) => Some(Either::Right(macro_def)), | 48 | Definition::Macro(macro_def) => Some(Either::Right(macro_def)), |
49 | _ => None, | 49 | _ => None, |
50 | }) | 50 | }), |
51 | .collect() | 51 | ); |
52 | |||
53 | candidates.into_iter().collect() | ||
52 | } | 54 | } |
53 | 55 | ||
54 | fn get_name_definition(&mut self, import_candidate: &FileSymbol) -> Option<Definition> { | 56 | fn get_name_definition(&mut self, import_candidate: &FileSymbol) -> Option<Definition> { |
diff --git a/crates/ra_ide_db/src/symbol_index.rs b/crates/ra_ide_db/src/symbol_index.rs index acc31fe3b..aab918973 100644 --- a/crates/ra_ide_db/src/symbol_index.rs +++ b/crates/ra_ide_db/src/symbol_index.rs | |||
@@ -29,9 +29,10 @@ use std::{ | |||
29 | }; | 29 | }; |
30 | 30 | ||
31 | use fst::{self, Streamer}; | 31 | use fst::{self, Streamer}; |
32 | use hir::db::DefDatabase; | ||
32 | use ra_db::{ | 33 | use ra_db::{ |
33 | salsa::{self, ParallelDatabase}, | 34 | salsa::{self, ParallelDatabase}, |
34 | FileId, SourceDatabaseExt, SourceRootId, | 35 | CrateId, FileId, SourceDatabaseExt, SourceRootId, |
35 | }; | 36 | }; |
36 | use ra_syntax::{ | 37 | use ra_syntax::{ |
37 | ast::{self, NameOwner}, | 38 | ast::{self, NameOwner}, |
@@ -110,6 +111,14 @@ fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> | |||
110 | Arc::new(SymbolIndex::new(symbols)) | 111 | Arc::new(SymbolIndex::new(symbols)) |
111 | } | 112 | } |
112 | 113 | ||
114 | /// Need to wrap Snapshot to provide `Clone` impl for `map_with` | ||
115 | struct Snap(salsa::Snapshot<RootDatabase>); | ||
116 | impl Clone for Snap { | ||
117 | fn clone(&self) -> Snap { | ||
118 | Snap(self.0.snapshot()) | ||
119 | } | ||
120 | } | ||
121 | |||
113 | // Feature: Workspace Symbol | 122 | // Feature: Workspace Symbol |
114 | // | 123 | // |
115 | // Uses fuzzy-search to find types, modules and functions by name across your | 124 | // Uses fuzzy-search to find types, modules and functions by name across your |
@@ -132,13 +141,7 @@ fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> | |||
132 | // | VS Code | kbd:[Ctrl+T] | 141 | // | VS Code | kbd:[Ctrl+T] |
133 | // |=== | 142 | // |=== |
134 | pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> { | 143 | pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> { |
135 | /// Need to wrap Snapshot to provide `Clone` impl for `map_with` | 144 | let _p = ra_prof::profile("world_symbols").detail(|| query.query.clone()); |
136 | struct Snap(salsa::Snapshot<RootDatabase>); | ||
137 | impl Clone for Snap { | ||
138 | fn clone(&self) -> Snap { | ||
139 | Snap(self.0.snapshot()) | ||
140 | } | ||
141 | } | ||
142 | 145 | ||
143 | let buf: Vec<Arc<SymbolIndex>> = if query.libs { | 146 | let buf: Vec<Arc<SymbolIndex>> = if query.libs { |
144 | let snap = Snap(db.snapshot()); | 147 | let snap = Snap(db.snapshot()); |
@@ -173,6 +176,33 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> { | |||
173 | query.search(&buf) | 176 | query.search(&buf) |
174 | } | 177 | } |
175 | 178 | ||
179 | pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<FileSymbol> { | ||
180 | // FIXME(#4842): This now depends on CrateDefMap, why not build the entire symbol index from | ||
181 | // that instead? | ||
182 | |||
183 | let def_map = db.crate_def_map(krate); | ||
184 | let mut files = Vec::new(); | ||
185 | let mut modules = vec![def_map.root]; | ||
186 | while let Some(module) = modules.pop() { | ||
187 | let data = &def_map[module]; | ||
188 | files.extend(data.origin.file_id()); | ||
189 | modules.extend(data.children.values()); | ||
190 | } | ||
191 | |||
192 | let snap = Snap(db.snapshot()); | ||
193 | |||
194 | #[cfg(not(feature = "wasm"))] | ||
195 | let buf = files | ||
196 | .par_iter() | ||
197 | .map_with(snap, |db, &file_id| db.0.file_symbols(file_id)) | ||
198 | .collect::<Vec<_>>(); | ||
199 | |||
200 | #[cfg(feature = "wasm")] | ||
201 | let buf = files.iter().map(|&file_id| snap.0.file_symbols(file_id)).collect::<Vec<_>>(); | ||
202 | |||
203 | query.search(&buf) | ||
204 | } | ||
205 | |||
176 | pub fn index_resolve(db: &RootDatabase, name_ref: &ast::NameRef) -> Vec<FileSymbol> { | 206 | pub fn index_resolve(db: &RootDatabase, name_ref: &ast::NameRef) -> Vec<FileSymbol> { |
177 | let name = name_ref.text(); | 207 | let name = name_ref.text(); |
178 | let mut query = Query::new(name.to_string()); | 208 | let mut query = Query::new(name.to_string()); |
@@ -298,9 +328,6 @@ impl Query { | |||
298 | let mut stream = op.union(); | 328 | let mut stream = op.union(); |
299 | let mut res = Vec::new(); | 329 | let mut res = Vec::new(); |
300 | while let Some((_, indexed_values)) = stream.next() { | 330 | while let Some((_, indexed_values)) = stream.next() { |
301 | if res.len() >= self.limit { | ||
302 | break; | ||
303 | } | ||
304 | for indexed_value in indexed_values { | 331 | for indexed_value in indexed_values { |
305 | let symbol_index = &indices[indexed_value.index]; | 332 | let symbol_index = &indices[indexed_value.index]; |
306 | let (start, end) = SymbolIndex::map_value_to_range(indexed_value.value); | 333 | let (start, end) = SymbolIndex::map_value_to_range(indexed_value.value); |
@@ -312,7 +339,11 @@ impl Query { | |||
312 | if self.exact && symbol.name != self.query { | 339 | if self.exact && symbol.name != self.query { |
313 | continue; | 340 | continue; |
314 | } | 341 | } |
342 | |||
315 | res.push(symbol.clone()); | 343 | res.push(symbol.clone()); |
344 | if res.len() >= self.limit { | ||
345 | return res; | ||
346 | } | ||
316 | } | 347 | } |
317 | } | 348 | } |
318 | } | 349 | } |