aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/imp.rs
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2018-10-25 16:04:48 +0100
committerbors[bot] <bors[bot]@users.noreply.github.com>2018-10-25 16:04:48 +0100
commit5932bd0bb5fcd066a9d16abcd1597b7097978085 (patch)
tree7b6ea86855fe34c3d45d14262c8cf94e315566e8 /crates/ra_analysis/src/imp.rs
parent2cb2074c4b7219b32993abdcc7084637c0123d49 (diff)
parent363adf07b7763cfe7e13fac0ee148361d51834e4 (diff)
Merge #162
162: Db everywhere r=matklad a=matklad This PR continues our switch to salsa. Now *all* state is handled by a single salsa database. Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_analysis/src/imp.rs')
-rw-r--r--crates/ra_analysis/src/imp.rs184
1 files changed, 104 insertions, 80 deletions
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index f3e5b2887..5a6e2450d 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,17 @@ 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
22 },
23 input::{SourceRootId, FilesDatabase, SourceRoot, WORKSPACE},
20 descriptors::module::{ModulesDatabase, ModuleTree, Problem}, 24 descriptors::module::{ModulesDatabase, ModuleTree, Problem},
21 descriptors::{FnDescriptor}, 25 descriptors::{FnDescriptor},
22 roots::{ReadonlySourceRoot, SourceRoot, WritableSourceRoot},
23 CrateGraph, CrateId, Diagnostic, FileId, FileResolver, FileSystemEdit, Position, 26 CrateGraph, CrateId, Diagnostic, FileId, FileResolver, FileSystemEdit, Position,
24 Query, SourceChange, SourceFileEdit, Cancelable, 27 Query, SourceChange, SourceFileEdit, Cancelable,
25}; 28};
@@ -80,96 +83,128 @@ impl Default for FileResolverImp {
80 } 83 }
81} 84}
82 85
83#[derive(Debug)] 86#[derive(Debug, Default)]
84pub(crate) struct AnalysisHostImpl { 87pub(crate) struct AnalysisHostImpl {
85 data: WorldData, 88 db: db::RootDatabase,
86} 89}
87 90
91
88impl AnalysisHostImpl { 92impl AnalysisHostImpl {
89 pub fn new() -> AnalysisHostImpl { 93 pub fn new() -> AnalysisHostImpl {
90 AnalysisHostImpl { 94 AnalysisHostImpl::default()
91 data: WorldData::default(),
92 }
93 } 95 }
94 pub fn analysis(&self) -> AnalysisImpl { 96 pub fn analysis(&self) -> AnalysisImpl {
95 AnalysisImpl { 97 AnalysisImpl {
96 data: self.data.clone(), 98 db: self.db.fork() // freeze revision here
97 } 99 }
98 } 100 }
99 pub fn change_files(&mut self, changes: &mut dyn Iterator<Item = (FileId, Option<String>)>) { 101 pub fn apply_change(&mut self, change: AnalysisChange) {
100 self.data_mut().root.apply_changes(changes, None); 102 log::info!("apply_change {:?}", change);
101 } 103
102 pub fn set_file_resolver(&mut self, resolver: FileResolverImp) { 104 for (file_id, text) in change.files_changed {
103 self.data_mut() 105 self.db
104 .root 106 .query(crate::input::FileTextQuery)
105 .apply_changes(&mut iter::empty(), Some(resolver)); 107 .set(file_id, Arc::new(text))
106 } 108 }
107 pub fn set_crate_graph(&mut self, graph: CrateGraph) { 109 if !(change.files_added.is_empty() && change.files_removed.is_empty()) {
108 let mut visited = FxHashSet::default(); 110 let file_resolver = change.file_resolver
109 for &file_id in graph.crate_roots.values() { 111 .expect("change resolver when changing set of files");
110 if !visited.insert(file_id) { 112 let mut source_root = SourceRoot::clone(&self.db.source_root(WORKSPACE));
111 panic!("duplicate crate root: {:?}", file_id); 113 for (file_id, text) in change.files_added {
114 self.db
115 .query(crate::input::FileTextQuery)
116 .set(file_id, Arc::new(text));
117 self.db
118 .query(crate::input::FileSourceRootQuery)
119 .set(file_id, crate::input::WORKSPACE);
120 source_root.files.insert(file_id);
121 }
122 for file_id in change.files_removed {
123 self.db
124 .query(crate::input::FileTextQuery)
125 .set(file_id, Arc::new(String::new()));
126 source_root.files.remove(&file_id);
112 } 127 }
128 source_root.file_resolver = file_resolver;
129 self.db
130 .query(crate::input::SourceRootQuery)
131 .set(WORKSPACE, Arc::new(source_root))
132 }
133 if !change.libraries_added.is_empty() {
134 let mut libraries = Vec::clone(&self.db.libraries());
135 for library in change.libraries_added {
136 let source_root_id = SourceRootId(1 + libraries.len() as u32);
137 libraries.push(source_root_id);
138 let mut files = FxHashSet::default();
139 for (file_id, text) in library.files {
140 files.insert(file_id);
141 self.db
142 .query(crate::input::FileSourceRootQuery)
143 .set_constant(file_id, source_root_id);
144 self.db
145 .query(crate::input::FileTextQuery)
146 .set_constant(file_id, Arc::new(text));
147 }
148 let source_root = SourceRoot {
149 files,
150 file_resolver: library.file_resolver,
151 };
152 self.db
153 .query(crate::input::SourceRootQuery)
154 .set(source_root_id, Arc::new(source_root));
155 self.db
156 .query(crate::input::LibrarySymbolsQuery)
157 .set(source_root_id, Arc::new(library.symbol_index));
158 }
159 self.db
160 .query(crate::input::LibrarieseQuery)
161 .set((), Arc::new(libraries));
162 }
163 if let Some(crate_graph) = change.crate_graph {
164 self.db.query(crate::input::CrateGraphQuery)
165 .set((), Arc::new(crate_graph))
113 } 166 }
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 } 167 }
122} 168}
123 169
170#[derive(Debug)]
124pub(crate) struct AnalysisImpl { 171pub(crate) struct AnalysisImpl {
125 data: WorldData, 172 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} 173}
133 174
134impl AnalysisImpl { 175impl 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 { 176 pub fn file_syntax(&self, file_id: FileId) -> File {
147 self.root(file_id).db().file_syntax(file_id) 177 self.db.file_syntax(file_id)
148 } 178 }
149 pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> { 179 pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> {
150 self.root(file_id).db().file_lines(file_id) 180 self.db.file_lines(file_id)
151 } 181 }
152 pub fn world_symbols(&self, query: Query) -> Cancelable<Vec<(FileId, FileSymbol)>> { 182 pub fn world_symbols(&self, query: Query) -> Cancelable<Vec<(FileId, FileSymbol)>> {
153 let mut buf = Vec::new(); 183 let mut buf = Vec::new();
154 if query.libs { 184 if query.libs {
155 for lib in self.data.libs.iter() { 185 for &lib_id in self.db.libraries().iter() {
156 lib.symbols(&mut buf)?; 186 buf.push(self.db.library_symbols(lib_id));
157 } 187 }
158 } else { 188 } else {
159 self.data.root.symbols(&mut buf)?; 189 for &file_id in self.db.source_root(WORKSPACE).files.iter() {
190 buf.push(self.db.file_symbols(file_id)?);
191 }
160 } 192 }
161 Ok(query.search(&buf)) 193 Ok(query.search(&buf))
162 } 194 }
195 fn module_tree(&self, file_id: FileId) -> Cancelable<Arc<ModuleTree>> {
196 let source_root = self.db.file_source_root(file_id);
197 self.db.module_tree(source_root)
198 }
163 pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> { 199 pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> {
164 let root = self.root(file_id); 200 let module_tree = self.module_tree(file_id)?;
165 let module_tree = root.db().module_tree()?;
166 201
167 let res = module_tree.modules_for_file(file_id) 202 let res = module_tree.modules_for_file(file_id)
168 .into_iter() 203 .into_iter()
169 .filter_map(|module_id| { 204 .filter_map(|module_id| {
170 let link = module_id.parent_link(&module_tree)?; 205 let link = module_id.parent_link(&module_tree)?;
171 let file_id = link.owner(&module_tree).file_id(&module_tree); 206 let file_id = link.owner(&module_tree).file_id(&module_tree);
172 let syntax = root.db().file_syntax(file_id); 207 let syntax = self.db.file_syntax(file_id);
173 let decl = link.bind_source(&module_tree, syntax.ast()); 208 let decl = link.bind_source(&module_tree, syntax.ast());
174 209
175 let sym = FileSymbol { 210 let sym = FileSymbol {
@@ -183,8 +218,8 @@ impl AnalysisImpl {
183 Ok(res) 218 Ok(res)
184 } 219 }
185 pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { 220 pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
186 let module_tree = self.root(file_id).db().module_tree()?; 221 let module_tree = self.module_tree(file_id)?;
187 let crate_graph = &self.data.crate_graph; 222 let crate_graph = self.db.crate_graph();
188 let res = module_tree.modules_for_file(file_id) 223 let res = module_tree.modules_for_file(file_id)
189 .into_iter() 224 .into_iter()
190 .map(|it| it.root(&module_tree)) 225 .map(|it| it.root(&module_tree))
@@ -195,7 +230,7 @@ impl AnalysisImpl {
195 Ok(res) 230 Ok(res)
196 } 231 }
197 pub fn crate_root(&self, crate_id: CrateId) -> FileId { 232 pub fn crate_root(&self, crate_id: CrateId) -> FileId {
198 self.data.crate_graph.crate_roots[&crate_id] 233 self.db.crate_graph().crate_roots[&crate_id]
199 } 234 }
200 pub fn completions(&self, file_id: FileId, offset: TextUnit) -> Cancelable<Option<Vec<CompletionItem>>> { 235 pub fn completions(&self, file_id: FileId, offset: TextUnit) -> Cancelable<Option<Vec<CompletionItem>>> {
201 let mut res = Vec::new(); 236 let mut res = Vec::new();
@@ -205,8 +240,7 @@ impl AnalysisImpl {
205 res.extend(scope_based); 240 res.extend(scope_based);
206 has_completions = true; 241 has_completions = true;
207 } 242 }
208 let root = self.root(file_id); 243 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); 244 res.extend(scope_based);
211 has_completions = true; 245 has_completions = true;
212 } 246 }
@@ -222,9 +256,8 @@ impl AnalysisImpl {
222 file_id: FileId, 256 file_id: FileId,
223 offset: TextUnit, 257 offset: TextUnit,
224 ) -> Cancelable<Vec<(FileId, FileSymbol)>> { 258 ) -> Cancelable<Vec<(FileId, FileSymbol)>> {
225 let root = self.root(file_id); 259 let module_tree = self.module_tree(file_id)?;
226 let module_tree = root.db().module_tree()?; 260 let file = self.db.file_syntax(file_id);
227 let file = root.db().file_syntax(file_id);
228 let syntax = file.syntax(); 261 let syntax = file.syntax();
229 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) { 262 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) {
230 // First try to resolve the symbol locally 263 // First try to resolve the symbol locally
@@ -273,8 +306,7 @@ impl AnalysisImpl {
273 } 306 }
274 307
275 pub fn find_all_refs(&self, file_id: FileId, offset: TextUnit) -> Vec<(FileId, TextRange)> { 308 pub fn find_all_refs(&self, file_id: FileId, offset: TextUnit) -> Vec<(FileId, TextRange)> {
276 let root = self.root(file_id); 309 let file = self.db.file_syntax(file_id);
277 let file = root.db().file_syntax(file_id);
278 let syntax = file.syntax(); 310 let syntax = file.syntax();
279 311
280 let mut ret = vec![]; 312 let mut ret = vec![];
@@ -305,9 +337,8 @@ impl AnalysisImpl {
305 } 337 }
306 338
307 pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { 339 pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> {
308 let root = self.root(file_id); 340 let module_tree = self.module_tree(file_id)?;
309 let module_tree = root.db().module_tree()?; 341 let syntax = self.db.file_syntax(file_id);
310 let syntax = root.db().file_syntax(file_id);
311 342
312 let mut res = ra_editor::diagnostics(&syntax) 343 let mut res = ra_editor::diagnostics(&syntax)
313 .into_iter() 344 .into_iter()
@@ -396,8 +427,7 @@ impl AnalysisImpl {
396 file_id: FileId, 427 file_id: FileId,
397 offset: TextUnit, 428 offset: TextUnit,
398 ) -> Cancelable<Option<(FnDescriptor, Option<usize>)>> { 429 ) -> Cancelable<Option<(FnDescriptor, Option<usize>)>> {
399 let root = self.root(file_id); 430 let file = self.db.file_syntax(file_id);
400 let file = root.db().file_syntax(file_id);
401 let syntax = file.syntax(); 431 let syntax = file.syntax();
402 432
403 // Find the calling expression and it's NameRef 433 // Find the calling expression and it's NameRef
@@ -412,9 +442,10 @@ impl AnalysisImpl {
412 442
413 // Resolve the function's NameRef (NOTE: this isn't entirely accurate). 443 // Resolve the function's NameRef (NOTE: this isn't entirely accurate).
414 let file_symbols = self.index_resolve(name_ref)?; 444 let file_symbols = self.index_resolve(name_ref)?;
415 for (_, fs) in file_symbols { 445 for (fn_fiel_id, fs) in file_symbols {
416 if fs.kind == FN_DEF { 446 if fs.kind == FN_DEF {
417 if let Some(fn_def) = find_node_at_offset(syntax, fs.node_range.start()) { 447 let fn_file = self.db.file_syntax(fn_fiel_id);
448 if let Some(fn_def) = find_node_at_offset(fn_file.syntax(), fs.node_range.start()) {
418 if let Some(descriptor) = FnDescriptor::new(fn_def) { 449 if let Some(descriptor) = FnDescriptor::new(fn_def) {
419 // If we have a calling expression let's find which argument we are on 450 // If we have a calling expression let's find which argument we are on
420 let mut current_parameter = None; 451 let mut current_parameter = None;
@@ -491,13 +522,6 @@ impl AnalysisImpl {
491 } 522 }
492} 523}
493 524
494#[derive(Default, Clone, Debug)]
495struct WorldData {
496 crate_graph: CrateGraph,
497 root: WritableSourceRoot,
498 libs: Vec<ReadonlySourceRoot>,
499}
500
501impl SourceChange { 525impl SourceChange {
502 pub(crate) fn from_local_edit(file_id: FileId, label: &str, edit: LocalEdit) -> SourceChange { 526 pub(crate) fn from_local_edit(file_id: FileId, label: &str, edit: LocalEdit) -> SourceChange {
503 let file_edit = SourceFileEdit { 527 let file_edit = SourceFileEdit {