fluidattacks-blends-domain 0.38.0

Blends functional core: pure AST graph to syntax graph (no_std)
Documentation
use crate::alloc::borrow::ToOwned;
use crate::ast::node_utils::{children, AstNodeAndId};
use crate::ast::{AstGraph, AstNode};
use crate::syntax::_node_builders::core::SyntaxNodeBuildError;
use crate::syntax::core_nodes::{ArrayExpression, CoreSyntaxNode, CoreSyntaxNodeWithId};
use alloc::vec::Vec;

fn filter_comments(items: Vec<CoreSyntaxNodeWithId>) -> Vec<CoreSyntaxNodeWithId> {
    items
        .into_iter()
        .filter(|(n, _)| !matches!(n, CoreSyntaxNode::Comment(_)))
        .collect()
}
fn ensure_one_expression(
    element_group: &[CoreSyntaxNodeWithId],
) -> Result<CoreSyntaxNodeWithId, SyntaxNodeBuildError> {
    match element_group {
        [unique] => Ok(unique.clone()),
        [_, ..] => Err(SyntaxNodeBuildError::Error(
            "There is more than one expression/node for an element of an ArrayExpression"
                .to_owned(),
        )),
        [] => Err(SyntaxNodeBuildError::Error(
            "An element group of an ArrayExpression is empty".to_owned(),
        )),
    }
}
pub fn build_array_expression(
    graph: &AstGraph,
    node: &AstNode,
    build_syntax_node: impl Fn(AstNodeAndId) -> Result<CoreSyntaxNodeWithId, SyntaxNodeBuildError>,
) -> Result<ArrayExpression, SyntaxNodeBuildError> {
    let all_children = children(graph, node).map_err(SyntaxNodeBuildError::ResolutionError)?;
    let removed_delimiters = all_children
        .iter()
        .filter(|(child, _)| !matches!(child.kind.as_str(), "[" | "]"))
        .collect::<Vec<_>>();
    let element_groups = removed_delimiters
        .split(|(child, _)| child.kind == ",")
        .collect::<Vec<_>>();
    let trimmed_groups = match element_groups.as_slice() {
        [rest @ .., []] => rest, // a trailing comma leaves an empty group that must be ignored
        all => all,
    };
    let transformed_groups = trimmed_groups.iter().map(|group| {
        group
            .iter()
            .map(|i| build_syntax_node(**i))
            .collect::<Result<Vec<_>, _>>()
    });
    let elements = transformed_groups
        .map(|r| {
            r.map(filter_comments)
                .and_then(|g| ensure_one_expression(g.as_slice()))
        })
        .collect::<Result<Vec<_>, _>>();
    elements.map(|e| ArrayExpression { elements: e })
}

#[cfg(test)]
mod tests;