fluidattacks-blends-domain 0.3.0

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

use crate::ast::AstGraph;
use crate::query::{adj_ast, label_text, match_ast_d, match_ast_group_d};
use crate::NodeId;

#[must_use]
pub fn extract_modifiers(graph: &AstGraph, n_id: NodeId) -> (Option<NodeId>, Option<String>) {
    let Some(modifiers_id) = match_ast_d(graph, n_id, "modifiers", None) else {
        return (None, None);
    };

    let mut annotation_ids = match_ast_group_d(graph, modifiers_id, "annotation", None);
    annotation_ids.extend(match_ast_group_d(
        graph,
        modifiers_id,
        "marker_annotation",
        None,
    ));

    let keyword_ids: Vec<NodeId> = adj_ast(graph, modifiers_id, None, &[])
        .into_iter()
        .filter(|c_id| !annotation_ids.contains(c_id))
        .collect();

    let kept_modifiers_id = (!annotation_ids.is_empty()).then_some(modifiers_id);

    let access_modifiers = (!keyword_ids.is_empty()).then(|| {
        let parts: Vec<&str> = keyword_ids
            .iter()
            .map(|c_id| label_text(graph, *c_id).unwrap_or_default())
            .collect();
        parts.join(" ")
    });

    (kept_modifiers_id, access_modifiers)
}

#[must_use]
pub fn inner_children(graph: &AstGraph, n_id: NodeId) -> Vec<NodeId> {
    let children = adj_ast(graph, n_id, None, &[]);
    children
        .get(1..children.len().saturating_sub(1))
        .map(<[NodeId]>::to_vec)
        .unwrap_or_default()
}