fluidattacks-blends-domain 0.6.0

Blends functional core: pure AST graph to syntax graph (no_std)
Documentation
use crate::syntax::readers::{javascript, typescript};
use crate::syntax::SyntaxReader;

#[must_use]
#[allow(clippy::too_many_lines, reason = "flat node-type dispatch table")]
pub fn dispatcher(node_type: &str) -> Option<SyntaxReader> {
    match node_type {
        "ambient_declaration" => Some(typescript::ambient_declaration::reader),
        "null" | "undefined" => Some(typescript::void::reader),
        "arguments" => Some(javascript::arguments::reader),
        "array" => Some(javascript::array_node::reader),
        "arrow_function" => Some(typescript::arrow_function::reader),
        "array_type" | "literal_type" | "optional_type" | "predefined_type" => {
            Some(typescript::predefined_type::reader)
        }
        "as_expression" => Some(typescript::as_expression::reader),
        "assignment_expression" | "augmented_assignment_expression" => {
            Some(javascript::assignment_expression::reader)
        }
        "await_expression" => Some(javascript::await_expression::reader),
        "binary_expression" => Some(javascript::binary_expression::reader),
        "boolean" | "false" | "true" => Some(javascript::boolean_literal::reader),
        "break_statement" => Some(javascript::break_statement::reader),
        "call_expression" => Some(javascript::call_expression::reader),
        "catch_clause" => Some(javascript::catch_clause::reader),
        "class_body" => Some(typescript::class_body::reader),
        "class_declaration" => Some(javascript::class_declaration::reader),
        "comment" => Some(javascript::comment::reader),
        "debugger_statement" => Some(javascript::debugger_statement::reader),
        "decorator" => Some(javascript::decorator::reader),
        "do_statement" => Some(javascript::do_statement::reader),
        "else_clause" => Some(javascript::else_clause::reader),
        "empty_statement" => Some(typescript::empty_statement::reader),
        "enum_assignment" => Some(typescript::enum_assignment::reader),
        "enum_body" => Some(typescript::enum_body::reader),
        "enum_declaration" => Some(typescript::enum_declaration::reader),
        "export_statement" => Some(javascript::export_statement::reader),
        "expression_statement" => Some(javascript::expression_statement::reader),
        "finally_clause" => Some(javascript::finally_clause::reader),
        "for_in_statement" => Some(javascript::for_each_statement::reader),
        "for_statement" => Some(javascript::for_statement::reader),
        "formal_parameters" | "type_arguments" => Some(javascript::parameter_list::reader),
        "function"
        | "function_declaration"
        | "function_expression"
        | "generator_function_declaration"
        | "method_definition" => Some(javascript::method_declaration::reader),
        "function_signature" => Some(typescript::function_signature::reader),
        "function_type" => Some(typescript::function_type::reader),
        "generic_type" => Some(typescript::generic_type::reader),
        "identifier"
        | "property_identifier"
        | "shorthand_property_identifier"
        | "shorthand_property_identifier_pattern"
        | "type_identifier" => Some(javascript::identifier::reader),
        "if_statement" => Some(javascript::if_statement::reader),
        "import_specifier" => Some(javascript::import_module::reader),
        "import_statement" => Some(javascript::import_global::reader),
        "index_signature" => Some(typescript::index_signature::reader),
        "interface_declaration" => Some(typescript::interface_declaration::reader),
        "internal_module" => Some(typescript::internal_module::reader),
        "intersection_type" => Some(typescript::intersection_type::reader),
        "jsx_attribute" => Some(javascript::jsx_attribute::reader),
        "jsx_element" | "jsx_opening_element" => Some(javascript::jsx_element::reader),
        "jsx_self_closing_element" => Some(javascript::jsx_self_closing_element::reader),
        "member_expression" => Some(javascript::member_expression::reader),
        "nested_identifier" => Some(javascript::nested_identifier::reader),
        "new_expression" => Some(javascript::new_expression::reader),
        "number" => Some(javascript::number_literal::reader),
        "interface_body" | "object" | "object_type" => Some(javascript::object::reader),
        "pair" => Some(javascript::pair::reader),
        "parenthesized_expression" => Some(javascript::parenthesized_expression::reader),
        "parenthesized_type" => Some(typescript::parenthesized_type::reader),
        "optional_parameter" | "required_parameter" => Some(typescript::required_parameter::reader),
        "program" => Some(javascript::program::reader),
        "property_signature" => Some(typescript::property_signature::reader),
        "public_field_definition" => Some(typescript::public_field_definition::reader),
        "regex" | "string" => Some(javascript::string_literal::reader),
        "rest_pattern" => Some(javascript::rest_pattern::reader),
        "return_statement" => Some(javascript::return_statement::reader),
        "spread_element" => Some(javascript::spread_element::reader),
        "statement_block" => Some(javascript::execution_block::reader),
        "subscript_expression" => Some(javascript::subscript_expression::reader),
        "super" | "this" => Some(javascript::this_node::reader),
        "switch_body" => Some(javascript::switch_body::reader),
        "switch_case" | "switch_default" => Some(javascript::switch_section::reader),
        "switch_statement" => Some(javascript::switch_statement::reader),
        "template_string" => Some(javascript::template_string::reader),
        "ternary_expression" => Some(typescript::ternary_expression::reader),
        "throw_statement" => Some(javascript::throw_statement::reader),
        "try_statement" => Some(javascript::try_statement::reader),
        "tuple_type" => Some(typescript::tuple_type::reader),
        "type_alias_declaration" => Some(typescript::type_alias_declaration::reader),
        "type_annotation" => Some(typescript::type_annotation::reader),
        "unary_expression" => Some(javascript::unary_expression::reader),
        "union_type" => Some(typescript::union_type::reader),
        "update_expression" => Some(javascript::update_expression::reader),
        "lexical_declaration" | "variable_declaration" => {
            Some(javascript::variable_declaration::reader)
        }
        "while_statement" => Some(javascript::while_statement::reader),
        "yield_expression" => Some(javascript::yield_expression::reader),
        _ => None,
    }
}

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

    #[test]
    #[allow(clippy::too_many_lines, reason = "flat node-type coverage checklist")]
    fn reuses_the_implemented_javascript_node_types() {
        assert!(dispatcher("program").is_some());
        assert!(dispatcher("comment").is_some());
        assert!(dispatcher("boolean").is_some());
        assert!(dispatcher("true").is_some());
        assert!(dispatcher("false").is_some());
        assert!(dispatcher("number").is_some());
        assert!(dispatcher("string").is_some());
        assert!(dispatcher("regex").is_some());
        assert!(dispatcher("assignment_expression").is_some());
        assert!(dispatcher("augmented_assignment_expression").is_some());
        assert!(dispatcher("await_expression").is_some());
        assert!(dispatcher("binary_expression").is_some());
        assert!(dispatcher("break_statement").is_some());
        assert!(dispatcher("parenthesized_expression").is_some());
        assert!(dispatcher("return_statement").is_some());
        assert!(dispatcher("throw_statement").is_some());
        assert!(dispatcher("unary_expression").is_some());
        assert!(dispatcher("update_expression").is_some());
        assert!(dispatcher("expression_statement").is_some());
        assert!(dispatcher("this").is_some());
        assert!(dispatcher("super").is_some());
        assert!(dispatcher("array").is_some());
        assert!(dispatcher("rest_pattern").is_some());
        assert!(dispatcher("identifier").is_some());
        assert!(dispatcher("property_identifier").is_some());
        assert!(dispatcher("type_identifier").is_some());
        assert!(dispatcher("member_expression").is_some());
        assert!(dispatcher("new_expression").is_some());
        assert!(dispatcher("spread_element").is_some());
        assert!(dispatcher("subscript_expression").is_some());
        assert!(dispatcher("decorator").is_some());
        assert!(dispatcher("nested_identifier").is_some());
        assert!(dispatcher("template_string").is_some());
        assert!(dispatcher("catch_clause").is_some());
        assert!(dispatcher("finally_clause").is_some());
        assert!(dispatcher("import_specifier").is_some());
        assert!(dispatcher("import_statement").is_some());
        assert!(dispatcher("jsx_element").is_some());
        assert!(dispatcher("jsx_opening_element").is_some());
        assert!(dispatcher("jsx_self_closing_element").is_some());
        assert!(dispatcher("jsx_attribute").is_some());
        assert!(dispatcher("arguments").is_some());
        assert!(dispatcher("call_expression").is_some());
        assert!(dispatcher("class_declaration").is_some());
        assert!(dispatcher("debugger_statement").is_some());
        assert!(dispatcher("do_statement").is_some());
        assert!(dispatcher("else_clause").is_some());
        assert!(dispatcher("export_statement").is_some());
        assert!(dispatcher("for_in_statement").is_some());
        assert!(dispatcher("for_statement").is_some());
        assert!(dispatcher("formal_parameters").is_some());
        assert!(dispatcher("type_arguments").is_some());
        assert!(dispatcher("function").is_some());
        assert!(dispatcher("function_declaration").is_some());
        assert!(dispatcher("function_expression").is_some());
        assert!(dispatcher("generator_function_declaration").is_some());
        assert!(dispatcher("method_definition").is_some());
        assert!(dispatcher("if_statement").is_some());
        assert!(dispatcher("interface_body").is_some());
        assert!(dispatcher("object").is_some());
        assert!(dispatcher("object_type").is_some());
        assert!(dispatcher("pair").is_some());
        assert!(dispatcher("statement_block").is_some());
        assert!(dispatcher("switch_body").is_some());
        assert!(dispatcher("switch_case").is_some());
        assert!(dispatcher("switch_default").is_some());
        assert!(dispatcher("switch_statement").is_some());
        assert!(dispatcher("try_statement").is_some());
        assert!(dispatcher("lexical_declaration").is_some());
        assert!(dispatcher("variable_declaration").is_some());
        assert!(dispatcher("while_statement").is_some());
        assert!(dispatcher("yield_expression").is_some());
    }

    #[test]
    fn maps_the_migrated_typescript_only_node_types() {
        assert!(dispatcher("as_expression").is_some());
        assert!(dispatcher("function_type").is_some());
        assert!(dispatcher("intersection_type").is_some());
        assert!(dispatcher("union_type").is_some());
        assert!(dispatcher("array_type").is_some());
        assert!(dispatcher("literal_type").is_some());
        assert!(dispatcher("optional_type").is_some());
        assert!(dispatcher("predefined_type").is_some());
        assert!(dispatcher("ambient_declaration").is_some());
        assert!(dispatcher("empty_statement").is_some());
        assert!(dispatcher("generic_type").is_some());
        assert!(dispatcher("internal_module").is_some());
        assert!(dispatcher("parenthesized_type").is_some());
        assert!(dispatcher("type_annotation").is_some());
        assert!(dispatcher("null").is_some());
        assert!(dispatcher("undefined").is_some());
        assert!(dispatcher("enum_assignment").is_some());
        assert!(dispatcher("enum_body").is_some());
        assert!(dispatcher("enum_declaration").is_some());
        assert!(dispatcher("function_signature").is_some());
        assert!(dispatcher("index_signature").is_some());
        assert!(dispatcher("interface_declaration").is_some());
        assert!(dispatcher("property_signature").is_some());
        assert!(dispatcher("public_field_definition").is_some());
        assert!(dispatcher("tuple_type").is_some());
        assert!(dispatcher("type_alias_declaration").is_some());
    }

    #[test]
    fn every_typescript_only_node_type_is_mapped() {
        for node_type in [
            "arrow_function",
            "class_body",
            "ternary_expression",
            "required_parameter",
            "optional_parameter",
        ] {
            assert!(dispatcher(node_type).is_some(), "{node_type} is unmapped");
        }
    }

    #[test]
    fn unknown_node_types_are_not_mapped() {
        assert!(dispatcher("").is_none());
        assert!(dispatcher("not_a_node_type").is_none());
    }
}