aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/db.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/src/db.rs')
-rw-r--r--crates/ra_analysis/src/db.rs164
1 files changed, 44 insertions, 120 deletions
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs
index 6b56f99ac..df2ef293d 100644
--- a/crates/ra_analysis/src/db.rs
+++ b/crates/ra_analysis/src/db.rs
@@ -1,171 +1,95 @@
1use std::sync::Arc; 1use std::sync::Arc;
2#[cfg(test)]
3use parking_lot::Mutex;
4use ra_editor::LineIndex;
5use ra_syntax::{SourceFileNode, SyntaxNode};
6use salsa::{self, Database}; 2use salsa::{self, Database};
3use ra_db::{LocationIntener, BaseDatabase};
4use hir::{self, DefId, DefLoc, FnId, SourceItemId};
7 5
8use crate::{ 6use crate::{
9 db, 7 symbol_index,
10 descriptors::{
11 DescriptorDatabase, FnScopesQuery, FnSyntaxQuery, ModuleTreeQuery,
12 SubmodulesQuery, ItemMapQuery, InputModuleItemsQuery,
13 },
14 symbol_index::SymbolIndex,
15 syntax_ptr::SyntaxPtr,
16 loc2id::{IdMaps, IdDatabase},
17 Cancelable, Canceled, FileId,
18}; 8};
19 9
20#[derive(Debug)] 10#[derive(Debug)]
21pub(crate) struct RootDatabase { 11pub(crate) struct RootDatabase {
22 #[cfg(test)]
23 events: Mutex<Option<Vec<salsa::Event<RootDatabase>>>>,
24 #[cfg(not(test))]
25 events: (),
26
27 runtime: salsa::Runtime<RootDatabase>, 12 runtime: salsa::Runtime<RootDatabase>,
28 id_maps: IdMaps, 13 id_maps: Arc<IdMaps>,
14}
15
16#[derive(Debug, Default)]
17struct IdMaps {
18 fns: LocationIntener<SourceItemId, FnId>,
19 defs: LocationIntener<DefLoc, DefId>,
29} 20}
30 21
31impl salsa::Database for RootDatabase { 22impl salsa::Database for RootDatabase {
32 fn salsa_runtime(&self) -> &salsa::Runtime<RootDatabase> { 23 fn salsa_runtime(&self) -> &salsa::Runtime<RootDatabase> {
33 &self.runtime 24 &self.runtime
34 } 25 }
35
36 #[allow(unused)]
37 fn salsa_event(&self, event: impl Fn() -> salsa::Event<RootDatabase>) {
38 #[cfg(test)]
39 {
40 let mut events = self.events.lock();
41 if let Some(events) = &mut *events {
42 events.push(event());
43 }
44 }
45 }
46} 26}
47 27
48impl Default for RootDatabase { 28impl Default for RootDatabase {
49 fn default() -> RootDatabase { 29 fn default() -> RootDatabase {
50 let mut db = RootDatabase { 30 let mut db = RootDatabase {
51 events: Default::default(),
52 runtime: salsa::Runtime::default(), 31 runtime: salsa::Runtime::default(),
53 id_maps: IdMaps::default(), 32 id_maps: Default::default(),
54 }; 33 };
55 db.query_mut(crate::input::SourceRootQuery) 34 db.query_mut(ra_db::SourceRootQuery)
56 .set(crate::input::WORKSPACE, Default::default()); 35 .set(ra_db::WORKSPACE, Default::default());
57 db.query_mut(crate::input::CrateGraphQuery) 36 db.query_mut(ra_db::CrateGraphQuery)
58 .set((), Default::default()); 37 .set((), Default::default());
59 db.query_mut(crate::input::LibrariesQuery) 38 db.query_mut(ra_db::LibrariesQuery)
60 .set((), Default::default()); 39 .set((), Default::default());
61 db 40 db
62 } 41 }
63} 42}
64 43
65pub(crate) fn check_canceled(db: &impl salsa::Database) -> Cancelable<()> {
66 if db.salsa_runtime().is_current_revision_canceled() {
67 Err(Canceled)
68 } else {
69 Ok(())
70 }
71}
72
73impl salsa::ParallelDatabase for RootDatabase { 44impl salsa::ParallelDatabase for RootDatabase {
74 fn snapshot(&self) -> salsa::Snapshot<RootDatabase> { 45 fn snapshot(&self) -> salsa::Snapshot<RootDatabase> {
75 salsa::Snapshot::new(RootDatabase { 46 salsa::Snapshot::new(RootDatabase {
76 events: Default::default(),
77 runtime: self.runtime.snapshot(self), 47 runtime: self.runtime.snapshot(self),
78 id_maps: self.id_maps.clone(), 48 id_maps: self.id_maps.clone(),
79 }) 49 })
80 } 50 }
81} 51}
82 52
83impl IdDatabase for RootDatabase { 53impl BaseDatabase for RootDatabase {}
84 fn id_maps(&self) -> &IdMaps {
85 &self.id_maps
86 }
87}
88 54
89#[cfg(test)] 55impl AsRef<LocationIntener<DefLoc, DefId>> for RootDatabase {
90impl RootDatabase { 56 fn as_ref(&self) -> &LocationIntener<DefLoc, DefId> {
91 pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<RootDatabase>> { 57 &self.id_maps.defs
92 *self.events.lock() = Some(Vec::new());
93 f();
94 let events = self.events.lock().take().unwrap();
95 events
96 } 58 }
59}
97 60
98 pub(crate) fn log_executed(&self, f: impl FnOnce()) -> Vec<String> { 61impl AsRef<LocationIntener<hir::SourceItemId, FnId>> for RootDatabase {
99 let events = self.log(f); 62 fn as_ref(&self) -> &LocationIntener<hir::SourceItemId, FnId> {
100 events 63 &self.id_maps.fns
101 .into_iter()
102 .filter_map(|e| match e.kind {
103 // This pretty horrible, but `Debug` is the only way to inspect
104 // QueryDescriptor at the moment.
105 salsa::EventKind::WillExecute { descriptor } => Some(format!("{:?}", descriptor)),
106 _ => None,
107 })
108 .collect()
109 } 64 }
110} 65}
111 66
112salsa::database_storage! { 67salsa::database_storage! {
113 pub(crate) struct RootDatabaseStorage for RootDatabase { 68 pub(crate) struct RootDatabaseStorage for RootDatabase {
114 impl crate::input::FilesDatabase { 69 impl ra_db::FilesDatabase {
115 fn file_text() for crate::input::FileTextQuery; 70 fn file_text() for ra_db::FileTextQuery;
116 fn file_source_root() for crate::input::FileSourceRootQuery; 71 fn file_source_root() for ra_db::FileSourceRootQuery;
117 fn source_root() for crate::input::SourceRootQuery; 72 fn source_root() for ra_db::SourceRootQuery;
118 fn libraries() for crate::input::LibrariesQuery; 73 fn libraries() for ra_db::LibrariesQuery;
119 fn library_symbols() for crate::input::LibrarySymbolsQuery; 74 fn crate_graph() for ra_db::CrateGraphQuery;
120 fn crate_graph() for crate::input::CrateGraphQuery;
121 }
122 impl SyntaxDatabase {
123 fn file_syntax() for FileSyntaxQuery;
124 fn file_lines() for FileLinesQuery;
125 fn file_symbols() for FileSymbolsQuery;
126 fn resolve_syntax_ptr() for ResolveSyntaxPtrQuery;
127 }
128 impl DescriptorDatabase {
129 fn module_tree() for ModuleTreeQuery;
130 fn fn_scopes() for FnScopesQuery;
131 fn _input_module_items() for InputModuleItemsQuery;
132 fn _item_map() for ItemMapQuery;
133 fn _fn_syntax() for FnSyntaxQuery;
134 fn _submodules() for SubmodulesQuery;
135 } 75 }
136 } 76 impl ra_db::SyntaxDatabase {
137} 77 fn source_file() for ra_db::SourceFileQuery;
138 78 fn file_lines() for ra_db::FileLinesQuery;
139salsa::query_group! {
140 pub(crate) trait SyntaxDatabase: crate::input::FilesDatabase {
141 fn file_syntax(file_id: FileId) -> SourceFileNode {
142 type FileSyntaxQuery;
143 } 79 }
144 fn file_lines(file_id: FileId) -> Arc<LineIndex> { 80 impl symbol_index::SymbolsDatabase {
145 type FileLinesQuery; 81 fn file_symbols() for symbol_index::FileSymbolsQuery;
82 fn library_symbols() for symbol_index::LibrarySymbolsQuery;
146 } 83 }
147 fn file_symbols(file_id: FileId) -> Cancelable<Arc<SymbolIndex>> { 84 impl hir::db::HirDatabase {
148 type FileSymbolsQuery; 85 fn module_tree() for hir::db::ModuleTreeQuery;
149 } 86 fn fn_scopes() for hir::db::FnScopesQuery;
150 fn resolve_syntax_ptr(ptr: SyntaxPtr) -> SyntaxNode { 87 fn file_items() for hir::db::SourceFileItemsQuery;
151 type ResolveSyntaxPtrQuery; 88 fn file_item() for hir::db::FileItemQuery;
152 // Don't retain syntax trees in memory 89 fn input_module_items() for hir::db::InputModuleItemsQuery;
153 storage volatile; 90 fn item_map() for hir::db::ItemMapQuery;
154 use fn crate::syntax_ptr::resolve_syntax_ptr; 91 fn fn_syntax() for hir::db::FnSyntaxQuery;
92 fn submodules() for hir::db::SubmodulesQuery;
155 } 93 }
156 } 94 }
157} 95}
158
159fn file_syntax(db: &impl SyntaxDatabase, file_id: FileId) -> SourceFileNode {
160 let text = db.file_text(file_id);
161 SourceFileNode::parse(&*text)
162}
163fn file_lines(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<LineIndex> {
164 let text = db.file_text(file_id);
165 Arc::new(LineIndex::new(&*text))
166}
167fn file_symbols(db: &impl SyntaxDatabase, file_id: FileId) -> Cancelable<Arc<SymbolIndex>> {
168 db::check_canceled(db)?;
169 let syntax = db.file_syntax(file_id);
170 Ok(Arc::new(SymbolIndex::for_file(file_id, syntax)))
171}