Skip to main content

the_code_graph_cli/commands/
impact.rs

1use std::path::PathBuf;
2
3use domain::error::Result;
4use domain::model::ImpactTarget;
5use domain::use_cases::impact::ImpactUseCase;
6
7use crate::commands::helpers::{open_graph, parse_confidence};
8use crate::commands::ImpactArgs;
9use crate::output::{print, OutputFormat};
10
11fn has_source_extension(s: &str) -> bool {
12    [".ts", ".tsx", ".js", ".jsx", ".rs", ".py", ".go"]
13        .iter()
14        .any(|ext| s.ends_with(ext))
15}
16
17fn disambiguate_target(target: &str) -> ImpactTarget {
18    if target.contains("::") {
19        ImpactTarget::Symbol(target.to_string())
20    } else if target.contains('/') || has_source_extension(target) {
21        ImpactTarget::File(PathBuf::from(target))
22    } else {
23        ImpactTarget::Symbol(target.to_string())
24    }
25}
26
27pub fn run_impact(args: &ImpactArgs, output_format: OutputFormat) -> Result<()> {
28    let (store, _root) = open_graph()?;
29    let target = disambiguate_target(&args.target);
30    let confidence = parse_confidence(&args.confidence)?;
31    let uc = ImpactUseCase::new(store);
32    let report = uc.blast_radius(&[target], args.depth, confidence)?;
33    print(&report, output_format);
34    Ok(())
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40
41    #[test]
42    fn disambiguate_qualified_name() {
43        match disambiguate_target("src/main.rs::foo") {
44            ImpactTarget::Symbol(s) => assert_eq!(s, "src/main.rs::foo"),
45            _ => panic!("expected Symbol"),
46        }
47    }
48
49    #[test]
50    fn disambiguate_file_path_with_slash() {
51        match disambiguate_target("src/main.rs") {
52            ImpactTarget::File(p) => assert_eq!(p, PathBuf::from("src/main.rs")),
53            _ => panic!("expected File"),
54        }
55    }
56
57    #[test]
58    fn disambiguate_file_with_known_extension() {
59        match disambiguate_target("main.ts") {
60            ImpactTarget::File(p) => assert_eq!(p, PathBuf::from("main.ts")),
61            _ => panic!("expected File"),
62        }
63    }
64
65    #[test]
66    fn disambiguate_bare_name_is_symbol() {
67        match disambiguate_target("MyClass") {
68            ImpactTarget::Symbol(s) => assert_eq!(s, "MyClass"),
69            _ => panic!("expected Symbol"),
70        }
71    }
72}