xbp-analysis 10.57.0

Language-agnostic static analysis (error-handling / Aspirator-style) for XBP
Documentation
//! Architecture tests: domain modules must not depend on infrastructure.

use std::fs;
use std::path::PathBuf;

fn crate_root() -> PathBuf {
    PathBuf::from(env!("CARGO_MANIFEST_DIR"))
}

fn collect_rs(dir: PathBuf, out: &mut Vec<PathBuf>) {
    if let Ok(rd) = fs::read_dir(&dir) {
        for e in rd.flatten() {
            let p = e.path();
            if p.is_dir() {
                collect_rs(p, out);
            } else if p.extension().and_then(|x| x.to_str()) == Some("rs") {
                out.push(p);
            }
        }
    }
}

#[test]
fn domain_does_not_import_adapters_or_languages() {
    let domain = crate_root().join("src/domain");
    let mut files = Vec::new();
    collect_rs(domain, &mut files);
    assert!(!files.is_empty());
    for f in files {
        let text = fs::read_to_string(&f).unwrap();
        for banned in [
            "crate::adapters",
            "crate::languages",
            "std::fs",
            "syn::",
            "clap::",
            "walkdir",
            "ignore::",
        ] {
            assert!(
                !text.contains(banned),
                "{} must not contain `{banned}`",
                f.display()
            );
        }
    }
}

#[test]
fn ports_do_not_import_adapters() {
    let ports = crate_root().join("src/ports");
    let mut files = Vec::new();
    collect_rs(ports, &mut files);
    for f in files {
        let text = fs::read_to_string(&f).unwrap();
        assert!(
            !text.contains("crate::adapters"),
            "{} must not depend on adapters",
            f.display()
        );
        assert!(
            !text.contains("crate::languages"),
            "{} must not depend on languages",
            f.display()
        );
    }
}