sofie_model/
cross_owner.rs1use std::path::{Path, PathBuf};
2
3use crate::Code;
4use crate::effects::Effects;
5
6#[derive(Clone, Debug, PartialEq, Eq)]
8pub struct CrossOwnerCheck {
9 pub aggregate: String,
10 pub caller: String,
12 pub file: PathBuf,
13 pub line: usize,
14}
15
16impl Code {
17 #[must_use]
18 pub fn cross_owner_checks(&self) -> Vec<CrossOwnerCheck> {
19 let functions = self.functions.iter().map(|function| {
20 let caller = function.path.join("::");
21 self.checks_in(&caller, &function.effects, &function.file)
22 });
23 let methods = self.methods.iter().map(|method| {
24 let caller = format!("{}::{}", method.owner, method.name);
25 self.checks_in(&caller, &method.effects, &method.file)
26 });
27 functions.chain(methods).flatten().collect()
28 }
29
30 fn checks_in(&self, caller: &str, effects: &Effects, file: &Path) -> Vec<CrossOwnerCheck> {
31 effects
32 .calls
33 .iter()
34 .filter_map(|call| {
35 let [.., aggregate, method] = call.path.as_slice() else {
36 return None;
37 };
38 let known = self.aggregates.iter().any(|known| known.name == *aggregate);
39 (method == "across" && known).then(|| CrossOwnerCheck {
40 aggregate: aggregate.clone(),
41 caller: caller.to_owned(),
42 file: file.to_path_buf(),
43 line: call.line,
44 })
45 })
46 .collect()
47 }
48}