fluidattacks-blends-domain 0.26.0

Blends functional core: pure AST graph to syntax graph (no_std)
Documentation
use crate::{
    ast::AstGraph,
    query::{adj_ast, match_ast_d, match_ast_group_d},
    syntax::{
        builders::class_declaration::build_class_node, fields::Field, SyntaxGraphArgs,
        SyntaxGraphError,
    },
    utilities::text_nodes::node_to_str,
    NodeId,
};
use alloc::borrow::ToOwned;
use alloc::string::String;

const NAME: Field<false> = Field::new("name_id");

#[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", Some(1)) else {
        return (None, None);
    };

    let access_modifiers = match_ast_d(graph, modifiers_id, "visibility_modifier", Some(1))
        .map(|vis_id| node_to_str(graph, vis_id).trim().to_owned());

    let annotation_ids = match_ast_group_d(graph, modifiers_id, "annotation", Some(1));
    let has_non_annotation = adj_ast(graph, modifiers_id, Some(1), &[])
        .iter()
        .any(|c_id| !annotation_ids.contains(c_id));

    (has_non_annotation.then_some(modifiers_id), access_modifiers)
}

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

    let name_id = args
        .optional_field_alt(n_id, NAME)
        .or_else(|| match_ast_d(graph, n_id, "identifier", Some(1)));
    let name = name_id.map_or_else(|| "AnonymousClass".to_owned(), |id| node_to_str(graph, id));

    let block_id = match_ast_d(graph, n_id, "class_body", Some(1))
        .or_else(|| adj_ast(graph, n_id, Some(1), &[]).last().copied());

    let (modifiers_id, access_modifiers) = extract_modifiers(graph, n_id);

    build_class_node(
        args,
        n_id,
        name,
        block_id,
        &[],
        None,
        modifiers_id,
        access_modifiers,
    )
    .map(Some)
}