aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/debug.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/debug.rs')
-rw-r--r--crates/ra_hir/src/debug.rs83
1 files changed, 83 insertions, 0 deletions
diff --git a/crates/ra_hir/src/debug.rs b/crates/ra_hir/src/debug.rs
new file mode 100644
index 000000000..87f3180c3
--- /dev/null
+++ b/crates/ra_hir/src/debug.rs
@@ -0,0 +1,83 @@
1//! printf debugging infrastructure for rust-analyzer.
2//!
3//! When you print a hir type, like a module, using `eprintln!("{:?}", module)`,
4//! you usually get back a numeric ID, which doesn't tell you much:
5//! `Module(92)`.
6//!
7//! This module adds convenience `debug` methods to various types, which resolve
8//! the id to a human-readable location info:
9//!
10//! ```not_rust
11//! eprintln!("{:?}", module.debug(db));
12//! =>
13//! Module { name: collections, path: "liballoc/collections/mod.rs" }
14//! ```
15//!
16//! Note that to get this info, we might need to execute queries! So
17//!
18//! * don't use the `debug` methods for logging
19//! * when debugging, be aware that interference is possible.
20
21use std::fmt;
22
23use ra_db::{CrateId, FileId};
24
25use crate::{db::HirDatabase, Crate, Module, Name};
26
27impl Crate {
28 pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ {
29 debug_fn(move |fmt| db.debug_crate(self, fmt))
30 }
31}
32
33impl Module {
34 pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ {
35 debug_fn(move |fmt| db.debug_module(self, fmt))
36 }
37}
38
39pub trait HirDebugHelper: HirDatabase {
40 fn crate_name(&self, _krate: CrateId) -> Option<String> {
41 None
42 }
43 fn file_path(&self, _file_id: FileId) -> Option<String> {
44 None
45 }
46}
47
48pub trait HirDebugDatabase {
49 fn debug_crate(&self, krate: Crate, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
50 fn debug_module(&self, module: Module, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
51}
52
53impl<DB: HirDebugHelper> HirDebugDatabase for DB {
54 fn debug_crate(&self, krate: Crate, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
55 let mut builder = fmt.debug_tuple("Crate");
56 match self.crate_name(krate.crate_id) {
57 Some(name) => builder.field(&name),
58 None => builder.field(&krate.crate_id),
59 }
60 .finish()
61 }
62
63 fn debug_module(&self, module: Module, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
64 let file_id = module.definition_source(self).file_id.original_file(self);
65 let path = self.file_path(file_id);
66 fmt.debug_struct("Module")
67 .field("name", &module.name(self).unwrap_or_else(Name::missing))
68 .field("path", &path.unwrap_or_else(|| "N/A".to_string()))
69 .finish()
70 }
71}
72
73fn debug_fn(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Debug {
74 struct DebugFn<F>(F);
75
76 impl<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result> fmt::Debug for DebugFn<F> {
77 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
78 (&self.0)(fmt)
79 }
80 }
81
82 DebugFn(f)
83}