fluidattacks-blends-domain 0.6.0

Blends functional core: pure AST graph to syntax graph (no_std)
Documentation
//! Node label to cfg builder table.

pub mod await_expression_node;
pub mod connect_to_block;
pub mod connect_to_declarations;
pub mod connect_to_next;
pub mod end_node;
pub mod if_node;
pub mod method_invocation_node;
pub mod multi_path;
pub mod multifile;
pub mod object_node;
pub mod pair_node;
pub mod step_by_step;
pub mod switch_body;
pub mod switch_section;
pub mod variable_declaration_node;

use crate::syntax::cfg::CfgBuilder;

#[must_use]
#[allow(
    clippy::too_many_lines,
    reason = "exhaustive 1:1 dispatch table: one arm per node label, nothing to extract"
)]
pub fn dispatcher(node_type: &str) -> Option<CfgBuilder> {
    match node_type {
        "Class" | "Declaration" | "DoStatement" | "ElseClause" | "ForEachStatement"
        | "ForStatement" | "MethodDeclaration" | "Namespace" | "SwitchStatement"
        | "UsingStatement" | "WhileStatement" => Some(connect_to_block::build),
        "ArgumentList" | "BinaryOperation" | "ClassBody" | "DeclarationBlock" | "File"
        | "TryStatement" => Some(multi_path::build),
        "ExecutionBlock" | "ExpressionStatement" | "ParameterList" => Some(step_by_step::build),
        "If" | "TernaryOperation" => Some(if_node::build),
        "SwitchBody" => Some(switch_body::build),
        "SwitchSection" => Some(switch_section::build),
        "MethodInvocation" => Some(method_invocation_node::build),
        "VariableDeclaration" => Some(variable_declaration_node::build),
        "AwaitExpression" => Some(await_expression_node::build),
        "Export" | "Return" => Some(connect_to_declarations::build),
        "ModuleImport" => Some(end_node::build),
        "Object" => Some(object_node::build),
        "Pair" => Some(pair_node::build),
        "Annotation"
        | "Argument"
        | "ArrayInitializer"
        | "Assignment"
        | "Attribute"
        | "Break"
        | "CatchClause"
        | "CatchDeclaration"
        | "Comment"
        | "Continue"
        | "ElementAccess"
        | "FinallyClause"
        | "Import"
        | "JsxElement"
        | "Literal"
        | "MemberAccess"
        | "MissingNode"
        | "Modifiers"
        | "NamedArgument"
        | "NewExpression"
        | "ObjectCreation"
        | "Parameter"
        | "ParenthesizedExpression"
        | "ReservedWord"
        | "RestPattern"
        | "Selector"
        | "SpreadElement"
        | "SymbolLookup"
        | "This"
        | "ThrowStatement"
        | "UnaryExpression" => Some(connect_to_next::build),
        _ => None,
    }
}

#[cfg(test)]
mod tests {
    use super::dispatcher;

    #[test]
    fn maps_one_representative_label_per_cfg_builder() {
        let representatives = [
            "Class",
            "File",
            "ExecutionBlock",
            "If",
            "SwitchBody",
            "SwitchSection",
            "MethodInvocation",
            "VariableDeclaration",
            "AwaitExpression",
            "Return",
            "ModuleImport",
            "Object",
            "Pair",
            "Assignment",
        ];
        for label in representatives {
            assert!(dispatcher(label).is_some(), "unmapped label: {label}");
        }
    }

    #[test]
    fn unmapped_node_types_have_no_builder() {
        assert!(dispatcher("Metadata").is_none());
        assert!(dispatcher("LambdaFunctionType").is_none());
        assert!(dispatcher("").is_none());
    }
}