weavatrix-rust 2.7.2

Protocol-independent Rust repository intelligence: typed evidence graphs for impact, architecture, APIs, Git, search, and memory
Documentation
use super::contract::{component_for, list_contains};
use super::rules::stable_hash;
use crate::engine::RepositoryState;
use blazingly_json::{Value, json};
use std::collections::BTreeMap;

pub(super) fn violations(state: &RepositoryState, contract: &Value) -> Vec<Value> {
    let mut output = BTreeMap::new();
    for diagnostic in state
        .snapshot()
        .diagnostics
        .iter()
        .filter(|diagnostic| diagnostic.code == "import.unresolved")
    {
        let Some(span) = diagnostic.span.as_ref() else {
            continue;
        };
        let Some(component) = component_for(contract, &span.file) else {
            continue;
        };
        for rule in unresolved_rules(contract, component) {
            let identity = format!(
                "{}|unresolved|{}|{}",
                rule["id"].as_str().unwrap_or("rule"),
                span.file,
                diagnostic.message
            );
            let fingerprint = stable_hash(&identity);
            output.entry(fingerprint.clone()).or_insert_with(|| {
                json!({
                    "fingerprint": fingerprint,
                    "category": "dependency",
                    "rule": rule,
                    "source": {
                        "file": span.file,
                        "component": component
                    },
                    "evidence": {
                        "kind": "unresolved_dependency",
                        "diagnostic": diagnostic
                    }
                })
            });
        }
    }
    output.into_values().collect()
}

fn unresolved_rules<'contract>(
    contract: &'contract Value,
    component: &str,
) -> impl Iterator<Item = &'contract Value> {
    contract
        .get("dependencyRules")
        .and_then(Value::as_array)
        .into_iter()
        .flatten()
        .filter(|rule| rule["action"] == "forbid")
        .filter(|rule| list_contains(rule.get("from"), component))
        .filter(|rule| list_contains(rule.get("kinds"), "unresolved"))
}