foundry_debugger/
debugger.rs

1//! Debugger implementation.
2
3use crate::{tui::TUI, DebugNode, DebuggerBuilder, ExitReason};
4use alloy_primitives::map::AddressHashMap;
5use eyre::Result;
6use foundry_common::evm::Breakpoints;
7use foundry_evm_traces::debug::ContractSources;
8use std::path::Path;
9
10pub struct DebuggerContext {
11    pub debug_arena: Vec<DebugNode>,
12    pub identified_contracts: AddressHashMap<String>,
13    /// Source map of contract sources
14    pub contracts_sources: ContractSources,
15    pub breakpoints: Breakpoints,
16}
17
18pub struct Debugger {
19    context: DebuggerContext,
20}
21
22impl Debugger {
23    /// Creates a new debugger builder.
24    #[inline]
25    pub fn builder() -> DebuggerBuilder {
26        DebuggerBuilder::new()
27    }
28
29    /// Creates a new debugger.
30    pub fn new(
31        debug_arena: Vec<DebugNode>,
32        identified_contracts: AddressHashMap<String>,
33        contracts_sources: ContractSources,
34        breakpoints: Breakpoints,
35    ) -> Self {
36        Self {
37            context: DebuggerContext {
38                debug_arena,
39                identified_contracts,
40                contracts_sources,
41                breakpoints,
42            },
43        }
44    }
45
46    /// Starts the debugger TUI. Terminates the current process on failure or user exit.
47    pub fn run_tui_exit(mut self) -> ! {
48        let code = match self.try_run_tui() {
49            Ok(ExitReason::CharExit) => 0,
50            Err(e) => {
51                let _ = sh_eprintln!("{e}");
52                1
53            }
54        };
55        std::process::exit(code)
56    }
57
58    /// Starts the debugger TUI.
59    pub fn try_run_tui(&mut self) -> Result<ExitReason> {
60        eyre::ensure!(!self.context.debug_arena.is_empty(), "debug arena is empty");
61
62        let mut tui = TUI::new(&mut self.context);
63        tui.try_run()
64    }
65
66    /// Dumps debugger data to file.
67    pub fn dump_to_file(&mut self, path: &Path) -> Result<()> {
68        eyre::ensure!(!self.context.debug_arena.is_empty(), "debug arena is empty");
69        crate::dump::dump(path, &self.context)
70    }
71}