aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-09-08 07:48:45 +0100
committerAleksey Kladov <[email protected]>2019-09-09 10:32:16 +0100
commitef2b84ddf119c950272c5f1eb321f3f9e90bedd4 (patch)
treed746c95cef14b27f67f1e5fd32d289e6d20b4d57 /crates/ra_hir
parent734a43e95afc97773c234956a95b78caed88f2a3 (diff)
introduce hir debugging infra
This is to make debugging rust-analyzer easier. The idea is that `dbg!(krate.debug(db))` will print the actual, fuzzy crate name, instead of precise ID. Debug printing infra is a separate thing, to make sure that the actual hir doesn't have access to global information. Do not use `.debug` for `log::` logging: debugging executes queries, and might introduce unneded dependencies to the crate graph
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/db.rs3
-rw-r--r--crates/ra_hir/src/debug.rs64
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir/src/mock.rs25
4 files changed, 90 insertions, 3 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 7b7974f5b..f7f124904 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -5,6 +5,7 @@ use ra_syntax::{ast, Parse, SmolStr, SyntaxNode};
5 5
6use crate::{ 6use crate::{
7 adt::{EnumData, StructData}, 7 adt::{EnumData, StructData},
8 debug::HirDebugDatabase,
8 generics::{GenericDef, GenericParams}, 9 generics::{GenericDef, GenericParams},
9 ids, 10 ids,
10 impl_block::{ImplBlock, ImplSourceMap, ModuleImplBlocks}, 11 impl_block::{ImplBlock, ImplSourceMap, ModuleImplBlocks},
@@ -83,7 +84,7 @@ pub trait AstDatabase: InternDatabase {
83// This database uses `AstDatabase` internally, 84// This database uses `AstDatabase` internally,
84#[salsa::query_group(DefDatabaseStorage)] 85#[salsa::query_group(DefDatabaseStorage)]
85#[salsa::requires(AstDatabase)] 86#[salsa::requires(AstDatabase)]
86pub trait DefDatabase: InternDatabase { 87pub trait DefDatabase: InternDatabase + HirDebugDatabase {
87 #[salsa::invoke(crate::adt::StructData::struct_data_query)] 88 #[salsa::invoke(crate::adt::StructData::struct_data_query)]
88 fn struct_data(&self, s: Struct) -> Arc<StructData>; 89 fn struct_data(&self, s: Struct) -> Arc<StructData>;
89 90
diff --git a/crates/ra_hir/src/debug.rs b/crates/ra_hir/src/debug.rs
new file mode 100644
index 000000000..5a835741d
--- /dev/null
+++ b/crates/ra_hir/src/debug.rs
@@ -0,0 +1,64 @@
1use std::{cell::Cell, fmt};
2
3use ra_db::{CrateId, FileId};
4
5use crate::{db::HirDatabase, Crate, Module, Name};
6
7impl Crate {
8 pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ {
9 debug_fn(move |fmt| db.debug_crate(self, fmt))
10 }
11}
12
13impl Module {
14 pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ {
15 debug_fn(move |fmt| db.debug_module(self, fmt))
16 }
17}
18
19pub trait HirDebugHelper: HirDatabase {
20 fn crate_name(&self, _krate: CrateId) -> Option<String> {
21 None
22 }
23 fn file_path(&self, _file_id: FileId) -> Option<String> {
24 None
25 }
26}
27
28pub trait HirDebugDatabase {
29 fn debug_crate(&self, krate: Crate, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
30 fn debug_module(&self, module: Module, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
31}
32
33impl<DB: HirDebugHelper> HirDebugDatabase for DB {
34 fn debug_crate(&self, krate: Crate, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
35 let mut builder = fmt.debug_tuple("Crate");
36 match self.crate_name(krate.crate_id) {
37 Some(name) => builder.field(&name),
38 None => builder.field(&krate.crate_id),
39 }
40 .finish()
41 }
42
43 fn debug_module(&self, module: Module, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
44 let file_id = module.definition_source(self).file_id.original_file(self);
45 let path = self.file_path(file_id);
46 fmt.debug_struct("Module")
47 .field("name", &module.name(self).unwrap_or_else(Name::missing))
48 .field("path", &path.unwrap_or_else(|| "N/A".to_string()))
49 .finish()
50 }
51}
52
53fn debug_fn(f: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Debug {
54 struct DebugFn<F>(Cell<Option<F>>);
55
56 impl<F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result> fmt::Debug for DebugFn<F> {
57 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
58 let f = self.0.take().unwrap();
59 f(fmt)
60 }
61 }
62
63 DebugFn(Cell::new(Some(f)))
64}
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 7c2a68992..24ee84f86 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -20,6 +20,7 @@ macro_rules! impl_froms {
20} 20}
21 21
22mod either; 22mod either;
23pub mod debug;
23 24
24pub mod db; 25pub mod db;
25#[macro_use] 26#[macro_use]
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index 972f0ece5..8dcea5071 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -2,13 +2,14 @@ use std::{panic, sync::Arc};
2 2
3use parking_lot::Mutex; 3use parking_lot::Mutex;
4use ra_db::{ 4use ra_db::{
5 salsa, CrateGraph, Edition, FileId, FilePosition, SourceDatabase, SourceRoot, SourceRootId, 5 salsa, CrateGraph, CrateId, Edition, FileId, FilePosition, SourceDatabase, SourceRoot,
6 SourceRootId,
6}; 7};
7use relative_path::RelativePathBuf; 8use relative_path::RelativePathBuf;
8use rustc_hash::FxHashMap; 9use rustc_hash::FxHashMap;
9use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; 10use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER};
10 11
11use crate::{db, diagnostics::DiagnosticSink}; 12use crate::{db, debug::HirDebugHelper, diagnostics::DiagnosticSink};
12 13
13pub const WORKSPACE: SourceRootId = SourceRootId(0); 14pub const WORKSPACE: SourceRootId = SourceRootId(0);
14 15
@@ -24,10 +25,22 @@ pub struct MockDatabase {
24 events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>, 25 events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>,
25 runtime: salsa::Runtime<MockDatabase>, 26 runtime: salsa::Runtime<MockDatabase>,
26 files: FxHashMap<String, FileId>, 27 files: FxHashMap<String, FileId>,
28 crate_names: Arc<FxHashMap<CrateId, String>>,
29 file_paths: Arc<FxHashMap<FileId, String>>,
27} 30}
28 31
29impl panic::RefUnwindSafe for MockDatabase {} 32impl panic::RefUnwindSafe for MockDatabase {}
30 33
34impl HirDebugHelper for MockDatabase {
35 fn crate_name(&self, krate: CrateId) -> Option<String> {
36 self.crate_names.get(&krate).cloned()
37 }
38
39 fn file_path(&self, file_id: FileId) -> Option<String> {
40 self.file_paths.get(&file_id).cloned()
41 }
42}
43
31impl MockDatabase { 44impl MockDatabase {
32 pub fn with_files(fixture: &str) -> MockDatabase { 45 pub fn with_files(fixture: &str) -> MockDatabase {
33 let (db, position) = MockDatabase::from_fixture(fixture); 46 let (db, position) = MockDatabase::from_fixture(fixture);
@@ -62,6 +75,7 @@ impl MockDatabase {
62 for (crate_name, (crate_root, edition, _)) in graph.0.iter() { 75 for (crate_name, (crate_root, edition, _)) in graph.0.iter() {
63 let crate_root = self.file_id_of(&crate_root); 76 let crate_root = self.file_id_of(&crate_root);
64 let crate_id = crate_graph.add_crate_root(crate_root, *edition); 77 let crate_id = crate_graph.add_crate_root(crate_root, *edition);
78 Arc::make_mut(&mut self.crate_names).insert(crate_id, crate_name.clone());
65 ids.insert(crate_name, crate_id); 79 ids.insert(crate_name, crate_id);
66 } 80 }
67 for (crate_name, (_, _, deps)) in graph.0.iter() { 81 for (crate_name, (_, _, deps)) in graph.0.iter() {
@@ -151,8 +165,11 @@ impl MockDatabase {
151 let is_crate_root = rel_path == "lib.rs" || rel_path == "/main.rs"; 165 let is_crate_root = rel_path == "lib.rs" || rel_path == "/main.rs";
152 166
153 let file_id = FileId(self.files.len() as u32); 167 let file_id = FileId(self.files.len() as u32);
168
154 let prev = self.files.insert(path.to_string(), file_id); 169 let prev = self.files.insert(path.to_string(), file_id);
155 assert!(prev.is_none(), "duplicate files in the text fixture"); 170 assert!(prev.is_none(), "duplicate files in the text fixture");
171 Arc::make_mut(&mut self.file_paths).insert(file_id, path.to_string());
172
156 let text = Arc::new(text.to_string()); 173 let text = Arc::new(text.to_string());
157 self.set_file_text(file_id, text); 174 self.set_file_text(file_id, text);
158 self.set_file_relative_path(file_id, rel_path.clone()); 175 self.set_file_relative_path(file_id, rel_path.clone());
@@ -200,6 +217,8 @@ impl Default for MockDatabase {
200 events: Default::default(), 217 events: Default::default(),
201 runtime: salsa::Runtime::default(), 218 runtime: salsa::Runtime::default(),
202 files: FxHashMap::default(), 219 files: FxHashMap::default(),
220 crate_names: Default::default(),
221 file_paths: Default::default(),
203 }; 222 };
204 db.set_crate_graph(Default::default()); 223 db.set_crate_graph(Default::default());
205 db 224 db
@@ -213,6 +232,8 @@ impl salsa::ParallelDatabase for MockDatabase {
213 runtime: self.runtime.snapshot(self), 232 runtime: self.runtime.snapshot(self),
214 // only the root database can be used to get file_id by path. 233 // only the root database can be used to get file_id by path.
215 files: FxHashMap::default(), 234 files: FxHashMap::default(),
235 file_paths: Arc::clone(&self.file_paths),
236 crate_names: Arc::clone(&self.crate_names),
216 }) 237 })
217 } 238 }
218} 239}