the_code_graph_domain/analysis/
impact.rs1use super::blast_radius::compute_blast_radius;
2use super::change_detection::find_affected_symbols;
3use crate::model::*;
4use crate::traversal::InMemoryGraph;
5
6pub fn compute_diff_impact(
8 graph: &InMemoryGraph,
9 hunks: &[DiffHunk],
10 symbols: &[SymbolNode],
11 max_depth: usize,
12) -> DiffImpactReport {
13 let changed = find_affected_symbols(hunks, symbols);
14 let targets: Vec<ImpactTarget> = changed
15 .iter()
16 .map(|s| ImpactTarget::Symbol(s.qualified_name.clone()))
17 .collect();
18 let impact = compute_blast_radius(graph, &targets, max_depth, Confidence::Structural);
19 DiffImpactReport {
20 changed_symbols: changed,
21 impact,
22 }
23}
24
25#[cfg(test)]
26mod tests {
27 use super::*;
28 use crate::traversal::InMemoryGraph;
29
30 #[test]
31 fn diff_impact_non_overlapping_returns_empty() {
32 let graph = InMemoryGraph::from_edges(vec![]);
33 let symbols: Vec<SymbolNode> = vec![];
34 let hunks = vec![DiffHunk {
35 file: "src/a.rs".into(),
36 old_start: 1,
37 old_count: 1,
38 new_start: 1,
39 new_count: 1,
40 }];
41 let report = compute_diff_impact(&graph, &hunks, &symbols, 3);
42 assert!(report.changed_symbols.is_empty());
43 assert!(report.impact.affected.is_empty());
44 }
45
46 #[test]
47 fn diff_impact_overlapping_hunk_produces_full_report() {
48 let symbols = vec![SymbolNode {
49 name: "foo".into(),
50 qualified_name: "a.rs::foo".into(),
51 kind: SymbolKind::Function,
52 location: Location {
53 file: "a.rs".into(),
54 line_start: 10,
55 line_end: 20,
56 col_start: 0,
57 col_end: 0,
58 },
59 visibility: Visibility::Public,
60 is_exported: false,
61 is_async: false,
62 is_test: false,
63 decorators: vec![],
64 signature: None,
65 }];
66 let edges = vec![Edge {
67 kind: EdgeKind::Calls,
68 source: "a.rs::foo".into(),
69 target: "b.rs::bar".into(),
70 metadata: None,
71 }];
72 let graph = InMemoryGraph::from_edges(edges);
73 let hunks = vec![DiffHunk {
74 file: "a.rs".into(),
75 old_start: 15,
76 old_count: 3,
77 new_start: 15,
78 new_count: 3,
79 }];
80 let report = compute_diff_impact(&graph, &hunks, &symbols, 3);
81 assert_eq!(report.changed_symbols.len(), 1);
82 assert_eq!(report.changed_symbols[0].name, "foo");
83 assert!(report
84 .impact
85 .affected
86 .iter()
87 .any(|n| n.qualified_name == "b.rs::bar"));
88 }
89}