fluidattacks-blends-domain 0.6.1

Blends functional core: pure AST graph to syntax graph (no_std)
Documentation
use crate::syntax::{SyntaxGraph, SyntaxNode};

#[must_use]
fn node_variable_type(node: &SyntaxNode) -> Option<&str> {
    match node {
        SyntaxNode::Parameter { variable_type, .. }
        | SyntaxNode::VariableDeclaration { variable_type, .. } => variable_type.as_deref(),
        _ => None,
    }
}

#[must_use]
pub fn fqn_from_graph_imports<'a>(sg: &'a SyntaxGraph, name: &str) -> Option<&'a str> {
    sg.nodes.values().find_map(|node| {
        if !matches!(node.label_type(), "Import" | "ModuleImport") {
            return None;
        }
        let expr = node.expression()?;
        if expr.is_empty() || expr.ends_with(".*") {
            return None;
        }
        (expr.rsplit('.').next() == Some(name)).then_some(expr)
    })
}

#[must_use]
pub fn fqn_from_graph_variable_type<'a>(sg: &'a SyntaxGraph, symbol: &str) -> Option<&'a str> {
    sg.symbol_index
        .get(symbol)
        .into_iter()
        .flat_map(|scopes| scopes.values())
        .flatten()
        .find_map(|nid| {
            let var_type = node_variable_type(sg.nodes.get(nid)?)?;
            if var_type.is_empty() {
                return None;
            }
            if var_type.contains('.') {
                return Some(var_type);
            }
            fqn_from_graph_imports(sg, var_type)
        })
}

#[must_use]
pub fn receiver_fqn_from_graph_symbol<'a>(sg: &'a SyntaxGraph, symbol: &str) -> Option<&'a str> {
    fqn_from_graph_imports(sg, symbol).or_else(|| fqn_from_graph_variable_type(sg, symbol))
}