aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_db
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_db')
-rw-r--r--crates/ra_ide_db/src/change.rs79
-rw-r--r--crates/ra_ide_db/src/symbol_index.rs90
2 files changed, 47 insertions, 122 deletions
diff --git a/crates/ra_ide_db/src/change.rs b/crates/ra_ide_db/src/change.rs
index 2fc796a85..78ee6a515 100644
--- a/crates/ra_ide_db/src/change.rs
+++ b/crates/ra_ide_db/src/change.rs
@@ -9,22 +9,15 @@ use ra_db::{
9 SourceRootId, 9 SourceRootId,
10}; 10};
11use ra_prof::{memory_usage, profile, Bytes}; 11use ra_prof::{memory_usage, profile, Bytes};
12use ra_syntax::SourceFile;
13#[cfg(not(feature = "wasm"))]
14use rayon::prelude::*;
15use rustc_hash::FxHashMap; 12use rustc_hash::FxHashMap;
16 13
17use crate::{ 14use crate::{symbol_index::SymbolsDatabase, RootDatabase};
18 symbol_index::{SymbolIndex, SymbolsDatabase},
19 RootDatabase,
20};
21 15
22#[derive(Default)] 16#[derive(Default)]
23pub struct AnalysisChange { 17pub struct AnalysisChange {
24 new_roots: Vec<(SourceRootId, bool)>, 18 new_roots: Vec<(SourceRootId, bool)>,
25 roots_changed: FxHashMap<SourceRootId, RootChange>, 19 roots_changed: FxHashMap<SourceRootId, RootChange>,
26 files_changed: Vec<(FileId, Arc<String>)>, 20 files_changed: Vec<(FileId, Arc<String>)>,
27 libraries_added: Vec<LibraryData>,
28 crate_graph: Option<CrateGraph>, 21 crate_graph: Option<CrateGraph>,
29} 22}
30 23
@@ -40,9 +33,6 @@ impl fmt::Debug for AnalysisChange {
40 if !self.files_changed.is_empty() { 33 if !self.files_changed.is_empty() {
41 d.field("files_changed", &self.files_changed.len()); 34 d.field("files_changed", &self.files_changed.len());
42 } 35 }
43 if !self.libraries_added.is_empty() {
44 d.field("libraries_added", &self.libraries_added.len());
45 }
46 if self.crate_graph.is_some() { 36 if self.crate_graph.is_some() {
47 d.field("crate_graph", &self.crate_graph); 37 d.field("crate_graph", &self.crate_graph);
48 } 38 }
@@ -79,10 +69,6 @@ impl AnalysisChange {
79 self.roots_changed.entry(root_id).or_default().removed.push(file); 69 self.roots_changed.entry(root_id).or_default().removed.push(file);
80 } 70 }
81 71
82 pub fn add_library(&mut self, data: LibraryData) {
83 self.libraries_added.push(data)
84 }
85
86 pub fn set_crate_graph(&mut self, graph: CrateGraph) { 72 pub fn set_crate_graph(&mut self, graph: CrateGraph) {
87 self.crate_graph = Some(graph); 73 self.crate_graph = Some(graph);
88 } 74 }
@@ -116,47 +102,6 @@ impl fmt::Debug for RootChange {
116 } 102 }
117} 103}
118 104
119pub struct LibraryData {
120 root_id: SourceRootId,
121 root_change: RootChange,
122 symbol_index: SymbolIndex,
123}
124
125impl fmt::Debug for LibraryData {
126 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
127 f.debug_struct("LibraryData")
128 .field("root_id", &self.root_id)
129 .field("root_change", &self.root_change)
130 .field("n_symbols", &self.symbol_index.len())
131 .finish()
132 }
133}
134
135impl LibraryData {
136 pub fn prepare(
137 root_id: SourceRootId,
138 files: Vec<(FileId, RelativePathBuf, Arc<String>)>,
139 ) -> LibraryData {
140 let _p = profile("LibraryData::prepare");
141
142 #[cfg(not(feature = "wasm"))]
143 let iter = files.par_iter();
144 #[cfg(feature = "wasm")]
145 let iter = files.iter();
146
147 let symbol_index = SymbolIndex::for_files(iter.map(|(file_id, _, text)| {
148 let parse = SourceFile::parse(text);
149 (*file_id, parse)
150 }));
151 let mut root_change = RootChange::default();
152 root_change.added = files
153 .into_iter()
154 .map(|(file_id, path, text)| AddFile { file_id, path, text })
155 .collect();
156 LibraryData { root_id, root_change, symbol_index }
157 }
158}
159
160const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100); 105const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100);
161 106
162impl RootDatabase { 107impl RootDatabase {
@@ -171,6 +116,7 @@ impl RootDatabase {
171 log::info!("apply_change {:?}", change); 116 log::info!("apply_change {:?}", change);
172 if !change.new_roots.is_empty() { 117 if !change.new_roots.is_empty() {
173 let mut local_roots = Vec::clone(&self.local_roots()); 118 let mut local_roots = Vec::clone(&self.local_roots());
119 let mut libraries = Vec::clone(&self.library_roots());
174 for (root_id, is_local) in change.new_roots { 120 for (root_id, is_local) in change.new_roots {
175 let root = 121 let root =
176 if is_local { SourceRoot::new_local() } else { SourceRoot::new_library() }; 122 if is_local { SourceRoot::new_local() } else { SourceRoot::new_library() };
@@ -178,9 +124,12 @@ impl RootDatabase {
178 self.set_source_root_with_durability(root_id, Arc::new(root), durability); 124 self.set_source_root_with_durability(root_id, Arc::new(root), durability);
179 if is_local { 125 if is_local {
180 local_roots.push(root_id); 126 local_roots.push(root_id);
127 } else {
128 libraries.push(root_id)
181 } 129 }
182 } 130 }
183 self.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH); 131 self.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
132 self.set_library_roots_with_durability(Arc::new(libraries), Durability::HIGH);
184 } 133 }
185 134
186 for (root_id, root_change) in change.roots_changed { 135 for (root_id, root_change) in change.roots_changed {
@@ -192,24 +141,6 @@ impl RootDatabase {
192 let durability = durability(&source_root); 141 let durability = durability(&source_root);
193 self.set_file_text_with_durability(file_id, text, durability) 142 self.set_file_text_with_durability(file_id, text, durability)
194 } 143 }
195 if !change.libraries_added.is_empty() {
196 let mut libraries = Vec::clone(&self.library_roots());
197 for library in change.libraries_added {
198 libraries.push(library.root_id);
199 self.set_source_root_with_durability(
200 library.root_id,
201 Arc::new(SourceRoot::new_library()),
202 Durability::HIGH,
203 );
204 self.set_library_symbols_with_durability(
205 library.root_id,
206 Arc::new(library.symbol_index),
207 Durability::HIGH,
208 );
209 self.apply_root_change(library.root_id, library.root_change);
210 }
211 self.set_library_roots_with_durability(Arc::new(libraries), Durability::HIGH);
212 }
213 if let Some(crate_graph) = change.crate_graph { 144 if let Some(crate_graph) = change.crate_graph {
214 self.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH) 145 self.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH)
215 } 146 }
diff --git a/crates/ra_ide_db/src/symbol_index.rs b/crates/ra_ide_db/src/symbol_index.rs
index aab918973..25c99813f 100644
--- a/crates/ra_ide_db/src/symbol_index.rs
+++ b/crates/ra_ide_db/src/symbol_index.rs
@@ -34,14 +34,15 @@ use ra_db::{
34 salsa::{self, ParallelDatabase}, 34 salsa::{self, ParallelDatabase},
35 CrateId, FileId, SourceDatabaseExt, SourceRootId, 35 CrateId, FileId, SourceDatabaseExt, SourceRootId,
36}; 36};
37use ra_prof::profile;
37use ra_syntax::{ 38use ra_syntax::{
38 ast::{self, NameOwner}, 39 ast::{self, NameOwner},
39 match_ast, AstNode, Parse, SmolStr, SourceFile, 40 match_ast, AstNode, Parse, SmolStr, SourceFile,
40 SyntaxKind::{self, *}, 41 SyntaxKind::{self, *},
41 SyntaxNode, SyntaxNodePtr, TextRange, WalkEvent, 42 SyntaxNode, SyntaxNodePtr, TextRange, WalkEvent,
42}; 43};
43#[cfg(not(feature = "wasm"))]
44use rayon::prelude::*; 44use rayon::prelude::*;
45use rustc_hash::FxHashMap;
45 46
46use crate::RootDatabase; 47use crate::RootDatabase;
47 48
@@ -86,10 +87,9 @@ impl Query {
86} 87}
87 88
88#[salsa::query_group(SymbolsDatabaseStorage)] 89#[salsa::query_group(SymbolsDatabaseStorage)]
89pub trait SymbolsDatabase: hir::db::HirDatabase { 90pub trait SymbolsDatabase: hir::db::HirDatabase + SourceDatabaseExt + ParallelDatabase {
90 fn file_symbols(&self, file_id: FileId) -> Arc<SymbolIndex>; 91 fn file_symbols(&self, file_id: FileId) -> Arc<SymbolIndex>;
91 #[salsa::input] 92 fn library_symbols(&self) -> Arc<FxHashMap<SourceRootId, SymbolIndex>>;
92 fn library_symbols(&self, id: SourceRootId) -> Arc<SymbolIndex>;
93 /// The set of "local" (that is, from the current workspace) roots. 93 /// The set of "local" (that is, from the current workspace) roots.
94 /// Files in local roots are assumed to change frequently. 94 /// Files in local roots are assumed to change frequently.
95 #[salsa::input] 95 #[salsa::input]
@@ -100,6 +100,29 @@ pub trait SymbolsDatabase: hir::db::HirDatabase {
100 fn library_roots(&self) -> Arc<Vec<SourceRootId>>; 100 fn library_roots(&self) -> Arc<Vec<SourceRootId>>;
101} 101}
102 102
103fn library_symbols(
104 db: &(impl SymbolsDatabase + ParallelDatabase),
105) -> Arc<FxHashMap<SourceRootId, SymbolIndex>> {
106 let _p = profile("library_symbols");
107
108 let roots = db.library_roots();
109 let res = roots
110 .iter()
111 .map(|&root_id| {
112 let root = db.source_root(root_id);
113 let files = root
114 .walk()
115 .map(|it| (it, SourceDatabaseExt::file_text(db, it)))
116 .collect::<Vec<_>>();
117 let symbol_index = SymbolIndex::for_files(
118 files.into_par_iter().map(|(file, text)| (file, SourceFile::parse(&text))),
119 );
120 (root_id, symbol_index)
121 })
122 .collect();
123 Arc::new(res)
124}
125
103fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> { 126fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> {
104 db.check_canceled(); 127 db.check_canceled();
105 let parse = db.parse(file_id); 128 let parse = db.parse(file_id);
@@ -112,9 +135,9 @@ fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex>
112} 135}
113 136
114/// Need to wrap Snapshot to provide `Clone` impl for `map_with` 137/// Need to wrap Snapshot to provide `Clone` impl for `map_with`
115struct Snap(salsa::Snapshot<RootDatabase>); 138struct Snap<DB>(DB);
116impl Clone for Snap { 139impl<DB: ParallelDatabase> Clone for Snap<salsa::Snapshot<DB>> {
117 fn clone(&self) -> Snap { 140 fn clone(&self) -> Snap<salsa::Snapshot<DB>> {
118 Snap(self.0.snapshot()) 141 Snap(self.0.snapshot())
119 } 142 }
120} 143}
@@ -143,19 +166,11 @@ impl Clone for Snap {
143pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> { 166pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
144 let _p = ra_prof::profile("world_symbols").detail(|| query.query.clone()); 167 let _p = ra_prof::profile("world_symbols").detail(|| query.query.clone());
145 168
146 let buf: Vec<Arc<SymbolIndex>> = if query.libs { 169 let tmp1;
147 let snap = Snap(db.snapshot()); 170 let tmp2;
148 #[cfg(not(feature = "wasm"))] 171 let buf: Vec<&SymbolIndex> = if query.libs {
149 let buf = db 172 tmp1 = db.library_symbols();
150 .library_roots() 173 tmp1.values().collect()
151 .par_iter()
152 .map_with(snap, |db, &lib_id| db.0.library_symbols(lib_id))
153 .collect();
154
155 #[cfg(feature = "wasm")]
156 let buf = db.library_roots().iter().map(|&lib_id| snap.0.library_symbols(lib_id)).collect();
157
158 buf
159 } else { 174 } else {
160 let mut files = Vec::new(); 175 let mut files = Vec::new();
161 for &root in db.local_roots().iter() { 176 for &root in db.local_roots().iter() {
@@ -164,14 +179,11 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
164 } 179 }
165 180
166 let snap = Snap(db.snapshot()); 181 let snap = Snap(db.snapshot());
167 #[cfg(not(feature = "wasm"))] 182 tmp2 = files
168 let buf = 183 .par_iter()
169 files.par_iter().map_with(snap, |db, &file_id| db.0.file_symbols(file_id)).collect(); 184 .map_with(snap, |db, &file_id| db.0.file_symbols(file_id))
170 185 .collect::<Vec<_>>();
171 #[cfg(feature = "wasm")] 186 tmp2.iter().map(|it| &**it).collect()
172 let buf = files.iter().map(|&file_id| snap.0.file_symbols(file_id)).collect();
173
174 buf
175 }; 187 };
176 query.search(&buf) 188 query.search(&buf)
177} 189}
@@ -191,14 +203,11 @@ pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<Fil
191 203
192 let snap = Snap(db.snapshot()); 204 let snap = Snap(db.snapshot());
193 205
194 #[cfg(not(feature = "wasm"))]
195 let buf = files 206 let buf = files
196 .par_iter() 207 .par_iter()
197 .map_with(snap, |db, &file_id| db.0.file_symbols(file_id)) 208 .map_with(snap, |db, &file_id| db.0.file_symbols(file_id))
198 .collect::<Vec<_>>(); 209 .collect::<Vec<_>>();
199 210 let buf = buf.iter().map(|it| &**it).collect::<Vec<_>>();
200 #[cfg(feature = "wasm")]
201 let buf = files.iter().map(|&file_id| snap.0.file_symbols(file_id)).collect::<Vec<_>>();
202 211
203 query.search(&buf) 212 query.search(&buf)
204} 213}
@@ -245,12 +254,8 @@ impl SymbolIndex {
245 lhs_chars.cmp(rhs_chars) 254 lhs_chars.cmp(rhs_chars)
246 } 255 }
247 256
248 #[cfg(not(feature = "wasm"))]
249 symbols.par_sort_by(cmp); 257 symbols.par_sort_by(cmp);
250 258
251 #[cfg(feature = "wasm")]
252 symbols.sort_by(cmp);
253
254 let mut builder = fst::MapBuilder::memory(); 259 let mut builder = fst::MapBuilder::memory();
255 260
256 let mut last_batch_start = 0; 261 let mut last_batch_start = 0;
@@ -284,7 +289,6 @@ impl SymbolIndex {
284 self.map.as_fst().size() + self.symbols.len() * mem::size_of::<FileSymbol>() 289 self.map.as_fst().size() + self.symbols.len() * mem::size_of::<FileSymbol>()
285 } 290 }
286 291
287 #[cfg(not(feature = "wasm"))]
288 pub(crate) fn for_files( 292 pub(crate) fn for_files(
289 files: impl ParallelIterator<Item = (FileId, Parse<ast::SourceFile>)>, 293 files: impl ParallelIterator<Item = (FileId, Parse<ast::SourceFile>)>,
290 ) -> SymbolIndex { 294 ) -> SymbolIndex {
@@ -294,16 +298,6 @@ impl SymbolIndex {
294 SymbolIndex::new(symbols) 298 SymbolIndex::new(symbols)
295 } 299 }
296 300
297 #[cfg(feature = "wasm")]
298 pub(crate) fn for_files(
299 files: impl Iterator<Item = (FileId, Parse<ast::SourceFile>)>,
300 ) -> SymbolIndex {
301 let symbols = files
302 .flat_map(|(file_id, file)| source_file_to_file_symbols(&file.tree(), file_id))
303 .collect::<Vec<_>>();
304 SymbolIndex::new(symbols)
305 }
306
307 fn range_to_map_value(start: usize, end: usize) -> u64 { 301 fn range_to_map_value(start: usize, end: usize) -> u64 {
308 debug_assert![start <= (std::u32::MAX as usize)]; 302 debug_assert![start <= (std::u32::MAX as usize)];
309 debug_assert![end <= (std::u32::MAX as usize)]; 303 debug_assert![end <= (std::u32::MAX as usize)];
@@ -319,7 +313,7 @@ impl SymbolIndex {
319} 313}
320 314
321impl Query { 315impl Query {
322 pub(crate) fn search(self, indices: &[Arc<SymbolIndex>]) -> Vec<FileSymbol> { 316 pub(crate) fn search(self, indices: &[&SymbolIndex]) -> Vec<FileSymbol> {
323 let mut op = fst::map::OpBuilder::new(); 317 let mut op = fst::map::OpBuilder::new();
324 for file_symbols in indices.iter() { 318 for file_symbols in indices.iter() {
325 let automaton = fst::automaton::Subsequence::new(&self.lowercased); 319 let automaton = fst::automaton::Subsequence::new(&self.lowercased);