aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_analysis/src/db.rs41
-rw-r--r--crates/ra_analysis/src/descriptors/module/nameres.rs64
2 files changed, 104 insertions, 1 deletions
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs
index 887d687ea..7c28c9a2b 100644
--- a/crates/ra_analysis/src/db.rs
+++ b/crates/ra_analysis/src/db.rs
@@ -1,5 +1,6 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use parking_lot::Mutex;
3use ra_editor::LineIndex; 4use ra_editor::LineIndex;
4use ra_syntax::{SourceFileNode, SyntaxNode}; 5use ra_syntax::{SourceFileNode, SyntaxNode};
5use salsa::{self, Database}; 6use salsa::{self, Database};
@@ -18,6 +19,11 @@ use crate::{
18 19
19#[derive(Debug)] 20#[derive(Debug)]
20pub(crate) struct RootDatabase { 21pub(crate) struct RootDatabase {
22 #[cfg(test)]
23 events: Mutex<Option<Vec<salsa::Event<RootDatabase>>>>,
24 #[cfg(not(test))]
25 events: (),
26
21 runtime: salsa::Runtime<RootDatabase>, 27 runtime: salsa::Runtime<RootDatabase>,
22 id_maps: IdMaps, 28 id_maps: IdMaps,
23} 29}
@@ -26,11 +32,22 @@ impl salsa::Database for RootDatabase {
26 fn salsa_runtime(&self) -> &salsa::Runtime<RootDatabase> { 32 fn salsa_runtime(&self) -> &salsa::Runtime<RootDatabase> {
27 &self.runtime 33 &self.runtime
28 } 34 }
35
36 fn salsa_event(&self, event: impl Fn() -> salsa::Event<RootDatabase>) {
37 #[cfg(test)]
38 {
39 let mut events = self.events.lock();
40 if let Some(events) = &mut *events {
41 events.push(event());
42 }
43 }
44 }
29} 45}
30 46
31impl Default for RootDatabase { 47impl Default for RootDatabase {
32 fn default() -> RootDatabase { 48 fn default() -> RootDatabase {
33 let mut db = RootDatabase { 49 let mut db = RootDatabase {
50 events: Default::default(),
34 runtime: salsa::Runtime::default(), 51 runtime: salsa::Runtime::default(),
35 id_maps: IdMaps::default(), 52 id_maps: IdMaps::default(),
36 }; 53 };
@@ -55,6 +72,7 @@ pub(crate) fn check_canceled(db: &impl salsa::Database) -> Cancelable<()> {
55impl salsa::ParallelDatabase for RootDatabase { 72impl salsa::ParallelDatabase for RootDatabase {
56 fn snapshot(&self) -> salsa::Snapshot<RootDatabase> { 73 fn snapshot(&self) -> salsa::Snapshot<RootDatabase> {
57 salsa::Snapshot::new(RootDatabase { 74 salsa::Snapshot::new(RootDatabase {
75 events: Default::default(),
58 runtime: self.runtime.snapshot(self), 76 runtime: self.runtime.snapshot(self),
59 id_maps: self.id_maps.clone(), 77 id_maps: self.id_maps.clone(),
60 }) 78 })
@@ -67,6 +85,29 @@ impl IdDatabase for RootDatabase {
67 } 85 }
68} 86}
69 87
88#[cfg(test)]
89impl RootDatabase {
90 pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<RootDatabase>> {
91 *self.events.lock() = Some(Vec::new());
92 f();
93 let events = self.events.lock().take().unwrap();
94 events
95 }
96
97 pub(crate) fn log_executed(&self, f: impl FnOnce()) -> Vec<String> {
98 let events = self.log(f);
99 events
100 .into_iter()
101 .filter_map(|e| match e.kind {
102 // This pretty horrible, but `Debug` is the only way to inspect
103 // QueryDescriptor at the moment.
104 salsa::EventKind::WillExecute { descriptor } => Some(format!("{:?}", descriptor)),
105 _ => None,
106 })
107 .collect()
108 }
109}
110
70salsa::database_storage! { 111salsa::database_storage! {
71 pub(crate) struct RootDatabaseStorage for RootDatabase { 112 pub(crate) struct RootDatabaseStorage for RootDatabase {
72 impl crate::input::FilesDatabase { 113 impl crate::input::FilesDatabase {
diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs
index 4c555421d..648ec5e43 100644
--- a/crates/ra_analysis/src/descriptors/module/nameres.rs
+++ b/crates/ra_analysis/src/descriptors/module/nameres.rs
@@ -358,7 +358,8 @@ where
358#[cfg(test)] 358#[cfg(test)]
359mod tests { 359mod tests {
360 use crate::{ 360 use crate::{
361 mock_analysis::analysis_and_position, 361 AnalysisChange,
362 mock_analysis::{MockAnalysis, analysis_and_position},
362 descriptors::{DescriptorDatabase, module::ModuleDescriptor}, 363 descriptors::{DescriptorDatabase, module::ModuleDescriptor},
363 input::FilesDatabase, 364 input::FilesDatabase,
364}; 365};
@@ -396,4 +397,65 @@ mod tests {
396 let resolution = &item_map.per_module[&module_id].items[&name]; 397 let resolution = &item_map.per_module[&module_id].items[&name];
397 assert!(resolution.def_id.is_some()); 398 assert!(resolution.def_id.is_some());
398 } 399 }
400
401 #[test]
402 fn typing_inside_a_function_should_not_invalidate_item_map() {
403 let mock_analysis = MockAnalysis::with_files(
404 "
405 //- /lib.rs
406 mod foo;
407
408 use crate::foo::bar::Baz;
409
410 fn foo() -> i32 {
411 1 + 1
412 }
413 //- /foo/mod.rs
414 pub mod bar;
415
416 //- /foo/bar.rs
417 pub struct Baz;
418 ",
419 );
420
421 let file_id = mock_analysis.id_of("/lib.rs");
422 let mut host = mock_analysis.analysis_host();
423
424 let source_root = host.analysis().imp.db.file_source_root(file_id);
425
426 {
427 let db = host.analysis().imp.db;
428 let events = db.log_executed(|| {
429 db._item_map(source_root).unwrap();
430 });
431 assert!(format!("{:?}", events).contains("_item_map"))
432 }
433
434 let mut change = AnalysisChange::new();
435
436 change.change_file(
437 file_id,
438 "
439 mod foo;
440
441 use crate::foo::bar::Baz;
442
443 fn foo() -> i32 { 92 }
444 "
445 .to_string(),
446 );
447
448 host.apply_change(change);
449
450 {
451 let db = host.analysis().imp.db;
452 let events = db.log_executed(|| {
453 db._item_map(source_root).unwrap();
454 });
455 // assert!(
456 // !format!("{:?}", events).contains("_item_map"),
457 // "{:#?}", events
458 // )
459 }
460 }
399} 461}