Skip to main content

fallow_engine/
trace_chain.rs

1//! Symbol trace types exposed through the engine boundary.
2
3use fallow_config::ResolvedConfig;
4
5use crate::{EngineError, EngineResult, session::AnalysisSession};
6
7use fallow_types::trace_chain::{SymbolChainQuery, SymbolChainTrace};
8
9#[expect(
10    unused_imports,
11    reason = "engine owns a copied trace-chain implementation whose internal pub uses serve its tests"
12)]
13#[path = "trace_chain_impl.rs"]
14mod trace_chain_impl;
15
16/// Run symbol-level call-chain tracing through the engine boundary.
17///
18/// # Errors
19///
20/// Returns an error if parsing, graph construction, or retained module
21/// analysis fails.
22pub fn trace_symbol_chain(
23    config: &ResolvedConfig,
24    query: SymbolChainQuery<'_>,
25) -> EngineResult<Option<SymbolChainTrace>> {
26    let session = AnalysisSession::from_resolved_config(config.clone());
27    trace_symbol_chain_with_session(&session, query)
28}
29
30/// Run symbol-level call-chain tracing through an existing analysis session.
31///
32/// # Errors
33///
34/// Returns an error if parsing, graph construction, or retained module
35/// analysis fails.
36pub fn trace_symbol_chain_with_session(
37    session: &AnalysisSession,
38    query: SymbolChainQuery<'_>,
39) -> EngineResult<Option<SymbolChainTrace>> {
40    let output = session.analyze_dead_code_with_shared_artifacts(true, true)?;
41    let graph = output
42        .graph
43        .as_ref()
44        .ok_or_else(|| EngineError::new("trace requires a retained module graph"))?;
45    let modules = output.modules.as_deref().unwrap_or(&[]);
46    Ok(trace_chain_impl::trace_symbol_chain(
47        graph.as_graph(),
48        modules,
49        session.root(),
50        query,
51    ))
52}