weavatrix-rust 2.16.0

Protocol-independent Rust repository intelligence: typed evidence graphs for impact, architecture, APIs, Git, search, and memory
Documentation
use super::detect::is_links_file;
use super::model::binding_kind;
use super::span::span_for;
use crate::language::{DomainFact, FileFacts, SymbolFact, SymbolLocator};
use blazingly_json::Value;
use weavatrix_graph::{EdgeKind, NodeKind};

#[must_use]
pub(crate) fn analyze_links(path: &str, raw: &str, value: &Value) -> Option<FileFacts> {
    if !looks_like(path, value) {
        return None;
    }
    let links = value.get("links")?.as_array()?;
    let mut facts = FileFacts::default();
    for (index, link) in links.iter().enumerate() {
        let diagram = link.get("diagram").and_then(Value::as_str).unwrap_or("");
        let element = link.get("element").and_then(Value::as_str).unwrap_or("");
        if diagram.is_empty() || element.is_empty() {
            continue;
        }
        let span = span_for(path, raw, 0, raw.len().max(1));
        let name = format!("{diagram}#{element}");
        let symbol = SymbolFact {
            name: name.clone(),
            kind: binding_kind(),
            span: span.clone(),
            test_only: false,
            exported: false,
            source_fingerprint: None,
            source_extent: None,
            owner: None,
        };
        let owner = SymbolLocator {
            name: symbol.name.clone(),
            kind: symbol.kind.clone(),
            span: span.clone(),
        };
        facts.symbols.push(symbol);
        for (prefix, key) in [
            ("diagram", "diagram"),
            ("element", "element"),
            ("kind", "kind"),
            ("selector", "selector"),
            ("artifact", "artifact"),
            ("id", "id"),
        ] {
            if let Some(value) = link
                .get(key)
                .and_then(Value::as_str)
                .filter(|value| !value.is_empty())
            {
                facts.domains.push(DomainFact {
                    name: format!("{prefix}:{value}"),
                    kind: NodeKind::Unknown,
                    relation: EdgeKind::Configures,
                    span: span.clone(),
                    owner: Some(owner.clone()),
                });
            }
        }
        facts.domains.push(DomainFact {
            name: format!("declared:{index}"),
            kind: NodeKind::Unknown,
            relation: EdgeKind::Configures,
            span,
            owner: Some(owner),
        });
    }
    Some(facts)
}

fn looks_like(path: &str, value: &Value) -> bool {
    if is_links_file(path) {
        return true;
    }
    value
        .get("$schema")
        .and_then(Value::as_str)
        .is_some_and(|schema| schema.contains("diagram-links"))
}