diff options
Diffstat (limited to 'crates/ra_ide_db/src')
-rw-r--r-- | crates/ra_ide_db/src/change.rs | 254 | ||||
-rw-r--r-- | crates/ra_ide_db/src/defs.rs | 69 | ||||
-rw-r--r-- | crates/ra_ide_db/src/imports_locator.rs | 84 | ||||
-rw-r--r-- | crates/ra_ide_db/src/lib.rs | 80 | ||||
-rw-r--r-- | crates/ra_ide_db/src/search.rs | 16 | ||||
-rw-r--r-- | crates/ra_ide_db/src/source_change.rs | 31 | ||||
-rw-r--r-- | crates/ra_ide_db/src/symbol_index.rs | 138 |
7 files changed, 291 insertions, 381 deletions
diff --git a/crates/ra_ide_db/src/change.rs b/crates/ra_ide_db/src/change.rs index 8446ef88e..a1bb3043b 100644 --- a/crates/ra_ide_db/src/change.rs +++ b/crates/ra_ide_db/src/change.rs | |||
@@ -5,45 +5,29 @@ use std::{fmt, sync::Arc, time}; | |||
5 | 5 | ||
6 | use ra_db::{ | 6 | use ra_db::{ |
7 | salsa::{Database, Durability, SweepStrategy}, | 7 | salsa::{Database, Durability, SweepStrategy}, |
8 | CrateGraph, FileId, RelativePathBuf, SourceDatabase, SourceDatabaseExt, SourceRoot, | 8 | CrateGraph, FileId, SourceDatabase, SourceDatabaseExt, SourceRoot, SourceRootId, |
9 | SourceRootId, | ||
10 | }; | 9 | }; |
11 | use ra_prof::{memory_usage, profile, Bytes}; | 10 | use ra_prof::{memory_usage, profile, Bytes}; |
12 | use ra_syntax::SourceFile; | 11 | use rustc_hash::FxHashSet; |
13 | #[cfg(not(feature = "wasm"))] | 12 | |
14 | use rayon::prelude::*; | 13 | use crate::{symbol_index::SymbolsDatabase, RootDatabase}; |
15 | use rustc_hash::FxHashMap; | ||
16 | |||
17 | use crate::{ | ||
18 | symbol_index::{SymbolIndex, SymbolsDatabase}, | ||
19 | DebugData, RootDatabase, | ||
20 | }; | ||
21 | 14 | ||
22 | #[derive(Default)] | 15 | #[derive(Default)] |
23 | pub struct AnalysisChange { | 16 | pub struct AnalysisChange { |
24 | new_roots: Vec<(SourceRootId, bool)>, | 17 | roots: Option<Vec<SourceRoot>>, |
25 | roots_changed: FxHashMap<SourceRootId, RootChange>, | 18 | files_changed: Vec<(FileId, Option<Arc<String>>)>, |
26 | files_changed: Vec<(FileId, Arc<String>)>, | ||
27 | libraries_added: Vec<LibraryData>, | ||
28 | crate_graph: Option<CrateGraph>, | 19 | crate_graph: Option<CrateGraph>, |
29 | debug_data: DebugData, | ||
30 | } | 20 | } |
31 | 21 | ||
32 | impl fmt::Debug for AnalysisChange { | 22 | impl fmt::Debug for AnalysisChange { |
33 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | 23 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
34 | let mut d = fmt.debug_struct("AnalysisChange"); | 24 | let mut d = fmt.debug_struct("AnalysisChange"); |
35 | if !self.new_roots.is_empty() { | 25 | if let Some(roots) = &self.roots { |
36 | d.field("new_roots", &self.new_roots); | 26 | d.field("roots", roots); |
37 | } | ||
38 | if !self.roots_changed.is_empty() { | ||
39 | d.field("roots_changed", &self.roots_changed); | ||
40 | } | 27 | } |
41 | if !self.files_changed.is_empty() { | 28 | if !self.files_changed.is_empty() { |
42 | d.field("files_changed", &self.files_changed.len()); | 29 | d.field("files_changed", &self.files_changed.len()); |
43 | } | 30 | } |
44 | if !self.libraries_added.is_empty() { | ||
45 | d.field("libraries_added", &self.libraries_added.len()); | ||
46 | } | ||
47 | if self.crate_graph.is_some() { | 31 | if self.crate_graph.is_some() { |
48 | d.field("crate_graph", &self.crate_graph); | 32 | d.field("crate_graph", &self.crate_graph); |
49 | } | 33 | } |
@@ -56,54 +40,30 @@ impl AnalysisChange { | |||
56 | AnalysisChange::default() | 40 | AnalysisChange::default() |
57 | } | 41 | } |
58 | 42 | ||
59 | pub fn add_root(&mut self, root_id: SourceRootId, is_local: bool) { | 43 | pub fn set_roots(&mut self, roots: Vec<SourceRoot>) { |
60 | self.new_roots.push((root_id, is_local)); | 44 | self.roots = Some(roots); |
61 | } | 45 | } |
62 | 46 | ||
63 | pub fn add_file( | 47 | pub fn change_file(&mut self, file_id: FileId, new_text: Option<Arc<String>>) { |
64 | &mut self, | ||
65 | root_id: SourceRootId, | ||
66 | file_id: FileId, | ||
67 | path: RelativePathBuf, | ||
68 | text: Arc<String>, | ||
69 | ) { | ||
70 | let file = AddFile { file_id, path, text }; | ||
71 | self.roots_changed.entry(root_id).or_default().added.push(file); | ||
72 | } | ||
73 | |||
74 | pub fn change_file(&mut self, file_id: FileId, new_text: Arc<String>) { | ||
75 | self.files_changed.push((file_id, new_text)) | 48 | self.files_changed.push((file_id, new_text)) |
76 | } | 49 | } |
77 | 50 | ||
78 | pub fn remove_file(&mut self, root_id: SourceRootId, file_id: FileId, path: RelativePathBuf) { | ||
79 | let file = RemoveFile { file_id, path }; | ||
80 | self.roots_changed.entry(root_id).or_default().removed.push(file); | ||
81 | } | ||
82 | |||
83 | pub fn add_library(&mut self, data: LibraryData) { | ||
84 | self.libraries_added.push(data) | ||
85 | } | ||
86 | |||
87 | pub fn set_crate_graph(&mut self, graph: CrateGraph) { | 51 | pub fn set_crate_graph(&mut self, graph: CrateGraph) { |
88 | self.crate_graph = Some(graph); | 52 | self.crate_graph = Some(graph); |
89 | } | 53 | } |
90 | |||
91 | pub fn set_debug_root_path(&mut self, source_root_id: SourceRootId, path: String) { | ||
92 | self.debug_data.root_paths.insert(source_root_id, path); | ||
93 | } | ||
94 | } | 54 | } |
95 | 55 | ||
96 | #[derive(Debug)] | 56 | #[derive(Debug)] |
97 | struct AddFile { | 57 | struct AddFile { |
98 | file_id: FileId, | 58 | file_id: FileId, |
99 | path: RelativePathBuf, | 59 | path: String, |
100 | text: Arc<String>, | 60 | text: Arc<String>, |
101 | } | 61 | } |
102 | 62 | ||
103 | #[derive(Debug)] | 63 | #[derive(Debug)] |
104 | struct RemoveFile { | 64 | struct RemoveFile { |
105 | file_id: FileId, | 65 | file_id: FileId, |
106 | path: RelativePathBuf, | 66 | path: String, |
107 | } | 67 | } |
108 | 68 | ||
109 | #[derive(Default)] | 69 | #[derive(Default)] |
@@ -121,47 +81,6 @@ impl fmt::Debug for RootChange { | |||
121 | } | 81 | } |
122 | } | 82 | } |
123 | 83 | ||
124 | pub struct LibraryData { | ||
125 | root_id: SourceRootId, | ||
126 | root_change: RootChange, | ||
127 | symbol_index: SymbolIndex, | ||
128 | } | ||
129 | |||
130 | impl fmt::Debug for LibraryData { | ||
131 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
132 | f.debug_struct("LibraryData") | ||
133 | .field("root_id", &self.root_id) | ||
134 | .field("root_change", &self.root_change) | ||
135 | .field("n_symbols", &self.symbol_index.len()) | ||
136 | .finish() | ||
137 | } | ||
138 | } | ||
139 | |||
140 | impl LibraryData { | ||
141 | pub fn prepare( | ||
142 | root_id: SourceRootId, | ||
143 | files: Vec<(FileId, RelativePathBuf, Arc<String>)>, | ||
144 | ) -> LibraryData { | ||
145 | let _p = profile("LibraryData::prepare"); | ||
146 | |||
147 | #[cfg(not(feature = "wasm"))] | ||
148 | let iter = files.par_iter(); | ||
149 | #[cfg(feature = "wasm")] | ||
150 | let iter = files.iter(); | ||
151 | |||
152 | let symbol_index = SymbolIndex::for_files(iter.map(|(file_id, _, text)| { | ||
153 | let parse = SourceFile::parse(text); | ||
154 | (*file_id, parse) | ||
155 | })); | ||
156 | let mut root_change = RootChange::default(); | ||
157 | root_change.added = files | ||
158 | .into_iter() | ||
159 | .map(|(file_id, path, text)| AddFile { file_id, path, text }) | ||
160 | .collect(); | ||
161 | LibraryData { root_id, root_change, symbol_index } | ||
162 | } | ||
163 | } | ||
164 | |||
165 | const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100); | 84 | const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100); |
166 | 85 | ||
167 | impl RootDatabase { | 86 | impl RootDatabase { |
@@ -174,72 +93,37 @@ impl RootDatabase { | |||
174 | let _p = profile("RootDatabase::apply_change"); | 93 | let _p = profile("RootDatabase::apply_change"); |
175 | self.request_cancellation(); | 94 | self.request_cancellation(); |
176 | log::info!("apply_change {:?}", change); | 95 | log::info!("apply_change {:?}", change); |
177 | if !change.new_roots.is_empty() { | 96 | if let Some(roots) = change.roots { |
178 | let mut local_roots = Vec::clone(&self.local_roots()); | 97 | let mut local_roots = FxHashSet::default(); |
179 | for (root_id, is_local) in change.new_roots { | 98 | let mut library_roots = FxHashSet::default(); |
180 | let root = | 99 | for (idx, root) in roots.into_iter().enumerate() { |
181 | if is_local { SourceRoot::new_local() } else { SourceRoot::new_library() }; | 100 | let root_id = SourceRootId(idx as u32); |
182 | let durability = durability(&root); | 101 | let durability = durability(&root); |
183 | self.set_source_root_with_durability(root_id, Arc::new(root), durability); | 102 | if root.is_library { |
184 | if is_local { | 103 | library_roots.insert(root_id); |
185 | local_roots.push(root_id); | 104 | } else { |
105 | local_roots.insert(root_id); | ||
186 | } | 106 | } |
107 | for file_id in root.iter() { | ||
108 | self.set_file_source_root_with_durability(file_id, root_id, durability); | ||
109 | } | ||
110 | self.set_source_root_with_durability(root_id, Arc::new(root), durability); | ||
187 | } | 111 | } |
188 | self.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH); | 112 | self.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH); |
113 | self.set_library_roots_with_durability(Arc::new(library_roots), Durability::HIGH); | ||
189 | } | 114 | } |
190 | 115 | ||
191 | for (root_id, root_change) in change.roots_changed { | ||
192 | self.apply_root_change(root_id, root_change); | ||
193 | } | ||
194 | for (file_id, text) in change.files_changed { | 116 | for (file_id, text) in change.files_changed { |
195 | let source_root_id = self.file_source_root(file_id); | 117 | let source_root_id = self.file_source_root(file_id); |
196 | let source_root = self.source_root(source_root_id); | 118 | let source_root = self.source_root(source_root_id); |
197 | let durability = durability(&source_root); | 119 | let durability = durability(&source_root); |
120 | // XXX: can't actually remove the file, just reset the text | ||
121 | let text = text.unwrap_or_default(); | ||
198 | self.set_file_text_with_durability(file_id, text, durability) | 122 | self.set_file_text_with_durability(file_id, text, durability) |
199 | } | 123 | } |
200 | if !change.libraries_added.is_empty() { | ||
201 | let mut libraries = Vec::clone(&self.library_roots()); | ||
202 | for library in change.libraries_added { | ||
203 | libraries.push(library.root_id); | ||
204 | self.set_source_root_with_durability( | ||
205 | library.root_id, | ||
206 | Arc::new(SourceRoot::new_library()), | ||
207 | Durability::HIGH, | ||
208 | ); | ||
209 | self.set_library_symbols_with_durability( | ||
210 | library.root_id, | ||
211 | Arc::new(library.symbol_index), | ||
212 | Durability::HIGH, | ||
213 | ); | ||
214 | self.apply_root_change(library.root_id, library.root_change); | ||
215 | } | ||
216 | self.set_library_roots_with_durability(Arc::new(libraries), Durability::HIGH); | ||
217 | } | ||
218 | if let Some(crate_graph) = change.crate_graph { | 124 | if let Some(crate_graph) = change.crate_graph { |
219 | self.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH) | 125 | self.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH) |
220 | } | 126 | } |
221 | |||
222 | Arc::make_mut(&mut self.debug_data).merge(change.debug_data) | ||
223 | } | ||
224 | |||
225 | fn apply_root_change(&mut self, root_id: SourceRootId, root_change: RootChange) { | ||
226 | let mut source_root = SourceRoot::clone(&self.source_root(root_id)); | ||
227 | let durability = durability(&source_root); | ||
228 | for add_file in root_change.added { | ||
229 | self.set_file_text_with_durability(add_file.file_id, add_file.text, durability); | ||
230 | self.set_file_relative_path_with_durability( | ||
231 | add_file.file_id, | ||
232 | add_file.path.clone(), | ||
233 | durability, | ||
234 | ); | ||
235 | self.set_file_source_root_with_durability(add_file.file_id, root_id, durability); | ||
236 | source_root.insert_file(add_file.path, add_file.file_id); | ||
237 | } | ||
238 | for remove_file in root_change.removed { | ||
239 | self.set_file_text_with_durability(remove_file.file_id, Default::default(), durability); | ||
240 | source_root.remove_file(&remove_file.path); | ||
241 | } | ||
242 | self.set_source_root_with_durability(root_id, Arc::new(source_root), durability); | ||
243 | } | 127 | } |
244 | 128 | ||
245 | pub fn maybe_collect_garbage(&mut self) { | 129 | pub fn maybe_collect_garbage(&mut self) { |
@@ -262,37 +146,46 @@ impl RootDatabase { | |||
262 | 146 | ||
263 | let sweep = SweepStrategy::default().discard_values().sweep_all_revisions(); | 147 | let sweep = SweepStrategy::default().discard_values().sweep_all_revisions(); |
264 | 148 | ||
265 | self.query(ra_db::ParseQuery).sweep(sweep); | 149 | ra_db::ParseQuery.in_db(self).sweep(sweep); |
266 | self.query(hir::db::ParseMacroQuery).sweep(sweep); | 150 | hir::db::ParseMacroQuery.in_db(self).sweep(sweep); |
267 | 151 | ||
268 | // Macros do take significant space, but less then the syntax trees | 152 | // Macros do take significant space, but less then the syntax trees |
269 | // self.query(hir::db::MacroDefQuery).sweep(sweep); | 153 | // self.query(hir::db::MacroDefQuery).sweep(sweep); |
270 | // self.query(hir::db::MacroArgQuery).sweep(sweep); | 154 | // self.query(hir::db::MacroArgQuery).sweep(sweep); |
271 | // self.query(hir::db::MacroExpandQuery).sweep(sweep); | 155 | // self.query(hir::db::MacroExpandQuery).sweep(sweep); |
272 | 156 | ||
273 | self.query(hir::db::AstIdMapQuery).sweep(sweep); | 157 | hir::db::AstIdMapQuery.in_db(self).sweep(sweep); |
274 | 158 | ||
275 | self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep); | 159 | hir::db::BodyWithSourceMapQuery.in_db(self).sweep(sweep); |
276 | 160 | ||
277 | self.query(hir::db::ExprScopesQuery).sweep(sweep); | 161 | hir::db::ExprScopesQuery.in_db(self).sweep(sweep); |
278 | self.query(hir::db::InferQueryQuery).sweep(sweep); | 162 | hir::db::InferQueryQuery.in_db(self).sweep(sweep); |
279 | self.query(hir::db::BodyQuery).sweep(sweep); | 163 | hir::db::BodyQuery.in_db(self).sweep(sweep); |
280 | } | 164 | } |
281 | 165 | ||
166 | // Feature: Memory Usage | ||
167 | // | ||
168 | // Clears rust-analyzer's internal database and prints memory usage statistics. | ||
169 | // | ||
170 | // |=== | ||
171 | // | Editor | Action Name | ||
172 | // | ||
173 | // | VS Code | **Rust Analyzer: Memory Usage (Clears Database)** | ||
174 | // |=== | ||
282 | pub fn per_query_memory_usage(&mut self) -> Vec<(String, Bytes)> { | 175 | pub fn per_query_memory_usage(&mut self) -> Vec<(String, Bytes)> { |
283 | let mut acc: Vec<(String, Bytes)> = vec![]; | 176 | let mut acc: Vec<(String, Bytes)> = vec![]; |
284 | let sweep = SweepStrategy::default().discard_values().sweep_all_revisions(); | 177 | let sweep = SweepStrategy::default().discard_values().sweep_all_revisions(); |
285 | macro_rules! sweep_each_query { | 178 | macro_rules! sweep_each_query { |
286 | ($($q:path)*) => {$( | 179 | ($($q:path)*) => {$( |
287 | let before = memory_usage().allocated; | 180 | let before = memory_usage().allocated; |
288 | self.query($q).sweep(sweep); | 181 | $q.in_db(self).sweep(sweep); |
289 | let after = memory_usage().allocated; | 182 | let after = memory_usage().allocated; |
290 | let q: $q = Default::default(); | 183 | let q: $q = Default::default(); |
291 | let name = format!("{:?}", q); | 184 | let name = format!("{:?}", q); |
292 | acc.push((name, before - after)); | 185 | acc.push((name, before - after)); |
293 | 186 | ||
294 | let before = memory_usage().allocated; | 187 | let before = memory_usage().allocated; |
295 | self.query($q).sweep(sweep.discard_everything()); | 188 | $q.in_db(self).sweep(sweep.discard_everything()); |
296 | let after = memory_usage().allocated; | 189 | let after = memory_usage().allocated; |
297 | let q: $q = Default::default(); | 190 | let q: $q = Default::default(); |
298 | let name = format!("{:?} (deps)", q); | 191 | let name = format!("{:?} (deps)", q); |
@@ -306,15 +199,13 @@ impl RootDatabase { | |||
306 | 199 | ||
307 | // AstDatabase | 200 | // AstDatabase |
308 | hir::db::AstIdMapQuery | 201 | hir::db::AstIdMapQuery |
309 | hir::db::InternMacroQuery | ||
310 | hir::db::MacroArgQuery | 202 | hir::db::MacroArgQuery |
311 | hir::db::MacroDefQuery | 203 | hir::db::MacroDefQuery |
312 | hir::db::ParseMacroQuery | 204 | hir::db::ParseMacroQuery |
313 | hir::db::MacroExpandQuery | 205 | hir::db::MacroExpandQuery |
314 | hir::db::InternEagerExpansionQuery | ||
315 | 206 | ||
316 | // DefDatabase | 207 | // DefDatabase |
317 | hir::db::RawItemsQuery | 208 | hir::db::ItemTreeQuery |
318 | hir::db::CrateDefMapQueryQuery | 209 | hir::db::CrateDefMapQueryQuery |
319 | hir::db::StructDataQuery | 210 | hir::db::StructDataQuery |
320 | hir::db::UnionDataQuery | 211 | hir::db::UnionDataQuery |
@@ -334,17 +225,7 @@ impl RootDatabase { | |||
334 | hir::db::CrateLangItemsQuery | 225 | hir::db::CrateLangItemsQuery |
335 | hir::db::LangItemQuery | 226 | hir::db::LangItemQuery |
336 | hir::db::DocumentationQuery | 227 | hir::db::DocumentationQuery |
337 | 228 | hir::db::ImportMapQuery | |
338 | // InternDatabase | ||
339 | hir::db::InternFunctionQuery | ||
340 | hir::db::InternStructQuery | ||
341 | hir::db::InternUnionQuery | ||
342 | hir::db::InternEnumQuery | ||
343 | hir::db::InternConstQuery | ||
344 | hir::db::InternStaticQuery | ||
345 | hir::db::InternTraitQuery | ||
346 | hir::db::InternTypeAliasQuery | ||
347 | hir::db::InternImplQuery | ||
348 | 229 | ||
349 | // HirDatabase | 230 | // HirDatabase |
350 | hir::db::InferQueryQuery | 231 | hir::db::InferQueryQuery |
@@ -357,18 +238,16 @@ impl RootDatabase { | |||
357 | hir::db::GenericPredicatesForParamQuery | 238 | hir::db::GenericPredicatesForParamQuery |
358 | hir::db::GenericPredicatesQuery | 239 | hir::db::GenericPredicatesQuery |
359 | hir::db::GenericDefaultsQuery | 240 | hir::db::GenericDefaultsQuery |
360 | hir::db::ImplsInCrateQuery | 241 | hir::db::InherentImplsInCrateQuery |
361 | hir::db::ImplsForTraitQuery | 242 | hir::db::TraitImplsInCrateQuery |
362 | hir::db::InternTypeCtorQuery | 243 | hir::db::TraitImplsInDepsQuery |
363 | hir::db::InternTypeParamIdQuery | ||
364 | hir::db::InternChalkImplQuery | ||
365 | hir::db::InternAssocTyValueQuery | ||
366 | hir::db::AssociatedTyDataQuery | 244 | hir::db::AssociatedTyDataQuery |
367 | hir::db::TraitDatumQuery | 245 | hir::db::TraitDatumQuery |
368 | hir::db::StructDatumQuery | 246 | hir::db::StructDatumQuery |
369 | hir::db::ImplDatumQuery | 247 | hir::db::ImplDatumQuery |
370 | hir::db::AssociatedTyValueQuery | 248 | hir::db::AssociatedTyValueQuery |
371 | hir::db::TraitSolveQuery | 249 | hir::db::TraitSolveQuery |
250 | hir::db::ReturnTypeImplTraitsQuery | ||
372 | 251 | ||
373 | // SymbolsDatabase | 252 | // SymbolsDatabase |
374 | crate::symbol_index::FileSymbolsQuery | 253 | crate::symbol_index::FileSymbolsQuery |
@@ -376,6 +255,33 @@ impl RootDatabase { | |||
376 | // LineIndexDatabase | 255 | // LineIndexDatabase |
377 | crate::LineIndexQuery | 256 | crate::LineIndexQuery |
378 | ]; | 257 | ]; |
258 | |||
259 | // To collect interned data, we need to bump the revision counter by performing a synthetic | ||
260 | // write. | ||
261 | // We do this after collecting the non-interned queries to correctly attribute memory used | ||
262 | // by interned data. | ||
263 | self.salsa_runtime_mut().synthetic_write(Durability::HIGH); | ||
264 | |||
265 | sweep_each_query![ | ||
266 | // AstDatabase | ||
267 | hir::db::InternMacroQuery | ||
268 | hir::db::InternEagerExpansionQuery | ||
269 | |||
270 | // InternDatabase | ||
271 | hir::db::InternFunctionQuery | ||
272 | hir::db::InternStructQuery | ||
273 | hir::db::InternUnionQuery | ||
274 | hir::db::InternEnumQuery | ||
275 | hir::db::InternConstQuery | ||
276 | hir::db::InternStaticQuery | ||
277 | hir::db::InternTraitQuery | ||
278 | hir::db::InternTypeAliasQuery | ||
279 | hir::db::InternImplQuery | ||
280 | |||
281 | // HirDatabase | ||
282 | hir::db::InternTypeParamIdQuery | ||
283 | ]; | ||
284 | |||
379 | acc.sort_by_key(|it| std::cmp::Reverse(it.1)); | 285 | acc.sort_by_key(|it| std::cmp::Reverse(it.1)); |
380 | acc | 286 | acc |
381 | } | 287 | } |
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs index 8b06cbfc5..bcaabca92 100644 --- a/crates/ra_ide_db/src/defs.rs +++ b/crates/ra_ide_db/src/defs.rs | |||
@@ -18,7 +18,7 @@ use ra_syntax::{ | |||
18 | use crate::RootDatabase; | 18 | use crate::RootDatabase; |
19 | 19 | ||
20 | // FIXME: a more precise name would probably be `Symbol`? | 20 | // FIXME: a more precise name would probably be `Symbol`? |
21 | #[derive(Debug, PartialEq, Eq)] | 21 | #[derive(Debug, PartialEq, Eq, Copy, Clone)] |
22 | pub enum Definition { | 22 | pub enum Definition { |
23 | Macro(MacroDef), | 23 | Macro(MacroDef), |
24 | Field(Field), | 24 | Field(Field), |
@@ -78,10 +78,15 @@ impl Definition { | |||
78 | } | 78 | } |
79 | } | 79 | } |
80 | 80 | ||
81 | #[derive(Debug)] | ||
81 | pub enum NameClass { | 82 | pub enum NameClass { |
82 | Definition(Definition), | 83 | Definition(Definition), |
83 | /// `None` in `if let None = Some(82) {}` | 84 | /// `None` in `if let None = Some(82) {}` |
84 | ConstReference(Definition), | 85 | ConstReference(Definition), |
86 | FieldShorthand { | ||
87 | local: Local, | ||
88 | field: Definition, | ||
89 | }, | ||
85 | } | 90 | } |
86 | 91 | ||
87 | impl NameClass { | 92 | impl NameClass { |
@@ -89,12 +94,14 @@ impl NameClass { | |||
89 | match self { | 94 | match self { |
90 | NameClass::Definition(it) => Some(it), | 95 | NameClass::Definition(it) => Some(it), |
91 | NameClass::ConstReference(_) => None, | 96 | NameClass::ConstReference(_) => None, |
97 | NameClass::FieldShorthand { local, field: _ } => Some(Definition::Local(local)), | ||
92 | } | 98 | } |
93 | } | 99 | } |
94 | 100 | ||
95 | pub fn definition(self) -> Definition { | 101 | pub fn definition(self) -> Definition { |
96 | match self { | 102 | match self { |
97 | NameClass::Definition(it) | NameClass::ConstReference(it) => it, | 103 | NameClass::Definition(it) | NameClass::ConstReference(it) => it, |
104 | NameClass::FieldShorthand { local: _, field } => field, | ||
98 | } | 105 | } |
99 | } | 106 | } |
100 | } | 107 | } |
@@ -102,18 +109,14 @@ impl NameClass { | |||
102 | pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> { | 109 | pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> { |
103 | let _p = profile("classify_name"); | 110 | let _p = profile("classify_name"); |
104 | 111 | ||
105 | if let Some(bind_pat) = name.syntax().parent().and_then(ast::BindPat::cast) { | 112 | let parent = name.syntax().parent()?; |
113 | |||
114 | if let Some(bind_pat) = ast::BindPat::cast(parent.clone()) { | ||
106 | if let Some(def) = sema.resolve_bind_pat_to_const(&bind_pat) { | 115 | if let Some(def) = sema.resolve_bind_pat_to_const(&bind_pat) { |
107 | return Some(NameClass::ConstReference(Definition::ModuleDef(def))); | 116 | return Some(NameClass::ConstReference(Definition::ModuleDef(def))); |
108 | } | 117 | } |
109 | } | 118 | } |
110 | 119 | ||
111 | classify_name_inner(sema, name).map(NameClass::Definition) | ||
112 | } | ||
113 | |||
114 | fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<Definition> { | ||
115 | let parent = name.syntax().parent()?; | ||
116 | |||
117 | match_ast! { | 120 | match_ast! { |
118 | match parent { | 121 | match parent { |
119 | ast::Alias(it) => { | 122 | ast::Alias(it) => { |
@@ -123,63 +126,73 @@ fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Opti | |||
123 | let name_ref = path_segment.name_ref()?; | 126 | let name_ref = path_segment.name_ref()?; |
124 | let name_ref_class = classify_name_ref(sema, &name_ref)?; | 127 | let name_ref_class = classify_name_ref(sema, &name_ref)?; |
125 | 128 | ||
126 | Some(name_ref_class.definition()) | 129 | Some(NameClass::Definition(name_ref_class.definition())) |
127 | }, | 130 | }, |
128 | ast::BindPat(it) => { | 131 | ast::BindPat(it) => { |
129 | let local = sema.to_def(&it)?; | 132 | let local = sema.to_def(&it)?; |
130 | Some(Definition::Local(local)) | 133 | |
134 | if let Some(record_field_pat) = it.syntax().parent().and_then(ast::RecordFieldPat::cast) { | ||
135 | if record_field_pat.name_ref().is_none() { | ||
136 | if let Some(field) = sema.resolve_record_field_pat(&record_field_pat) { | ||
137 | let field = Definition::Field(field); | ||
138 | return Some(NameClass::FieldShorthand { local, field }); | ||
139 | } | ||
140 | } | ||
141 | } | ||
142 | |||
143 | Some(NameClass::Definition(Definition::Local(local))) | ||
131 | }, | 144 | }, |
132 | ast::RecordFieldDef(it) => { | 145 | ast::RecordFieldDef(it) => { |
133 | let field: hir::Field = sema.to_def(&it)?; | 146 | let field: hir::Field = sema.to_def(&it)?; |
134 | Some(Definition::Field(field)) | 147 | Some(NameClass::Definition(Definition::Field(field))) |
135 | }, | 148 | }, |
136 | ast::Module(it) => { | 149 | ast::Module(it) => { |
137 | let def = sema.to_def(&it)?; | 150 | let def = sema.to_def(&it)?; |
138 | Some(Definition::ModuleDef(def.into())) | 151 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
139 | }, | 152 | }, |
140 | ast::StructDef(it) => { | 153 | ast::StructDef(it) => { |
141 | let def: hir::Struct = sema.to_def(&it)?; | 154 | let def: hir::Struct = sema.to_def(&it)?; |
142 | Some(Definition::ModuleDef(def.into())) | 155 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
143 | }, | 156 | }, |
144 | ast::UnionDef(it) => { | 157 | ast::UnionDef(it) => { |
145 | let def: hir::Union = sema.to_def(&it)?; | 158 | let def: hir::Union = sema.to_def(&it)?; |
146 | Some(Definition::ModuleDef(def.into())) | 159 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
147 | }, | 160 | }, |
148 | ast::EnumDef(it) => { | 161 | ast::EnumDef(it) => { |
149 | let def: hir::Enum = sema.to_def(&it)?; | 162 | let def: hir::Enum = sema.to_def(&it)?; |
150 | Some(Definition::ModuleDef(def.into())) | 163 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
151 | }, | 164 | }, |
152 | ast::TraitDef(it) => { | 165 | ast::TraitDef(it) => { |
153 | let def: hir::Trait = sema.to_def(&it)?; | 166 | let def: hir::Trait = sema.to_def(&it)?; |
154 | Some(Definition::ModuleDef(def.into())) | 167 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
155 | }, | 168 | }, |
156 | ast::StaticDef(it) => { | 169 | ast::StaticDef(it) => { |
157 | let def: hir::Static = sema.to_def(&it)?; | 170 | let def: hir::Static = sema.to_def(&it)?; |
158 | Some(Definition::ModuleDef(def.into())) | 171 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
159 | }, | 172 | }, |
160 | ast::EnumVariant(it) => { | 173 | ast::EnumVariant(it) => { |
161 | let def: hir::EnumVariant = sema.to_def(&it)?; | 174 | let def: hir::EnumVariant = sema.to_def(&it)?; |
162 | Some(Definition::ModuleDef(def.into())) | 175 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
163 | }, | 176 | }, |
164 | ast::FnDef(it) => { | 177 | ast::FnDef(it) => { |
165 | let def: hir::Function = sema.to_def(&it)?; | 178 | let def: hir::Function = sema.to_def(&it)?; |
166 | Some(Definition::ModuleDef(def.into())) | 179 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
167 | }, | 180 | }, |
168 | ast::ConstDef(it) => { | 181 | ast::ConstDef(it) => { |
169 | let def: hir::Const = sema.to_def(&it)?; | 182 | let def: hir::Const = sema.to_def(&it)?; |
170 | Some(Definition::ModuleDef(def.into())) | 183 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
171 | }, | 184 | }, |
172 | ast::TypeAliasDef(it) => { | 185 | ast::TypeAliasDef(it) => { |
173 | let def: hir::TypeAlias = sema.to_def(&it)?; | 186 | let def: hir::TypeAlias = sema.to_def(&it)?; |
174 | Some(Definition::ModuleDef(def.into())) | 187 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
175 | }, | 188 | }, |
176 | ast::MacroCall(it) => { | 189 | ast::MacroCall(it) => { |
177 | let def = sema.to_def(&it)?; | 190 | let def = sema.to_def(&it)?; |
178 | Some(Definition::Macro(def)) | 191 | Some(NameClass::Definition(Definition::Macro(def))) |
179 | }, | 192 | }, |
180 | ast::TypeParam(it) => { | 193 | ast::TypeParam(it) => { |
181 | let def = sema.to_def(&it)?; | 194 | let def = sema.to_def(&it)?; |
182 | Some(Definition::TypeParam(def)) | 195 | Some(NameClass::Definition(Definition::TypeParam(def))) |
183 | }, | 196 | }, |
184 | _ => None, | 197 | _ => None, |
185 | } | 198 | } |
@@ -242,8 +255,14 @@ pub fn classify_name_ref( | |||
242 | } | 255 | } |
243 | 256 | ||
244 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { | 257 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { |
245 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { | 258 | if let Some(path) = macro_call.path() { |
246 | return Some(NameRefClass::Definition(Definition::Macro(macro_def))); | 259 | if path.qualifier().is_none() { |
260 | // Only use this to resolve single-segment macro calls like `foo!()`. Multi-segment | ||
261 | // paths are handled below (allowing `log<|>::info!` to resolve to the log crate). | ||
262 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { | ||
263 | return Some(NameRefClass::Definition(Definition::Macro(macro_def))); | ||
264 | } | ||
265 | } | ||
247 | } | 266 | } |
248 | } | 267 | } |
249 | 268 | ||
diff --git a/crates/ra_ide_db/src/imports_locator.rs b/crates/ra_ide_db/src/imports_locator.rs index bf0d8db60..1fba71ff8 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,57 +11,55 @@ 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 fn find_imports<'a>( |
16 | sema: Semantics<'a, RootDatabase>, | 17 | sema: &Semantics<'a, RootDatabase>, |
17 | } | 18 | krate: Crate, |
18 | 19 | name_to_import: &str, | |
19 | impl<'a> ImportsLocator<'a> { | 20 | ) -> Vec<Either<ModuleDef, MacroDef>> { |
20 | pub fn new(db: &'a RootDatabase) -> Self { | 21 | let _p = profile("search_for_imports"); |
21 | Self { sema: Semantics::new(db) } | 22 | let db = sema.db; |
22 | } | ||
23 | 23 | ||
24 | pub fn find_imports(&mut self, name_to_import: &str) -> Vec<Either<ModuleDef, MacroDef>> { | 24 | // Query dependencies first. |
25 | let _p = profile("search_for_imports"); | 25 | let mut candidates: FxHashSet<_> = |
26 | let db = self.sema.db; | 26 | krate.query_external_importables(db, name_to_import).collect(); |
27 | 27 | ||
28 | let project_results = { | 28 | // Query the local crate using the symbol index. |
29 | let mut query = Query::new(name_to_import.to_string()); | 29 | let local_results = { |
30 | query.exact(); | 30 | let mut query = Query::new(name_to_import.to_string()); |
31 | query.limit(40); | 31 | query.exact(); |
32 | symbol_index::world_symbols(db, query) | 32 | query.limit(40); |
33 | }; | 33 | symbol_index::crate_symbols(db, krate.into(), query) |
34 | let lib_results = { | 34 | }; |
35 | let mut query = Query::new(name_to_import.to_string()); | ||
36 | query.libs(); | ||
37 | query.exact(); | ||
38 | query.limit(40); | ||
39 | symbol_index::world_symbols(db, query) | ||
40 | }; | ||
41 | 35 | ||
42 | project_results | 36 | candidates.extend( |
37 | local_results | ||
43 | .into_iter() | 38 | .into_iter() |
44 | .chain(lib_results.into_iter()) | 39 | .filter_map(|import_candidate| get_name_definition(sema, &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 { | 40 | .filter_map(|name_definition_to_import| match name_definition_to_import { |
47 | Definition::ModuleDef(module_def) => Some(Either::Left(module_def)), | 41 | Definition::ModuleDef(module_def) => Some(Either::Left(module_def)), |
48 | Definition::Macro(macro_def) => Some(Either::Right(macro_def)), | 42 | Definition::Macro(macro_def) => Some(Either::Right(macro_def)), |
49 | _ => None, | 43 | _ => None, |
50 | }) | 44 | }), |
51 | .collect() | 45 | ); |
52 | } | 46 | |
47 | candidates.into_iter().collect() | ||
48 | } | ||
53 | 49 | ||
54 | fn get_name_definition(&mut self, import_candidate: &FileSymbol) -> Option<Definition> { | 50 | fn get_name_definition<'a>( |
55 | let _p = profile("get_name_definition"); | 51 | sema: &Semantics<'a, RootDatabase>, |
56 | let file_id = import_candidate.file_id; | 52 | import_candidate: &FileSymbol, |
53 | ) -> Option<Definition> { | ||
54 | let _p = profile("get_name_definition"); | ||
55 | let file_id = import_candidate.file_id; | ||
57 | 56 | ||
58 | let candidate_node = import_candidate.ptr.to_node(self.sema.parse(file_id).syntax()); | 57 | let candidate_node = import_candidate.ptr.to_node(sema.parse(file_id).syntax()); |
59 | let candidate_name_node = if candidate_node.kind() != NAME { | 58 | let candidate_name_node = if candidate_node.kind() != NAME { |
60 | candidate_node.children().find(|it| it.kind() == NAME)? | 59 | candidate_node.children().find(|it| it.kind() == NAME)? |
61 | } else { | 60 | } else { |
62 | candidate_node | 61 | candidate_node |
63 | }; | 62 | }; |
64 | let name = ast::Name::cast(candidate_name_node)?; | 63 | let name = ast::Name::cast(candidate_name_node)?; |
65 | classify_name(&self.sema, &name)?.into_definition() | 64 | classify_name(sema, &name)?.into_definition() |
66 | } | ||
67 | } | 65 | } |
diff --git a/crates/ra_ide_db/src/lib.rs b/crates/ra_ide_db/src/lib.rs index 1b74e6558..6900cac73 100644 --- a/crates/ra_ide_db/src/lib.rs +++ b/crates/ra_ide_db/src/lib.rs | |||
@@ -11,15 +11,15 @@ pub mod imports_locator; | |||
11 | pub mod source_change; | 11 | pub mod source_change; |
12 | mod wasm_shims; | 12 | mod wasm_shims; |
13 | 13 | ||
14 | use std::sync::Arc; | 14 | use std::{fmt, sync::Arc}; |
15 | 15 | ||
16 | use hir::db::{AstDatabase, DefDatabase}; | 16 | use hir::db::{AstDatabase, DefDatabase, HirDatabase}; |
17 | use ra_db::{ | 17 | use ra_db::{ |
18 | salsa::{self, Database, Durability}, | 18 | salsa::{self, Durability}, |
19 | Canceled, CheckCanceled, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath, | 19 | Canceled, CheckCanceled, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, |
20 | SourceDatabase, SourceRootId, Upcast, | 20 | Upcast, |
21 | }; | 21 | }; |
22 | use rustc_hash::FxHashMap; | 22 | use rustc_hash::FxHashSet; |
23 | 23 | ||
24 | use crate::{line_index::LineIndex, symbol_index::SymbolsDatabase}; | 24 | use crate::{line_index::LineIndex, symbol_index::SymbolsDatabase}; |
25 | 25 | ||
@@ -33,14 +33,18 @@ use crate::{line_index::LineIndex, symbol_index::SymbolsDatabase}; | |||
33 | hir::db::DefDatabaseStorage, | 33 | hir::db::DefDatabaseStorage, |
34 | hir::db::HirDatabaseStorage | 34 | hir::db::HirDatabaseStorage |
35 | )] | 35 | )] |
36 | #[derive(Debug)] | ||
37 | pub struct RootDatabase { | 36 | pub struct RootDatabase { |
38 | runtime: salsa::Runtime<RootDatabase>, | 37 | storage: salsa::Storage<RootDatabase>, |
39 | pub(crate) debug_data: Arc<DebugData>, | ||
40 | pub last_gc: crate::wasm_shims::Instant, | 38 | pub last_gc: crate::wasm_shims::Instant, |
41 | pub last_gc_check: crate::wasm_shims::Instant, | 39 | pub last_gc_check: crate::wasm_shims::Instant, |
42 | } | 40 | } |
43 | 41 | ||
42 | impl fmt::Debug for RootDatabase { | ||
43 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
44 | f.debug_struct("RootDatabase").finish() | ||
45 | } | ||
46 | } | ||
47 | |||
44 | impl Upcast<dyn AstDatabase> for RootDatabase { | 48 | impl Upcast<dyn AstDatabase> for RootDatabase { |
45 | fn upcast(&self) -> &(dyn AstDatabase + 'static) { | 49 | fn upcast(&self) -> &(dyn AstDatabase + 'static) { |
46 | &*self | 50 | &*self |
@@ -53,41 +57,30 @@ impl Upcast<dyn DefDatabase> for RootDatabase { | |||
53 | } | 57 | } |
54 | } | 58 | } |
55 | 59 | ||
60 | impl Upcast<dyn HirDatabase> for RootDatabase { | ||
61 | fn upcast(&self) -> &(dyn HirDatabase + 'static) { | ||
62 | &*self | ||
63 | } | ||
64 | } | ||
65 | |||
56 | impl FileLoader for RootDatabase { | 66 | impl FileLoader for RootDatabase { |
57 | fn file_text(&self, file_id: FileId) -> Arc<String> { | 67 | fn file_text(&self, file_id: FileId) -> Arc<String> { |
58 | FileLoaderDelegate(self).file_text(file_id) | 68 | FileLoaderDelegate(self).file_text(file_id) |
59 | } | 69 | } |
60 | fn resolve_relative_path( | 70 | fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { |
61 | &self, | 71 | FileLoaderDelegate(self).resolve_path(anchor, path) |
62 | anchor: FileId, | ||
63 | relative_path: &RelativePath, | ||
64 | ) -> Option<FileId> { | ||
65 | FileLoaderDelegate(self).resolve_relative_path(anchor, relative_path) | ||
66 | } | 72 | } |
67 | fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { | 73 | fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> { |
68 | FileLoaderDelegate(self).relevant_crates(file_id) | 74 | FileLoaderDelegate(self).relevant_crates(file_id) |
69 | } | 75 | } |
70 | fn resolve_extern_path( | ||
71 | &self, | ||
72 | extern_id: ra_db::ExternSourceId, | ||
73 | relative_path: &RelativePath, | ||
74 | ) -> Option<FileId> { | ||
75 | FileLoaderDelegate(self).resolve_extern_path(extern_id, relative_path) | ||
76 | } | ||
77 | } | 76 | } |
78 | 77 | ||
79 | impl salsa::Database for RootDatabase { | 78 | impl salsa::Database for RootDatabase { |
80 | fn salsa_runtime(&self) -> &salsa::Runtime<RootDatabase> { | ||
81 | &self.runtime | ||
82 | } | ||
83 | fn salsa_runtime_mut(&mut self) -> &mut salsa::Runtime<Self> { | ||
84 | &mut self.runtime | ||
85 | } | ||
86 | fn on_propagated_panic(&self) -> ! { | 79 | fn on_propagated_panic(&self) -> ! { |
87 | Canceled::throw() | 80 | Canceled::throw() |
88 | } | 81 | } |
89 | fn salsa_event(&self, event: impl Fn() -> salsa::Event<RootDatabase>) { | 82 | fn salsa_event(&self, event: salsa::Event) { |
90 | match event().kind { | 83 | match event.kind { |
91 | salsa::EventKind::DidValidateMemoizedValue { .. } | 84 | salsa::EventKind::DidValidateMemoizedValue { .. } |
92 | | salsa::EventKind::WillExecute { .. } => { | 85 | | salsa::EventKind::WillExecute { .. } => { |
93 | self.check_canceled(); | 86 | self.check_canceled(); |
@@ -106,10 +99,9 @@ impl Default for RootDatabase { | |||
106 | impl RootDatabase { | 99 | impl RootDatabase { |
107 | pub fn new(lru_capacity: Option<usize>) -> RootDatabase { | 100 | pub fn new(lru_capacity: Option<usize>) -> RootDatabase { |
108 | let mut db = RootDatabase { | 101 | let mut db = RootDatabase { |
109 | runtime: salsa::Runtime::default(), | 102 | storage: salsa::Storage::default(), |
110 | last_gc: crate::wasm_shims::Instant::now(), | 103 | last_gc: crate::wasm_shims::Instant::now(), |
111 | last_gc_check: crate::wasm_shims::Instant::now(), | 104 | last_gc_check: crate::wasm_shims::Instant::now(), |
112 | debug_data: Default::default(), | ||
113 | }; | 105 | }; |
114 | db.set_crate_graph_with_durability(Default::default(), Durability::HIGH); | 106 | db.set_crate_graph_with_durability(Default::default(), Durability::HIGH); |
115 | db.set_local_roots_with_durability(Default::default(), Durability::HIGH); | 107 | db.set_local_roots_with_durability(Default::default(), Durability::HIGH); |
@@ -120,19 +112,18 @@ impl RootDatabase { | |||
120 | 112 | ||
121 | pub fn update_lru_capacity(&mut self, lru_capacity: Option<usize>) { | 113 | pub fn update_lru_capacity(&mut self, lru_capacity: Option<usize>) { |
122 | let lru_capacity = lru_capacity.unwrap_or(ra_db::DEFAULT_LRU_CAP); | 114 | let lru_capacity = lru_capacity.unwrap_or(ra_db::DEFAULT_LRU_CAP); |
123 | self.query_mut(ra_db::ParseQuery).set_lru_capacity(lru_capacity); | 115 | ra_db::ParseQuery.in_db_mut(self).set_lru_capacity(lru_capacity); |
124 | self.query_mut(hir::db::ParseMacroQuery).set_lru_capacity(lru_capacity); | 116 | hir::db::ParseMacroQuery.in_db_mut(self).set_lru_capacity(lru_capacity); |
125 | self.query_mut(hir::db::MacroExpandQuery).set_lru_capacity(lru_capacity); | 117 | hir::db::MacroExpandQuery.in_db_mut(self).set_lru_capacity(lru_capacity); |
126 | } | 118 | } |
127 | } | 119 | } |
128 | 120 | ||
129 | impl salsa::ParallelDatabase for RootDatabase { | 121 | impl salsa::ParallelDatabase for RootDatabase { |
130 | fn snapshot(&self) -> salsa::Snapshot<RootDatabase> { | 122 | fn snapshot(&self) -> salsa::Snapshot<RootDatabase> { |
131 | salsa::Snapshot::new(RootDatabase { | 123 | salsa::Snapshot::new(RootDatabase { |
132 | runtime: self.runtime.snapshot(self), | 124 | storage: self.storage.snapshot(), |
133 | last_gc: self.last_gc, | 125 | last_gc: self.last_gc, |
134 | last_gc_check: self.last_gc_check, | 126 | last_gc_check: self.last_gc_check, |
135 | debug_data: Arc::clone(&self.debug_data), | ||
136 | }) | 127 | }) |
137 | } | 128 | } |
138 | } | 129 | } |
@@ -142,18 +133,7 @@ pub trait LineIndexDatabase: ra_db::SourceDatabase + CheckCanceled { | |||
142 | fn line_index(&self, file_id: FileId) -> Arc<LineIndex>; | 133 | fn line_index(&self, file_id: FileId) -> Arc<LineIndex>; |
143 | } | 134 | } |
144 | 135 | ||
145 | fn line_index(db: &impl LineIndexDatabase, file_id: FileId) -> Arc<LineIndex> { | 136 | fn line_index(db: &dyn LineIndexDatabase, file_id: FileId) -> Arc<LineIndex> { |
146 | let text = db.file_text(file_id); | 137 | let text = db.file_text(file_id); |
147 | Arc::new(LineIndex::new(&*text)) | 138 | Arc::new(LineIndex::new(&*text)) |
148 | } | 139 | } |
149 | |||
150 | #[derive(Debug, Default, Clone)] | ||
151 | pub(crate) struct DebugData { | ||
152 | pub(crate) root_paths: FxHashMap<SourceRootId, String>, | ||
153 | } | ||
154 | |||
155 | impl DebugData { | ||
156 | pub(crate) fn merge(&mut self, other: DebugData) { | ||
157 | self.root_paths.extend(other.root_paths.into_iter()); | ||
158 | } | ||
159 | } | ||
diff --git a/crates/ra_ide_db/src/search.rs b/crates/ra_ide_db/src/search.rs index 335a1ad03..81553150b 100644 --- a/crates/ra_ide_db/src/search.rs +++ b/crates/ra_ide_db/src/search.rs | |||
@@ -157,14 +157,14 @@ impl Definition { | |||
157 | if let Some(Visibility::Public) = vis { | 157 | if let Some(Visibility::Public) = vis { |
158 | let source_root_id = db.file_source_root(file_id); | 158 | let source_root_id = db.file_source_root(file_id); |
159 | let source_root = db.source_root(source_root_id); | 159 | let source_root = db.source_root(source_root_id); |
160 | let mut res = source_root.walk().map(|id| (id, None)).collect::<FxHashMap<_, _>>(); | 160 | let mut res = source_root.iter().map(|id| (id, None)).collect::<FxHashMap<_, _>>(); |
161 | 161 | ||
162 | let krate = module.krate(); | 162 | let krate = module.krate(); |
163 | for rev_dep in krate.reverse_dependencies(db) { | 163 | for rev_dep in krate.reverse_dependencies(db) { |
164 | let root_file = rev_dep.root_file(db); | 164 | let root_file = rev_dep.root_file(db); |
165 | let source_root_id = db.file_source_root(root_file); | 165 | let source_root_id = db.file_source_root(root_file); |
166 | let source_root = db.source_root(source_root_id); | 166 | let source_root = db.source_root(source_root_id); |
167 | res.extend(source_root.walk().map(|id| (id, None))); | 167 | res.extend(source_root.iter().map(|id| (id, None))); |
168 | } | 168 | } |
169 | return SearchScope::new(res); | 169 | return SearchScope::new(res); |
170 | } | 170 | } |
@@ -180,20 +180,20 @@ impl Definition { | |||
180 | 180 | ||
181 | pub fn find_usages( | 181 | pub fn find_usages( |
182 | &self, | 182 | &self, |
183 | db: &RootDatabase, | 183 | sema: &Semantics<RootDatabase>, |
184 | search_scope: Option<SearchScope>, | 184 | search_scope: Option<SearchScope>, |
185 | ) -> Vec<Reference> { | 185 | ) -> Vec<Reference> { |
186 | let _p = profile("Definition::find_usages"); | 186 | let _p = profile("Definition::find_usages"); |
187 | 187 | ||
188 | let search_scope = { | 188 | let search_scope = { |
189 | let base = self.search_scope(db); | 189 | let base = self.search_scope(sema.db); |
190 | match search_scope { | 190 | match search_scope { |
191 | None => base, | 191 | None => base, |
192 | Some(scope) => base.intersection(&scope), | 192 | Some(scope) => base.intersection(&scope), |
193 | } | 193 | } |
194 | }; | 194 | }; |
195 | 195 | ||
196 | let name = match self.name(db) { | 196 | let name = match self.name(sema.db) { |
197 | None => return Vec::new(), | 197 | None => return Vec::new(), |
198 | Some(it) => it.to_string(), | 198 | Some(it) => it.to_string(), |
199 | }; | 199 | }; |
@@ -202,11 +202,10 @@ impl Definition { | |||
202 | let mut refs = vec![]; | 202 | let mut refs = vec![]; |
203 | 203 | ||
204 | for (file_id, search_range) in search_scope { | 204 | for (file_id, search_range) in search_scope { |
205 | let text = db.file_text(file_id); | 205 | let text = sema.db.file_text(file_id); |
206 | let search_range = | 206 | let search_range = |
207 | search_range.unwrap_or(TextRange::up_to(TextSize::of(text.as_str()))); | 207 | search_range.unwrap_or(TextRange::up_to(TextSize::of(text.as_str()))); |
208 | 208 | ||
209 | let sema = Semantics::new(db); | ||
210 | let tree = Lazy::new(|| sema.parse(file_id).syntax().clone()); | 209 | let tree = Lazy::new(|| sema.parse(file_id).syntax().clone()); |
211 | 210 | ||
212 | for (idx, _) in text.match_indices(pat) { | 211 | for (idx, _) in text.match_indices(pat) { |
@@ -222,9 +221,6 @@ impl Definition { | |||
222 | continue; | 221 | continue; |
223 | }; | 222 | }; |
224 | 223 | ||
225 | // FIXME: reuse sb | ||
226 | // See https://github.com/rust-lang/rust/pull/68198#issuecomment-574269098 | ||
227 | |||
228 | match classify_name_ref(&sema, &name_ref) { | 224 | match classify_name_ref(&sema, &name_ref) { |
229 | Some(NameRefClass::Definition(def)) if &def == self => { | 225 | Some(NameRefClass::Definition(def)) if &def == self => { |
230 | let kind = if is_record_lit_name_ref(&name_ref) | 226 | let kind = if is_record_lit_name_ref(&name_ref) |
diff --git a/crates/ra_ide_db/src/source_change.rs b/crates/ra_ide_db/src/source_change.rs index e713f4b7e..abb83f421 100644 --- a/crates/ra_ide_db/src/source_change.rs +++ b/crates/ra_ide_db/src/source_change.rs | |||
@@ -3,10 +3,10 @@ | |||
3 | //! | 3 | //! |
4 | //! It can be viewed as a dual for `AnalysisChange`. | 4 | //! It can be viewed as a dual for `AnalysisChange`. |
5 | 5 | ||
6 | use ra_db::{FileId, RelativePathBuf, SourceRootId}; | 6 | use ra_db::FileId; |
7 | use ra_text_edit::TextEdit; | 7 | use ra_text_edit::TextEdit; |
8 | 8 | ||
9 | #[derive(Debug, Clone)] | 9 | #[derive(Default, Debug, Clone)] |
10 | pub struct SourceChange { | 10 | pub struct SourceChange { |
11 | pub source_file_edits: Vec<SourceFileEdit>, | 11 | pub source_file_edits: Vec<SourceFileEdit>, |
12 | pub file_system_edits: Vec<FileSystemEdit>, | 12 | pub file_system_edits: Vec<FileSystemEdit>, |
@@ -22,17 +22,6 @@ impl SourceChange { | |||
22 | ) -> Self { | 22 | ) -> Self { |
23 | SourceChange { source_file_edits, file_system_edits, is_snippet: false } | 23 | SourceChange { source_file_edits, file_system_edits, is_snippet: false } |
24 | } | 24 | } |
25 | |||
26 | /// Creates a new SourceChange with the given label, | ||
27 | /// containing only the given `SourceFileEdits`. | ||
28 | pub fn source_file_edits(edits: Vec<SourceFileEdit>) -> Self { | ||
29 | SourceChange { source_file_edits: edits, file_system_edits: vec![], is_snippet: false } | ||
30 | } | ||
31 | /// Creates a new SourceChange with the given label | ||
32 | /// from the given `FileId` and `TextEdit` | ||
33 | pub fn source_file_edit_from(file_id: FileId, edit: TextEdit) -> Self { | ||
34 | SourceFileEdit { file_id, edit }.into() | ||
35 | } | ||
36 | } | 25 | } |
37 | 26 | ||
38 | #[derive(Debug, Clone)] | 27 | #[derive(Debug, Clone)] |
@@ -43,18 +32,20 @@ pub struct SourceFileEdit { | |||
43 | 32 | ||
44 | impl From<SourceFileEdit> for SourceChange { | 33 | impl From<SourceFileEdit> for SourceChange { |
45 | fn from(edit: SourceFileEdit) -> SourceChange { | 34 | fn from(edit: SourceFileEdit) -> SourceChange { |
46 | SourceChange { | 35 | vec![edit].into() |
47 | source_file_edits: vec![edit], | 36 | } |
48 | file_system_edits: Vec::new(), | 37 | } |
49 | is_snippet: false, | 38 | |
50 | } | 39 | impl From<Vec<SourceFileEdit>> for SourceChange { |
40 | fn from(source_file_edits: Vec<SourceFileEdit>) -> SourceChange { | ||
41 | SourceChange { source_file_edits, file_system_edits: Vec::new(), is_snippet: false } | ||
51 | } | 42 | } |
52 | } | 43 | } |
53 | 44 | ||
54 | #[derive(Debug, Clone)] | 45 | #[derive(Debug, Clone)] |
55 | pub enum FileSystemEdit { | 46 | pub enum FileSystemEdit { |
56 | CreateFile { source_root: SourceRootId, path: RelativePathBuf }, | 47 | CreateFile { anchor: FileId, dst: String }, |
57 | MoveFile { src: FileId, dst_source_root: SourceRootId, dst_path: RelativePathBuf }, | 48 | MoveFile { src: FileId, anchor: FileId, dst: String }, |
58 | } | 49 | } |
59 | 50 | ||
60 | impl From<FileSystemEdit> for SourceChange { | 51 | impl From<FileSystemEdit> for SourceChange { |
diff --git a/crates/ra_ide_db/src/symbol_index.rs b/crates/ra_ide_db/src/symbol_index.rs index acc31fe3b..131e2a128 100644 --- a/crates/ra_ide_db/src/symbol_index.rs +++ b/crates/ra_ide_db/src/symbol_index.rs | |||
@@ -29,18 +29,20 @@ 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 | }; |
37 | use ra_prof::profile; | ||
36 | use ra_syntax::{ | 38 | use ra_syntax::{ |
37 | ast::{self, NameOwner}, | 39 | ast::{self, NameOwner}, |
38 | match_ast, AstNode, Parse, SmolStr, SourceFile, | 40 | match_ast, AstNode, Parse, SmolStr, SourceFile, |
39 | SyntaxKind::{self, *}, | 41 | SyntaxKind::{self, *}, |
40 | SyntaxNode, SyntaxNodePtr, TextRange, WalkEvent, | 42 | SyntaxNode, SyntaxNodePtr, TextRange, WalkEvent, |
41 | }; | 43 | }; |
42 | #[cfg(not(feature = "wasm"))] | ||
43 | use rayon::prelude::*; | 44 | use rayon::prelude::*; |
45 | use rustc_hash::{FxHashMap, FxHashSet}; | ||
44 | 46 | ||
45 | use crate::RootDatabase; | 47 | use crate::RootDatabase; |
46 | 48 | ||
@@ -85,21 +87,41 @@ impl Query { | |||
85 | } | 87 | } |
86 | 88 | ||
87 | #[salsa::query_group(SymbolsDatabaseStorage)] | 89 | #[salsa::query_group(SymbolsDatabaseStorage)] |
88 | pub trait SymbolsDatabase: hir::db::HirDatabase { | 90 | pub trait SymbolsDatabase: hir::db::HirDatabase + SourceDatabaseExt { |
89 | fn file_symbols(&self, file_id: FileId) -> Arc<SymbolIndex>; | 91 | fn file_symbols(&self, file_id: FileId) -> Arc<SymbolIndex>; |
90 | #[salsa::input] | 92 | fn library_symbols(&self) -> Arc<FxHashMap<SourceRootId, SymbolIndex>>; |
91 | fn library_symbols(&self, id: SourceRootId) -> Arc<SymbolIndex>; | ||
92 | /// The set of "local" (that is, from the current workspace) roots. | 93 | /// The set of "local" (that is, from the current workspace) roots. |
93 | /// Files in local roots are assumed to change frequently. | 94 | /// Files in local roots are assumed to change frequently. |
94 | #[salsa::input] | 95 | #[salsa::input] |
95 | fn local_roots(&self) -> Arc<Vec<SourceRootId>>; | 96 | fn local_roots(&self) -> Arc<FxHashSet<SourceRootId>>; |
96 | /// The set of roots for crates.io libraries. | 97 | /// The set of roots for crates.io libraries. |
97 | /// Files in libraries are assumed to never change. | 98 | /// Files in libraries are assumed to never change. |
98 | #[salsa::input] | 99 | #[salsa::input] |
99 | fn library_roots(&self) -> Arc<Vec<SourceRootId>>; | 100 | fn library_roots(&self) -> Arc<FxHashSet<SourceRootId>>; |
101 | } | ||
102 | |||
103 | fn library_symbols(db: &dyn SymbolsDatabase) -> Arc<FxHashMap<SourceRootId, SymbolIndex>> { | ||
104 | let _p = profile("library_symbols"); | ||
105 | |||
106 | let roots = db.library_roots(); | ||
107 | let res = roots | ||
108 | .iter() | ||
109 | .map(|&root_id| { | ||
110 | let root = db.source_root(root_id); | ||
111 | let files = root | ||
112 | .iter() | ||
113 | .map(|it| (it, SourceDatabaseExt::file_text(db, it))) | ||
114 | .collect::<Vec<_>>(); | ||
115 | let symbol_index = SymbolIndex::for_files( | ||
116 | files.into_par_iter().map(|(file, text)| (file, SourceFile::parse(&text))), | ||
117 | ); | ||
118 | (root_id, symbol_index) | ||
119 | }) | ||
120 | .collect(); | ||
121 | Arc::new(res) | ||
100 | } | 122 | } |
101 | 123 | ||
102 | fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> { | 124 | fn file_symbols(db: &dyn SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> { |
103 | db.check_canceled(); | 125 | db.check_canceled(); |
104 | let parse = db.parse(file_id); | 126 | let parse = db.parse(file_id); |
105 | 127 | ||
@@ -110,6 +132,14 @@ fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> | |||
110 | Arc::new(SymbolIndex::new(symbols)) | 132 | Arc::new(SymbolIndex::new(symbols)) |
111 | } | 133 | } |
112 | 134 | ||
135 | /// Need to wrap Snapshot to provide `Clone` impl for `map_with` | ||
136 | struct Snap<DB>(DB); | ||
137 | impl<DB: ParallelDatabase> Clone for Snap<salsa::Snapshot<DB>> { | ||
138 | fn clone(&self) -> Snap<salsa::Snapshot<DB>> { | ||
139 | Snap(self.0.snapshot()) | ||
140 | } | ||
141 | } | ||
142 | |||
113 | // Feature: Workspace Symbol | 143 | // Feature: Workspace Symbol |
114 | // | 144 | // |
115 | // Uses fuzzy-search to find types, modules and functions by name across your | 145 | // Uses fuzzy-search to find types, modules and functions by name across your |
@@ -132,44 +162,51 @@ fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> | |||
132 | // | VS Code | kbd:[Ctrl+T] | 162 | // | VS Code | kbd:[Ctrl+T] |
133 | // |=== | 163 | // |=== |
134 | pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> { | 164 | pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> { |
135 | /// Need to wrap Snapshot to provide `Clone` impl for `map_with` | 165 | 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 | 166 | ||
143 | let buf: Vec<Arc<SymbolIndex>> = if query.libs { | 167 | let tmp1; |
144 | let snap = Snap(db.snapshot()); | 168 | let tmp2; |
145 | #[cfg(not(feature = "wasm"))] | 169 | let buf: Vec<&SymbolIndex> = if query.libs { |
146 | let buf = db | 170 | tmp1 = db.library_symbols(); |
147 | .library_roots() | 171 | tmp1.values().collect() |
148 | .par_iter() | ||
149 | .map_with(snap, |db, &lib_id| db.0.library_symbols(lib_id)) | ||
150 | .collect(); | ||
151 | |||
152 | #[cfg(feature = "wasm")] | ||
153 | let buf = db.library_roots().iter().map(|&lib_id| snap.0.library_symbols(lib_id)).collect(); | ||
154 | |||
155 | buf | ||
156 | } else { | 172 | } else { |
157 | let mut files = Vec::new(); | 173 | let mut files = Vec::new(); |
158 | for &root in db.local_roots().iter() { | 174 | for &root in db.local_roots().iter() { |
159 | let sr = db.source_root(root); | 175 | let sr = db.source_root(root); |
160 | files.extend(sr.walk()) | 176 | files.extend(sr.iter()) |
161 | } | 177 | } |
162 | 178 | ||
163 | let snap = Snap(db.snapshot()); | 179 | let snap = Snap(db.snapshot()); |
164 | #[cfg(not(feature = "wasm"))] | 180 | tmp2 = files |
165 | let buf = | 181 | .par_iter() |
166 | files.par_iter().map_with(snap, |db, &file_id| db.0.file_symbols(file_id)).collect(); | 182 | .map_with(snap, |db, &file_id| db.0.file_symbols(file_id)) |
183 | .collect::<Vec<_>>(); | ||
184 | tmp2.iter().map(|it| &**it).collect() | ||
185 | }; | ||
186 | query.search(&buf) | ||
187 | } | ||
167 | 188 | ||
168 | #[cfg(feature = "wasm")] | 189 | pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<FileSymbol> { |
169 | let buf = files.iter().map(|&file_id| snap.0.file_symbols(file_id)).collect(); | 190 | // FIXME(#4842): This now depends on CrateDefMap, why not build the entire symbol index from |
191 | // that instead? | ||
192 | |||
193 | let def_map = db.crate_def_map(krate); | ||
194 | let mut files = Vec::new(); | ||
195 | let mut modules = vec![def_map.root]; | ||
196 | while let Some(module) = modules.pop() { | ||
197 | let data = &def_map[module]; | ||
198 | files.extend(data.origin.file_id()); | ||
199 | modules.extend(data.children.values()); | ||
200 | } | ||
201 | |||
202 | let snap = Snap(db.snapshot()); | ||
203 | |||
204 | let buf = files | ||
205 | .par_iter() | ||
206 | .map_with(snap, |db, &file_id| db.0.file_symbols(file_id)) | ||
207 | .collect::<Vec<_>>(); | ||
208 | let buf = buf.iter().map(|it| &**it).collect::<Vec<_>>(); | ||
170 | 209 | ||
171 | buf | ||
172 | }; | ||
173 | query.search(&buf) | 210 | query.search(&buf) |
174 | } | 211 | } |
175 | 212 | ||
@@ -215,12 +252,8 @@ impl SymbolIndex { | |||
215 | lhs_chars.cmp(rhs_chars) | 252 | lhs_chars.cmp(rhs_chars) |
216 | } | 253 | } |
217 | 254 | ||
218 | #[cfg(not(feature = "wasm"))] | ||
219 | symbols.par_sort_by(cmp); | 255 | symbols.par_sort_by(cmp); |
220 | 256 | ||
221 | #[cfg(feature = "wasm")] | ||
222 | symbols.sort_by(cmp); | ||
223 | |||
224 | let mut builder = fst::MapBuilder::memory(); | 257 | let mut builder = fst::MapBuilder::memory(); |
225 | 258 | ||
226 | let mut last_batch_start = 0; | 259 | let mut last_batch_start = 0; |
@@ -254,7 +287,6 @@ impl SymbolIndex { | |||
254 | self.map.as_fst().size() + self.symbols.len() * mem::size_of::<FileSymbol>() | 287 | self.map.as_fst().size() + self.symbols.len() * mem::size_of::<FileSymbol>() |
255 | } | 288 | } |
256 | 289 | ||
257 | #[cfg(not(feature = "wasm"))] | ||
258 | pub(crate) fn for_files( | 290 | pub(crate) fn for_files( |
259 | files: impl ParallelIterator<Item = (FileId, Parse<ast::SourceFile>)>, | 291 | files: impl ParallelIterator<Item = (FileId, Parse<ast::SourceFile>)>, |
260 | ) -> SymbolIndex { | 292 | ) -> SymbolIndex { |
@@ -264,16 +296,6 @@ impl SymbolIndex { | |||
264 | SymbolIndex::new(symbols) | 296 | SymbolIndex::new(symbols) |
265 | } | 297 | } |
266 | 298 | ||
267 | #[cfg(feature = "wasm")] | ||
268 | pub(crate) fn for_files( | ||
269 | files: impl Iterator<Item = (FileId, Parse<ast::SourceFile>)>, | ||
270 | ) -> SymbolIndex { | ||
271 | let symbols = files | ||
272 | .flat_map(|(file_id, file)| source_file_to_file_symbols(&file.tree(), file_id)) | ||
273 | .collect::<Vec<_>>(); | ||
274 | SymbolIndex::new(symbols) | ||
275 | } | ||
276 | |||
277 | fn range_to_map_value(start: usize, end: usize) -> u64 { | 299 | fn range_to_map_value(start: usize, end: usize) -> u64 { |
278 | debug_assert![start <= (std::u32::MAX as usize)]; | 300 | debug_assert![start <= (std::u32::MAX as usize)]; |
279 | debug_assert![end <= (std::u32::MAX as usize)]; | 301 | debug_assert![end <= (std::u32::MAX as usize)]; |
@@ -289,7 +311,7 @@ impl SymbolIndex { | |||
289 | } | 311 | } |
290 | 312 | ||
291 | impl Query { | 313 | impl Query { |
292 | pub(crate) fn search(self, indices: &[Arc<SymbolIndex>]) -> Vec<FileSymbol> { | 314 | pub(crate) fn search(self, indices: &[&SymbolIndex]) -> Vec<FileSymbol> { |
293 | let mut op = fst::map::OpBuilder::new(); | 315 | let mut op = fst::map::OpBuilder::new(); |
294 | for file_symbols in indices.iter() { | 316 | for file_symbols in indices.iter() { |
295 | let automaton = fst::automaton::Subsequence::new(&self.lowercased); | 317 | let automaton = fst::automaton::Subsequence::new(&self.lowercased); |
@@ -298,9 +320,6 @@ impl Query { | |||
298 | let mut stream = op.union(); | 320 | let mut stream = op.union(); |
299 | let mut res = Vec::new(); | 321 | let mut res = Vec::new(); |
300 | while let Some((_, indexed_values)) = stream.next() { | 322 | while let Some((_, indexed_values)) = stream.next() { |
301 | if res.len() >= self.limit { | ||
302 | break; | ||
303 | } | ||
304 | for indexed_value in indexed_values { | 323 | for indexed_value in indexed_values { |
305 | let symbol_index = &indices[indexed_value.index]; | 324 | let symbol_index = &indices[indexed_value.index]; |
306 | let (start, end) = SymbolIndex::map_value_to_range(indexed_value.value); | 325 | let (start, end) = SymbolIndex::map_value_to_range(indexed_value.value); |
@@ -312,7 +331,11 @@ impl Query { | |||
312 | if self.exact && symbol.name != self.query { | 331 | if self.exact && symbol.name != self.query { |
313 | continue; | 332 | continue; |
314 | } | 333 | } |
334 | |||
315 | res.push(symbol.clone()); | 335 | res.push(symbol.clone()); |
336 | if res.len() >= self.limit { | ||
337 | return res; | ||
338 | } | ||
316 | } | 339 | } |
317 | } | 340 | } |
318 | } | 341 | } |
@@ -321,10 +344,7 @@ impl Query { | |||
321 | } | 344 | } |
322 | 345 | ||
323 | fn is_type(kind: SyntaxKind) -> bool { | 346 | fn is_type(kind: SyntaxKind) -> bool { |
324 | match kind { | 347 | matches!(kind, STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF) |
325 | STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => true, | ||
326 | _ => false, | ||
327 | } | ||
328 | } | 348 | } |
329 | 349 | ||
330 | /// The actual data that is stored in the index. It should be as compact as | 350 | /// The actual data that is stored in the index. It should be as compact as |