backyard-generator 0.1.10

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

use crate::generator::{
  Builder,
  EndMode,
  Generator,
  GeneratorArgument,
  InternalGenerator,
  DEFAULT_GENERATORS,
};

pub struct BlockGenerator;

impl BlockGenerator {
  pub fn generate_single<'arena>(
    generator: &mut Generator<'arena, '_>,
    builder: &mut Builder,
    node: &Node<'arena>
  ) {
    builder.push("{");
    let mut block = Self::generate_base(generator, node, &DEFAULT_GENERATORS);
    block.indent();
    builder.extend(block);
    builder.new_line();
    builder.push("}");
  }

  pub fn generate<'arena>(
    generator: &mut Generator<'arena, '_>,
    builder: &mut Builder,
    node: &Node<'arena>,
    short_close: Option<&str>
  ) {
    Self::generate_specific(generator, builder, node, short_close, &DEFAULT_GENERATORS)
  }

  pub fn generate_specific<'arena>(
    generator: &mut Generator<'arena, '_>,
    builder: &mut Builder,
    node: &Node<'arena>,
    short_close: Option<&str>,
    generators: &[(NodeType, InternalGenerator)]
  ) {
    let leadings = &node.leadings;
    let trailings = &node.trailings;
    if
      (leadings.is_some() && !leadings.as_ref().unwrap().is_empty()) ||
      (trailings.is_some() && !trailings.as_ref().unwrap().is_empty())
    {
      let mut scoped_builder = Builder::new();
      if let Some(leadings) = leadings {
        generator.handle_comments(&mut scoped_builder, leadings);
      }
      if scoped_builder.total_len() == 0 {
        scoped_builder.new_line();
      }
      Self::print_block(generator, &mut scoped_builder, node, short_close, generators);
      if let Some(trailings) = trailings {
        generator.handle_comments(&mut scoped_builder, trailings);
      }
      builder.extend_first_line(scoped_builder);
    } else {
      Self::print_block(generator, builder, node, short_close, generators);
    }
  }

  fn print_block<'arena>(
    generator: &mut Generator<'arena, '_>,
    builder: &mut Builder,
    node: &Node<'arena>,
    short_close: Option<&str>,
    generators: &[(NodeType, InternalGenerator)]
  ) {
    let mut block = Self::generate_base(generator, node, generators);
    block.indent();
    if let Some(close) = short_close {
      builder.push(":");
      builder.extend(block);
      builder.new_line();
      builder.push(close);
    } else {
      if node.leadings.is_none() || node.leadings.as_ref().unwrap().is_empty() {
        builder.push(" ");
      }
      builder.push("{");
      builder.extend(block);
      builder.new_line();
      builder.push("}");
    }
  }

  pub fn generate_base<'arena>(
    generator: &mut Generator<'arena, '_>,
    node: &Node<'arena>,
    generators: &[(NodeType, InternalGenerator)]
  ) -> Builder {
    let mut block = Builder::new();
    let node = if let NodeWrapper::Block(n) = &node.wrapper {
      n
    } else {
      return block;
    };
    generator.generate_nodes(
      &mut block,
      &node.statements,
      &mut GeneratorArgument::new(EndMode::SemicolonDynamic, generators)
    );
    block
  }
}