backyard-generator 0.1.10

Convert AST node back to PHP code.
Documentation
use backyard_nodes::{ cast_node, Node, NodeType, NodeWrapper };

use crate::generator::{ Builder, Generator };

pub struct TypeGenerator;

impl TypeGenerator {
  pub fn generate<'arena>(
    generator: &mut Generator<'arena, '_>,
    builder: &mut Builder,
    node: &Node<'arena>
  ) {
    match node.node_type {
      NodeType::Type => Self::generate_basic(generator, builder, node),
      NodeType::UnionType => Self::generate_union(generator, builder, node),
      NodeType::IntersectionType => Self::generate_intersection(generator, builder, node),
      _ => panic!("TypeGenerator::generate: failed to generate type"),
    }
  }

  fn generate_basic(_: &mut Generator, builder: &mut Builder, node: &Node) {
    let node = cast_node!(Type, &node.wrapper);
    if node.is_nullable {
      builder.push("?");
    }
    builder.push(&node.name.to_string());
  }

  fn generate_union<'arena>(
    generator: &mut Generator<'arena, '_>,
    builder: &mut Builder,
    node: &Node<'arena>
  ) {
    let node = cast_node!(UnionType, &node.wrapper);
    let types = Self::map_types(generator, &node.types);
    builder.push(&types.join("|"));
  }

  fn generate_intersection<'arena>(
    generator: &mut Generator<'arena, '_>,
    builder: &mut Builder,
    node: &Node<'arena>
  ) {
    let node = cast_node!(IntersectionType, &node.wrapper);
    let types = Self::map_types(generator, &node.types);

    builder.push(&types.join("&"));
  }

  fn map_types<'arena>(
    generator: &mut Generator<'arena, '_>,
    types: &[Node<'arena>]
  ) -> Vec<String> {
    types
      .iter()
      .map(|x| {
        let mut scoped_builder = Builder::new();
        scoped_builder.new_line();
        match x.node_type {
          NodeType::Type => Self::generate_basic(generator, &mut scoped_builder, x),
          NodeType::UnionType => {
            scoped_builder.push("(");
            Self::generate_union(generator, &mut scoped_builder, x);
            scoped_builder.push(")");
          }
          NodeType::IntersectionType => {
            scoped_builder.push("(");
            Self::generate_intersection(generator, &mut scoped_builder, x);
            scoped_builder.push(")");
          }
          _ => {
            panic!("TypeGenerator::generate_union: failed to get type");
          }
        }
        scoped_builder.print("")
      })
      .collect::<Vec<String>>()
  }
}