aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_db/src/apply_change.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-10-02 14:45:09 +0100
committerAleksey Kladov <[email protected]>2020-10-02 15:45:08 +0100
commit8716c4cec3a05ba891b20b5f28df69d925b913ad (patch)
treee2f073c459e9a1e1c98b98d524565633524b84c2 /crates/ide_db/src/apply_change.rs
parent700c9bc019346a321d230c51bbea597a497bed84 (diff)
Move ide::AnalysisChange -> base_db::Change
This seems like a better factoring logically; ideally, clients shouldn't touch `set_` methods of the database directly. Additionally, I think this should remove the unfortunate duplication in fixture code.
Diffstat (limited to 'crates/ide_db/src/apply_change.rs')
-rw-r--r--crates/ide_db/src/apply_change.rs239
1 files changed, 239 insertions, 0 deletions
diff --git a/crates/ide_db/src/apply_change.rs b/crates/ide_db/src/apply_change.rs
new file mode 100644
index 000000000..da16fa21d
--- /dev/null
+++ b/crates/ide_db/src/apply_change.rs
@@ -0,0 +1,239 @@
1//! Applies changes to the IDE state transactionally.
2
3use std::{fmt, sync::Arc};
4
5use base_db::{
6 salsa::{Database, Durability, SweepStrategy},
7 Change, FileId, SourceRootId,
8};
9use profile::{memory_usage, Bytes};
10use rustc_hash::FxHashSet;
11
12use crate::{symbol_index::SymbolsDatabase, RootDatabase};
13
14#[derive(Debug)]
15struct AddFile {
16 file_id: FileId,
17 path: String,
18 text: Arc<String>,
19}
20
21#[derive(Debug)]
22struct RemoveFile {
23 file_id: FileId,
24 path: String,
25}
26
27#[derive(Default)]
28struct RootChange {
29 added: Vec<AddFile>,
30 removed: Vec<RemoveFile>,
31}
32
33impl fmt::Debug for RootChange {
34 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
35 fmt.debug_struct("AnalysisChange")
36 .field("added", &self.added.len())
37 .field("removed", &self.removed.len())
38 .finish()
39 }
40}
41
42impl RootDatabase {
43 pub fn request_cancellation(&mut self) {
44 let _p = profile::span("RootDatabase::request_cancellation");
45 self.salsa_runtime_mut().synthetic_write(Durability::LOW);
46 }
47
48 pub fn apply_change(&mut self, change: Change) {
49 let _p = profile::span("RootDatabase::apply_change");
50 self.request_cancellation();
51 log::info!("apply_change {:?}", change);
52 if let Some(roots) = &change.roots {
53 let mut local_roots = FxHashSet::default();
54 let mut library_roots = FxHashSet::default();
55 for (idx, root) in roots.iter().enumerate() {
56 let root_id = SourceRootId(idx as u32);
57 if root.is_library {
58 library_roots.insert(root_id);
59 } else {
60 local_roots.insert(root_id);
61 }
62 }
63 self.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
64 self.set_library_roots_with_durability(Arc::new(library_roots), Durability::HIGH);
65 }
66 change.apply(self);
67 }
68
69 pub fn collect_garbage(&mut self) {
70 if cfg!(feature = "wasm") {
71 return;
72 }
73
74 let _p = profile::span("RootDatabase::collect_garbage");
75
76 let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();
77
78 base_db::ParseQuery.in_db(self).sweep(sweep);
79 hir::db::ParseMacroQuery.in_db(self).sweep(sweep);
80
81 // Macros do take significant space, but less then the syntax trees
82 // self.query(hir::db::MacroDefQuery).sweep(sweep);
83 // self.query(hir::db::MacroArgTextQuery).sweep(sweep);
84 // self.query(hir::db::MacroExpandQuery).sweep(sweep);
85
86 hir::db::AstIdMapQuery.in_db(self).sweep(sweep);
87
88 hir::db::BodyWithSourceMapQuery.in_db(self).sweep(sweep);
89
90 hir::db::ExprScopesQuery.in_db(self).sweep(sweep);
91 hir::db::InferQueryQuery.in_db(self).sweep(sweep);
92 hir::db::BodyQuery.in_db(self).sweep(sweep);
93 }
94
95 // Feature: Memory Usage
96 //
97 // Clears rust-analyzer's internal database and prints memory usage statistics.
98 //
99 // |===
100 // | Editor | Action Name
101 //
102 // | VS Code | **Rust Analyzer: Memory Usage (Clears Database)**
103 // |===
104 pub fn per_query_memory_usage(&mut self) -> Vec<(String, Bytes)> {
105 let mut acc: Vec<(String, Bytes)> = vec![];
106 let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();
107 macro_rules! sweep_each_query {
108 ($($q:path)*) => {$(
109 let before = memory_usage().allocated;
110 $q.in_db(self).sweep(sweep);
111 let after = memory_usage().allocated;
112 let q: $q = Default::default();
113 let name = format!("{:?}", q);
114 acc.push((name, before - after));
115
116 let before = memory_usage().allocated;
117 $q.in_db(self).sweep(sweep.discard_everything());
118 let after = memory_usage().allocated;
119 let q: $q = Default::default();
120 let name = format!("{:?} (deps)", q);
121 acc.push((name, before - after));
122
123 let before = memory_usage().allocated;
124 $q.in_db(self).purge();
125 let after = memory_usage().allocated;
126 let q: $q = Default::default();
127 let name = format!("{:?} (purge)", q);
128 acc.push((name, before - after));
129 )*}
130 }
131 sweep_each_query![
132 // SourceDatabase
133 base_db::ParseQuery
134 base_db::CrateGraphQuery
135
136 // SourceDatabaseExt
137 base_db::FileTextQuery
138 base_db::FileSourceRootQuery
139 base_db::SourceRootQuery
140 base_db::SourceRootCratesQuery
141
142 // AstDatabase
143 hir::db::AstIdMapQuery
144 hir::db::MacroArgTextQuery
145 hir::db::MacroDefQuery
146 hir::db::ParseMacroQuery
147 hir::db::MacroExpandQuery
148
149 // DefDatabase
150 hir::db::ItemTreeQuery
151 hir::db::CrateDefMapQueryQuery
152 hir::db::StructDataQuery
153 hir::db::UnionDataQuery
154 hir::db::EnumDataQuery
155 hir::db::ImplDataQuery
156 hir::db::TraitDataQuery
157 hir::db::TypeAliasDataQuery
158 hir::db::FunctionDataQuery
159 hir::db::ConstDataQuery
160 hir::db::StaticDataQuery
161 hir::db::BodyWithSourceMapQuery
162 hir::db::BodyQuery
163 hir::db::ExprScopesQuery
164 hir::db::GenericParamsQuery
165 hir::db::AttrsQuery
166 hir::db::ModuleLangItemsQuery
167 hir::db::CrateLangItemsQuery
168 hir::db::LangItemQuery
169 hir::db::DocumentationQuery
170 hir::db::ImportMapQuery
171
172 // HirDatabase
173 hir::db::InferQueryQuery
174 hir::db::TyQuery
175 hir::db::ValueTyQuery
176 hir::db::ImplSelfTyQuery
177 hir::db::ImplTraitQuery
178 hir::db::FieldTypesQuery
179 hir::db::CallableItemSignatureQuery
180 hir::db::GenericPredicatesForParamQuery
181 hir::db::GenericPredicatesQuery
182 hir::db::GenericDefaultsQuery
183 hir::db::InherentImplsInCrateQuery
184 hir::db::TraitImplsInCrateQuery
185 hir::db::TraitImplsInDepsQuery
186 hir::db::AssociatedTyDataQuery
187 hir::db::AssociatedTyDataQuery
188 hir::db::TraitDatumQuery
189 hir::db::StructDatumQuery
190 hir::db::ImplDatumQuery
191 hir::db::FnDefDatumQuery
192 hir::db::ReturnTypeImplTraitsQuery
193 hir::db::InternCallableDefQuery
194 hir::db::InternTypeParamIdQuery
195 hir::db::InternImplTraitIdQuery
196 hir::db::InternClosureQuery
197 hir::db::AssociatedTyValueQuery
198 hir::db::TraitSolveQuery
199
200 // SymbolsDatabase
201 crate::symbol_index::FileSymbolsQuery
202 crate::symbol_index::LibrarySymbolsQuery
203 crate::symbol_index::LocalRootsQuery
204 crate::symbol_index::LibraryRootsQuery
205
206 // LineIndexDatabase
207 crate::LineIndexQuery
208 ];
209
210 // To collect interned data, we need to bump the revision counter by performing a synthetic
211 // write.
212 // We do this after collecting the non-interned queries to correctly attribute memory used
213 // by interned data.
214 self.salsa_runtime_mut().synthetic_write(Durability::HIGH);
215
216 sweep_each_query![
217 // AstDatabase
218 hir::db::InternMacroQuery
219 hir::db::InternEagerExpansionQuery
220
221 // InternDatabase
222 hir::db::InternFunctionQuery
223 hir::db::InternStructQuery
224 hir::db::InternUnionQuery
225 hir::db::InternEnumQuery
226 hir::db::InternConstQuery
227 hir::db::InternStaticQuery
228 hir::db::InternTraitQuery
229 hir::db::InternTypeAliasQuery
230 hir::db::InternImplQuery
231
232 // HirDatabase
233 hir::db::InternTypeParamIdQuery
234 ];
235
236 acc.sort_by_key(|it| std::cmp::Reverse(it.1));
237 acc
238 }
239}