backhopper_xref/
suites.rs1use std::collections::BTreeSet;
11
12use backhopper_core::{ApplicationName, Mfa, ModuleName};
13use backhopper_xref_graph::{Functions, Vertex, VertexSet};
14use serde::{Deserialize, Serialize};
15
16use crate::xref::Xref;
17
18#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
19pub struct SuiteRef {
20 pub application: Option<ApplicationName>,
21 pub module: ModuleName,
22}
23
24pub fn suites_referencing(
29 xref: &Xref<Functions>,
30 modules: &BTreeSet<ModuleName>,
31 suite_predicate: impl Fn(&ModuleName) -> bool,
32) -> BTreeSet<SuiteRef> {
33 let targets: VertexSet = modules.iter().map(|m| Vertex::Module(m.clone())).collect();
34 let callers = xref.graph().module_edges().preimage(&targets);
35 callers
36 .iter()
37 .filter_map(|v| v.as_module().cloned())
38 .filter(|m| suite_predicate(m))
39 .map(|module| {
40 let application = xref
41 .graph()
42 .module(&module)
43 .and_then(|s| s.application.clone());
44 SuiteRef {
45 application,
46 module,
47 }
48 })
49 .collect()
50}
51
52pub fn suites_referencing_mfas(
54 xref: &Xref<Functions>,
55 targets: &BTreeSet<Mfa>,
56 suite_predicate: impl Fn(&ModuleName) -> bool,
57) -> BTreeSet<SuiteRef> {
58 let target_vs: VertexSet = targets
59 .iter()
60 .map(|m| Vertex::Function(m.clone()))
61 .collect();
62 let callers = xref.graph().external_calls().preimage(&target_vs);
63 let mut suite_modules: BTreeSet<ModuleName> = BTreeSet::new();
64 for v in callers.iter() {
65 if let Vertex::Function(mfa) = v {
66 if suite_predicate(&mfa.module) {
67 suite_modules.insert(mfa.module.clone());
68 }
69 }
70 }
71 suite_modules
72 .into_iter()
73 .map(|module| {
74 let application = xref
75 .graph()
76 .module(&module)
77 .and_then(|s| s.application.clone());
78 SuiteRef {
79 application,
80 module,
81 }
82 })
83 .collect()
84}
85
86pub fn is_suite_module(name: &ModuleName) -> bool {
88 name.as_str().ends_with("_SUITE")
89}