Skip to content

Commit

Permalink
introduce hir debugging infra
Browse files Browse the repository at this point in the history
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
  • Loading branch information
matklad committed Sep 9, 2019
1 parent 734a43e commit ef2b84d
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 18 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 13 additions & 3 deletions crates/ra_db/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ pub struct CyclicDependencies;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CrateId(pub u32);

impl CrateId {
pub fn shift(self, amount: u32) -> CrateId {
CrateId(self.0 + amount)
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Edition {
Edition2018,
Expand Down Expand Up @@ -178,15 +184,19 @@ impl CrateGraph {

/// Extends this crate graph by adding a complete disjoint second crate
/// graph.
pub fn extend(&mut self, other: CrateGraph) {
///
/// The ids of the crates in the `other` graph are shifted by the return
/// amount.
pub fn extend(&mut self, other: CrateGraph) -> u32 {
let start = self.arena.len() as u32;
self.arena.extend(other.arena.into_iter().map(|(id, mut data)| {
let new_id = CrateId(id.0 + start);
let new_id = id.shift(start);
for dep in &mut data.dependencies {
dep.crate_id = CrateId(dep.crate_id.0 + start);
dep.crate_id = dep.crate_id.shift(start);
}
(new_id, data)
}));
start
}

fn dfs_find(&self, target: CrateId, from: CrateId, visited: &mut FxHashSet<CrateId>) -> bool {
Expand Down
3 changes: 2 additions & 1 deletion crates/ra_hir/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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>;

Expand Down
64 changes: 64 additions & 0 deletions crates/ra_hir/src/debug.rs
Original file line number Diff line number Diff line change
@@ -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)))
}
1 change: 1 addition & 0 deletions crates/ra_hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ macro_rules! impl_froms {
}

mod either;
pub mod debug;

pub mod db;
#[macro_use]
Expand Down
25 changes: 23 additions & 2 deletions crates/ra_hir/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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
Expand All @@ -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),
})
}
}
Expand Down
15 changes: 13 additions & 2 deletions crates/ra_ide_api/src/change.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{fmt, sync::Arc, time};

use ra_db::{
salsa::{Database, Durability, SweepStrategy},
CrateGraph, FileId, SourceDatabase, SourceRoot, SourceRootId,
CrateGraph, CrateId, FileId, SourceDatabase, SourceRoot, SourceRootId,
};
use ra_prof::{memory_usage, profile, Bytes};
use ra_syntax::SourceFile;
Expand All @@ -11,7 +11,7 @@ use relative_path::RelativePathBuf;
use rustc_hash::FxHashMap;

use crate::{
db::RootDatabase,
db::{DebugData, RootDatabase},
status::syntax_tree_stats,
symbol_index::{SymbolIndex, SymbolsDatabase},
};
Expand All @@ -23,6 +23,7 @@ pub struct AnalysisChange {
files_changed: Vec<(FileId, Arc<String>)>,
libraries_added: Vec<LibraryData>,
crate_graph: Option<CrateGraph>,
debug_data: DebugData,
}

impl fmt::Debug for AnalysisChange {
Expand Down Expand Up @@ -83,6 +84,14 @@ impl AnalysisChange {
pub fn set_crate_graph(&mut self, graph: CrateGraph) {
self.crate_graph = Some(graph);
}

pub fn set_debug_crate_name(&mut self, crate_id: CrateId, name: String) {
self.debug_data.crate_names.insert(crate_id, name);
}

pub fn set_debug_root_path(&mut self, source_root_id: SourceRootId, path: String) {
self.debug_data.root_paths.insert(source_root_id, path);
}
}

#[derive(Debug)]
Expand Down Expand Up @@ -200,6 +209,8 @@ impl RootDatabase {
if let Some(crate_graph) = change.crate_graph {
self.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH)
}

Arc::make_mut(&mut self.debug_data).merge(change.debug_data)
}

fn apply_root_change(&mut self, root_id: SourceRootId, root_change: RootChange) {
Expand Down
31 changes: 30 additions & 1 deletion crates/ra_ide_api/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ use std::{sync::Arc, time};

use ra_db::{
salsa::{self, Database, Durability},
Canceled, CheckCanceled, FileId, SourceDatabase,
Canceled, CheckCanceled, CrateId, FileId, SourceDatabase, SourceRootId,
};
use rustc_hash::FxHashMap;

use crate::{
symbol_index::{self, SymbolsDatabase},
Expand All @@ -23,10 +24,23 @@ use crate::{
pub(crate) struct RootDatabase {
runtime: salsa::Runtime<RootDatabase>,
pub(crate) feature_flags: Arc<FeatureFlags>,
pub(crate) debug_data: Arc<DebugData>,
pub(crate) last_gc: time::Instant,
pub(crate) last_gc_check: time::Instant,
}

impl hir::debug::HirDebugHelper for RootDatabase {
fn crate_name(&self, krate: CrateId) -> Option<String> {
self.debug_data.crate_names.get(&krate).cloned()
}
fn file_path(&self, file_id: FileId) -> Option<String> {
let source_root_id = self.file_source_root(file_id);
let source_root_path = self.debug_data.root_paths.get(&source_root_id)?;
let file_path = self.file_relative_path(file_id);
Some(format!("{}/{}", source_root_path, file_path.display()))
}
}

impl salsa::Database for RootDatabase {
fn salsa_runtime(&self) -> &salsa::Runtime<RootDatabase> {
&self.runtime
Expand Down Expand Up @@ -58,6 +72,7 @@ impl RootDatabase {
last_gc: time::Instant::now(),
last_gc_check: time::Instant::now(),
feature_flags: Arc::new(feature_flags),
debug_data: Default::default(),
};
db.set_crate_graph_with_durability(Default::default(), Durability::HIGH);
db.set_local_roots_with_durability(Default::default(), Durability::HIGH);
Expand All @@ -77,6 +92,7 @@ impl salsa::ParallelDatabase for RootDatabase {
last_gc: self.last_gc,
last_gc_check: self.last_gc_check,
feature_flags: Arc::clone(&self.feature_flags),
debug_data: Arc::clone(&self.debug_data),
})
}
}
Expand All @@ -90,3 +106,16 @@ fn line_index(db: &impl ra_db::SourceDatabase, file_id: FileId) -> Arc<LineIndex
let text = db.file_text(file_id);
Arc::new(LineIndex::new(&*text))
}

#[derive(Debug, Default, Clone)]
pub(crate) struct DebugData {
pub(crate) root_paths: FxHashMap<SourceRootId, String>,
pub(crate) crate_names: FxHashMap<CrateId, String>,
}

impl DebugData {
pub(crate) fn merge(&mut self, other: DebugData) {
self.root_paths.extend(other.root_paths.into_iter());
self.crate_names.extend(other.crate_names.into_iter());
}
}
1 change: 1 addition & 0 deletions crates/ra_lsp_server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ parking_lot = "0.9.0"
jod-thread = "0.1.0"
ra_vfs = "0.4.0"
ra_syntax = { path = "../ra_syntax" }
ra_db = { path = "../ra_db" }
ra_text_edit = { path = "../ra_text_edit" }
ra_ide_api = { path = "../ra_ide_api" }
lsp-server = "0.2.0"
Expand Down
7 changes: 6 additions & 1 deletion crates/ra_lsp_server/src/world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ impl WorldState {
let vfs_root_path = vfs.root2path(r);
let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it));
change.add_root(SourceRootId(r.0), is_local);
change.set_debug_root_path(SourceRootId(r.0), vfs_root_path.display().to_string());
}

// Create crate graph from all the workspaces
Expand All @@ -101,7 +102,11 @@ impl WorldState {
vfs_file.map(|f| FileId(f.0))
};
for ws in workspaces.iter() {
crate_graph.extend(ws.to_crate_graph(&mut load));
let (graph, crate_names) = ws.to_crate_graph(&mut load);
let shift = crate_graph.extend(graph);
for (crate_id, name) in crate_names {
change.set_debug_crate_name(crate_id.shift(shift), name)
}
}
change.set_crate_graph(crate_graph);

Expand Down
Loading

0 comments on commit ef2b84d

Please sign in to comment.