aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_db/src/change.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_db/src/change.rs')
-rw-r--r--crates/ra_ide_db/src/change.rs296
1 files changed, 0 insertions, 296 deletions
diff --git a/crates/ra_ide_db/src/change.rs b/crates/ra_ide_db/src/change.rs
deleted file mode 100644
index 32d9a8d1f..000000000
--- a/crates/ra_ide_db/src/change.rs
+++ /dev/null
@@ -1,296 +0,0 @@
1//! Defines a unit of change that can applied to a state of IDE to get the next
2//! state. Changes are transactional.
3
4use std::{fmt, sync::Arc, time};
5
6use ra_db::{
7 salsa::{Database, Durability, SweepStrategy},
8 CrateGraph, FileId, SourceDatabase, SourceDatabaseExt, SourceRoot, SourceRootId,
9};
10use ra_prof::{memory_usage, profile, Bytes};
11use rustc_hash::FxHashSet;
12
13use crate::{symbol_index::SymbolsDatabase, RootDatabase};
14
15#[derive(Default)]
16pub struct AnalysisChange {
17 roots: Option<Vec<SourceRoot>>,
18 files_changed: Vec<(FileId, Option<Arc<String>>)>,
19 crate_graph: Option<CrateGraph>,
20}
21
22impl fmt::Debug for AnalysisChange {
23 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
24 let mut d = fmt.debug_struct("AnalysisChange");
25 if let Some(roots) = &self.roots {
26 d.field("roots", roots);
27 }
28 if !self.files_changed.is_empty() {
29 d.field("files_changed", &self.files_changed.len());
30 }
31 if self.crate_graph.is_some() {
32 d.field("crate_graph", &self.crate_graph);
33 }
34 d.finish()
35 }
36}
37
38impl AnalysisChange {
39 pub fn new() -> AnalysisChange {
40 AnalysisChange::default()
41 }
42
43 pub fn set_roots(&mut self, roots: Vec<SourceRoot>) {
44 self.roots = Some(roots);
45 }
46
47 pub fn change_file(&mut self, file_id: FileId, new_text: Option<Arc<String>>) {
48 self.files_changed.push((file_id, new_text))
49 }
50
51 pub fn set_crate_graph(&mut self, graph: CrateGraph) {
52 self.crate_graph = Some(graph);
53 }
54}
55
56#[derive(Debug)]
57struct AddFile {
58 file_id: FileId,
59 path: String,
60 text: Arc<String>,
61}
62
63#[derive(Debug)]
64struct RemoveFile {
65 file_id: FileId,
66 path: String,
67}
68
69#[derive(Default)]
70struct RootChange {
71 added: Vec<AddFile>,
72 removed: Vec<RemoveFile>,
73}
74
75impl fmt::Debug for RootChange {
76 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
77 fmt.debug_struct("AnalysisChange")
78 .field("added", &self.added.len())
79 .field("removed", &self.removed.len())
80 .finish()
81 }
82}
83
84const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100);
85
86impl RootDatabase {
87 pub fn request_cancellation(&mut self) {
88 let _p = profile("RootDatabase::request_cancellation");
89 self.salsa_runtime_mut().synthetic_write(Durability::LOW);
90 }
91
92 pub fn apply_change(&mut self, change: AnalysisChange) {
93 let _p = profile("RootDatabase::apply_change");
94 self.request_cancellation();
95 log::info!("apply_change {:?}", change);
96 if let Some(roots) = change.roots {
97 let mut local_roots = FxHashSet::default();
98 let mut library_roots = FxHashSet::default();
99 for (idx, root) in roots.into_iter().enumerate() {
100 let root_id = SourceRootId(idx as u32);
101 let durability = durability(&root);
102 if root.is_library {
103 library_roots.insert(root_id);
104 } else {
105 local_roots.insert(root_id);
106 }
107 for file_id in root.iter() {
108 self.set_file_source_root_with_durability(file_id, root_id, durability);
109 }
110 self.set_source_root_with_durability(root_id, Arc::new(root), durability);
111 }
112 self.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
113 self.set_library_roots_with_durability(Arc::new(library_roots), Durability::HIGH);
114 }
115
116 for (file_id, text) in change.files_changed {
117 let source_root_id = self.file_source_root(file_id);
118 let source_root = self.source_root(source_root_id);
119 let durability = durability(&source_root);
120 // XXX: can't actually remove the file, just reset the text
121 let text = text.unwrap_or_default();
122 self.set_file_text_with_durability(file_id, text, durability)
123 }
124 if let Some(crate_graph) = change.crate_graph {
125 self.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH)
126 }
127 }
128
129 pub fn maybe_collect_garbage(&mut self) {
130 if cfg!(feature = "wasm") {
131 return;
132 }
133
134 if self.last_gc_check.elapsed() > GC_COOLDOWN {
135 self.last_gc_check = crate::wasm_shims::Instant::now();
136 }
137 }
138
139 pub fn collect_garbage(&mut self) {
140 if cfg!(feature = "wasm") {
141 return;
142 }
143
144 let _p = profile("RootDatabase::collect_garbage");
145 self.last_gc = crate::wasm_shims::Instant::now();
146
147 let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();
148
149 ra_db::ParseQuery.in_db(self).sweep(sweep);
150 hir::db::ParseMacroQuery.in_db(self).sweep(sweep);
151
152 // Macros do take significant space, but less then the syntax trees
153 // self.query(hir::db::MacroDefQuery).sweep(sweep);
154 // self.query(hir::db::MacroArgTextQuery).sweep(sweep);
155 // self.query(hir::db::MacroExpandQuery).sweep(sweep);
156
157 hir::db::AstIdMapQuery.in_db(self).sweep(sweep);
158
159 hir::db::BodyWithSourceMapQuery.in_db(self).sweep(sweep);
160
161 hir::db::ExprScopesQuery.in_db(self).sweep(sweep);
162 hir::db::InferQueryQuery.in_db(self).sweep(sweep);
163 hir::db::BodyQuery.in_db(self).sweep(sweep);
164 }
165
166 // Feature: Memory Usage
167 //
168 // Clears rust-analyzer's internal database and prints memory usage statistics.
169 //
170 // |===
171 // | Editor | Action Name
172 //
173 // | VS Code | **Rust Analyzer: Memory Usage (Clears Database)**
174 // |===
175 pub fn per_query_memory_usage(&mut self) -> Vec<(String, Bytes)> {
176 let mut acc: Vec<(String, Bytes)> = vec![];
177 let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();
178 macro_rules! sweep_each_query {
179 ($($q:path)*) => {$(
180 let before = memory_usage().allocated;
181 $q.in_db(self).sweep(sweep);
182 let after = memory_usage().allocated;
183 let q: $q = Default::default();
184 let name = format!("{:?}", q);
185 acc.push((name, before - after));
186
187 let before = memory_usage().allocated;
188 $q.in_db(self).sweep(sweep.discard_everything());
189 let after = memory_usage().allocated;
190 let q: $q = Default::default();
191 let name = format!("{:?} (deps)", q);
192 acc.push((name, before - after));
193 )*}
194 }
195 sweep_each_query![
196 // SourceDatabase
197 ra_db::ParseQuery
198 ra_db::SourceRootCratesQuery
199
200 // AstDatabase
201 hir::db::AstIdMapQuery
202 hir::db::MacroArgTextQuery
203 hir::db::MacroDefQuery
204 hir::db::ParseMacroQuery
205 hir::db::MacroExpandQuery
206
207 // DefDatabase
208 hir::db::ItemTreeQuery
209 hir::db::CrateDefMapQueryQuery
210 hir::db::StructDataQuery
211 hir::db::UnionDataQuery
212 hir::db::EnumDataQuery
213 hir::db::ImplDataQuery
214 hir::db::TraitDataQuery
215 hir::db::TypeAliasDataQuery
216 hir::db::FunctionDataQuery
217 hir::db::ConstDataQuery
218 hir::db::StaticDataQuery
219 hir::db::BodyWithSourceMapQuery
220 hir::db::BodyQuery
221 hir::db::ExprScopesQuery
222 hir::db::GenericParamsQuery
223 hir::db::AttrsQuery
224 hir::db::ModuleLangItemsQuery
225 hir::db::CrateLangItemsQuery
226 hir::db::LangItemQuery
227 hir::db::DocumentationQuery
228 hir::db::ImportMapQuery
229
230 // HirDatabase
231 hir::db::InferQueryQuery
232 hir::db::TyQuery
233 hir::db::ValueTyQuery
234 hir::db::ImplSelfTyQuery
235 hir::db::ImplTraitQuery
236 hir::db::FieldTypesQuery
237 hir::db::CallableItemSignatureQuery
238 hir::db::GenericPredicatesForParamQuery
239 hir::db::GenericPredicatesQuery
240 hir::db::GenericDefaultsQuery
241 hir::db::InherentImplsInCrateQuery
242 hir::db::TraitImplsInCrateQuery
243 hir::db::TraitImplsInDepsQuery
244 hir::db::AssociatedTyDataQuery
245 hir::db::TraitDatumQuery
246 hir::db::StructDatumQuery
247 hir::db::ImplDatumQuery
248 hir::db::AssociatedTyValueQuery
249 hir::db::TraitSolveQuery
250 hir::db::ReturnTypeImplTraitsQuery
251
252 // SymbolsDatabase
253 crate::symbol_index::FileSymbolsQuery
254
255 // LineIndexDatabase
256 crate::LineIndexQuery
257 ];
258
259 // To collect interned data, we need to bump the revision counter by performing a synthetic
260 // write.
261 // We do this after collecting the non-interned queries to correctly attribute memory used
262 // by interned data.
263 self.salsa_runtime_mut().synthetic_write(Durability::HIGH);
264
265 sweep_each_query![
266 // AstDatabase
267 hir::db::InternMacroQuery
268 hir::db::InternEagerExpansionQuery
269
270 // InternDatabase
271 hir::db::InternFunctionQuery
272 hir::db::InternStructQuery
273 hir::db::InternUnionQuery
274 hir::db::InternEnumQuery
275 hir::db::InternConstQuery
276 hir::db::InternStaticQuery
277 hir::db::InternTraitQuery
278 hir::db::InternTypeAliasQuery
279 hir::db::InternImplQuery
280
281 // HirDatabase
282 hir::db::InternTypeParamIdQuery
283 ];
284
285 acc.sort_by_key(|it| std::cmp::Reverse(it.1));
286 acc
287 }
288}
289
290fn durability(source_root: &SourceRoot) -> Durability {
291 if source_root.is_library {
292 Durability::HIGH
293 } else {
294 Durability::LOW
295 }
296}