// NOTE: This file is generated by the templates/template.rb script and should not
// be modified manually. See /home/runner/work/herb/herb/templates/rust/src/visitor.rs.erb

use crate::nodes::*;
use crate::union_types::*;

/// Visitor trait for traversing the Herb AST.
///
/// Provides a visit/walk separation pattern:
/// - `visit_*` methods are the entry points for each node type (override these in rules)
/// - `walk_*` methods traverse child nodes (call these explicitly from `visit_*` overrides)
///
/// Default `visit_*` implementations call the corresponding `walk_*` method.
/// Override `visit_*` to add custom behavior, then call `walk_*` to continue traversal.
pub trait Visitor {
  fn visit(&mut self, node: &AnyNode) {
    match node {
      AnyNode::DocumentNode(n) => self.visit_document_node(n),
      AnyNode::LiteralNode(n) => self.visit_literal_node(n),
      AnyNode::HTMLOpenTagNode(n) => self.visit_html_open_tag_node(n),
      AnyNode::HTMLConditionalOpenTagNode(n) => self.visit_html_conditional_open_tag_node(n),
      AnyNode::HTMLCloseTagNode(n) => self.visit_html_close_tag_node(n),
      AnyNode::HTMLOmittedCloseTagNode(n) => self.visit_html_omitted_close_tag_node(n),
      AnyNode::HTMLVirtualCloseTagNode(n) => self.visit_html_virtual_close_tag_node(n),
      AnyNode::HTMLElementNode(n) => self.visit_html_element_node(n),
      AnyNode::HTMLConditionalElementNode(n) => self.visit_html_conditional_element_node(n),
      AnyNode::HTMLAttributeValueNode(n) => self.visit_html_attribute_value_node(n),
      AnyNode::HTMLAttributeNameNode(n) => self.visit_html_attribute_name_node(n),
      AnyNode::HTMLAttributeNode(n) => self.visit_html_attribute_node(n),
      AnyNode::RubyLiteralNode(n) => self.visit_ruby_literal_node(n),
      AnyNode::RubyHTMLAttributesSplatNode(n) => self.visit_ruby_html_attributes_splat_node(n),
      AnyNode::ERBOpenTagNode(n) => self.visit_erb_open_tag_node(n),
      AnyNode::HTMLTextNode(n) => self.visit_html_text_node(n),
      AnyNode::HTMLCommentNode(n) => self.visit_html_comment_node(n),
      AnyNode::HTMLDoctypeNode(n) => self.visit_html_doctype_node(n),
      AnyNode::XMLDeclarationNode(n) => self.visit_xml_declaration_node(n),
      AnyNode::CDATANode(n) => self.visit_cdata_node(n),
      AnyNode::WhitespaceNode(n) => self.visit_whitespace_node(n),
      AnyNode::ERBContentNode(n) => self.visit_erb_content_node(n),
      AnyNode::ERBEndNode(n) => self.visit_erb_end_node(n),
      AnyNode::ERBElseNode(n) => self.visit_erb_else_node(n),
      AnyNode::ERBIfNode(n) => self.visit_erb_if_node(n),
      AnyNode::ERBBlockNode(n) => self.visit_erb_block_node(n),
      AnyNode::ERBWhenNode(n) => self.visit_erb_when_node(n),
      AnyNode::ERBCaseNode(n) => self.visit_erb_case_node(n),
      AnyNode::ERBCaseMatchNode(n) => self.visit_erb_case_match_node(n),
      AnyNode::ERBWhileNode(n) => self.visit_erb_while_node(n),
      AnyNode::ERBUntilNode(n) => self.visit_erb_until_node(n),
      AnyNode::ERBForNode(n) => self.visit_erb_for_node(n),
      AnyNode::ERBRescueNode(n) => self.visit_erb_rescue_node(n),
      AnyNode::ERBEnsureNode(n) => self.visit_erb_ensure_node(n),
      AnyNode::ERBBeginNode(n) => self.visit_erb_begin_node(n),
      AnyNode::ERBUnlessNode(n) => self.visit_erb_unless_node(n),
      AnyNode::RubyRenderLocalNode(n) => self.visit_ruby_render_local_node(n),
      AnyNode::ERBRenderNode(n) => self.visit_erb_render_node(n),
      AnyNode::RubyStrictLocalNode(n) => self.visit_ruby_strict_local_node(n),
      AnyNode::ERBStrictLocalsNode(n) => self.visit_erb_strict_locals_node(n),
      AnyNode::ERBYieldNode(n) => self.visit_erb_yield_node(n),
      AnyNode::ERBInNode(n) => self.visit_erb_in_node(n),
    }
  }

  fn visit_all(&mut self, nodes: &[AnyNode]) {
    for node in nodes {
      self.visit(node);
    }
  }

  fn visit_erb_node(&mut self, _node: &dyn ERBNode) {
    // Default implementation does nothing
  }

  fn visit_document_node(&mut self, node: &DocumentNode) {
    self.walk_document_node(node);
  }

  fn walk_document_node(&mut self, node: &DocumentNode) {
    self.visit_all(&node.children);
  }

  fn visit_literal_node(&mut self, node: &LiteralNode) {
    self.walk_literal_node(node);
  }

  fn walk_literal_node(&mut self, node: &LiteralNode) {
    let _ = node;
  }

  fn visit_html_open_tag_node(&mut self, node: &HTMLOpenTagNode) {
    self.walk_html_open_tag_node(node);
  }

  fn walk_html_open_tag_node(&mut self, node: &HTMLOpenTagNode) {
    self.visit_all(&node.children);
  }

  fn visit_html_conditional_open_tag_node(&mut self, node: &HTMLConditionalOpenTagNode) {
    self.walk_html_conditional_open_tag_node(node);
  }

  fn walk_html_conditional_open_tag_node(&mut self, node: &HTMLConditionalOpenTagNode) {
    if let Some(ref child) = node.conditional {
      match child {
        ERBIfNodeOrERBUnlessNode::ERBIfNode(n) => self.visit_erb_if_node(n),
        ERBIfNodeOrERBUnlessNode::ERBUnlessNode(n) => self.visit_erb_unless_node(n),
      }
    }
  }

  fn visit_html_close_tag_node(&mut self, node: &HTMLCloseTagNode) {
    self.walk_html_close_tag_node(node);
  }

  fn walk_html_close_tag_node(&mut self, node: &HTMLCloseTagNode) {
    self.visit_all(&node.children);
  }

  fn visit_html_omitted_close_tag_node(&mut self, node: &HTMLOmittedCloseTagNode) {
    self.walk_html_omitted_close_tag_node(node);
  }

  fn walk_html_omitted_close_tag_node(&mut self, node: &HTMLOmittedCloseTagNode) {
    let _ = node;
  }

  fn visit_html_virtual_close_tag_node(&mut self, node: &HTMLVirtualCloseTagNode) {
    self.walk_html_virtual_close_tag_node(node);
  }

  fn walk_html_virtual_close_tag_node(&mut self, node: &HTMLVirtualCloseTagNode) {
    let _ = node;
  }

  fn visit_html_element_node(&mut self, node: &HTMLElementNode) {
    self.walk_html_element_node(node);
  }

  fn walk_html_element_node(&mut self, node: &HTMLElementNode) {
    if let Some(ref child) = node.open_tag {
      match child {
        ERBOpenTagNodeOrHTMLConditionalOpenTagNodeOrHTMLOpenTagNode::HTMLOpenTagNode(n) => self.visit_html_open_tag_node(n),
        ERBOpenTagNodeOrHTMLConditionalOpenTagNodeOrHTMLOpenTagNode::HTMLConditionalOpenTagNode(n) => self.visit_html_conditional_open_tag_node(n),
        ERBOpenTagNodeOrHTMLConditionalOpenTagNodeOrHTMLOpenTagNode::ERBOpenTagNode(n) => self.visit_erb_open_tag_node(n),
      }
    }
    self.visit_all(&node.body);
    if let Some(ref child) = node.close_tag {
      match child {
        ERBEndNodeOrHTMLCloseTagNodeOrHTMLOmittedCloseTagNodeOrHTMLVirtualCloseTagNode::HTMLCloseTagNode(n) => self.visit_html_close_tag_node(n),
        ERBEndNodeOrHTMLCloseTagNodeOrHTMLOmittedCloseTagNodeOrHTMLVirtualCloseTagNode::HTMLOmittedCloseTagNode(n) => self.visit_html_omitted_close_tag_node(n),
        ERBEndNodeOrHTMLCloseTagNodeOrHTMLOmittedCloseTagNodeOrHTMLVirtualCloseTagNode::HTMLVirtualCloseTagNode(n) => self.visit_html_virtual_close_tag_node(n),
        ERBEndNodeOrHTMLCloseTagNodeOrHTMLOmittedCloseTagNodeOrHTMLVirtualCloseTagNode::ERBEndNode(n) => self.visit_erb_end_node(n),
      }
    }
  }

  fn visit_html_conditional_element_node(&mut self, node: &HTMLConditionalElementNode) {
    self.walk_html_conditional_element_node(node);
  }

  fn walk_html_conditional_element_node(&mut self, node: &HTMLConditionalElementNode) {
    if let Some(ref child) = node.open_conditional {
      match child {
        ERBIfNodeOrERBUnlessNode::ERBIfNode(n) => self.visit_erb_if_node(n),
        ERBIfNodeOrERBUnlessNode::ERBUnlessNode(n) => self.visit_erb_unless_node(n),
      }
    }
    if let Some(ref child) = node.open_tag {
      self.visit_html_open_tag_node(child);
    }
    self.visit_all(&node.body);
    if let Some(ref child) = node.close_tag {
      match child {
        HTMLCloseTagNodeOrHTMLOmittedCloseTagNode::HTMLCloseTagNode(n) => self.visit_html_close_tag_node(n),
        HTMLCloseTagNodeOrHTMLOmittedCloseTagNode::HTMLOmittedCloseTagNode(n) => self.visit_html_omitted_close_tag_node(n),
      }
    }
    if let Some(ref child) = node.close_conditional {
      match child {
        ERBIfNodeOrERBUnlessNode::ERBIfNode(n) => self.visit_erb_if_node(n),
        ERBIfNodeOrERBUnlessNode::ERBUnlessNode(n) => self.visit_erb_unless_node(n),
      }
    }
  }

  fn visit_html_attribute_value_node(&mut self, node: &HTMLAttributeValueNode) {
    self.walk_html_attribute_value_node(node);
  }

  fn walk_html_attribute_value_node(&mut self, node: &HTMLAttributeValueNode) {
    self.visit_all(&node.children);
  }

  fn visit_html_attribute_name_node(&mut self, node: &HTMLAttributeNameNode) {
    self.walk_html_attribute_name_node(node);
  }

  fn walk_html_attribute_name_node(&mut self, node: &HTMLAttributeNameNode) {
    self.visit_all(&node.children);
  }

  fn visit_html_attribute_node(&mut self, node: &HTMLAttributeNode) {
    self.walk_html_attribute_node(node);
  }

  fn walk_html_attribute_node(&mut self, node: &HTMLAttributeNode) {
    if let Some(ref child) = node.name {
      self.visit_html_attribute_name_node(child);
    }
    if let Some(ref child) = node.value {
      self.visit_html_attribute_value_node(child);
    }
  }

  fn visit_ruby_literal_node(&mut self, node: &RubyLiteralNode) {
    self.walk_ruby_literal_node(node);
  }

  fn walk_ruby_literal_node(&mut self, node: &RubyLiteralNode) {
    let _ = node;
  }

  fn visit_ruby_html_attributes_splat_node(&mut self, node: &RubyHTMLAttributesSplatNode) {
    self.walk_ruby_html_attributes_splat_node(node);
  }

  fn walk_ruby_html_attributes_splat_node(&mut self, node: &RubyHTMLAttributesSplatNode) {
    let _ = node;
  }

  fn visit_erb_open_tag_node(&mut self, node: &ERBOpenTagNode) {
    self.visit_erb_node(node);
    self.walk_erb_open_tag_node(node);
  }

  fn walk_erb_open_tag_node(&mut self, node: &ERBOpenTagNode) {
    self.visit_all(&node.children);
  }

  fn visit_html_text_node(&mut self, node: &HTMLTextNode) {
    self.walk_html_text_node(node);
  }

  fn walk_html_text_node(&mut self, node: &HTMLTextNode) {
    let _ = node;
  }

  fn visit_html_comment_node(&mut self, node: &HTMLCommentNode) {
    self.walk_html_comment_node(node);
  }

  fn walk_html_comment_node(&mut self, node: &HTMLCommentNode) {
    self.visit_all(&node.children);
  }

  fn visit_html_doctype_node(&mut self, node: &HTMLDoctypeNode) {
    self.walk_html_doctype_node(node);
  }

  fn walk_html_doctype_node(&mut self, node: &HTMLDoctypeNode) {
    self.visit_all(&node.children);
  }

  fn visit_xml_declaration_node(&mut self, node: &XMLDeclarationNode) {
    self.walk_xml_declaration_node(node);
  }

  fn walk_xml_declaration_node(&mut self, node: &XMLDeclarationNode) {
    self.visit_all(&node.children);
  }

  fn visit_cdata_node(&mut self, node: &CDATANode) {
    self.walk_cdata_node(node);
  }

  fn walk_cdata_node(&mut self, node: &CDATANode) {
    self.visit_all(&node.children);
  }

  fn visit_whitespace_node(&mut self, node: &WhitespaceNode) {
    self.walk_whitespace_node(node);
  }

  fn walk_whitespace_node(&mut self, node: &WhitespaceNode) {
    let _ = node;
  }

  fn visit_erb_content_node(&mut self, node: &ERBContentNode) {
    self.visit_erb_node(node);
    self.walk_erb_content_node(node);
  }

  fn walk_erb_content_node(&mut self, node: &ERBContentNode) {
    let _ = node;
  }

  fn visit_erb_end_node(&mut self, node: &ERBEndNode) {
    self.visit_erb_node(node);
    self.walk_erb_end_node(node);
  }

  fn walk_erb_end_node(&mut self, node: &ERBEndNode) {
    let _ = node;
  }

  fn visit_erb_else_node(&mut self, node: &ERBElseNode) {
    self.visit_erb_node(node);
    self.walk_erb_else_node(node);
  }

  fn walk_erb_else_node(&mut self, node: &ERBElseNode) {
    self.visit_all(&node.statements);
  }

  fn visit_erb_if_node(&mut self, node: &ERBIfNode) {
    self.visit_erb_node(node);
    self.walk_erb_if_node(node);
  }

  fn walk_erb_if_node(&mut self, node: &ERBIfNode) {
    self.visit_all(&node.statements);
    if let Some(ref child) = node.subsequent {
      match child {
        ERBElseNodeOrERBIfNode::ERBIfNode(n) => self.visit_erb_if_node(n),
        ERBElseNodeOrERBIfNode::ERBElseNode(n) => self.visit_erb_else_node(n),
      }
    }
    if let Some(ref child) = node.end_node {
      self.visit_erb_end_node(child);
    }
  }

  fn visit_erb_block_node(&mut self, node: &ERBBlockNode) {
    self.visit_erb_node(node);
    self.walk_erb_block_node(node);
  }

  fn walk_erb_block_node(&mut self, node: &ERBBlockNode) {
    self.visit_all(&node.body);
    if let Some(ref child) = node.rescue_clause {
      self.visit_erb_rescue_node(child);
    }
    if let Some(ref child) = node.else_clause {
      self.visit_erb_else_node(child);
    }
    if let Some(ref child) = node.ensure_clause {
      self.visit_erb_ensure_node(child);
    }
    if let Some(ref child) = node.end_node {
      self.visit_erb_end_node(child);
    }
  }

  fn visit_erb_when_node(&mut self, node: &ERBWhenNode) {
    self.visit_erb_node(node);
    self.walk_erb_when_node(node);
  }

  fn walk_erb_when_node(&mut self, node: &ERBWhenNode) {
    self.visit_all(&node.statements);
  }

  fn visit_erb_case_node(&mut self, node: &ERBCaseNode) {
    self.visit_erb_node(node);
    self.walk_erb_case_node(node);
  }

  fn walk_erb_case_node(&mut self, node: &ERBCaseNode) {
    self.visit_all(&node.children);
    self.visit_all(&node.conditions);
    if let Some(ref child) = node.else_clause {
      self.visit_erb_else_node(child);
    }
    if let Some(ref child) = node.end_node {
      self.visit_erb_end_node(child);
    }
  }

  fn visit_erb_case_match_node(&mut self, node: &ERBCaseMatchNode) {
    self.visit_erb_node(node);
    self.walk_erb_case_match_node(node);
  }

  fn walk_erb_case_match_node(&mut self, node: &ERBCaseMatchNode) {
    self.visit_all(&node.children);
    self.visit_all(&node.conditions);
    if let Some(ref child) = node.else_clause {
      self.visit_erb_else_node(child);
    }
    if let Some(ref child) = node.end_node {
      self.visit_erb_end_node(child);
    }
  }

  fn visit_erb_while_node(&mut self, node: &ERBWhileNode) {
    self.visit_erb_node(node);
    self.walk_erb_while_node(node);
  }

  fn walk_erb_while_node(&mut self, node: &ERBWhileNode) {
    self.visit_all(&node.statements);
    if let Some(ref child) = node.end_node {
      self.visit_erb_end_node(child);
    }
  }

  fn visit_erb_until_node(&mut self, node: &ERBUntilNode) {
    self.visit_erb_node(node);
    self.walk_erb_until_node(node);
  }

  fn walk_erb_until_node(&mut self, node: &ERBUntilNode) {
    self.visit_all(&node.statements);
    if let Some(ref child) = node.end_node {
      self.visit_erb_end_node(child);
    }
  }

  fn visit_erb_for_node(&mut self, node: &ERBForNode) {
    self.visit_erb_node(node);
    self.walk_erb_for_node(node);
  }

  fn walk_erb_for_node(&mut self, node: &ERBForNode) {
    self.visit_all(&node.statements);
    if let Some(ref child) = node.end_node {
      self.visit_erb_end_node(child);
    }
  }

  fn visit_erb_rescue_node(&mut self, node: &ERBRescueNode) {
    self.visit_erb_node(node);
    self.walk_erb_rescue_node(node);
  }

  fn walk_erb_rescue_node(&mut self, node: &ERBRescueNode) {
    self.visit_all(&node.statements);
    if let Some(ref child) = node.subsequent {
      self.visit_erb_rescue_node(child);
    }
  }

  fn visit_erb_ensure_node(&mut self, node: &ERBEnsureNode) {
    self.visit_erb_node(node);
    self.walk_erb_ensure_node(node);
  }

  fn walk_erb_ensure_node(&mut self, node: &ERBEnsureNode) {
    self.visit_all(&node.statements);
  }

  fn visit_erb_begin_node(&mut self, node: &ERBBeginNode) {
    self.visit_erb_node(node);
    self.walk_erb_begin_node(node);
  }

  fn walk_erb_begin_node(&mut self, node: &ERBBeginNode) {
    self.visit_all(&node.statements);
    if let Some(ref child) = node.rescue_clause {
      self.visit_erb_rescue_node(child);
    }
    if let Some(ref child) = node.else_clause {
      self.visit_erb_else_node(child);
    }
    if let Some(ref child) = node.ensure_clause {
      self.visit_erb_ensure_node(child);
    }
    if let Some(ref child) = node.end_node {
      self.visit_erb_end_node(child);
    }
  }

  fn visit_erb_unless_node(&mut self, node: &ERBUnlessNode) {
    self.visit_erb_node(node);
    self.walk_erb_unless_node(node);
  }

  fn walk_erb_unless_node(&mut self, node: &ERBUnlessNode) {
    self.visit_all(&node.statements);
    if let Some(ref child) = node.else_clause {
      self.visit_erb_else_node(child);
    }
    if let Some(ref child) = node.end_node {
      self.visit_erb_end_node(child);
    }
  }

  fn visit_ruby_render_local_node(&mut self, node: &RubyRenderLocalNode) {
    self.walk_ruby_render_local_node(node);
  }

  fn walk_ruby_render_local_node(&mut self, node: &RubyRenderLocalNode) {
    if let Some(ref child) = node.value {
      self.visit_ruby_literal_node(child);
    }
  }

  fn visit_erb_render_node(&mut self, node: &ERBRenderNode) {
    self.visit_erb_node(node);
    self.walk_erb_render_node(node);
  }

  fn walk_erb_render_node(&mut self, node: &ERBRenderNode) {
    self.visit_all(&node.locals);
  }

  fn visit_ruby_strict_local_node(&mut self, node: &RubyStrictLocalNode) {
    self.walk_ruby_strict_local_node(node);
  }

  fn walk_ruby_strict_local_node(&mut self, node: &RubyStrictLocalNode) {
    if let Some(ref child) = node.default_value {
      self.visit_ruby_literal_node(child);
    }
  }

  fn visit_erb_strict_locals_node(&mut self, node: &ERBStrictLocalsNode) {
    self.visit_erb_node(node);
    self.walk_erb_strict_locals_node(node);
  }

  fn walk_erb_strict_locals_node(&mut self, node: &ERBStrictLocalsNode) {
    self.visit_all(&node.locals);
  }

  fn visit_erb_yield_node(&mut self, node: &ERBYieldNode) {
    self.visit_erb_node(node);
    self.walk_erb_yield_node(node);
  }

  fn walk_erb_yield_node(&mut self, node: &ERBYieldNode) {
    let _ = node;
  }

  fn visit_erb_in_node(&mut self, node: &ERBInNode) {
    self.visit_erb_node(node);
    self.walk_erb_in_node(node);
  }

  fn walk_erb_in_node(&mut self, node: &ERBInNode) {
    self.visit_all(&node.statements);
  }

}
