mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 22:01:37 +00:00
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
This commit is contained in:
parent
734a43e95a
commit
ef2b84ddf1
11 changed files with 166 additions and 18 deletions
|
@ -5,6 +5,7 @@ use ra_syntax::{ast, Parse, SmolStr, SyntaxNode};
|
|||
|
||||
use crate::{
|
||||
adt::{EnumData, StructData},
|
||||
debug::HirDebugDatabase,
|
||||
generics::{GenericDef, GenericParams},
|
||||
ids,
|
||||
impl_block::{ImplBlock, ImplSourceMap, ModuleImplBlocks},
|
||||
|
@ -83,7 +84,7 @@ pub trait AstDatabase: InternDatabase {
|
|||
// This database uses `AstDatabase` internally,
|
||||
#[salsa::query_group(DefDatabaseStorage)]
|
||||
#[salsa::requires(AstDatabase)]
|
||||
pub trait DefDatabase: InternDatabase {
|
||||
pub trait DefDatabase: InternDatabase + HirDebugDatabase {
|
||||
#[salsa::invoke(crate::adt::StructData::struct_data_query)]
|
||||
fn struct_data(&self, s: Struct) -> Arc<StructData>;
|
||||
|
||||
|
|
64
crates/ra_hir/src/debug.rs
Normal file
64
crates/ra_hir/src/debug.rs
Normal file
|
@ -0,0 +1,64 @@
|
|||
use std::{cell::Cell, fmt};
|
||||
|
||||
use ra_db::{CrateId, FileId};
|
||||
|
||||
use crate::{db::HirDatabase, Crate, Module, Name};
|
||||
|
||||
impl Crate {
|
||||
pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ {
|
||||
debug_fn(move |fmt| db.debug_crate(self, fmt))
|
||||
}
|
||||
}
|
||||
|
||||
impl Module {
|
||||
pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ {
|
||||
debug_fn(move |fmt| db.debug_module(self, fmt))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HirDebugHelper: HirDatabase {
|
||||
fn crate_name(&self, _krate: CrateId) -> Option<String> {
|
||||
None
|
||||
}
|
||||
fn file_path(&self, _file_id: FileId) -> Option<String> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HirDebugDatabase {
|
||||
fn debug_crate(&self, krate: Crate, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
|
||||
fn debug_module(&self, module: Module, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
|
||||
}
|
||||
|
||||
impl<DB: HirDebugHelper> HirDebugDatabase for DB {
|
||||
fn debug_crate(&self, krate: Crate, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut builder = fmt.debug_tuple("Crate");
|
||||
match self.crate_name(krate.crate_id) {
|
||||
Some(name) => builder.field(&name),
|
||||
None => builder.field(&krate.crate_id),
|
||||
}
|
||||
.finish()
|
||||
}
|
||||
|
||||
fn debug_module(&self, module: Module, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let file_id = module.definition_source(self).file_id.original_file(self);
|
||||
let path = self.file_path(file_id);
|
||||
fmt.debug_struct("Module")
|
||||
.field("name", &module.name(self).unwrap_or_else(Name::missing))
|
||||
.field("path", &path.unwrap_or_else(|| "N/A".to_string()))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
fn debug_fn(f: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Debug {
|
||||
struct DebugFn<F>(Cell<Option<F>>);
|
||||
|
||||
impl<F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result> fmt::Debug for DebugFn<F> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let f = self.0.take().unwrap();
|
||||
f(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
DebugFn(Cell::new(Some(f)))
|
||||
}
|
|
@ -20,6 +20,7 @@ macro_rules! impl_froms {
|
|||
}
|
||||
|
||||
mod either;
|
||||
pub mod debug;
|
||||
|
||||
pub mod db;
|
||||
#[macro_use]
|
||||
|
|
|
@ -2,13 +2,14 @@ use std::{panic, sync::Arc};
|
|||
|
||||
use parking_lot::Mutex;
|
||||
use ra_db::{
|
||||
salsa, CrateGraph, Edition, FileId, FilePosition, SourceDatabase, SourceRoot, SourceRootId,
|
||||
salsa, CrateGraph, CrateId, Edition, FileId, FilePosition, SourceDatabase, SourceRoot,
|
||||
SourceRootId,
|
||||
};
|
||||
use relative_path::RelativePathBuf;
|
||||
use rustc_hash::FxHashMap;
|
||||
use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER};
|
||||
|
||||
use crate::{db, diagnostics::DiagnosticSink};
|
||||
use crate::{db, debug::HirDebugHelper, diagnostics::DiagnosticSink};
|
||||
|
||||
pub const WORKSPACE: SourceRootId = SourceRootId(0);
|
||||
|
||||
|
@ -24,10 +25,22 @@ pub struct MockDatabase {
|
|||
events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>,
|
||||
runtime: salsa::Runtime<MockDatabase>,
|
||||
files: FxHashMap<String, FileId>,
|
||||
crate_names: Arc<FxHashMap<CrateId, String>>,
|
||||
file_paths: Arc<FxHashMap<FileId, String>>,
|
||||
}
|
||||
|
||||
impl panic::RefUnwindSafe for MockDatabase {}
|
||||
|
||||
impl HirDebugHelper for MockDatabase {
|
||||
fn crate_name(&self, krate: CrateId) -> Option<String> {
|
||||
self.crate_names.get(&krate).cloned()
|
||||
}
|
||||
|
||||
fn file_path(&self, file_id: FileId) -> Option<String> {
|
||||
self.file_paths.get(&file_id).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
impl MockDatabase {
|
||||
pub fn with_files(fixture: &str) -> MockDatabase {
|
||||
let (db, position) = MockDatabase::from_fixture(fixture);
|
||||
|
@ -62,6 +75,7 @@ impl MockDatabase {
|
|||
for (crate_name, (crate_root, edition, _)) in graph.0.iter() {
|
||||
let crate_root = self.file_id_of(&crate_root);
|
||||
let crate_id = crate_graph.add_crate_root(crate_root, *edition);
|
||||
Arc::make_mut(&mut self.crate_names).insert(crate_id, crate_name.clone());
|
||||
ids.insert(crate_name, crate_id);
|
||||
}
|
||||
for (crate_name, (_, _, deps)) in graph.0.iter() {
|
||||
|
@ -151,8 +165,11 @@ impl MockDatabase {
|
|||
let is_crate_root = rel_path == "lib.rs" || rel_path == "/main.rs";
|
||||
|
||||
let file_id = FileId(self.files.len() as u32);
|
||||
|
||||
let prev = self.files.insert(path.to_string(), file_id);
|
||||
assert!(prev.is_none(), "duplicate files in the text fixture");
|
||||
Arc::make_mut(&mut self.file_paths).insert(file_id, path.to_string());
|
||||
|
||||
let text = Arc::new(text.to_string());
|
||||
self.set_file_text(file_id, text);
|
||||
self.set_file_relative_path(file_id, rel_path.clone());
|
||||
|
@ -200,6 +217,8 @@ impl Default for MockDatabase {
|
|||
events: Default::default(),
|
||||
runtime: salsa::Runtime::default(),
|
||||
files: FxHashMap::default(),
|
||||
crate_names: Default::default(),
|
||||
file_paths: Default::default(),
|
||||
};
|
||||
db.set_crate_graph(Default::default());
|
||||
db
|
||||
|
@ -213,6 +232,8 @@ impl salsa::ParallelDatabase for MockDatabase {
|
|||
runtime: self.runtime.snapshot(self),
|
||||
// only the root database can be used to get file_id by path.
|
||||
files: FxHashMap::default(),
|
||||
file_paths: Arc::clone(&self.file_paths),
|
||||
crate_names: Arc::clone(&self.crate_names),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue