diff options
Diffstat (limited to 'crates/ra_analysis/src/db.rs')
-rw-r--r-- | crates/ra_analysis/src/db.rs | 164 |
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 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | #[cfg(test)] | ||
3 | use parking_lot::Mutex; | ||
4 | use ra_editor::LineIndex; | ||
5 | use ra_syntax::{SourceFileNode, SyntaxNode}; | ||
6 | use salsa::{self, Database}; | 2 | use salsa::{self, Database}; |
3 | use ra_db::{LocationIntener, BaseDatabase}; | ||
4 | use hir::{self, DefId, DefLoc, FnId, SourceItemId}; | ||
7 | 5 | ||
8 | use crate::{ | 6 | use 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)] |
21 | pub(crate) struct RootDatabase { | 11 | pub(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)] | ||
17 | struct IdMaps { | ||
18 | fns: LocationIntener<SourceItemId, FnId>, | ||
19 | defs: LocationIntener<DefLoc, DefId>, | ||
29 | } | 20 | } |
30 | 21 | ||
31 | impl salsa::Database for RootDatabase { | 22 | impl 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 | ||
48 | impl Default for RootDatabase { | 28 | impl 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 | ||
65 | pub(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 | |||
73 | impl salsa::ParallelDatabase for RootDatabase { | 44 | impl 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 | ||
83 | impl IdDatabase for RootDatabase { | 53 | impl BaseDatabase for RootDatabase {} |
84 | fn id_maps(&self) -> &IdMaps { | ||
85 | &self.id_maps | ||
86 | } | ||
87 | } | ||
88 | 54 | ||
89 | #[cfg(test)] | 55 | impl AsRef<LocationIntener<DefLoc, DefId>> for RootDatabase { |
90 | impl 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> { | 61 | impl 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 | ||
112 | salsa::database_storage! { | 67 | salsa::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; | |
139 | salsa::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 | |||
159 | fn file_syntax(db: &impl SyntaxDatabase, file_id: FileId) -> SourceFileNode { | ||
160 | let text = db.file_text(file_id); | ||
161 | SourceFileNode::parse(&*text) | ||
162 | } | ||
163 | fn 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 | } | ||
167 | fn 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 | } | ||