Skip to main content

backhopper_xref/
xref.rs

1// Copyright (C) 2026 Michael S. Klishin and Contributors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// See LICENSE-APACHE and LICENSE-MIT for details.
4
5//! `Xref<M>`: the queryable façade over a built `CallGraph`.
6//!
7//! Wraps a `CallGraph<M, Built>` plus a few memoised derived views.
8
9use std::sync::{Arc, OnceLock};
10
11use backhopper_xref_graph::{Built, CallGraph, Functions, Mode, Relation};
12use backhopper_xref_reader::ReadWarning;
13
14#[derive(Debug, Clone)]
15pub struct Xref<M: Mode> {
16    pub(crate) graph: Arc<CallGraph<M, Built>>,
17    pub(crate) warnings: Arc<Vec<ReadWarning>>,
18    pub(crate) closure_memo: OnceLock<Arc<Relation>>,
19}
20
21impl<M: Mode> Xref<M> {
22    pub(crate) fn from_graph(graph: CallGraph<M, Built>, warnings: Vec<ReadWarning>) -> Self {
23        Self {
24            graph: Arc::new(graph),
25            warnings: Arc::new(warnings),
26            closure_memo: OnceLock::new(),
27        }
28    }
29
30    pub fn graph(&self) -> &CallGraph<M, Built> {
31        &self.graph
32    }
33
34    pub fn warnings(&self) -> &[ReadWarning] {
35        &self.warnings
36    }
37}
38
39impl Xref<Functions> {
40    /// Transitive closure of every function call, computed once and
41    /// reused: the closure is the dominant cost of reachability queries
42    /// and the graph is immutable
43    pub(crate) fn all_calls_closure(&self) -> &Relation {
44        self.closure_memo
45            .get_or_init(|| Arc::new(self.graph.all_calls().transitive_closure()))
46    }
47}