fluidattacks-blends-domain 0.2.0

Blends functional core: pure AST graph to syntax graph (no_std)
Documentation
//! Cfg builder that descends into an invocation's callbacks, chained calls
//! and blocks.

use crate::query::match_ast_d;
use crate::syntax::cfg::{SyntaxCfgArgs, SyntaxCfgError};
use crate::syntax::SyntaxNode;
use crate::CodeGraph;
use crate::NodeId;

pub fn build(
    args: &mut SyntaxCfgArgs<'_>,
    n_id: NodeId,
    nxt_id: Option<NodeId>,
) -> Result<NodeId, SyntaxCfgError> {
    let Some(&SyntaxNode::MethodInvocation {
        arguments_id,
        expression_id,
        block_id,
        ..
    }) = args.graph.nodes.get(&n_id)
    else {
        return Ok(n_id);
    };

    if let Some(al_id) = arguments_id
        .filter(|al_id| match_ast_d(args.graph, *al_id, "MethodDeclaration", None).is_some())
    {
        let built = args.generic(al_id, nxt_id)?;
        args.graph.add_cfg_edge(n_id, built);
    }

    if let Some(mi_id) = expression_id
        .filter(|el_id| args.graph.label_type(*el_id) == Some("MemberAccess"))
        .and_then(|el_id| match_ast_d(args.graph, el_id, "MethodInvocation", Some(1)))
    {
        let built = args.generic(mi_id, nxt_id)?;
        args.graph.add_cfg_edge(n_id, built);
    }

    if let Some(bl_id) = block_id.or_else(|| match_ast_d(args.graph, n_id, "ExecutionBlock", None))
    {
        let built = args.generic(bl_id, nxt_id)?;
        args.graph.add_cfg_edge(n_id, built);
    }

    if let Some(nxt_id) = nxt_id {
        args.graph.add_cfg_edge(n_id, nxt_id);
    }

    Ok(n_id)
}