fluidattacks-blends-domain 0.6.1

Blends functional core: pure AST graph to syntax graph (no_std)
Documentation
use alloc::vec::Vec;

use crate::query::{adj_ast, match_ast};
use crate::syntax::builders::argument::build_argument_node;
use crate::syntax::builders::named_argument::build_named_argument_node;
use crate::syntax::fields::c_sharp::{argument, attribute_argument};
use crate::syntax::readers::constants::C_SHARP_EXPRESSION;
use crate::syntax::{SyntaxGraphArgs, SyntaxGraphError};
use crate::utilities::text_nodes::node_to_str;
use crate::{CodeGraph, NodeId};

fn is_valid_argument_type(kind: &str) -> bool {
    C_SHARP_EXPRESSION.contains(&kind) || kind == "declaration_expression"
}

pub fn reader(
    args: &mut SyntaxGraphArgs<'_>,
    n_id: NodeId,
) -> Result<Option<NodeId>, SyntaxGraphError> {
    let graph = args.ast_graph;
    let match_map = match_ast(graph, n_id, &[":"], None);

    let name_field = match graph.label_type(n_id) {
        Some("argument") => args.optional_field_alt(n_id, argument::NAME),
        Some("attribute_argument") => args.optional_field_alt(n_id, attribute_argument::NAME),
        _ => return Err(SyntaxGraphError::UnexpectedAstShape),
    };
    if let Some(var_id) = name_field {
        if match_map.get(":").copied().flatten().is_some() {
            if let Some(val_id) = match_map.get("__1__").copied().flatten() {
                let name = node_to_str(graph, var_id);
                return build_named_argument_node(args, n_id, Some(name), val_id).map(Some);
            }
        }

        let value_ids: Vec<NodeId> = adj_ast(graph, n_id, Some(1), &[])
            .into_iter()
            .filter(|c_id| *c_id != var_id)
            .filter(|c_id| graph.label_type(*c_id).is_some_and(is_valid_argument_type))
            .collect();
        if let Some(val_id) = value_ids.last().copied() {
            let name = node_to_str(graph, var_id);
            return build_named_argument_node(args, n_id, Some(name), val_id).map(Some);
        }
    }

    let valid_children: Vec<NodeId> = adj_ast(graph, n_id, Some(1), &[])
        .into_iter()
        .filter(|c_id| graph.label_type(*c_id).is_some_and(is_valid_argument_type))
        .collect();

    build_argument_node(args, n_id, &valid_children).map(Some)
}