aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/imp.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-10-25 08:57:55 +0100
committerAleksey Kladov <[email protected]>2018-10-25 14:25:40 +0100
commitee4d904cfb1b604bc8627491e05980ac43cd59e3 (patch)
tree54d1b937de544b8f6a8f2821ad9599aa82192375 /crates/ra_analysis/src/imp.rs
parent2cb2074c4b7219b32993abdcc7084637c0123d49 (diff)
Store all the data in the Salsa Database
Diffstat (limited to 'crates/ra_analysis/src/imp.rs')
-rw-r--r--crates/ra_analysis/src/imp.rs179
1 files changed, 98 insertions, 81 deletions
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index f3e5b2887..97ed55465 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -1,7 +1,5 @@
1use std::{ 1use std::{
2 fmt,
3 hash::{Hash, Hasher}, 2 hash::{Hash, Hasher},
4 iter,
5 sync::Arc, 3 sync::Arc,
6}; 4};
7 5
@@ -14,12 +12,16 @@ use ra_syntax::{
14}; 12};
15use relative_path::RelativePath; 13use relative_path::RelativePath;
16use rustc_hash::FxHashSet; 14use rustc_hash::FxHashSet;
15use salsa::{ParallelDatabase, Database};
17 16
18use crate::{ 17use crate::{
19 db::SyntaxDatabase, 18 AnalysisChange,
19 db::{
20 self, SyntaxDatabase,
21 input::{SourceRootId, FilesDatabase, SourceRoot, WORKSPACE}
22 },
20 descriptors::module::{ModulesDatabase, ModuleTree, Problem}, 23 descriptors::module::{ModulesDatabase, ModuleTree, Problem},
21 descriptors::{FnDescriptor}, 24 descriptors::{FnDescriptor},
22 roots::{ReadonlySourceRoot, SourceRoot, WritableSourceRoot},
23 CrateGraph, CrateId, Diagnostic, FileId, FileResolver, FileSystemEdit, Position, 25 CrateGraph, CrateId, Diagnostic, FileId, FileResolver, FileSystemEdit, Position,
24 Query, SourceChange, SourceFileEdit, Cancelable, 26 Query, SourceChange, SourceFileEdit, Cancelable,
25}; 27};
@@ -80,96 +82,123 @@ impl Default for FileResolverImp {
80 } 82 }
81} 83}
82 84
83#[derive(Debug)] 85#[derive(Debug, Default)]
84pub(crate) struct AnalysisHostImpl { 86pub(crate) struct AnalysisHostImpl {
85 data: WorldData, 87 db: db::RootDatabase,
86} 88}
87 89
90
88impl AnalysisHostImpl { 91impl AnalysisHostImpl {
89 pub fn new() -> AnalysisHostImpl { 92 pub fn new() -> AnalysisHostImpl {
90 AnalysisHostImpl { 93 AnalysisHostImpl::default()
91 data: WorldData::default(),
92 }
93 } 94 }
94 pub fn analysis(&self) -> AnalysisImpl { 95 pub fn analysis(&self) -> AnalysisImpl {
95 AnalysisImpl { 96 AnalysisImpl {
96 data: self.data.clone(), 97 db: self.db.fork() // freeze revision here
97 } 98 }
98 } 99 }
99 pub fn change_files(&mut self, changes: &mut dyn Iterator<Item = (FileId, Option<String>)>) { 100 pub fn apply_change(&mut self, change: AnalysisChange) {
100 self.data_mut().root.apply_changes(changes, None); 101 for (file_id, text) in change.files_changed {
101 } 102 self.db
102 pub fn set_file_resolver(&mut self, resolver: FileResolverImp) { 103 .query(db::input::FileTextQuery)
103 self.data_mut() 104 .set(file_id, Arc::new(text))
104 .root 105 }
105 .apply_changes(&mut iter::empty(), Some(resolver)); 106 if !(change.files_added.is_empty() && change.files_removed.is_empty()) {
106 } 107 let file_resolver = change.file_resolver
107 pub fn set_crate_graph(&mut self, graph: CrateGraph) { 108 .expect("change resolver when changing set of files");
108 let mut visited = FxHashSet::default(); 109 let mut source_root = SourceRoot::clone(&self.db.source_root(WORKSPACE));
109 for &file_id in graph.crate_roots.values() { 110 for (file_id, text) in change.files_added {
110 if !visited.insert(file_id) { 111 self.db
111 panic!("duplicate crate root: {:?}", file_id); 112 .query(db::input::FileTextQuery)
113 .set(file_id, Arc::new(text));
114 self.db
115 .query(db::input::FileSourceRootQuery)
116 .set(file_id, db::input::WORKSPACE);
117 source_root.files.insert(file_id);
118 }
119 for file_id in change.files_removed {
120 self.db
121 .query(db::input::FileTextQuery)
122 .set(file_id, Arc::new(String::new()));
123 source_root.files.remove(&file_id);
112 } 124 }
125 source_root.file_resolver = file_resolver;
126 self.db
127 .query(db::input::SourceRootQuery)
128 .set(WORKSPACE, Arc::new(source_root))
129 }
130 if !change.libraries_added.is_empty() {
131 let mut libraries = Vec::clone(&self.db.libraries());
132 for library in change.libraries_added {
133 let source_root_id = SourceRootId(1 + libraries.len() as u32);
134 libraries.push(source_root_id);
135 let mut files = FxHashSet::default();
136 for (file_id, text) in library.files {
137 files.insert(file_id);
138 self.db
139 .query(db::input::FileSourceRootQuery)
140 .set_constant(file_id, source_root_id);
141 self.db
142 .query(db::input::FileTextQuery)
143 .set_constant(file_id, Arc::new(text));
144 }
145 let source_root = SourceRoot {
146 files,
147 file_resolver: library.file_resolver,
148 };
149 self.db
150 .query(db::input::SourceRootQuery)
151 .set(source_root_id, Arc::new(source_root));
152 self.db
153 .query(db::input::LibrarySymbolsQuery)
154 .set(source_root_id, Arc::new(library.symbol_index));
155 }
156 self.db
157 .query(db::input::LibrarieseQuery)
158 .set((), Arc::new(libraries));
159 }
160 if let Some(crate_graph) = change.crate_graph {
161 self.db.query(db::input::CrateGraphQuery)
162 .set((), Arc::new(crate_graph))
113 } 163 }
114 self.data_mut().crate_graph = graph;
115 }
116 pub fn add_library(&mut self, root: ReadonlySourceRoot) {
117 self.data_mut().libs.push(root);
118 }
119 fn data_mut(&mut self) -> &mut WorldData {
120 &mut self.data
121 } 164 }
122} 165}
123 166
167#[derive(Debug)]
124pub(crate) struct AnalysisImpl { 168pub(crate) struct AnalysisImpl {
125 data: WorldData, 169 db: db::RootDatabase,
126}
127
128impl fmt::Debug for AnalysisImpl {
129 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
130 self.data.fmt(f)
131 }
132} 170}
133 171
134impl AnalysisImpl { 172impl AnalysisImpl {
135 fn root(&self, file_id: FileId) -> &SourceRoot {
136 if self.data.root.contains(file_id) {
137 return &self.data.root;
138 }
139 self
140 .data
141 .libs
142 .iter()
143 .find(|it| it.contains(file_id))
144 .unwrap()
145 }
146 pub fn file_syntax(&self, file_id: FileId) -> File { 173 pub fn file_syntax(&self, file_id: FileId) -> File {
147 self.root(file_id).db().file_syntax(file_id) 174 self.db.file_syntax(file_id)
148 } 175 }
149 pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> { 176 pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> {
150 self.root(file_id).db().file_lines(file_id) 177 self.db.file_lines(file_id)
151 } 178 }
152 pub fn world_symbols(&self, query: Query) -> Cancelable<Vec<(FileId, FileSymbol)>> { 179 pub fn world_symbols(&self, query: Query) -> Cancelable<Vec<(FileId, FileSymbol)>> {
153 let mut buf = Vec::new(); 180 let mut buf = Vec::new();
154 if query.libs { 181 for &lib_id in self.db.libraries().iter() {
155 for lib in self.data.libs.iter() { 182 buf.push(self.db.library_symbols(lib_id));
156 lib.symbols(&mut buf)?; 183 }
157 } 184 for &file_id in self.db.source_root(WORKSPACE).files.iter() {
158 } else { 185 buf.push(self.db.file_symbols(file_id)?);
159 self.data.root.symbols(&mut buf)?;
160 } 186 }
161 Ok(query.search(&buf)) 187 Ok(query.search(&buf))
162 } 188 }
189 fn module_tree(&self, file_id: FileId) -> Cancelable<Arc<ModuleTree>> {
190 let source_root = self.db.file_source_root(file_id);
191 self.db.module_tree(source_root)
192 }
163 pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> { 193 pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> {
164 let root = self.root(file_id); 194 let module_tree = self.module_tree(file_id)?;
165 let module_tree = root.db().module_tree()?;
166 195
167 let res = module_tree.modules_for_file(file_id) 196 let res = module_tree.modules_for_file(file_id)
168 .into_iter() 197 .into_iter()
169 .filter_map(|module_id| { 198 .filter_map(|module_id| {
170 let link = module_id.parent_link(&module_tree)?; 199 let link = module_id.parent_link(&module_tree)?;
171 let file_id = link.owner(&module_tree).file_id(&module_tree); 200 let file_id = link.owner(&module_tree).file_id(&module_tree);
172 let syntax = root.db().file_syntax(file_id); 201 let syntax = self.db.file_syntax(file_id);
173 let decl = link.bind_source(&module_tree, syntax.ast()); 202 let decl = link.bind_source(&module_tree, syntax.ast());
174 203
175 let sym = FileSymbol { 204 let sym = FileSymbol {
@@ -183,8 +212,8 @@ impl AnalysisImpl {
183 Ok(res) 212 Ok(res)
184 } 213 }
185 pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { 214 pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
186 let module_tree = self.root(file_id).db().module_tree()?; 215 let module_tree = self.module_tree(file_id)?;
187 let crate_graph = &self.data.crate_graph; 216 let crate_graph = self.db.crate_graph();
188 let res = module_tree.modules_for_file(file_id) 217 let res = module_tree.modules_for_file(file_id)
189 .into_iter() 218 .into_iter()
190 .map(|it| it.root(&module_tree)) 219 .map(|it| it.root(&module_tree))
@@ -195,7 +224,7 @@ impl AnalysisImpl {
195 Ok(res) 224 Ok(res)
196 } 225 }
197 pub fn crate_root(&self, crate_id: CrateId) -> FileId { 226 pub fn crate_root(&self, crate_id: CrateId) -> FileId {
198 self.data.crate_graph.crate_roots[&crate_id] 227 self.db.crate_graph().crate_roots[&crate_id]
199 } 228 }
200 pub fn completions(&self, file_id: FileId, offset: TextUnit) -> Cancelable<Option<Vec<CompletionItem>>> { 229 pub fn completions(&self, file_id: FileId, offset: TextUnit) -> Cancelable<Option<Vec<CompletionItem>>> {
201 let mut res = Vec::new(); 230 let mut res = Vec::new();
@@ -205,8 +234,7 @@ impl AnalysisImpl {
205 res.extend(scope_based); 234 res.extend(scope_based);
206 has_completions = true; 235 has_completions = true;
207 } 236 }
208 let root = self.root(file_id); 237 if let Some(scope_based) = crate::completion::resolve_based_completion(&self.db, file_id, offset)? {
209 if let Some(scope_based) = crate::completion::resolve_based_completion(root.db(), file_id, offset)? {
210 res.extend(scope_based); 238 res.extend(scope_based);
211 has_completions = true; 239 has_completions = true;
212 } 240 }
@@ -222,9 +250,8 @@ impl AnalysisImpl {
222 file_id: FileId, 250 file_id: FileId,
223 offset: TextUnit, 251 offset: TextUnit,
224 ) -> Cancelable<Vec<(FileId, FileSymbol)>> { 252 ) -> Cancelable<Vec<(FileId, FileSymbol)>> {
225 let root = self.root(file_id); 253 let module_tree = self.module_tree(file_id)?;
226 let module_tree = root.db().module_tree()?; 254 let file = self.db.file_syntax(file_id);
227 let file = root.db().file_syntax(file_id);
228 let syntax = file.syntax(); 255 let syntax = file.syntax();
229 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) { 256 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) {
230 // First try to resolve the symbol locally 257 // First try to resolve the symbol locally
@@ -273,8 +300,7 @@ impl AnalysisImpl {
273 } 300 }
274 301
275 pub fn find_all_refs(&self, file_id: FileId, offset: TextUnit) -> Vec<(FileId, TextRange)> { 302 pub fn find_all_refs(&self, file_id: FileId, offset: TextUnit) -> Vec<(FileId, TextRange)> {
276 let root = self.root(file_id); 303 let file = self.db.file_syntax(file_id);
277 let file = root.db().file_syntax(file_id);
278 let syntax = file.syntax(); 304 let syntax = file.syntax();
279 305
280 let mut ret = vec![]; 306 let mut ret = vec![];
@@ -305,9 +331,8 @@ impl AnalysisImpl {
305 } 331 }
306 332
307 pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { 333 pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> {
308 let root = self.root(file_id); 334 let module_tree = self.module_tree(file_id)?;
309 let module_tree = root.db().module_tree()?; 335 let syntax = self.db.file_syntax(file_id);
310 let syntax = root.db().file_syntax(file_id);
311 336
312 let mut res = ra_editor::diagnostics(&syntax) 337 let mut res = ra_editor::diagnostics(&syntax)
313 .into_iter() 338 .into_iter()
@@ -396,8 +421,7 @@ impl AnalysisImpl {
396 file_id: FileId, 421 file_id: FileId,
397 offset: TextUnit, 422 offset: TextUnit,
398 ) -> Cancelable<Option<(FnDescriptor, Option<usize>)>> { 423 ) -> Cancelable<Option<(FnDescriptor, Option<usize>)>> {
399 let root = self.root(file_id); 424 let file = self.db.file_syntax(file_id);
400 let file = root.db().file_syntax(file_id);
401 let syntax = file.syntax(); 425 let syntax = file.syntax();
402 426
403 // Find the calling expression and it's NameRef 427 // Find the calling expression and it's NameRef
@@ -491,13 +515,6 @@ impl AnalysisImpl {
491 } 515 }
492} 516}
493 517
494#[derive(Default, Clone, Debug)]
495struct WorldData {
496 crate_graph: CrateGraph,
497 root: WritableSourceRoot,
498 libs: Vec<ReadonlySourceRoot>,
499}
500
501impl SourceChange { 518impl SourceChange {
502 pub(crate) fn from_local_edit(file_id: FileId, label: &str, edit: LocalEdit) -> SourceChange { 519 pub(crate) fn from_local_edit(file_id: FileId, label: &str, edit: LocalEdit) -> SourceChange {
503 let file_edit = SourceFileEdit { 520 let file_edit = SourceFileEdit {