# frozen_string_literal: true
=begin
This file is generated by the bin/template script and should not be
modified manually. See templates/lib/yarp/node.rb.erb
if you are looking to modify the template
=end

module YARP
  # Represents the use of the `alias` keyword.
  #
  #     alias foo bar
  #     ^^^^^^^^^^^^^
  class AliasNode < Node
    # attr_reader new_name: Node
    attr_reader :new_name

    # attr_reader old_name: Node
    attr_reader :old_name

    # attr_reader keyword_loc: Location
    attr_reader :keyword_loc

    # def initialize: (new_name: Node, old_name: Node, keyword_loc: Location, location: Location) -> void
    def initialize(new_name, old_name, keyword_loc, location)
      @new_name = new_name
      @old_name = old_name
      @keyword_loc = keyword_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_alias_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [new_name, old_name]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { new_name: new_name, old_name: old_name, keyword_loc: keyword_loc, location: location }
    end

    # def keyword: () -> String
    def keyword
      keyword_loc.slice
    end
  end

  # Represents an alternation pattern in pattern matching.
  #
  #     foo => bar | baz
  #            ^^^^^^^^^
  class AlternationPatternNode < Node
    # attr_reader left: Node
    attr_reader :left

    # attr_reader right: Node
    attr_reader :right

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # def initialize: (left: Node, right: Node, operator_loc: Location, location: Location) -> void
    def initialize(left, right, operator_loc, location)
      @left = left
      @right = right
      @operator_loc = operator_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_alternation_pattern_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [left, right]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { left: left, right: right, operator_loc: operator_loc, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents the use of the `&&` operator or the `and` keyword.
  #
  #     left and right
  #     ^^^^^^^^^^^^^^
  class AndNode < Node
    # attr_reader left: Node
    attr_reader :left

    # attr_reader right: Node
    attr_reader :right

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # def initialize: (left: Node, right: Node, operator_loc: Location, location: Location) -> void
    def initialize(left, right, operator_loc, location)
      @left = left
      @right = right
      @operator_loc = operator_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_and_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [left, right]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { left: left, right: right, operator_loc: operator_loc, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents a set of arguments to a method or a keyword.
  #
  #     return foo, bar, baz
  #            ^^^^^^^^^^^^^
  class ArgumentsNode < Node
    # attr_reader arguments: Array[Node]
    attr_reader :arguments

    # def initialize: (arguments: Array[Node], location: Location) -> void
    def initialize(arguments, location)
      @arguments = arguments
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_arguments_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [*arguments]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { arguments: arguments, location: location }
    end
  end

  # Represents an array literal. This can be a regular array using brackets or
  # a special array using % like %w or %i.
  #
  #     [1, 2, 3]
  #     ^^^^^^^^^
  class ArrayNode < Node
    # attr_reader elements: Array[Node]
    attr_reader :elements

    # attr_reader opening_loc: Location?
    attr_reader :opening_loc

    # attr_reader closing_loc: Location?
    attr_reader :closing_loc

    # def initialize: (elements: Array[Node], opening_loc: Location?, closing_loc: Location?, location: Location) -> void
    def initialize(elements, opening_loc, closing_loc, location)
      @elements = elements
      @opening_loc = opening_loc
      @closing_loc = closing_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_array_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [*elements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { elements: elements, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
    end

    # def opening: () -> String?
    def opening
      opening_loc&.slice
    end

    # def closing: () -> String?
    def closing
      closing_loc&.slice
    end
  end

  # Represents an array pattern in pattern matching.
  #
  #     foo in 1, 2
  #     ^^^^^^^^^^^
  #
  #     foo in [1, 2]
  #     ^^^^^^^^^^^^^
  #
  #     foo in *1
  #     ^^^^^^^^^
  #
  #     foo in Bar[]
  #     ^^^^^^^^^^^^
  #
  #     foo in Bar[1, 2, 3]
  #     ^^^^^^^^^^^^^^^^^^^
  class ArrayPatternNode < Node
    # attr_reader constant: Node?
    attr_reader :constant

    # attr_reader requireds: Array[Node]
    attr_reader :requireds

    # attr_reader rest: Node?
    attr_reader :rest

    # attr_reader posts: Array[Node]
    attr_reader :posts

    # attr_reader opening_loc: Location?
    attr_reader :opening_loc

    # attr_reader closing_loc: Location?
    attr_reader :closing_loc

    # def initialize: (constant: Node?, requireds: Array[Node], rest: Node?, posts: Array[Node], opening_loc: Location?, closing_loc: Location?, location: Location) -> void
    def initialize(constant, requireds, rest, posts, opening_loc, closing_loc, location)
      @constant = constant
      @requireds = requireds
      @rest = rest
      @posts = posts
      @opening_loc = opening_loc
      @closing_loc = closing_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_array_pattern_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [constant, *requireds, rest, *posts]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { constant: constant, requireds: requireds, rest: rest, posts: posts, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
    end

    # def opening: () -> String?
    def opening
      opening_loc&.slice
    end

    # def closing: () -> String?
    def closing
      closing_loc&.slice
    end
  end

  # Represents a hash key/value pair.
  #
  #     { a => b }
  #       ^^^^^^
  class AssocNode < Node
    # attr_reader key: Node
    attr_reader :key

    # attr_reader value: Node?
    attr_reader :value

    # attr_reader operator_loc: Location?
    attr_reader :operator_loc

    # def initialize: (key: Node, value: Node?, operator_loc: Location?, location: Location) -> void
    def initialize(key, value, operator_loc, location)
      @key = key
      @value = value
      @operator_loc = operator_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_assoc_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [key, value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { key: key, value: value, operator_loc: operator_loc, location: location }
    end

    # def operator: () -> String?
    def operator
      operator_loc&.slice
    end
  end

  # Represents a splat in a hash literal.
  #
  #     { **foo }
  #       ^^^^^
  class AssocSplatNode < Node
    # attr_reader value: Node?
    attr_reader :value

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # def initialize: (value: Node?, operator_loc: Location, location: Location) -> void
    def initialize(value, operator_loc, location)
      @value = value
      @operator_loc = operator_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_assoc_splat_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { value: value, operator_loc: operator_loc, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents reading a reference to a field in the previous match.
  #
  #     $'
  #     ^^
  class BackReferenceReadNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_back_reference_read_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents a begin statement.
  #
  #     begin
  #       foo
  #     end
  #     ^^^^^
  class BeginNode < Node
    # attr_reader begin_keyword_loc: Location?
    attr_reader :begin_keyword_loc

    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader rescue_clause: Node?
    attr_reader :rescue_clause

    # attr_reader else_clause: Node?
    attr_reader :else_clause

    # attr_reader ensure_clause: Node?
    attr_reader :ensure_clause

    # attr_reader end_keyword_loc: Location?
    attr_reader :end_keyword_loc

    # def initialize: (begin_keyword_loc: Location?, statements: Node?, rescue_clause: Node?, else_clause: Node?, ensure_clause: Node?, end_keyword_loc: Location?, location: Location) -> void
    def initialize(begin_keyword_loc, statements, rescue_clause, else_clause, ensure_clause, end_keyword_loc, location)
      @begin_keyword_loc = begin_keyword_loc
      @statements = statements
      @rescue_clause = rescue_clause
      @else_clause = else_clause
      @ensure_clause = ensure_clause
      @end_keyword_loc = end_keyword_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_begin_node(self)
    end

    def set_newline_flag(newline_marked)
      # Never mark BeginNode with a newline flag, mark children instead
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [statements, rescue_clause, else_clause, ensure_clause]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { begin_keyword_loc: begin_keyword_loc, statements: statements, rescue_clause: rescue_clause, else_clause: else_clause, ensure_clause: ensure_clause, end_keyword_loc: end_keyword_loc, location: location }
    end

    # def begin_keyword: () -> String?
    def begin_keyword
      begin_keyword_loc&.slice
    end

    # def end_keyword: () -> String?
    def end_keyword
      end_keyword_loc&.slice
    end
  end

  # Represents block method arguments.
  #
  #     bar(&args)
  #     ^^^^^^^^^^
  class BlockArgumentNode < Node
    # attr_reader expression: Node?
    attr_reader :expression

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # def initialize: (expression: Node?, operator_loc: Location, location: Location) -> void
    def initialize(expression, operator_loc, location)
      @expression = expression
      @operator_loc = operator_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_block_argument_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [expression]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { expression: expression, operator_loc: operator_loc, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents a block of ruby code.
  #
  # [1, 2, 3].each { |i| puts x }
  #                ^^^^^^^^^^^^^^
  class BlockNode < Node
    # attr_reader locals: Array[Symbol]
    attr_reader :locals

    # attr_reader parameters: Node?
    attr_reader :parameters

    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader opening_loc: Location
    attr_reader :opening_loc

    # attr_reader closing_loc: Location
    attr_reader :closing_loc

    # def initialize: (locals: Array[Symbol], parameters: Node?, statements: Node?, opening_loc: Location, closing_loc: Location, location: Location) -> void
    def initialize(locals, parameters, statements, opening_loc, closing_loc, location)
      @locals = locals
      @parameters = parameters
      @statements = statements
      @opening_loc = opening_loc
      @closing_loc = closing_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_block_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [parameters, statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { locals: locals, parameters: parameters, statements: statements, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
    end

    # def opening: () -> String
    def opening
      opening_loc.slice
    end

    # def closing: () -> String
    def closing
      closing_loc.slice
    end
  end

  # Represents a block parameter to a method, block, or lambda definition.
  #
  #     def a(&b)
  #           ^^
  #     end
  class BlockParameterNode < Node
    # attr_reader name_loc: Location?
    attr_reader :name_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # def initialize: (name_loc: Location?, operator_loc: Location, location: Location) -> void
    def initialize(name_loc, operator_loc, location)
      @name_loc = name_loc
      @operator_loc = operator_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_block_parameter_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, operator_loc: operator_loc, location: location }
    end

    # def name: () -> String?
    def name
      name_loc&.slice
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents a block's parameters declaration.
  #
  #     -> (a, b = 1; local) { }
  #        ^^^^^^^^^^^^^^^^^
  #
  #     foo do |a, b = 1; local|
  #            ^^^^^^^^^^^^^^^^^
  #     end
  class BlockParametersNode < Node
    # attr_reader parameters: Node?
    attr_reader :parameters

    # attr_reader locals: Array[Location]
    attr_reader :locals

    # attr_reader opening_loc: Location?
    attr_reader :opening_loc

    # attr_reader closing_loc: Location?
    attr_reader :closing_loc

    # def initialize: (parameters: Node?, locals: Array[Location], opening_loc: Location?, closing_loc: Location?, location: Location) -> void
    def initialize(parameters, locals, opening_loc, closing_loc, location)
      @parameters = parameters
      @locals = locals
      @opening_loc = opening_loc
      @closing_loc = closing_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_block_parameters_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [parameters]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { parameters: parameters, locals: locals, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
    end

    # def opening: () -> String?
    def opening
      opening_loc&.slice
    end

    # def closing: () -> String?
    def closing
      closing_loc&.slice
    end
  end

  # Represents the use of the `break` keyword.
  #
  #     break foo
  #     ^^^^^^^^^
  class BreakNode < Node
    # attr_reader arguments: Node?
    attr_reader :arguments

    # attr_reader keyword_loc: Location
    attr_reader :keyword_loc

    # def initialize: (arguments: Node?, keyword_loc: Location, location: Location) -> void
    def initialize(arguments, keyword_loc, location)
      @arguments = arguments
      @keyword_loc = keyword_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_break_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [arguments]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { arguments: arguments, keyword_loc: keyword_loc, location: location }
    end

    # def keyword: () -> String
    def keyword
      keyword_loc.slice
    end
  end

  # Represents a method call, in all of the various forms that can take.
  #
  #     foo
  #     ^^^
  #
  #     foo()
  #     ^^^^^
  #
  #     +foo
  #     ^^^^
  #
  #     foo + bar
  #     ^^^^^^^^^
  #
  #     foo.bar
  #     ^^^^^^^
  #
  #     foo&.bar
  #     ^^^^^^^^
  class CallNode < Node
    # attr_reader receiver: Node?
    attr_reader :receiver

    # attr_reader operator_loc: Location?
    attr_reader :operator_loc

    # attr_reader message_loc: Location?
    attr_reader :message_loc

    # attr_reader opening_loc: Location?
    attr_reader :opening_loc

    # attr_reader arguments: Node?
    attr_reader :arguments

    # attr_reader closing_loc: Location?
    attr_reader :closing_loc

    # attr_reader block: Node?
    attr_reader :block

    # attr_reader flags: Integer
    attr_reader :flags

    # attr_reader name: String
    attr_reader :name

    # def initialize: (receiver: Node?, operator_loc: Location?, message_loc: Location?, opening_loc: Location?, arguments: Node?, closing_loc: Location?, block: Node?, flags: Integer, name: String, location: Location) -> void
    def initialize(receiver, operator_loc, message_loc, opening_loc, arguments, closing_loc, block, flags, name, location)
      @receiver = receiver
      @operator_loc = operator_loc
      @message_loc = message_loc
      @opening_loc = opening_loc
      @arguments = arguments
      @closing_loc = closing_loc
      @block = block
      @flags = flags
      @name = name
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_call_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [receiver, arguments, block]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { receiver: receiver, operator_loc: operator_loc, message_loc: message_loc, opening_loc: opening_loc, arguments: arguments, closing_loc: closing_loc, block: block, flags: flags, name: name, location: location }
    end

    # def operator: () -> String?
    def operator
      operator_loc&.slice
    end

    # def message: () -> String?
    def message
      message_loc&.slice
    end

    # def opening: () -> String?
    def opening
      opening_loc&.slice
    end

    # def closing: () -> String?
    def closing
      closing_loc&.slice
    end

    # def safe_navigation?: () -> bool
    def safe_navigation?
      flags.anybits?(CallNodeFlags::SAFE_NAVIGATION)
    end

    # def variable_call?: () -> bool
    def variable_call?
      flags.anybits?(CallNodeFlags::VARIABLE_CALL)
    end
  end

  # Represents the use of the `&&=` operator on a call.
  #
  #     foo.bar &&= value
  #     ^^^^^^^^^^^^^^^^^
  class CallOperatorAndWriteNode < Node
    # attr_reader target: Node
    attr_reader :target

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # def initialize: (target: Node, operator_loc: Location, value: Node, location: Location) -> void
    def initialize(target, operator_loc, value, location)
      @target = target
      @operator_loc = operator_loc
      @value = value
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_call_operator_and_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [target, value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { target: target, operator_loc: operator_loc, value: value, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents the use of the `||=` operator on a call.
  #
  #     foo.bar ||= value
  #     ^^^^^^^^^^^^^^^^^
  class CallOperatorOrWriteNode < Node
    # attr_reader target: Node
    attr_reader :target

    # attr_reader value: Node
    attr_reader :value

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # def initialize: (target: Node, value: Node, operator_loc: Location, location: Location) -> void
    def initialize(target, value, operator_loc, location)
      @target = target
      @value = value
      @operator_loc = operator_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_call_operator_or_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [target, value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { target: target, value: value, operator_loc: operator_loc, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents the use of an assignment operator on a call.
  #
  #     foo.bar += baz
  #     ^^^^^^^^^^^^^^
  class CallOperatorWriteNode < Node
    # attr_reader target: Node
    attr_reader :target

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # attr_reader operator_id: Symbol
    attr_reader :operator_id

    # def initialize: (target: Node, operator_loc: Location, value: Node, operator_id: Symbol, location: Location) -> void
    def initialize(target, operator_loc, value, operator_id, location)
      @target = target
      @operator_loc = operator_loc
      @value = value
      @operator_id = operator_id
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_call_operator_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [target, value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { target: target, operator_loc: operator_loc, value: value, operator_id: operator_id, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents assigning to a local variable in pattern matching.
  #
  #     foo => [bar => baz]
  #            ^^^^^^^^^^^^
  class CapturePatternNode < Node
    # attr_reader value: Node
    attr_reader :value

    # attr_reader target: Node
    attr_reader :target

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # def initialize: (value: Node, target: Node, operator_loc: Location, location: Location) -> void
    def initialize(value, target, operator_loc, location)
      @value = value
      @target = target
      @operator_loc = operator_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_capture_pattern_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value, target]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { value: value, target: target, operator_loc: operator_loc, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents the use of a case statement.
  #
  # case true
  # ^^^^^^^^^
  # when false
  # end
  class CaseNode < Node
    # attr_reader predicate: Node?
    attr_reader :predicate

    # attr_reader conditions: Array[Node]
    attr_reader :conditions

    # attr_reader consequent: Node?
    attr_reader :consequent

    # attr_reader case_keyword_loc: Location
    attr_reader :case_keyword_loc

    # attr_reader end_keyword_loc: Location
    attr_reader :end_keyword_loc

    # def initialize: (predicate: Node?, conditions: Array[Node], consequent: Node?, case_keyword_loc: Location, end_keyword_loc: Location, location: Location) -> void
    def initialize(predicate, conditions, consequent, case_keyword_loc, end_keyword_loc, location)
      @predicate = predicate
      @conditions = conditions
      @consequent = consequent
      @case_keyword_loc = case_keyword_loc
      @end_keyword_loc = end_keyword_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_case_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [predicate, *conditions, consequent]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { predicate: predicate, conditions: conditions, consequent: consequent, case_keyword_loc: case_keyword_loc, end_keyword_loc: end_keyword_loc, location: location }
    end

    # def case_keyword: () -> String
    def case_keyword
      case_keyword_loc.slice
    end

    # def end_keyword: () -> String
    def end_keyword
      end_keyword_loc.slice
    end
  end

  # Represents a class declaration involving the `class` keyword.
  #
  #     class Foo end
  #     ^^^^^^^^^^^^^
  class ClassNode < Node
    # attr_reader locals: Array[Symbol]
    attr_reader :locals

    # attr_reader class_keyword_loc: Location
    attr_reader :class_keyword_loc

    # attr_reader constant_path: Node
    attr_reader :constant_path

    # attr_reader inheritance_operator_loc: Location?
    attr_reader :inheritance_operator_loc

    # attr_reader superclass: Node?
    attr_reader :superclass

    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader end_keyword_loc: Location
    attr_reader :end_keyword_loc

    # def initialize: (locals: Array[Symbol], class_keyword_loc: Location, constant_path: Node, inheritance_operator_loc: Location?, superclass: Node?, statements: Node?, end_keyword_loc: Location, location: Location) -> void
    def initialize(locals, class_keyword_loc, constant_path, inheritance_operator_loc, superclass, statements, end_keyword_loc, location)
      @locals = locals
      @class_keyword_loc = class_keyword_loc
      @constant_path = constant_path
      @inheritance_operator_loc = inheritance_operator_loc
      @superclass = superclass
      @statements = statements
      @end_keyword_loc = end_keyword_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_class_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [constant_path, superclass, statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { locals: locals, class_keyword_loc: class_keyword_loc, constant_path: constant_path, inheritance_operator_loc: inheritance_operator_loc, superclass: superclass, statements: statements, end_keyword_loc: end_keyword_loc, location: location }
    end

    # def class_keyword: () -> String
    def class_keyword
      class_keyword_loc.slice
    end

    # def inheritance_operator: () -> String?
    def inheritance_operator
      inheritance_operator_loc&.slice
    end

    # def end_keyword: () -> String
    def end_keyword
      end_keyword_loc.slice
    end
  end

  # Represents the use of the `&&=` operator for assignment to a class variable.
  #
  #     @@target &&= value
  #     ^^^^^^^^^^^^^^^^
  class ClassVariableOperatorAndWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # def initialize: (name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
    def initialize(name_loc, operator_loc, value, location)
      @name_loc = name_loc
      @operator_loc = operator_loc
      @value = value
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_class_variable_operator_and_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents the use of the `||=` operator for assignment to a class variable.
  #
  #     @@target ||= value
  #     ^^^^^^^^^^^^^^^^^^
  class ClassVariableOperatorOrWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # def initialize: (name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
    def initialize(name_loc, operator_loc, value, location)
      @name_loc = name_loc
      @operator_loc = operator_loc
      @value = value
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_class_variable_operator_or_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents assigning to a class variable using an operator that isn't `=`.
  #
  #     @@target += value
  #     ^^^^^^^^^^^^^^^^^
  class ClassVariableOperatorWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # attr_reader operator: Symbol
    attr_reader :operator

    # def initialize: (name_loc: Location, operator_loc: Location, value: Node, operator: Symbol, location: Location) -> void
    def initialize(name_loc, operator_loc, value, operator, location)
      @name_loc = name_loc
      @operator_loc = operator_loc
      @value = value
      @operator = operator
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_class_variable_operator_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, operator_loc: operator_loc, value: value, operator: operator, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end
  end

  # Represents referencing a class variable.
  #
  #     @@foo
  #     ^^^^^
  class ClassVariableReadNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_class_variable_read_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents writing to a class variable.
  #
  #     @@foo = 1
  #     ^^^^^^^^^
  class ClassVariableWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader value: Node?
    attr_reader :value

    # attr_reader operator_loc: Location?
    attr_reader :operator_loc

    # def initialize: (name_loc: Location, value: Node?, operator_loc: Location?, location: Location) -> void
    def initialize(name_loc, value, operator_loc, location)
      @name_loc = name_loc
      @value = value
      @operator_loc = operator_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_class_variable_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, value: value, operator_loc: operator_loc, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def operator: () -> String?
    def operator
      operator_loc&.slice
    end
  end

  # Represents the use of the `&&=` operator for assignment to a constant.
  #
  #     Target &&= value
  #     ^^^^^^^^^^^^^^^^
  class ConstantOperatorAndWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # def initialize: (name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
    def initialize(name_loc, operator_loc, value, location)
      @name_loc = name_loc
      @operator_loc = operator_loc
      @value = value
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_constant_operator_and_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents the use of the `||=` operator for assignment to a constant.
  #
  #     Target ||= value
  #     ^^^^^^^^^^^^^^^^
  class ConstantOperatorOrWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # def initialize: (name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
    def initialize(name_loc, operator_loc, value, location)
      @name_loc = name_loc
      @operator_loc = operator_loc
      @value = value
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_constant_operator_or_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents assigning to a constant using an operator that isn't `=`.
  #
  #     Target += value
  #     ^^^^^^^^^^^^^^^
  class ConstantOperatorWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # attr_reader operator: Symbol
    attr_reader :operator

    # def initialize: (name_loc: Location, operator_loc: Location, value: Node, operator: Symbol, location: Location) -> void
    def initialize(name_loc, operator_loc, value, operator, location)
      @name_loc = name_loc
      @operator_loc = operator_loc
      @value = value
      @operator = operator
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_constant_operator_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, operator_loc: operator_loc, value: value, operator: operator, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end
  end

  # Represents accessing a constant through a path of `::` operators.
  #
  #     Foo::Bar
  #     ^^^^^^^^
  class ConstantPathNode < Node
    # attr_reader parent: Node?
    attr_reader :parent

    # attr_reader child: Node
    attr_reader :child

    # attr_reader delimiter_loc: Location
    attr_reader :delimiter_loc

    # def initialize: (parent: Node?, child: Node, delimiter_loc: Location, location: Location) -> void
    def initialize(parent, child, delimiter_loc, location)
      @parent = parent
      @child = child
      @delimiter_loc = delimiter_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_constant_path_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [parent, child]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { parent: parent, child: child, delimiter_loc: delimiter_loc, location: location }
    end

    # def delimiter: () -> String
    def delimiter
      delimiter_loc.slice
    end
  end

  # Represents the use of the `&&=` operator for assignment to a constant path.
  #
  #     Parent::Child &&= value
  #     ^^^^^^^^^^^^^^^^^^^^^^^
  class ConstantPathOperatorAndWriteNode < Node
    # attr_reader target: Node
    attr_reader :target

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # def initialize: (target: Node, operator_loc: Location, value: Node, location: Location) -> void
    def initialize(target, operator_loc, value, location)
      @target = target
      @operator_loc = operator_loc
      @value = value
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_constant_path_operator_and_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [target, value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { target: target, operator_loc: operator_loc, value: value, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents the use of the `||=` operator for assignment to a constant path.
  #
  #     Parent::Child ||= value
  #     ^^^^^^^^^^^^^^^^^^^^^^^
  class ConstantPathOperatorOrWriteNode < Node
    # attr_reader target: Node
    attr_reader :target

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # def initialize: (target: Node, operator_loc: Location, value: Node, location: Location) -> void
    def initialize(target, operator_loc, value, location)
      @target = target
      @operator_loc = operator_loc
      @value = value
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_constant_path_operator_or_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [target, value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { target: target, operator_loc: operator_loc, value: value, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents assigning to a constant path using an operator that isn't `=`.
  #
  #     Parent::Child += value
  #     ^^^^^^^^^^^^^^^^^^^^^^
  class ConstantPathOperatorWriteNode < Node
    # attr_reader target: Node
    attr_reader :target

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # attr_reader operator: Symbol
    attr_reader :operator

    # def initialize: (target: Node, operator_loc: Location, value: Node, operator: Symbol, location: Location) -> void
    def initialize(target, operator_loc, value, operator, location)
      @target = target
      @operator_loc = operator_loc
      @value = value
      @operator = operator
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_constant_path_operator_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [target, value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { target: target, operator_loc: operator_loc, value: value, operator: operator, location: location }
    end
  end

  # Represents writing to a constant path.
  #
  #     ::Foo = 1
  #     ^^^^^^^^^
  #
  #     Foo::Bar = 1
  #     ^^^^^^^^^^^^
  #
  #     ::Foo::Bar = 1
  #     ^^^^^^^^^^^^^^
  class ConstantPathWriteNode < Node
    # attr_reader target: Node
    attr_reader :target

    # attr_reader operator_loc: Location?
    attr_reader :operator_loc

    # attr_reader value: Node?
    attr_reader :value

    # def initialize: (target: Node, operator_loc: Location?, value: Node?, location: Location) -> void
    def initialize(target, operator_loc, value, location)
      @target = target
      @operator_loc = operator_loc
      @value = value
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_constant_path_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [target, value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { target: target, operator_loc: operator_loc, value: value, location: location }
    end

    # def operator: () -> String?
    def operator
      operator_loc&.slice
    end
  end

  # Represents referencing a constant.
  #
  #     Foo
  #     ^^^
  class ConstantReadNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_constant_read_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents writing to a constant.
  #
  #     Foo = 1
  #     ^^^^^^^
  class ConstantWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader value: Node?
    attr_reader :value

    # attr_reader operator_loc: Location?
    attr_reader :operator_loc

    # def initialize: (name_loc: Location, value: Node?, operator_loc: Location?, location: Location) -> void
    def initialize(name_loc, value, operator_loc, location)
      @name_loc = name_loc
      @value = value
      @operator_loc = operator_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_constant_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, value: value, operator_loc: operator_loc, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def operator: () -> String?
    def operator
      operator_loc&.slice
    end
  end

  # Represents a method definition.
  #
  #     def method
  #     end
  #     ^^^^^^^^^^
  class DefNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader receiver: Node?
    attr_reader :receiver

    # attr_reader parameters: Node?
    attr_reader :parameters

    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader locals: Array[Symbol]
    attr_reader :locals

    # attr_reader def_keyword_loc: Location
    attr_reader :def_keyword_loc

    # attr_reader operator_loc: Location?
    attr_reader :operator_loc

    # attr_reader lparen_loc: Location?
    attr_reader :lparen_loc

    # attr_reader rparen_loc: Location?
    attr_reader :rparen_loc

    # attr_reader equal_loc: Location?
    attr_reader :equal_loc

    # attr_reader end_keyword_loc: Location?
    attr_reader :end_keyword_loc

    # def initialize: (name_loc: Location, receiver: Node?, parameters: Node?, statements: Node?, locals: Array[Symbol], def_keyword_loc: Location, operator_loc: Location?, lparen_loc: Location?, rparen_loc: Location?, equal_loc: Location?, end_keyword_loc: Location?, location: Location) -> void
    def initialize(name_loc, receiver, parameters, statements, locals, def_keyword_loc, operator_loc, lparen_loc, rparen_loc, equal_loc, end_keyword_loc, location)
      @name_loc = name_loc
      @receiver = receiver
      @parameters = parameters
      @statements = statements
      @locals = locals
      @def_keyword_loc = def_keyword_loc
      @operator_loc = operator_loc
      @lparen_loc = lparen_loc
      @rparen_loc = rparen_loc
      @equal_loc = equal_loc
      @end_keyword_loc = end_keyword_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_def_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [receiver, parameters, statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, receiver: receiver, parameters: parameters, statements: statements, locals: locals, def_keyword_loc: def_keyword_loc, operator_loc: operator_loc, lparen_loc: lparen_loc, rparen_loc: rparen_loc, equal_loc: equal_loc, end_keyword_loc: end_keyword_loc, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def def_keyword: () -> String
    def def_keyword
      def_keyword_loc.slice
    end

    # def operator: () -> String?
    def operator
      operator_loc&.slice
    end

    # def lparen: () -> String?
    def lparen
      lparen_loc&.slice
    end

    # def rparen: () -> String?
    def rparen
      rparen_loc&.slice
    end

    # def equal: () -> String?
    def equal
      equal_loc&.slice
    end

    # def end_keyword: () -> String?
    def end_keyword
      end_keyword_loc&.slice
    end
  end

  # Represents the use of the `defined?` keyword.
  #
  #     defined?(a)
  #     ^^^^^^^^^^^
  class DefinedNode < Node
    # attr_reader lparen_loc: Location?
    attr_reader :lparen_loc

    # attr_reader value: Node
    attr_reader :value

    # attr_reader rparen_loc: Location?
    attr_reader :rparen_loc

    # attr_reader keyword_loc: Location
    attr_reader :keyword_loc

    # def initialize: (lparen_loc: Location?, value: Node, rparen_loc: Location?, keyword_loc: Location, location: Location) -> void
    def initialize(lparen_loc, value, rparen_loc, keyword_loc, location)
      @lparen_loc = lparen_loc
      @value = value
      @rparen_loc = rparen_loc
      @keyword_loc = keyword_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_defined_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { lparen_loc: lparen_loc, value: value, rparen_loc: rparen_loc, keyword_loc: keyword_loc, location: location }
    end

    # def lparen: () -> String?
    def lparen
      lparen_loc&.slice
    end

    # def rparen: () -> String?
    def rparen
      rparen_loc&.slice
    end

    # def keyword: () -> String
    def keyword
      keyword_loc.slice
    end
  end

  # Represents an `else` clause in a `case`, `if`, or `unless` statement.
  #
  #     if a then b else c end
  #                 ^^^^^^^^^^
  class ElseNode < Node
    # attr_reader else_keyword_loc: Location
    attr_reader :else_keyword_loc

    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader end_keyword_loc: Location?
    attr_reader :end_keyword_loc

    # def initialize: (else_keyword_loc: Location, statements: Node?, end_keyword_loc: Location?, location: Location) -> void
    def initialize(else_keyword_loc, statements, end_keyword_loc, location)
      @else_keyword_loc = else_keyword_loc
      @statements = statements
      @end_keyword_loc = end_keyword_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_else_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { else_keyword_loc: else_keyword_loc, statements: statements, end_keyword_loc: end_keyword_loc, location: location }
    end

    # def else_keyword: () -> String
    def else_keyword
      else_keyword_loc.slice
    end

    # def end_keyword: () -> String?
    def end_keyword
      end_keyword_loc&.slice
    end
  end

  # Represents an interpolated set of statements.
  #
  #     "foo #{bar}"
  #          ^^^^^^
  class EmbeddedStatementsNode < Node
    # attr_reader opening_loc: Location
    attr_reader :opening_loc

    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader closing_loc: Location
    attr_reader :closing_loc

    # def initialize: (opening_loc: Location, statements: Node?, closing_loc: Location, location: Location) -> void
    def initialize(opening_loc, statements, closing_loc, location)
      @opening_loc = opening_loc
      @statements = statements
      @closing_loc = closing_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_embedded_statements_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { opening_loc: opening_loc, statements: statements, closing_loc: closing_loc, location: location }
    end

    # def opening: () -> String
    def opening
      opening_loc.slice
    end

    # def closing: () -> String
    def closing
      closing_loc.slice
    end
  end

  # Represents an interpolated variable.
  #
  #     "foo #@bar"
  #          ^^^^^
  class EmbeddedVariableNode < Node
    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader variable: Node
    attr_reader :variable

    # def initialize: (operator_loc: Location, variable: Node, location: Location) -> void
    def initialize(operator_loc, variable, location)
      @operator_loc = operator_loc
      @variable = variable
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_embedded_variable_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [variable]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { operator_loc: operator_loc, variable: variable, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents an `ensure` clause in a `begin` statement.
  #
  #     begin
  #       foo
  #     ensure
  #     ^^^^^^
  #       bar
  #     end
  class EnsureNode < Node
    # attr_reader ensure_keyword_loc: Location
    attr_reader :ensure_keyword_loc

    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader end_keyword_loc: Location
    attr_reader :end_keyword_loc

    # def initialize: (ensure_keyword_loc: Location, statements: Node?, end_keyword_loc: Location, location: Location) -> void
    def initialize(ensure_keyword_loc, statements, end_keyword_loc, location)
      @ensure_keyword_loc = ensure_keyword_loc
      @statements = statements
      @end_keyword_loc = end_keyword_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_ensure_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { ensure_keyword_loc: ensure_keyword_loc, statements: statements, end_keyword_loc: end_keyword_loc, location: location }
    end

    # def ensure_keyword: () -> String
    def ensure_keyword
      ensure_keyword_loc.slice
    end

    # def end_keyword: () -> String
    def end_keyword
      end_keyword_loc.slice
    end
  end

  # Represents the use of the literal `false` keyword.
  #
  #     false
  #     ^^^^^
  class FalseNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_false_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents a find pattern in pattern matching.
  #
  #     foo in *bar, baz, *qux
  #     ^^^^^^^^^^^^^^^^^^^^^^
  #
  #     foo in [*bar, baz, *qux]
  #     ^^^^^^^^^^^^^^^^^^^^^^^^
  #
  #     foo in Foo(*bar, baz, *qux)
  #     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  class FindPatternNode < Node
    # attr_reader constant: Node?
    attr_reader :constant

    # attr_reader left: Node
    attr_reader :left

    # attr_reader requireds: Array[Node]
    attr_reader :requireds

    # attr_reader right: Node
    attr_reader :right

    # attr_reader opening_loc: Location?
    attr_reader :opening_loc

    # attr_reader closing_loc: Location?
    attr_reader :closing_loc

    # def initialize: (constant: Node?, left: Node, requireds: Array[Node], right: Node, opening_loc: Location?, closing_loc: Location?, location: Location) -> void
    def initialize(constant, left, requireds, right, opening_loc, closing_loc, location)
      @constant = constant
      @left = left
      @requireds = requireds
      @right = right
      @opening_loc = opening_loc
      @closing_loc = closing_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_find_pattern_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [constant, left, *requireds, right]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { constant: constant, left: left, requireds: requireds, right: right, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
    end

    # def opening: () -> String?
    def opening
      opening_loc&.slice
    end

    # def closing: () -> String?
    def closing
      closing_loc&.slice
    end
  end

  # Represents the use of the `..` or `...` operators to create flip flops.
  #
  #     baz if foo .. bar
  #            ^^^^^^^^^^
  class FlipFlopNode < Node
    # attr_reader left: Node?
    attr_reader :left

    # attr_reader right: Node?
    attr_reader :right

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader flags: Integer
    attr_reader :flags

    # def initialize: (left: Node?, right: Node?, operator_loc: Location, flags: Integer, location: Location) -> void
    def initialize(left, right, operator_loc, flags, location)
      @left = left
      @right = right
      @operator_loc = operator_loc
      @flags = flags
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_flip_flop_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [left, right]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { left: left, right: right, operator_loc: operator_loc, flags: flags, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end

    # def exclude_end?: () -> bool
    def exclude_end?
      flags.anybits?(RangeFlags::EXCLUDE_END)
    end
  end

  # Represents a floating point number literal.
  #
  #     1.0
  #     ^^^
  class FloatNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_float_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents the use of the `for` keyword.
  #
  #     for i in a end
  #     ^^^^^^^^^^^^^^
  class ForNode < Node
    # attr_reader index: Node
    attr_reader :index

    # attr_reader collection: Node
    attr_reader :collection

    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader for_keyword_loc: Location
    attr_reader :for_keyword_loc

    # attr_reader in_keyword_loc: Location
    attr_reader :in_keyword_loc

    # attr_reader do_keyword_loc: Location?
    attr_reader :do_keyword_loc

    # attr_reader end_keyword_loc: Location
    attr_reader :end_keyword_loc

    # def initialize: (index: Node, collection: Node, statements: Node?, for_keyword_loc: Location, in_keyword_loc: Location, do_keyword_loc: Location?, end_keyword_loc: Location, location: Location) -> void
    def initialize(index, collection, statements, for_keyword_loc, in_keyword_loc, do_keyword_loc, end_keyword_loc, location)
      @index = index
      @collection = collection
      @statements = statements
      @for_keyword_loc = for_keyword_loc
      @in_keyword_loc = in_keyword_loc
      @do_keyword_loc = do_keyword_loc
      @end_keyword_loc = end_keyword_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_for_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [index, collection, statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { index: index, collection: collection, statements: statements, for_keyword_loc: for_keyword_loc, in_keyword_loc: in_keyword_loc, do_keyword_loc: do_keyword_loc, end_keyword_loc: end_keyword_loc, location: location }
    end

    # def for_keyword: () -> String
    def for_keyword
      for_keyword_loc.slice
    end

    # def in_keyword: () -> String
    def in_keyword
      in_keyword_loc.slice
    end

    # def do_keyword: () -> String?
    def do_keyword
      do_keyword_loc&.slice
    end

    # def end_keyword: () -> String
    def end_keyword
      end_keyword_loc.slice
    end
  end

  # Represents forwarding all arguments to this method to another method.
  #
  #     def foo(...)
  #       bar(...)
  #       ^^^^^^^^
  #     end
  class ForwardingArgumentsNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_forwarding_arguments_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents the use of the forwarding parameter in a method, block, or lambda declaration.
  #
  #     def foo(...)
  #             ^^^
  #     end
  class ForwardingParameterNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_forwarding_parameter_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents the use of the `super` keyword without parentheses or arguments.
  #
  #     super
  #     ^^^^^
  class ForwardingSuperNode < Node
    # attr_reader block: Node?
    attr_reader :block

    # def initialize: (block: Node?, location: Location) -> void
    def initialize(block, location)
      @block = block
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_forwarding_super_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [block]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { block: block, location: location }
    end
  end

  # Represents the use of the `&&=` operator for assignment to a global variable.
  #
  #     $target &&= value
  #     ^^^^^^^^^^^^^^^^^
  class GlobalVariableOperatorAndWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # def initialize: (name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
    def initialize(name_loc, operator_loc, value, location)
      @name_loc = name_loc
      @operator_loc = operator_loc
      @value = value
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_global_variable_operator_and_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents the use of the `||=` operator for assignment to a global variable.
  #
  #     $target ||= value
  #     ^^^^^^^^^^^^^^^^^
  class GlobalVariableOperatorOrWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # def initialize: (name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
    def initialize(name_loc, operator_loc, value, location)
      @name_loc = name_loc
      @operator_loc = operator_loc
      @value = value
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_global_variable_operator_or_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents assigning to a global variable using an operator that isn't `=`.
  #
  #     $target += value
  #     ^^^^^^^^^^^^^^^^
  class GlobalVariableOperatorWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # attr_reader operator: Symbol
    attr_reader :operator

    # def initialize: (name_loc: Location, operator_loc: Location, value: Node, operator: Symbol, location: Location) -> void
    def initialize(name_loc, operator_loc, value, operator, location)
      @name_loc = name_loc
      @operator_loc = operator_loc
      @value = value
      @operator = operator
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_global_variable_operator_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, operator_loc: operator_loc, value: value, operator: operator, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end
  end

  # Represents referencing a global variable.
  #
  #     $foo
  #     ^^^^
  class GlobalVariableReadNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_global_variable_read_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents writing to a global variable.
  #
  #     $foo = 1
  #     ^^^^^^^^
  class GlobalVariableWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location?
    attr_reader :operator_loc

    # attr_reader value: Node?
    attr_reader :value

    # def initialize: (name_loc: Location, operator_loc: Location?, value: Node?, location: Location) -> void
    def initialize(name_loc, operator_loc, value, location)
      @name_loc = name_loc
      @operator_loc = operator_loc
      @value = value
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_global_variable_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def operator: () -> String?
    def operator
      operator_loc&.slice
    end
  end

  # Represents a hash literal.
  #
  #     { a => b }
  #     ^^^^^^^^^^
  class HashNode < Node
    # attr_reader opening_loc: Location
    attr_reader :opening_loc

    # attr_reader elements: Array[Node]
    attr_reader :elements

    # attr_reader closing_loc: Location
    attr_reader :closing_loc

    # def initialize: (opening_loc: Location, elements: Array[Node], closing_loc: Location, location: Location) -> void
    def initialize(opening_loc, elements, closing_loc, location)
      @opening_loc = opening_loc
      @elements = elements
      @closing_loc = closing_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_hash_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [*elements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { opening_loc: opening_loc, elements: elements, closing_loc: closing_loc, location: location }
    end

    # def opening: () -> String
    def opening
      opening_loc.slice
    end

    # def closing: () -> String
    def closing
      closing_loc.slice
    end
  end

  # Represents a hash pattern in pattern matching.
  #
  #     foo => { a: 1, b: 2 }
  #            ^^^^^^^^^^^^^^
  #
  #     foo => { a: 1, b: 2, **c }
  #            ^^^^^^^^^^^^^^^^^^^
  class HashPatternNode < Node
    # attr_reader constant: Node?
    attr_reader :constant

    # attr_reader assocs: Array[Node]
    attr_reader :assocs

    # attr_reader kwrest: Node?
    attr_reader :kwrest

    # attr_reader opening_loc: Location?
    attr_reader :opening_loc

    # attr_reader closing_loc: Location?
    attr_reader :closing_loc

    # def initialize: (constant: Node?, assocs: Array[Node], kwrest: Node?, opening_loc: Location?, closing_loc: Location?, location: Location) -> void
    def initialize(constant, assocs, kwrest, opening_loc, closing_loc, location)
      @constant = constant
      @assocs = assocs
      @kwrest = kwrest
      @opening_loc = opening_loc
      @closing_loc = closing_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_hash_pattern_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [constant, *assocs, kwrest]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { constant: constant, assocs: assocs, kwrest: kwrest, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
    end

    # def opening: () -> String?
    def opening
      opening_loc&.slice
    end

    # def closing: () -> String?
    def closing
      closing_loc&.slice
    end
  end

  # Represents the use of the `if` keyword, either in the block form or the modifier form.
  #
  #     bar if foo
  #     ^^^^^^^^^^
  #
  #     if foo then bar end
  #     ^^^^^^^^^^^^^^^^^^^
  class IfNode < Node
    # attr_reader if_keyword_loc: Location?
    attr_reader :if_keyword_loc

    # attr_reader predicate: Node
    attr_reader :predicate

    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader consequent: Node?
    attr_reader :consequent

    # attr_reader end_keyword_loc: Location?
    attr_reader :end_keyword_loc

    # def initialize: (if_keyword_loc: Location?, predicate: Node, statements: Node?, consequent: Node?, end_keyword_loc: Location?, location: Location) -> void
    def initialize(if_keyword_loc, predicate, statements, consequent, end_keyword_loc, location)
      @if_keyword_loc = if_keyword_loc
      @predicate = predicate
      @statements = statements
      @consequent = consequent
      @end_keyword_loc = end_keyword_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_if_node(self)
    end

    def set_newline_flag(newline_marked)
      predicate.set_newline_flag(newline_marked)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [predicate, statements, consequent]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { if_keyword_loc: if_keyword_loc, predicate: predicate, statements: statements, consequent: consequent, end_keyword_loc: end_keyword_loc, location: location }
    end

    # def if_keyword: () -> String?
    def if_keyword
      if_keyword_loc&.slice
    end

    # def end_keyword: () -> String?
    def end_keyword
      end_keyword_loc&.slice
    end
  end

  # Represents an imaginary number literal.
  #
  #     1.0i
  #     ^^^^
  class ImaginaryNode < Node
    # attr_reader numeric: Node
    attr_reader :numeric

    # def initialize: (numeric: Node, location: Location) -> void
    def initialize(numeric, location)
      @numeric = numeric
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_imaginary_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [numeric]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { numeric: numeric, location: location }
    end
  end

  # Represents the use of the `in` keyword in a case statement.
  #
  #     case a; in b then c end
  #             ^^^^^^^^^^^
  class InNode < Node
    # attr_reader pattern: Node
    attr_reader :pattern

    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader in_loc: Location
    attr_reader :in_loc

    # attr_reader then_loc: Location?
    attr_reader :then_loc

    # def initialize: (pattern: Node, statements: Node?, in_loc: Location, then_loc: Location?, location: Location) -> void
    def initialize(pattern, statements, in_loc, then_loc, location)
      @pattern = pattern
      @statements = statements
      @in_loc = in_loc
      @then_loc = then_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_in_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [pattern, statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { pattern: pattern, statements: statements, in_loc: in_loc, then_loc: then_loc, location: location }
    end

    # def in: () -> String
    def in
      in_loc.slice
    end

    # def then: () -> String?
    def then
      then_loc&.slice
    end
  end

  # Represents the use of the `&&=` operator for assignment to an instance variable.
  #
  #     @target &&= value
  #     ^^^^^^^^^^^^^^^^^
  class InstanceVariableOperatorAndWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # def initialize: (name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
    def initialize(name_loc, operator_loc, value, location)
      @name_loc = name_loc
      @operator_loc = operator_loc
      @value = value
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_instance_variable_operator_and_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents the use of the `||=` operator for assignment to an instance variable.
  #
  #     @target ||= value
  #     ^^^^^^^^^^^^^^^^^
  class InstanceVariableOperatorOrWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # def initialize: (name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
    def initialize(name_loc, operator_loc, value, location)
      @name_loc = name_loc
      @operator_loc = operator_loc
      @value = value
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_instance_variable_operator_or_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents assigning to an instance variable using an operator that isn't `=`.
  #
  #     @target += value
  #     ^^^^^^^^^^^^^^^^
  class InstanceVariableOperatorWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # attr_reader operator: Symbol
    attr_reader :operator

    # def initialize: (name_loc: Location, operator_loc: Location, value: Node, operator: Symbol, location: Location) -> void
    def initialize(name_loc, operator_loc, value, operator, location)
      @name_loc = name_loc
      @operator_loc = operator_loc
      @value = value
      @operator = operator
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_instance_variable_operator_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, operator_loc: operator_loc, value: value, operator: operator, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end
  end

  # Represents referencing an instance variable.
  #
  #     @foo
  #     ^^^^
  class InstanceVariableReadNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_instance_variable_read_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents writing to an instance variable.
  #
  #     @foo = 1
  #     ^^^^^^^^
  class InstanceVariableWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader value: Node?
    attr_reader :value

    # attr_reader operator_loc: Location?
    attr_reader :operator_loc

    # def initialize: (name_loc: Location, value: Node?, operator_loc: Location?, location: Location) -> void
    def initialize(name_loc, value, operator_loc, location)
      @name_loc = name_loc
      @value = value
      @operator_loc = operator_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_instance_variable_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, value: value, operator_loc: operator_loc, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def operator: () -> String?
    def operator
      operator_loc&.slice
    end
  end

  # Represents an integer number literal.
  #
  #     1
  #     ^
  class IntegerNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_integer_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents a regular expression literal that contains interpolation.
  #
  #     /foo #{bar} baz/
  #     ^^^^^^^^^^^^^^^^
  class InterpolatedRegularExpressionNode < Node
    # attr_reader opening_loc: Location
    attr_reader :opening_loc

    # attr_reader parts: Array[Node]
    attr_reader :parts

    # attr_reader closing_loc: Location
    attr_reader :closing_loc

    # attr_reader flags: Integer
    attr_reader :flags

    # def initialize: (opening_loc: Location, parts: Array[Node], closing_loc: Location, flags: Integer, location: Location) -> void
    def initialize(opening_loc, parts, closing_loc, flags, location)
      @opening_loc = opening_loc
      @parts = parts
      @closing_loc = closing_loc
      @flags = flags
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_interpolated_regular_expression_node(self)
    end

    def set_newline_flag(newline_marked)
      first = parts.first
      first.set_newline_flag(newline_marked) if first
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [*parts]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { opening_loc: opening_loc, parts: parts, closing_loc: closing_loc, flags: flags, location: location }
    end

    # def opening: () -> String
    def opening
      opening_loc.slice
    end

    # def closing: () -> String
    def closing
      closing_loc.slice
    end

    # def ignore_case?: () -> bool
    def ignore_case?
      flags.anybits?(RegularExpressionFlags::IGNORE_CASE)
    end

    # def multi_line?: () -> bool
    def multi_line?
      flags.anybits?(RegularExpressionFlags::MULTI_LINE)
    end

    # def extended?: () -> bool
    def extended?
      flags.anybits?(RegularExpressionFlags::EXTENDED)
    end

    # def euc_jp?: () -> bool
    def euc_jp?
      flags.anybits?(RegularExpressionFlags::EUC_JP)
    end

    # def ascii_8bit?: () -> bool
    def ascii_8bit?
      flags.anybits?(RegularExpressionFlags::ASCII_8BIT)
    end

    # def windows_31j?: () -> bool
    def windows_31j?
      flags.anybits?(RegularExpressionFlags::WINDOWS_31J)
    end

    # def utf_8?: () -> bool
    def utf_8?
      flags.anybits?(RegularExpressionFlags::UTF_8)
    end

    # def once?: () -> bool
    def once?
      flags.anybits?(RegularExpressionFlags::ONCE)
    end
  end

  # Represents a string literal that contains interpolation.
  #
  #     "foo #{bar} baz"
  #     ^^^^^^^^^^^^^^^^
  class InterpolatedStringNode < Node
    # attr_reader opening_loc: Location?
    attr_reader :opening_loc

    # attr_reader parts: Array[Node]
    attr_reader :parts

    # attr_reader closing_loc: Location?
    attr_reader :closing_loc

    # def initialize: (opening_loc: Location?, parts: Array[Node], closing_loc: Location?, location: Location) -> void
    def initialize(opening_loc, parts, closing_loc, location)
      @opening_loc = opening_loc
      @parts = parts
      @closing_loc = closing_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_interpolated_string_node(self)
    end

    def set_newline_flag(newline_marked)
      first = parts.first
      first.set_newline_flag(newline_marked) if first
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [*parts]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { opening_loc: opening_loc, parts: parts, closing_loc: closing_loc, location: location }
    end

    # def opening: () -> String?
    def opening
      opening_loc&.slice
    end

    # def closing: () -> String?
    def closing
      closing_loc&.slice
    end
  end

  # Represents a symbol literal that contains interpolation.
  #
  #     :"foo #{bar} baz"
  #     ^^^^^^^^^^^^^^^^^
  class InterpolatedSymbolNode < Node
    # attr_reader opening_loc: Location?
    attr_reader :opening_loc

    # attr_reader parts: Array[Node]
    attr_reader :parts

    # attr_reader closing_loc: Location?
    attr_reader :closing_loc

    # def initialize: (opening_loc: Location?, parts: Array[Node], closing_loc: Location?, location: Location) -> void
    def initialize(opening_loc, parts, closing_loc, location)
      @opening_loc = opening_loc
      @parts = parts
      @closing_loc = closing_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_interpolated_symbol_node(self)
    end

    def set_newline_flag(newline_marked)
      first = parts.first
      first.set_newline_flag(newline_marked) if first
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [*parts]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { opening_loc: opening_loc, parts: parts, closing_loc: closing_loc, location: location }
    end

    # def opening: () -> String?
    def opening
      opening_loc&.slice
    end

    # def closing: () -> String?
    def closing
      closing_loc&.slice
    end
  end

  # Represents an xstring literal that contains interpolation.
  #
  #     `foo #{bar} baz`
  #     ^^^^^^^^^^^^^^^^
  class InterpolatedXStringNode < Node
    # attr_reader opening_loc: Location
    attr_reader :opening_loc

    # attr_reader parts: Array[Node]
    attr_reader :parts

    # attr_reader closing_loc: Location
    attr_reader :closing_loc

    # def initialize: (opening_loc: Location, parts: Array[Node], closing_loc: Location, location: Location) -> void
    def initialize(opening_loc, parts, closing_loc, location)
      @opening_loc = opening_loc
      @parts = parts
      @closing_loc = closing_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_interpolated_x_string_node(self)
    end

    def set_newline_flag(newline_marked)
      first = parts.first
      first.set_newline_flag(newline_marked) if first
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [*parts]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { opening_loc: opening_loc, parts: parts, closing_loc: closing_loc, location: location }
    end

    # def opening: () -> String
    def opening
      opening_loc.slice
    end

    # def closing: () -> String
    def closing
      closing_loc.slice
    end
  end

  # Represents a hash literal without opening and closing braces.
  #
  #     foo(a: b)
  #         ^^^^
  class KeywordHashNode < Node
    # attr_reader elements: Array[Node]
    attr_reader :elements

    # def initialize: (elements: Array[Node], location: Location) -> void
    def initialize(elements, location)
      @elements = elements
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_keyword_hash_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [*elements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { elements: elements, location: location }
    end
  end

  # Represents a keyword parameter to a method, block, or lambda definition.
  #
  #     def a(b:)
  #           ^^
  #     end
  #
  #     def a(b: 1)
  #           ^^^^
  #     end
  class KeywordParameterNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader value: Node?
    attr_reader :value

    # def initialize: (name_loc: Location, value: Node?, location: Location) -> void
    def initialize(name_loc, value, location)
      @name_loc = name_loc
      @value = value
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_keyword_parameter_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, value: value, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end
  end

  # Represents a keyword rest parameter to a method, block, or lambda definition.
  #
  #     def a(**b)
  #           ^^^
  #     end
  class KeywordRestParameterNode < Node
    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader name_loc: Location?
    attr_reader :name_loc

    # def initialize: (operator_loc: Location, name_loc: Location?, location: Location) -> void
    def initialize(operator_loc, name_loc, location)
      @operator_loc = operator_loc
      @name_loc = name_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_keyword_rest_parameter_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { operator_loc: operator_loc, name_loc: name_loc, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end

    # def name: () -> String?
    def name
      name_loc&.slice
    end
  end

  # Represents using a lambda literal (not the lambda method call).
  #
  #     ->(value) { value * 2 }
  #     ^^^^^^^^^^^^^^^^^^^^^^^
  class LambdaNode < Node
    # attr_reader locals: Array[Symbol]
    attr_reader :locals

    # attr_reader opening_loc: Location
    attr_reader :opening_loc

    # attr_reader parameters: Node?
    attr_reader :parameters

    # attr_reader statements: Node?
    attr_reader :statements

    # def initialize: (locals: Array[Symbol], opening_loc: Location, parameters: Node?, statements: Node?, location: Location) -> void
    def initialize(locals, opening_loc, parameters, statements, location)
      @locals = locals
      @opening_loc = opening_loc
      @parameters = parameters
      @statements = statements
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_lambda_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [parameters, statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { locals: locals, opening_loc: opening_loc, parameters: parameters, statements: statements, location: location }
    end

    # def opening: () -> String
    def opening
      opening_loc.slice
    end
  end

  # Represents the use of the `&&=` operator for assignment to a local variable.
  #
  #     target &&= value
  #     ^^^^^^^^^^^^^^^^
  class LocalVariableOperatorAndWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # attr_reader constant_id: Symbol
    attr_reader :constant_id

    # def initialize: (name_loc: Location, operator_loc: Location, value: Node, constant_id: Symbol, location: Location) -> void
    def initialize(name_loc, operator_loc, value, constant_id, location)
      @name_loc = name_loc
      @operator_loc = operator_loc
      @value = value
      @constant_id = constant_id
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_local_variable_operator_and_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, operator_loc: operator_loc, value: value, constant_id: constant_id, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents the use of the `||=` operator for assignment to a local variable.
  #
  #     target ||= value
  #     ^^^^^^^^^^^^^^^^
  class LocalVariableOperatorOrWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # attr_reader constant_id: Symbol
    attr_reader :constant_id

    # def initialize: (name_loc: Location, operator_loc: Location, value: Node, constant_id: Symbol, location: Location) -> void
    def initialize(name_loc, operator_loc, value, constant_id, location)
      @name_loc = name_loc
      @operator_loc = operator_loc
      @value = value
      @constant_id = constant_id
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_local_variable_operator_or_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, operator_loc: operator_loc, value: value, constant_id: constant_id, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents assigning to a local variable using an operator that isn't `=`.
  #
  #     target += value
  #     ^^^^^^^^^^^^^^^
  class LocalVariableOperatorWriteNode < Node
    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # attr_reader constant_id: Symbol
    attr_reader :constant_id

    # attr_reader operator_id: Symbol
    attr_reader :operator_id

    # def initialize: (name_loc: Location, operator_loc: Location, value: Node, constant_id: Symbol, operator_id: Symbol, location: Location) -> void
    def initialize(name_loc, operator_loc, value, constant_id, operator_id, location)
      @name_loc = name_loc
      @operator_loc = operator_loc
      @value = value
      @constant_id = constant_id
      @operator_id = operator_id
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_local_variable_operator_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { name_loc: name_loc, operator_loc: operator_loc, value: value, constant_id: constant_id, operator_id: operator_id, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents reading a local variable. Note that this requires that a local
  # variable of the same name has already been written to in the same scope,
  # otherwise it is parsed as a method call.
  #
  #     foo
  #     ^^^
  class LocalVariableReadNode < Node
    # attr_reader constant_id: Symbol
    attr_reader :constant_id

    # attr_reader depth: Integer
    attr_reader :depth

    # def initialize: (constant_id: Symbol, depth: Integer, location: Location) -> void
    def initialize(constant_id, depth, location)
      @constant_id = constant_id
      @depth = depth
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_local_variable_read_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { constant_id: constant_id, depth: depth, location: location }
    end
  end

  # Represents writing to a local variable.
  #
  #     foo = 1
  #     ^^^^^^^
  class LocalVariableWriteNode < Node
    # attr_reader constant_id: Symbol
    attr_reader :constant_id

    # attr_reader depth: Integer
    attr_reader :depth

    # attr_reader value: Node?
    attr_reader :value

    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location?
    attr_reader :operator_loc

    # def initialize: (constant_id: Symbol, depth: Integer, value: Node?, name_loc: Location, operator_loc: Location?, location: Location) -> void
    def initialize(constant_id, depth, value, name_loc, operator_loc, location)
      @constant_id = constant_id
      @depth = depth
      @value = value
      @name_loc = name_loc
      @operator_loc = operator_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_local_variable_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { constant_id: constant_id, depth: depth, value: value, name_loc: name_loc, operator_loc: operator_loc, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def operator: () -> String?
    def operator
      operator_loc&.slice
    end
  end

  # Represents the use of the modifier `in` operator.
  #
  #     foo in bar
  #     ^^^^^^^^^^
  class MatchPredicateNode < Node
    # attr_reader value: Node
    attr_reader :value

    # attr_reader pattern: Node
    attr_reader :pattern

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # def initialize: (value: Node, pattern: Node, operator_loc: Location, location: Location) -> void
    def initialize(value, pattern, operator_loc, location)
      @value = value
      @pattern = pattern
      @operator_loc = operator_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_match_predicate_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value, pattern]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { value: value, pattern: pattern, operator_loc: operator_loc, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents the use of the `=>` operator.
  #
  #     foo => bar
  #     ^^^^^^^^^^
  class MatchRequiredNode < Node
    # attr_reader value: Node
    attr_reader :value

    # attr_reader pattern: Node
    attr_reader :pattern

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # def initialize: (value: Node, pattern: Node, operator_loc: Location, location: Location) -> void
    def initialize(value, pattern, operator_loc, location)
      @value = value
      @pattern = pattern
      @operator_loc = operator_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_match_required_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value, pattern]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { value: value, pattern: pattern, operator_loc: operator_loc, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents a node that is missing from the source and results in a syntax
  # error.
  class MissingNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_missing_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents a module declaration involving the `module` keyword.
  #
  #     module Foo end
  #     ^^^^^^^^^^^^^^
  class ModuleNode < Node
    # attr_reader locals: Array[Symbol]
    attr_reader :locals

    # attr_reader module_keyword_loc: Location
    attr_reader :module_keyword_loc

    # attr_reader constant_path: Node
    attr_reader :constant_path

    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader end_keyword_loc: Location
    attr_reader :end_keyword_loc

    # def initialize: (locals: Array[Symbol], module_keyword_loc: Location, constant_path: Node, statements: Node?, end_keyword_loc: Location, location: Location) -> void
    def initialize(locals, module_keyword_loc, constant_path, statements, end_keyword_loc, location)
      @locals = locals
      @module_keyword_loc = module_keyword_loc
      @constant_path = constant_path
      @statements = statements
      @end_keyword_loc = end_keyword_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_module_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [constant_path, statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { locals: locals, module_keyword_loc: module_keyword_loc, constant_path: constant_path, statements: statements, end_keyword_loc: end_keyword_loc, location: location }
    end

    # def module_keyword: () -> String
    def module_keyword
      module_keyword_loc.slice
    end

    # def end_keyword: () -> String
    def end_keyword
      end_keyword_loc.slice
    end
  end

  # Represents a multi-target expression.
  #
  #     a, b, c = 1, 2, 3
  #     ^^^^^^^^^^^^^^^^^
  class MultiWriteNode < Node
    # attr_reader targets: Array[Node]
    attr_reader :targets

    # attr_reader operator_loc: Location?
    attr_reader :operator_loc

    # attr_reader value: Node?
    attr_reader :value

    # attr_reader lparen_loc: Location?
    attr_reader :lparen_loc

    # attr_reader rparen_loc: Location?
    attr_reader :rparen_loc

    # def initialize: (targets: Array[Node], operator_loc: Location?, value: Node?, lparen_loc: Location?, rparen_loc: Location?, location: Location) -> void
    def initialize(targets, operator_loc, value, lparen_loc, rparen_loc, location)
      @targets = targets
      @operator_loc = operator_loc
      @value = value
      @lparen_loc = lparen_loc
      @rparen_loc = rparen_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_multi_write_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [*targets, value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { targets: targets, operator_loc: operator_loc, value: value, lparen_loc: lparen_loc, rparen_loc: rparen_loc, location: location }
    end

    # def operator: () -> String?
    def operator
      operator_loc&.slice
    end

    # def lparen: () -> String?
    def lparen
      lparen_loc&.slice
    end

    # def rparen: () -> String?
    def rparen
      rparen_loc&.slice
    end
  end

  # Represents the use of the `next` keyword.
  #
  #     next 1
  #     ^^^^^^
  class NextNode < Node
    # attr_reader arguments: Node?
    attr_reader :arguments

    # attr_reader keyword_loc: Location
    attr_reader :keyword_loc

    # def initialize: (arguments: Node?, keyword_loc: Location, location: Location) -> void
    def initialize(arguments, keyword_loc, location)
      @arguments = arguments
      @keyword_loc = keyword_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_next_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [arguments]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { arguments: arguments, keyword_loc: keyword_loc, location: location }
    end

    # def keyword: () -> String
    def keyword
      keyword_loc.slice
    end
  end

  # Represents the use of the `nil` keyword.
  #
  #     nil
  #     ^^^
  class NilNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_nil_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents the use of `**nil` inside method arguments.
  #
  #     def a(**nil)
  #           ^^^^^
  #     end
  class NoKeywordsParameterNode < Node
    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader keyword_loc: Location
    attr_reader :keyword_loc

    # def initialize: (operator_loc: Location, keyword_loc: Location, location: Location) -> void
    def initialize(operator_loc, keyword_loc, location)
      @operator_loc = operator_loc
      @keyword_loc = keyword_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_no_keywords_parameter_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { operator_loc: operator_loc, keyword_loc: keyword_loc, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end

    # def keyword: () -> String
    def keyword
      keyword_loc.slice
    end
  end

  # Represents reading a numbered reference to a capture in the previous match.
  #
  #     $1
  #     ^^
  class NumberedReferenceReadNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_numbered_reference_read_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents an optional parameter to a method, block, or lambda definition.
  #
  #     def a(b = 1)
  #           ^^^^^
  #     end
  class OptionalParameterNode < Node
    # attr_reader constant_id: Symbol
    attr_reader :constant_id

    # attr_reader name_loc: Location
    attr_reader :name_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader value: Node
    attr_reader :value

    # def initialize: (constant_id: Symbol, name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
    def initialize(constant_id, name_loc, operator_loc, value, location)
      @constant_id = constant_id
      @name_loc = name_loc
      @operator_loc = operator_loc
      @value = value
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_optional_parameter_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [value]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { constant_id: constant_id, name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
    end

    # def name: () -> String
    def name
      name_loc.slice
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents the use of the `||` operator or the `or` keyword.
  #
  #     left or right
  #     ^^^^^^^^^^^^^
  class OrNode < Node
    # attr_reader left: Node
    attr_reader :left

    # attr_reader right: Node
    attr_reader :right

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # def initialize: (left: Node, right: Node, operator_loc: Location, location: Location) -> void
    def initialize(left, right, operator_loc, location)
      @left = left
      @right = right
      @operator_loc = operator_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_or_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [left, right]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { left: left, right: right, operator_loc: operator_loc, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents the list of parameters on a method, block, or lambda definition.
  #
  #     def a(b, c, d)
  #           ^^^^^^^
  #     end
  class ParametersNode < Node
    # attr_reader requireds: Array[Node]
    attr_reader :requireds

    # attr_reader optionals: Array[Node]
    attr_reader :optionals

    # attr_reader posts: Array[Node]
    attr_reader :posts

    # attr_reader rest: Node?
    attr_reader :rest

    # attr_reader keywords: Array[Node]
    attr_reader :keywords

    # attr_reader keyword_rest: Node?
    attr_reader :keyword_rest

    # attr_reader block: Node?
    attr_reader :block

    # def initialize: (requireds: Array[Node], optionals: Array[Node], posts: Array[Node], rest: Node?, keywords: Array[Node], keyword_rest: Node?, block: Node?, location: Location) -> void
    def initialize(requireds, optionals, posts, rest, keywords, keyword_rest, block, location)
      @requireds = requireds
      @optionals = optionals
      @posts = posts
      @rest = rest
      @keywords = keywords
      @keyword_rest = keyword_rest
      @block = block
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_parameters_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [*requireds, *optionals, *posts, rest, *keywords, keyword_rest, block]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { requireds: requireds, optionals: optionals, posts: posts, rest: rest, keywords: keywords, keyword_rest: keyword_rest, block: block, location: location }
    end
  end

  # Represents a parenthesized expression
  #
  #     (10 + 34)
  #     ^^^^^^^^^
  class ParenthesesNode < Node
    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader opening_loc: Location
    attr_reader :opening_loc

    # attr_reader closing_loc: Location
    attr_reader :closing_loc

    # def initialize: (statements: Node?, opening_loc: Location, closing_loc: Location, location: Location) -> void
    def initialize(statements, opening_loc, closing_loc, location)
      @statements = statements
      @opening_loc = opening_loc
      @closing_loc = closing_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_parentheses_node(self)
    end

    def set_newline_flag(newline_marked)
      # Never mark ParenthesesNode with a newline flag, mark children instead
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { statements: statements, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
    end

    # def opening: () -> String
    def opening
      opening_loc.slice
    end

    # def closing: () -> String
    def closing
      closing_loc.slice
    end
  end

  # Represents the use of the `^` operator for pinning an expression in a
  # pattern matching expression.
  #
  #     foo in ^(bar)
  #            ^^^^^^
  class PinnedExpressionNode < Node
    # attr_reader expression: Node
    attr_reader :expression

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader lparen_loc: Location
    attr_reader :lparen_loc

    # attr_reader rparen_loc: Location
    attr_reader :rparen_loc

    # def initialize: (expression: Node, operator_loc: Location, lparen_loc: Location, rparen_loc: Location, location: Location) -> void
    def initialize(expression, operator_loc, lparen_loc, rparen_loc, location)
      @expression = expression
      @operator_loc = operator_loc
      @lparen_loc = lparen_loc
      @rparen_loc = rparen_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_pinned_expression_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [expression]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { expression: expression, operator_loc: operator_loc, lparen_loc: lparen_loc, rparen_loc: rparen_loc, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end

    # def lparen: () -> String
    def lparen
      lparen_loc.slice
    end

    # def rparen: () -> String
    def rparen
      rparen_loc.slice
    end
  end

  # Represents the use of the `^` operator for pinning a variable in a pattern
  # matching expression.
  #
  #     foo in ^bar
  #            ^^^^
  class PinnedVariableNode < Node
    # attr_reader variable: Node
    attr_reader :variable

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # def initialize: (variable: Node, operator_loc: Location, location: Location) -> void
    def initialize(variable, operator_loc, location)
      @variable = variable
      @operator_loc = operator_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_pinned_variable_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [variable]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { variable: variable, operator_loc: operator_loc, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents the use of the `END` keyword.
  #
  #     END { foo }
  #     ^^^^^^^^^^^
  class PostExecutionNode < Node
    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader keyword_loc: Location
    attr_reader :keyword_loc

    # attr_reader opening_loc: Location
    attr_reader :opening_loc

    # attr_reader closing_loc: Location
    attr_reader :closing_loc

    # def initialize: (statements: Node?, keyword_loc: Location, opening_loc: Location, closing_loc: Location, location: Location) -> void
    def initialize(statements, keyword_loc, opening_loc, closing_loc, location)
      @statements = statements
      @keyword_loc = keyword_loc
      @opening_loc = opening_loc
      @closing_loc = closing_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_post_execution_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { statements: statements, keyword_loc: keyword_loc, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
    end

    # def keyword: () -> String
    def keyword
      keyword_loc.slice
    end

    # def opening: () -> String
    def opening
      opening_loc.slice
    end

    # def closing: () -> String
    def closing
      closing_loc.slice
    end
  end

  # Represents the use of the `BEGIN` keyword.
  #
  #     BEGIN { foo }
  #     ^^^^^^^^^^^^^
  class PreExecutionNode < Node
    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader keyword_loc: Location
    attr_reader :keyword_loc

    # attr_reader opening_loc: Location
    attr_reader :opening_loc

    # attr_reader closing_loc: Location
    attr_reader :closing_loc

    # def initialize: (statements: Node?, keyword_loc: Location, opening_loc: Location, closing_loc: Location, location: Location) -> void
    def initialize(statements, keyword_loc, opening_loc, closing_loc, location)
      @statements = statements
      @keyword_loc = keyword_loc
      @opening_loc = opening_loc
      @closing_loc = closing_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_pre_execution_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { statements: statements, keyword_loc: keyword_loc, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
    end

    # def keyword: () -> String
    def keyword
      keyword_loc.slice
    end

    # def opening: () -> String
    def opening
      opening_loc.slice
    end

    # def closing: () -> String
    def closing
      closing_loc.slice
    end
  end

  # The top level node of any parse tree.
  class ProgramNode < Node
    # attr_reader locals: Array[Symbol]
    attr_reader :locals

    # attr_reader statements: Node
    attr_reader :statements

    # def initialize: (locals: Array[Symbol], statements: Node, location: Location) -> void
    def initialize(locals, statements, location)
      @locals = locals
      @statements = statements
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_program_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { locals: locals, statements: statements, location: location }
    end
  end

  # Represents the use of the `..` or `...` operators.
  #
  #     1..2
  #     ^^^^
  #
  #     c if a =~ /left/ ... b =~ /right/
  #          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  class RangeNode < Node
    # attr_reader left: Node?
    attr_reader :left

    # attr_reader right: Node?
    attr_reader :right

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader flags: Integer
    attr_reader :flags

    # def initialize: (left: Node?, right: Node?, operator_loc: Location, flags: Integer, location: Location) -> void
    def initialize(left, right, operator_loc, flags, location)
      @left = left
      @right = right
      @operator_loc = operator_loc
      @flags = flags
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_range_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [left, right]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { left: left, right: right, operator_loc: operator_loc, flags: flags, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end

    # def exclude_end?: () -> bool
    def exclude_end?
      flags.anybits?(RangeFlags::EXCLUDE_END)
    end
  end

  # Represents a rational number literal.
  #
  #     1.0r
  #     ^^^^
  class RationalNode < Node
    # attr_reader numeric: Node
    attr_reader :numeric

    # def initialize: (numeric: Node, location: Location) -> void
    def initialize(numeric, location)
      @numeric = numeric
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_rational_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [numeric]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { numeric: numeric, location: location }
    end
  end

  # Represents the use of the `redo` keyword.
  #
  #     redo
  #     ^^^^
  class RedoNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_redo_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents a regular expression literal with no interpolation.
  #
  #     /foo/i
  #     ^^^^^^
  class RegularExpressionNode < Node
    # attr_reader opening_loc: Location
    attr_reader :opening_loc

    # attr_reader content_loc: Location
    attr_reader :content_loc

    # attr_reader closing_loc: Location
    attr_reader :closing_loc

    # attr_reader unescaped: String
    attr_reader :unescaped

    # attr_reader flags: Integer
    attr_reader :flags

    # def initialize: (opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String, flags: Integer, location: Location) -> void
    def initialize(opening_loc, content_loc, closing_loc, unescaped, flags, location)
      @opening_loc = opening_loc
      @content_loc = content_loc
      @closing_loc = closing_loc
      @unescaped = unescaped
      @flags = flags
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_regular_expression_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { opening_loc: opening_loc, content_loc: content_loc, closing_loc: closing_loc, unescaped: unescaped, flags: flags, location: location }
    end

    # def opening: () -> String
    def opening
      opening_loc.slice
    end

    # def content: () -> String
    def content
      content_loc.slice
    end

    # def closing: () -> String
    def closing
      closing_loc.slice
    end

    # def ignore_case?: () -> bool
    def ignore_case?
      flags.anybits?(RegularExpressionFlags::IGNORE_CASE)
    end

    # def multi_line?: () -> bool
    def multi_line?
      flags.anybits?(RegularExpressionFlags::MULTI_LINE)
    end

    # def extended?: () -> bool
    def extended?
      flags.anybits?(RegularExpressionFlags::EXTENDED)
    end

    # def euc_jp?: () -> bool
    def euc_jp?
      flags.anybits?(RegularExpressionFlags::EUC_JP)
    end

    # def ascii_8bit?: () -> bool
    def ascii_8bit?
      flags.anybits?(RegularExpressionFlags::ASCII_8BIT)
    end

    # def windows_31j?: () -> bool
    def windows_31j?
      flags.anybits?(RegularExpressionFlags::WINDOWS_31J)
    end

    # def utf_8?: () -> bool
    def utf_8?
      flags.anybits?(RegularExpressionFlags::UTF_8)
    end

    # def once?: () -> bool
    def once?
      flags.anybits?(RegularExpressionFlags::ONCE)
    end
  end

  # Represents a destructured required parameter node.
  #
  #     def foo((bar, baz))
  #             ^^^^^^^^^^
  #     end
  class RequiredDestructuredParameterNode < Node
    # attr_reader parameters: Array[Node]
    attr_reader :parameters

    # attr_reader opening_loc: Location
    attr_reader :opening_loc

    # attr_reader closing_loc: Location
    attr_reader :closing_loc

    # def initialize: (parameters: Array[Node], opening_loc: Location, closing_loc: Location, location: Location) -> void
    def initialize(parameters, opening_loc, closing_loc, location)
      @parameters = parameters
      @opening_loc = opening_loc
      @closing_loc = closing_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_required_destructured_parameter_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [*parameters]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { parameters: parameters, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
    end

    # def opening: () -> String
    def opening
      opening_loc.slice
    end

    # def closing: () -> String
    def closing
      closing_loc.slice
    end
  end

  # Represents a required parameter to a method, block, or lambda definition.
  #
  #     def a(b)
  #           ^
  #     end
  class RequiredParameterNode < Node
    # attr_reader constant_id: Symbol
    attr_reader :constant_id

    # def initialize: (constant_id: Symbol, location: Location) -> void
    def initialize(constant_id, location)
      @constant_id = constant_id
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_required_parameter_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { constant_id: constant_id, location: location }
    end
  end

  # Represents an expression modified with a rescue.
  #
  #   foo rescue nil
  #   ^^^^^^^^^^^^^^
  class RescueModifierNode < Node
    # attr_reader expression: Node
    attr_reader :expression

    # attr_reader keyword_loc: Location
    attr_reader :keyword_loc

    # attr_reader rescue_expression: Node
    attr_reader :rescue_expression

    # def initialize: (expression: Node, keyword_loc: Location, rescue_expression: Node, location: Location) -> void
    def initialize(expression, keyword_loc, rescue_expression, location)
      @expression = expression
      @keyword_loc = keyword_loc
      @rescue_expression = rescue_expression
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_rescue_modifier_node(self)
    end

    def set_newline_flag(newline_marked)
      expression.set_newline_flag(newline_marked)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [expression, rescue_expression]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { expression: expression, keyword_loc: keyword_loc, rescue_expression: rescue_expression, location: location }
    end

    # def keyword: () -> String
    def keyword
      keyword_loc.slice
    end
  end

  # Represents a rescue statement.
  #
  #     begin
  #     rescue Foo, *splat, Bar => ex
  #     ^^^^^^
  #       foo
  #     end
  #
  # `Foo, *splat, Bar` are in the `exceptions` field.
  # `ex` is in the `exception` field.
  class RescueNode < Node
    # attr_reader keyword_loc: Location
    attr_reader :keyword_loc

    # attr_reader exceptions: Array[Node]
    attr_reader :exceptions

    # attr_reader operator_loc: Location?
    attr_reader :operator_loc

    # attr_reader reference: Node?
    attr_reader :reference

    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader consequent: Node?
    attr_reader :consequent

    # def initialize: (keyword_loc: Location, exceptions: Array[Node], operator_loc: Location?, reference: Node?, statements: Node?, consequent: Node?, location: Location) -> void
    def initialize(keyword_loc, exceptions, operator_loc, reference, statements, consequent, location)
      @keyword_loc = keyword_loc
      @exceptions = exceptions
      @operator_loc = operator_loc
      @reference = reference
      @statements = statements
      @consequent = consequent
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_rescue_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [*exceptions, reference, statements, consequent]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { keyword_loc: keyword_loc, exceptions: exceptions, operator_loc: operator_loc, reference: reference, statements: statements, consequent: consequent, location: location }
    end

    # def keyword: () -> String
    def keyword
      keyword_loc.slice
    end

    # def operator: () -> String?
    def operator
      operator_loc&.slice
    end
  end

  # Represents a rest parameter to a method, block, or lambda definition.
  #
  #     def a(*b)
  #           ^^
  #     end
  class RestParameterNode < Node
    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader name_loc: Location?
    attr_reader :name_loc

    # def initialize: (operator_loc: Location, name_loc: Location?, location: Location) -> void
    def initialize(operator_loc, name_loc, location)
      @operator_loc = operator_loc
      @name_loc = name_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_rest_parameter_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { operator_loc: operator_loc, name_loc: name_loc, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end

    # def name: () -> String?
    def name
      name_loc&.slice
    end
  end

  # Represents the use of the `retry` keyword.
  #
  #     retry
  #     ^^^^^
  class RetryNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_retry_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents the use of the `return` keyword.
  #
  #     return 1
  #     ^^^^^^^^
  class ReturnNode < Node
    # attr_reader keyword_loc: Location
    attr_reader :keyword_loc

    # attr_reader arguments: Node?
    attr_reader :arguments

    # def initialize: (keyword_loc: Location, arguments: Node?, location: Location) -> void
    def initialize(keyword_loc, arguments, location)
      @keyword_loc = keyword_loc
      @arguments = arguments
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_return_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [arguments]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { keyword_loc: keyword_loc, arguments: arguments, location: location }
    end

    # def keyword: () -> String
    def keyword
      keyword_loc.slice
    end
  end

  # Represents the `self` keyword.
  #
  #     self
  #     ^^^^
  class SelfNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_self_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents a singleton class declaration involving the `class` keyword.
  #
  #     class << self end
  #     ^^^^^^^^^^^^^^^^^
  class SingletonClassNode < Node
    # attr_reader locals: Array[Symbol]
    attr_reader :locals

    # attr_reader class_keyword_loc: Location
    attr_reader :class_keyword_loc

    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader expression: Node
    attr_reader :expression

    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader end_keyword_loc: Location
    attr_reader :end_keyword_loc

    # def initialize: (locals: Array[Symbol], class_keyword_loc: Location, operator_loc: Location, expression: Node, statements: Node?, end_keyword_loc: Location, location: Location) -> void
    def initialize(locals, class_keyword_loc, operator_loc, expression, statements, end_keyword_loc, location)
      @locals = locals
      @class_keyword_loc = class_keyword_loc
      @operator_loc = operator_loc
      @expression = expression
      @statements = statements
      @end_keyword_loc = end_keyword_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_singleton_class_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [expression, statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { locals: locals, class_keyword_loc: class_keyword_loc, operator_loc: operator_loc, expression: expression, statements: statements, end_keyword_loc: end_keyword_loc, location: location }
    end

    # def class_keyword: () -> String
    def class_keyword
      class_keyword_loc.slice
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end

    # def end_keyword: () -> String
    def end_keyword
      end_keyword_loc.slice
    end
  end

  # Represents the use of the `__ENCODING__` keyword.
  #
  #     __ENCODING__
  #     ^^^^^^^^^^^^
  class SourceEncodingNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_source_encoding_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents the use of the `__FILE__` keyword.
  #
  #     __FILE__
  #     ^^^^^^^^
  class SourceFileNode < Node
    # attr_reader filepath: String
    attr_reader :filepath

    # def initialize: (filepath: String, location: Location) -> void
    def initialize(filepath, location)
      @filepath = filepath
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_source_file_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { filepath: filepath, location: location }
    end
  end

  # Represents the use of the `__LINE__` keyword.
  #
  #     __LINE__
  #     ^^^^^^^^
  class SourceLineNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_source_line_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents the use of the splat operator.
  #
  #     [*a]
  #      ^^
  class SplatNode < Node
    # attr_reader operator_loc: Location
    attr_reader :operator_loc

    # attr_reader expression: Node?
    attr_reader :expression

    # def initialize: (operator_loc: Location, expression: Node?, location: Location) -> void
    def initialize(operator_loc, expression, location)
      @operator_loc = operator_loc
      @expression = expression
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_splat_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [expression]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { operator_loc: operator_loc, expression: expression, location: location }
    end

    # def operator: () -> String
    def operator
      operator_loc.slice
    end
  end

  # Represents a set of statements contained within some scope.
  #
  #     foo; bar; baz
  #     ^^^^^^^^^^^^^
  class StatementsNode < Node
    # attr_reader body: Array[Node]
    attr_reader :body

    # def initialize: (body: Array[Node], location: Location) -> void
    def initialize(body, location)
      @body = body
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_statements_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [*body]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { body: body, location: location }
    end
  end

  # Represents the use of compile-time string concatenation.
  #
  #     "foo" "bar"
  #     ^^^^^^^^^^^
  class StringConcatNode < Node
    # attr_reader left: Node
    attr_reader :left

    # attr_reader right: Node
    attr_reader :right

    # def initialize: (left: Node, right: Node, location: Location) -> void
    def initialize(left, right, location)
      @left = left
      @right = right
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_string_concat_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [left, right]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { left: left, right: right, location: location }
    end
  end

  # Represents a string literal, a string contained within a `%w` list, or
  # plain string content within an interpolated string.
  #
  #     "foo"
  #     ^^^^^
  #
  #     %w[foo]
  #        ^^^
  #
  #     "foo #{bar} baz"
  #      ^^^^      ^^^^
  class StringNode < Node
    # attr_reader opening_loc: Location?
    attr_reader :opening_loc

    # attr_reader content_loc: Location
    attr_reader :content_loc

    # attr_reader closing_loc: Location?
    attr_reader :closing_loc

    # attr_reader unescaped: String
    attr_reader :unescaped

    # def initialize: (opening_loc: Location?, content_loc: Location, closing_loc: Location?, unescaped: String, location: Location) -> void
    def initialize(opening_loc, content_loc, closing_loc, unescaped, location)
      @opening_loc = opening_loc
      @content_loc = content_loc
      @closing_loc = closing_loc
      @unescaped = unescaped
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_string_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { opening_loc: opening_loc, content_loc: content_loc, closing_loc: closing_loc, unescaped: unescaped, location: location }
    end

    # def opening: () -> String?
    def opening
      opening_loc&.slice
    end

    # def content: () -> String
    def content
      content_loc.slice
    end

    # def closing: () -> String?
    def closing
      closing_loc&.slice
    end
  end

  # Represents the use of the `super` keyword with parentheses or arguments.
  #
  #     super()
  #     ^^^^^^^
  #
  #     super foo, bar
  #     ^^^^^^^^^^^^^^
  class SuperNode < Node
    # attr_reader keyword_loc: Location
    attr_reader :keyword_loc

    # attr_reader lparen_loc: Location?
    attr_reader :lparen_loc

    # attr_reader arguments: Node?
    attr_reader :arguments

    # attr_reader rparen_loc: Location?
    attr_reader :rparen_loc

    # attr_reader block: Node?
    attr_reader :block

    # def initialize: (keyword_loc: Location, lparen_loc: Location?, arguments: Node?, rparen_loc: Location?, block: Node?, location: Location) -> void
    def initialize(keyword_loc, lparen_loc, arguments, rparen_loc, block, location)
      @keyword_loc = keyword_loc
      @lparen_loc = lparen_loc
      @arguments = arguments
      @rparen_loc = rparen_loc
      @block = block
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_super_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [arguments, block]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { keyword_loc: keyword_loc, lparen_loc: lparen_loc, arguments: arguments, rparen_loc: rparen_loc, block: block, location: location }
    end

    # def keyword: () -> String
    def keyword
      keyword_loc.slice
    end

    # def lparen: () -> String?
    def lparen
      lparen_loc&.slice
    end

    # def rparen: () -> String?
    def rparen
      rparen_loc&.slice
    end
  end

  # Represents a symbol literal or a symbol contained within a `%i` list.
  #
  #     :foo
  #     ^^^^
  #
  #     %i[foo]
  #        ^^^
  class SymbolNode < Node
    # attr_reader opening_loc: Location?
    attr_reader :opening_loc

    # attr_reader value_loc: Location
    attr_reader :value_loc

    # attr_reader closing_loc: Location?
    attr_reader :closing_loc

    # attr_reader unescaped: String
    attr_reader :unescaped

    # def initialize: (opening_loc: Location?, value_loc: Location, closing_loc: Location?, unescaped: String, location: Location) -> void
    def initialize(opening_loc, value_loc, closing_loc, unescaped, location)
      @opening_loc = opening_loc
      @value_loc = value_loc
      @closing_loc = closing_loc
      @unescaped = unescaped
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_symbol_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { opening_loc: opening_loc, value_loc: value_loc, closing_loc: closing_loc, unescaped: unescaped, location: location }
    end

    # def opening: () -> String?
    def opening
      opening_loc&.slice
    end

    # def value: () -> String
    def value
      value_loc.slice
    end

    # def closing: () -> String?
    def closing
      closing_loc&.slice
    end
  end

  # Represents the use of the literal `true` keyword.
  #
  #     true
  #     ^^^^
  class TrueNode < Node
    # def initialize: (location: Location) -> void
    def initialize(location)
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_true_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { location: location }
    end
  end

  # Represents the use of the `undef` keyword.
  #
  #     undef :foo, :bar, :baz
  #     ^^^^^^^^^^^^^^^^^^^^^^
  class UndefNode < Node
    # attr_reader names: Array[Node]
    attr_reader :names

    # attr_reader keyword_loc: Location
    attr_reader :keyword_loc

    # def initialize: (names: Array[Node], keyword_loc: Location, location: Location) -> void
    def initialize(names, keyword_loc, location)
      @names = names
      @keyword_loc = keyword_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_undef_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [*names]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { names: names, keyword_loc: keyword_loc, location: location }
    end

    # def keyword: () -> String
    def keyword
      keyword_loc.slice
    end
  end

  # Represents the use of the `unless` keyword, either in the block form or the modifier form.
  #
  #     bar unless foo
  #     ^^^^^^^^^^^^^^
  #
  #     unless foo then bar end
  #     ^^^^^^^^^^^^^^^^^^^^^^^
  class UnlessNode < Node
    # attr_reader keyword_loc: Location
    attr_reader :keyword_loc

    # attr_reader predicate: Node
    attr_reader :predicate

    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader consequent: Node?
    attr_reader :consequent

    # attr_reader end_keyword_loc: Location?
    attr_reader :end_keyword_loc

    # def initialize: (keyword_loc: Location, predicate: Node, statements: Node?, consequent: Node?, end_keyword_loc: Location?, location: Location) -> void
    def initialize(keyword_loc, predicate, statements, consequent, end_keyword_loc, location)
      @keyword_loc = keyword_loc
      @predicate = predicate
      @statements = statements
      @consequent = consequent
      @end_keyword_loc = end_keyword_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_unless_node(self)
    end

    def set_newline_flag(newline_marked)
      predicate.set_newline_flag(newline_marked)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [predicate, statements, consequent]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { keyword_loc: keyword_loc, predicate: predicate, statements: statements, consequent: consequent, end_keyword_loc: end_keyword_loc, location: location }
    end

    # def keyword: () -> String
    def keyword
      keyword_loc.slice
    end

    # def end_keyword: () -> String?
    def end_keyword
      end_keyword_loc&.slice
    end
  end

  # Represents the use of the `until` keyword, either in the block form or the modifier form.
  #
  #     bar until foo
  #     ^^^^^^^^^^^^^
  #
  #     until foo do bar end
  #     ^^^^^^^^^^^^^^^^^^^^
  class UntilNode < Node
    # attr_reader keyword_loc: Location
    attr_reader :keyword_loc

    # attr_reader predicate: Node
    attr_reader :predicate

    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader flags: Integer
    attr_reader :flags

    # def initialize: (keyword_loc: Location, predicate: Node, statements: Node?, flags: Integer, location: Location) -> void
    def initialize(keyword_loc, predicate, statements, flags, location)
      @keyword_loc = keyword_loc
      @predicate = predicate
      @statements = statements
      @flags = flags
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_until_node(self)
    end

    def set_newline_flag(newline_marked)
      predicate.set_newline_flag(newline_marked)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [predicate, statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { keyword_loc: keyword_loc, predicate: predicate, statements: statements, flags: flags, location: location }
    end

    # def keyword: () -> String
    def keyword
      keyword_loc.slice
    end

    # def begin_modifier?: () -> bool
    def begin_modifier?
      flags.anybits?(LoopFlags::BEGIN_MODIFIER)
    end
  end

  # Represents the use of the `when` keyword within a case statement.
  #
  #     case true
  #     when true
  #     ^^^^^^^^^
  #     end
  class WhenNode < Node
    # attr_reader keyword_loc: Location
    attr_reader :keyword_loc

    # attr_reader conditions: Array[Node]
    attr_reader :conditions

    # attr_reader statements: Node?
    attr_reader :statements

    # def initialize: (keyword_loc: Location, conditions: Array[Node], statements: Node?, location: Location) -> void
    def initialize(keyword_loc, conditions, statements, location)
      @keyword_loc = keyword_loc
      @conditions = conditions
      @statements = statements
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_when_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [*conditions, statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { keyword_loc: keyword_loc, conditions: conditions, statements: statements, location: location }
    end

    # def keyword: () -> String
    def keyword
      keyword_loc.slice
    end
  end

  # Represents the use of the `while` keyword, either in the block form or the modifier form.
  #
  #     bar while foo
  #     ^^^^^^^^^^^^^
  #
  #     while foo do bar end
  #     ^^^^^^^^^^^^^^^^^^^^
  class WhileNode < Node
    # attr_reader keyword_loc: Location
    attr_reader :keyword_loc

    # attr_reader predicate: Node
    attr_reader :predicate

    # attr_reader statements: Node?
    attr_reader :statements

    # attr_reader flags: Integer
    attr_reader :flags

    # def initialize: (keyword_loc: Location, predicate: Node, statements: Node?, flags: Integer, location: Location) -> void
    def initialize(keyword_loc, predicate, statements, flags, location)
      @keyword_loc = keyword_loc
      @predicate = predicate
      @statements = statements
      @flags = flags
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_while_node(self)
    end

    def set_newline_flag(newline_marked)
      predicate.set_newline_flag(newline_marked)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [predicate, statements]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { keyword_loc: keyword_loc, predicate: predicate, statements: statements, flags: flags, location: location }
    end

    # def keyword: () -> String
    def keyword
      keyword_loc.slice
    end

    # def begin_modifier?: () -> bool
    def begin_modifier?
      flags.anybits?(LoopFlags::BEGIN_MODIFIER)
    end
  end

  # Represents an xstring literal with no interpolation.
  #
  #     `foo`
  #     ^^^^^
  class XStringNode < Node
    # attr_reader opening_loc: Location
    attr_reader :opening_loc

    # attr_reader content_loc: Location
    attr_reader :content_loc

    # attr_reader closing_loc: Location
    attr_reader :closing_loc

    # attr_reader unescaped: String
    attr_reader :unescaped

    # def initialize: (opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String, location: Location) -> void
    def initialize(opening_loc, content_loc, closing_loc, unescaped, location)
      @opening_loc = opening_loc
      @content_loc = content_loc
      @closing_loc = closing_loc
      @unescaped = unescaped
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_x_string_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      []
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { opening_loc: opening_loc, content_loc: content_loc, closing_loc: closing_loc, unescaped: unescaped, location: location }
    end

    # def opening: () -> String
    def opening
      opening_loc.slice
    end

    # def content: () -> String
    def content
      content_loc.slice
    end

    # def closing: () -> String
    def closing
      closing_loc.slice
    end
  end

  # Represents the use of the `yield` keyword.
  #
  #     yield 1
  #     ^^^^^^^
  class YieldNode < Node
    # attr_reader keyword_loc: Location
    attr_reader :keyword_loc

    # attr_reader lparen_loc: Location?
    attr_reader :lparen_loc

    # attr_reader arguments: Node?
    attr_reader :arguments

    # attr_reader rparen_loc: Location?
    attr_reader :rparen_loc

    # def initialize: (keyword_loc: Location, lparen_loc: Location?, arguments: Node?, rparen_loc: Location?, location: Location) -> void
    def initialize(keyword_loc, lparen_loc, arguments, rparen_loc, location)
      @keyword_loc = keyword_loc
      @lparen_loc = lparen_loc
      @arguments = arguments
      @rparen_loc = rparen_loc
      @location = location
    end

    # def accept: (visitor: Visitor) -> void
    def accept(visitor)
      visitor.visit_yield_node(self)
    end

    # def child_nodes: () -> Array[nil | Node]
    def child_nodes
      [arguments]
    end

    # def deconstruct: () -> Array[nil | Node]
    alias deconstruct child_nodes

    # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
    def deconstruct_keys(keys)
      { keyword_loc: keyword_loc, lparen_loc: lparen_loc, arguments: arguments, rparen_loc: rparen_loc, location: location }
    end

    # def keyword: () -> String
    def keyword
      keyword_loc.slice
    end

    # def lparen: () -> String?
    def lparen
      lparen_loc&.slice
    end

    # def rparen: () -> String?
    def rparen
      rparen_loc&.slice
    end
  end

  module CallNodeFlags
    # &. operator
    SAFE_NAVIGATION = 1 << 0

    # a call that could have been a local variable
    VARIABLE_CALL = 1 << 1
  end

  module LoopFlags
    # a loop after a begin statement, so the body is executed first before the condition
    BEGIN_MODIFIER = 1 << 0
  end

  module RangeFlags
    # ... operator
    EXCLUDE_END = 1 << 0
  end

  module RegularExpressionFlags
    # i - ignores the case of characters when matching
    IGNORE_CASE = 1 << 0

    # m - allows $ to match the end of lines within strings
    MULTI_LINE = 1 << 1

    # x - ignores whitespace and allows comments in regular expressions
    EXTENDED = 1 << 2

    # e - forces the EUC-JP encoding
    EUC_JP = 1 << 3

    # n - forces the ASCII-8BIT encoding
    ASCII_8BIT = 1 << 4

    # s - forces the Windows-31J encoding
    WINDOWS_31J = 1 << 5

    # u - forces the UTF-8 encoding
    UTF_8 = 1 << 6

    # o - only interpolates values into the regular expression once
    ONCE = 1 << 7
  end

  class Visitor < BasicVisitor
    # Visit a AliasNode node
    alias visit_alias_node visit_child_nodes

    # Visit a AlternationPatternNode node
    alias visit_alternation_pattern_node visit_child_nodes

    # Visit a AndNode node
    alias visit_and_node visit_child_nodes

    # Visit a ArgumentsNode node
    alias visit_arguments_node visit_child_nodes

    # Visit a ArrayNode node
    alias visit_array_node visit_child_nodes

    # Visit a ArrayPatternNode node
    alias visit_array_pattern_node visit_child_nodes

    # Visit a AssocNode node
    alias visit_assoc_node visit_child_nodes

    # Visit a AssocSplatNode node
    alias visit_assoc_splat_node visit_child_nodes

    # Visit a BackReferenceReadNode node
    alias visit_back_reference_read_node visit_child_nodes

    # Visit a BeginNode node
    alias visit_begin_node visit_child_nodes

    # Visit a BlockArgumentNode node
    alias visit_block_argument_node visit_child_nodes

    # Visit a BlockNode node
    alias visit_block_node visit_child_nodes

    # Visit a BlockParameterNode node
    alias visit_block_parameter_node visit_child_nodes

    # Visit a BlockParametersNode node
    alias visit_block_parameters_node visit_child_nodes

    # Visit a BreakNode node
    alias visit_break_node visit_child_nodes

    # Visit a CallNode node
    alias visit_call_node visit_child_nodes

    # Visit a CallOperatorAndWriteNode node
    alias visit_call_operator_and_write_node visit_child_nodes

    # Visit a CallOperatorOrWriteNode node
    alias visit_call_operator_or_write_node visit_child_nodes

    # Visit a CallOperatorWriteNode node
    alias visit_call_operator_write_node visit_child_nodes

    # Visit a CapturePatternNode node
    alias visit_capture_pattern_node visit_child_nodes

    # Visit a CaseNode node
    alias visit_case_node visit_child_nodes

    # Visit a ClassNode node
    alias visit_class_node visit_child_nodes

    # Visit a ClassVariableOperatorAndWriteNode node
    alias visit_class_variable_operator_and_write_node visit_child_nodes

    # Visit a ClassVariableOperatorOrWriteNode node
    alias visit_class_variable_operator_or_write_node visit_child_nodes

    # Visit a ClassVariableOperatorWriteNode node
    alias visit_class_variable_operator_write_node visit_child_nodes

    # Visit a ClassVariableReadNode node
    alias visit_class_variable_read_node visit_child_nodes

    # Visit a ClassVariableWriteNode node
    alias visit_class_variable_write_node visit_child_nodes

    # Visit a ConstantOperatorAndWriteNode node
    alias visit_constant_operator_and_write_node visit_child_nodes

    # Visit a ConstantOperatorOrWriteNode node
    alias visit_constant_operator_or_write_node visit_child_nodes

    # Visit a ConstantOperatorWriteNode node
    alias visit_constant_operator_write_node visit_child_nodes

    # Visit a ConstantPathNode node
    alias visit_constant_path_node visit_child_nodes

    # Visit a ConstantPathOperatorAndWriteNode node
    alias visit_constant_path_operator_and_write_node visit_child_nodes

    # Visit a ConstantPathOperatorOrWriteNode node
    alias visit_constant_path_operator_or_write_node visit_child_nodes

    # Visit a ConstantPathOperatorWriteNode node
    alias visit_constant_path_operator_write_node visit_child_nodes

    # Visit a ConstantPathWriteNode node
    alias visit_constant_path_write_node visit_child_nodes

    # Visit a ConstantReadNode node
    alias visit_constant_read_node visit_child_nodes

    # Visit a ConstantWriteNode node
    alias visit_constant_write_node visit_child_nodes

    # Visit a DefNode node
    alias visit_def_node visit_child_nodes

    # Visit a DefinedNode node
    alias visit_defined_node visit_child_nodes

    # Visit a ElseNode node
    alias visit_else_node visit_child_nodes

    # Visit a EmbeddedStatementsNode node
    alias visit_embedded_statements_node visit_child_nodes

    # Visit a EmbeddedVariableNode node
    alias visit_embedded_variable_node visit_child_nodes

    # Visit a EnsureNode node
    alias visit_ensure_node visit_child_nodes

    # Visit a FalseNode node
    alias visit_false_node visit_child_nodes

    # Visit a FindPatternNode node
    alias visit_find_pattern_node visit_child_nodes

    # Visit a FlipFlopNode node
    alias visit_flip_flop_node visit_child_nodes

    # Visit a FloatNode node
    alias visit_float_node visit_child_nodes

    # Visit a ForNode node
    alias visit_for_node visit_child_nodes

    # Visit a ForwardingArgumentsNode node
    alias visit_forwarding_arguments_node visit_child_nodes

    # Visit a ForwardingParameterNode node
    alias visit_forwarding_parameter_node visit_child_nodes

    # Visit a ForwardingSuperNode node
    alias visit_forwarding_super_node visit_child_nodes

    # Visit a GlobalVariableOperatorAndWriteNode node
    alias visit_global_variable_operator_and_write_node visit_child_nodes

    # Visit a GlobalVariableOperatorOrWriteNode node
    alias visit_global_variable_operator_or_write_node visit_child_nodes

    # Visit a GlobalVariableOperatorWriteNode node
    alias visit_global_variable_operator_write_node visit_child_nodes

    # Visit a GlobalVariableReadNode node
    alias visit_global_variable_read_node visit_child_nodes

    # Visit a GlobalVariableWriteNode node
    alias visit_global_variable_write_node visit_child_nodes

    # Visit a HashNode node
    alias visit_hash_node visit_child_nodes

    # Visit a HashPatternNode node
    alias visit_hash_pattern_node visit_child_nodes

    # Visit a IfNode node
    alias visit_if_node visit_child_nodes

    # Visit a ImaginaryNode node
    alias visit_imaginary_node visit_child_nodes

    # Visit a InNode node
    alias visit_in_node visit_child_nodes

    # Visit a InstanceVariableOperatorAndWriteNode node
    alias visit_instance_variable_operator_and_write_node visit_child_nodes

    # Visit a InstanceVariableOperatorOrWriteNode node
    alias visit_instance_variable_operator_or_write_node visit_child_nodes

    # Visit a InstanceVariableOperatorWriteNode node
    alias visit_instance_variable_operator_write_node visit_child_nodes

    # Visit a InstanceVariableReadNode node
    alias visit_instance_variable_read_node visit_child_nodes

    # Visit a InstanceVariableWriteNode node
    alias visit_instance_variable_write_node visit_child_nodes

    # Visit a IntegerNode node
    alias visit_integer_node visit_child_nodes

    # Visit a InterpolatedRegularExpressionNode node
    alias visit_interpolated_regular_expression_node visit_child_nodes

    # Visit a InterpolatedStringNode node
    alias visit_interpolated_string_node visit_child_nodes

    # Visit a InterpolatedSymbolNode node
    alias visit_interpolated_symbol_node visit_child_nodes

    # Visit a InterpolatedXStringNode node
    alias visit_interpolated_x_string_node visit_child_nodes

    # Visit a KeywordHashNode node
    alias visit_keyword_hash_node visit_child_nodes

    # Visit a KeywordParameterNode node
    alias visit_keyword_parameter_node visit_child_nodes

    # Visit a KeywordRestParameterNode node
    alias visit_keyword_rest_parameter_node visit_child_nodes

    # Visit a LambdaNode node
    alias visit_lambda_node visit_child_nodes

    # Visit a LocalVariableOperatorAndWriteNode node
    alias visit_local_variable_operator_and_write_node visit_child_nodes

    # Visit a LocalVariableOperatorOrWriteNode node
    alias visit_local_variable_operator_or_write_node visit_child_nodes

    # Visit a LocalVariableOperatorWriteNode node
    alias visit_local_variable_operator_write_node visit_child_nodes

    # Visit a LocalVariableReadNode node
    alias visit_local_variable_read_node visit_child_nodes

    # Visit a LocalVariableWriteNode node
    alias visit_local_variable_write_node visit_child_nodes

    # Visit a MatchPredicateNode node
    alias visit_match_predicate_node visit_child_nodes

    # Visit a MatchRequiredNode node
    alias visit_match_required_node visit_child_nodes

    # Visit a MissingNode node
    alias visit_missing_node visit_child_nodes

    # Visit a ModuleNode node
    alias visit_module_node visit_child_nodes

    # Visit a MultiWriteNode node
    alias visit_multi_write_node visit_child_nodes

    # Visit a NextNode node
    alias visit_next_node visit_child_nodes

    # Visit a NilNode node
    alias visit_nil_node visit_child_nodes

    # Visit a NoKeywordsParameterNode node
    alias visit_no_keywords_parameter_node visit_child_nodes

    # Visit a NumberedReferenceReadNode node
    alias visit_numbered_reference_read_node visit_child_nodes

    # Visit a OptionalParameterNode node
    alias visit_optional_parameter_node visit_child_nodes

    # Visit a OrNode node
    alias visit_or_node visit_child_nodes

    # Visit a ParametersNode node
    alias visit_parameters_node visit_child_nodes

    # Visit a ParenthesesNode node
    alias visit_parentheses_node visit_child_nodes

    # Visit a PinnedExpressionNode node
    alias visit_pinned_expression_node visit_child_nodes

    # Visit a PinnedVariableNode node
    alias visit_pinned_variable_node visit_child_nodes

    # Visit a PostExecutionNode node
    alias visit_post_execution_node visit_child_nodes

    # Visit a PreExecutionNode node
    alias visit_pre_execution_node visit_child_nodes

    # Visit a ProgramNode node
    alias visit_program_node visit_child_nodes

    # Visit a RangeNode node
    alias visit_range_node visit_child_nodes

    # Visit a RationalNode node
    alias visit_rational_node visit_child_nodes

    # Visit a RedoNode node
    alias visit_redo_node visit_child_nodes

    # Visit a RegularExpressionNode node
    alias visit_regular_expression_node visit_child_nodes

    # Visit a RequiredDestructuredParameterNode node
    alias visit_required_destructured_parameter_node visit_child_nodes

    # Visit a RequiredParameterNode node
    alias visit_required_parameter_node visit_child_nodes

    # Visit a RescueModifierNode node
    alias visit_rescue_modifier_node visit_child_nodes

    # Visit a RescueNode node
    alias visit_rescue_node visit_child_nodes

    # Visit a RestParameterNode node
    alias visit_rest_parameter_node visit_child_nodes

    # Visit a RetryNode node
    alias visit_retry_node visit_child_nodes

    # Visit a ReturnNode node
    alias visit_return_node visit_child_nodes

    # Visit a SelfNode node
    alias visit_self_node visit_child_nodes

    # Visit a SingletonClassNode node
    alias visit_singleton_class_node visit_child_nodes

    # Visit a SourceEncodingNode node
    alias visit_source_encoding_node visit_child_nodes

    # Visit a SourceFileNode node
    alias visit_source_file_node visit_child_nodes

    # Visit a SourceLineNode node
    alias visit_source_line_node visit_child_nodes

    # Visit a SplatNode node
    alias visit_splat_node visit_child_nodes

    # Visit a StatementsNode node
    alias visit_statements_node visit_child_nodes

    # Visit a StringConcatNode node
    alias visit_string_concat_node visit_child_nodes

    # Visit a StringNode node
    alias visit_string_node visit_child_nodes

    # Visit a SuperNode node
    alias visit_super_node visit_child_nodes

    # Visit a SymbolNode node
    alias visit_symbol_node visit_child_nodes

    # Visit a TrueNode node
    alias visit_true_node visit_child_nodes

    # Visit a UndefNode node
    alias visit_undef_node visit_child_nodes

    # Visit a UnlessNode node
    alias visit_unless_node visit_child_nodes

    # Visit a UntilNode node
    alias visit_until_node visit_child_nodes

    # Visit a WhenNode node
    alias visit_when_node visit_child_nodes

    # Visit a WhileNode node
    alias visit_while_node visit_child_nodes

    # Visit a XStringNode node
    alias visit_x_string_node visit_child_nodes

    # Visit a YieldNode node
    alias visit_yield_node visit_child_nodes
  end

  module DSL
    private

    # Create a new Location object
    def Location(source = nil, start_offset = 0, length = 0)
      Location.new(source, start_offset, length)
    end

    # Create a new AliasNode node
    def AliasNode(new_name, old_name, keyword_loc, location = Location())
      AliasNode.new(new_name, old_name, keyword_loc, location)
    end

    # Create a new AlternationPatternNode node
    def AlternationPatternNode(left, right, operator_loc, location = Location())
      AlternationPatternNode.new(left, right, operator_loc, location)
    end

    # Create a new AndNode node
    def AndNode(left, right, operator_loc, location = Location())
      AndNode.new(left, right, operator_loc, location)
    end

    # Create a new ArgumentsNode node
    def ArgumentsNode(arguments, location = Location())
      ArgumentsNode.new(arguments, location)
    end

    # Create a new ArrayNode node
    def ArrayNode(elements, opening_loc, closing_loc, location = Location())
      ArrayNode.new(elements, opening_loc, closing_loc, location)
    end

    # Create a new ArrayPatternNode node
    def ArrayPatternNode(constant, requireds, rest, posts, opening_loc, closing_loc, location = Location())
      ArrayPatternNode.new(constant, requireds, rest, posts, opening_loc, closing_loc, location)
    end

    # Create a new AssocNode node
    def AssocNode(key, value, operator_loc, location = Location())
      AssocNode.new(key, value, operator_loc, location)
    end

    # Create a new AssocSplatNode node
    def AssocSplatNode(value, operator_loc, location = Location())
      AssocSplatNode.new(value, operator_loc, location)
    end

    # Create a new BackReferenceReadNode node
    def BackReferenceReadNode(location = Location())
      BackReferenceReadNode.new(location)
    end

    # Create a new BeginNode node
    def BeginNode(begin_keyword_loc, statements, rescue_clause, else_clause, ensure_clause, end_keyword_loc, location = Location())
      BeginNode.new(begin_keyword_loc, statements, rescue_clause, else_clause, ensure_clause, end_keyword_loc, location)
    end

    # Create a new BlockArgumentNode node
    def BlockArgumentNode(expression, operator_loc, location = Location())
      BlockArgumentNode.new(expression, operator_loc, location)
    end

    # Create a new BlockNode node
    def BlockNode(locals, parameters, statements, opening_loc, closing_loc, location = Location())
      BlockNode.new(locals, parameters, statements, opening_loc, closing_loc, location)
    end

    # Create a new BlockParameterNode node
    def BlockParameterNode(name_loc, operator_loc, location = Location())
      BlockParameterNode.new(name_loc, operator_loc, location)
    end

    # Create a new BlockParametersNode node
    def BlockParametersNode(parameters, locals, opening_loc, closing_loc, location = Location())
      BlockParametersNode.new(parameters, locals, opening_loc, closing_loc, location)
    end

    # Create a new BreakNode node
    def BreakNode(arguments, keyword_loc, location = Location())
      BreakNode.new(arguments, keyword_loc, location)
    end

    # Create a new CallNode node
    def CallNode(receiver, operator_loc, message_loc, opening_loc, arguments, closing_loc, block, flags, name, location = Location())
      CallNode.new(receiver, operator_loc, message_loc, opening_loc, arguments, closing_loc, block, flags, name, location)
    end

    # Create a new CallOperatorAndWriteNode node
    def CallOperatorAndWriteNode(target, operator_loc, value, location = Location())
      CallOperatorAndWriteNode.new(target, operator_loc, value, location)
    end

    # Create a new CallOperatorOrWriteNode node
    def CallOperatorOrWriteNode(target, value, operator_loc, location = Location())
      CallOperatorOrWriteNode.new(target, value, operator_loc, location)
    end

    # Create a new CallOperatorWriteNode node
    def CallOperatorWriteNode(target, operator_loc, value, operator_id, location = Location())
      CallOperatorWriteNode.new(target, operator_loc, value, operator_id, location)
    end

    # Create a new CapturePatternNode node
    def CapturePatternNode(value, target, operator_loc, location = Location())
      CapturePatternNode.new(value, target, operator_loc, location)
    end

    # Create a new CaseNode node
    def CaseNode(predicate, conditions, consequent, case_keyword_loc, end_keyword_loc, location = Location())
      CaseNode.new(predicate, conditions, consequent, case_keyword_loc, end_keyword_loc, location)
    end

    # Create a new ClassNode node
    def ClassNode(locals, class_keyword_loc, constant_path, inheritance_operator_loc, superclass, statements, end_keyword_loc, location = Location())
      ClassNode.new(locals, class_keyword_loc, constant_path, inheritance_operator_loc, superclass, statements, end_keyword_loc, location)
    end

    # Create a new ClassVariableOperatorAndWriteNode node
    def ClassVariableOperatorAndWriteNode(name_loc, operator_loc, value, location = Location())
      ClassVariableOperatorAndWriteNode.new(name_loc, operator_loc, value, location)
    end

    # Create a new ClassVariableOperatorOrWriteNode node
    def ClassVariableOperatorOrWriteNode(name_loc, operator_loc, value, location = Location())
      ClassVariableOperatorOrWriteNode.new(name_loc, operator_loc, value, location)
    end

    # Create a new ClassVariableOperatorWriteNode node
    def ClassVariableOperatorWriteNode(name_loc, operator_loc, value, operator, location = Location())
      ClassVariableOperatorWriteNode.new(name_loc, operator_loc, value, operator, location)
    end

    # Create a new ClassVariableReadNode node
    def ClassVariableReadNode(location = Location())
      ClassVariableReadNode.new(location)
    end

    # Create a new ClassVariableWriteNode node
    def ClassVariableWriteNode(name_loc, value, operator_loc, location = Location())
      ClassVariableWriteNode.new(name_loc, value, operator_loc, location)
    end

    # Create a new ConstantOperatorAndWriteNode node
    def ConstantOperatorAndWriteNode(name_loc, operator_loc, value, location = Location())
      ConstantOperatorAndWriteNode.new(name_loc, operator_loc, value, location)
    end

    # Create a new ConstantOperatorOrWriteNode node
    def ConstantOperatorOrWriteNode(name_loc, operator_loc, value, location = Location())
      ConstantOperatorOrWriteNode.new(name_loc, operator_loc, value, location)
    end

    # Create a new ConstantOperatorWriteNode node
    def ConstantOperatorWriteNode(name_loc, operator_loc, value, operator, location = Location())
      ConstantOperatorWriteNode.new(name_loc, operator_loc, value, operator, location)
    end

    # Create a new ConstantPathNode node
    def ConstantPathNode(parent, child, delimiter_loc, location = Location())
      ConstantPathNode.new(parent, child, delimiter_loc, location)
    end

    # Create a new ConstantPathOperatorAndWriteNode node
    def ConstantPathOperatorAndWriteNode(target, operator_loc, value, location = Location())
      ConstantPathOperatorAndWriteNode.new(target, operator_loc, value, location)
    end

    # Create a new ConstantPathOperatorOrWriteNode node
    def ConstantPathOperatorOrWriteNode(target, operator_loc, value, location = Location())
      ConstantPathOperatorOrWriteNode.new(target, operator_loc, value, location)
    end

    # Create a new ConstantPathOperatorWriteNode node
    def ConstantPathOperatorWriteNode(target, operator_loc, value, operator, location = Location())
      ConstantPathOperatorWriteNode.new(target, operator_loc, value, operator, location)
    end

    # Create a new ConstantPathWriteNode node
    def ConstantPathWriteNode(target, operator_loc, value, location = Location())
      ConstantPathWriteNode.new(target, operator_loc, value, location)
    end

    # Create a new ConstantReadNode node
    def ConstantReadNode(location = Location())
      ConstantReadNode.new(location)
    end

    # Create a new ConstantWriteNode node
    def ConstantWriteNode(name_loc, value, operator_loc, location = Location())
      ConstantWriteNode.new(name_loc, value, operator_loc, location)
    end

    # Create a new DefNode node
    def DefNode(name_loc, receiver, parameters, statements, locals, def_keyword_loc, operator_loc, lparen_loc, rparen_loc, equal_loc, end_keyword_loc, location = Location())
      DefNode.new(name_loc, receiver, parameters, statements, locals, def_keyword_loc, operator_loc, lparen_loc, rparen_loc, equal_loc, end_keyword_loc, location)
    end

    # Create a new DefinedNode node
    def DefinedNode(lparen_loc, value, rparen_loc, keyword_loc, location = Location())
      DefinedNode.new(lparen_loc, value, rparen_loc, keyword_loc, location)
    end

    # Create a new ElseNode node
    def ElseNode(else_keyword_loc, statements, end_keyword_loc, location = Location())
      ElseNode.new(else_keyword_loc, statements, end_keyword_loc, location)
    end

    # Create a new EmbeddedStatementsNode node
    def EmbeddedStatementsNode(opening_loc, statements, closing_loc, location = Location())
      EmbeddedStatementsNode.new(opening_loc, statements, closing_loc, location)
    end

    # Create a new EmbeddedVariableNode node
    def EmbeddedVariableNode(operator_loc, variable, location = Location())
      EmbeddedVariableNode.new(operator_loc, variable, location)
    end

    # Create a new EnsureNode node
    def EnsureNode(ensure_keyword_loc, statements, end_keyword_loc, location = Location())
      EnsureNode.new(ensure_keyword_loc, statements, end_keyword_loc, location)
    end

    # Create a new FalseNode node
    def FalseNode(location = Location())
      FalseNode.new(location)
    end

    # Create a new FindPatternNode node
    def FindPatternNode(constant, left, requireds, right, opening_loc, closing_loc, location = Location())
      FindPatternNode.new(constant, left, requireds, right, opening_loc, closing_loc, location)
    end

    # Create a new FlipFlopNode node
    def FlipFlopNode(left, right, operator_loc, flags, location = Location())
      FlipFlopNode.new(left, right, operator_loc, flags, location)
    end

    # Create a new FloatNode node
    def FloatNode(location = Location())
      FloatNode.new(location)
    end

    # Create a new ForNode node
    def ForNode(index, collection, statements, for_keyword_loc, in_keyword_loc, do_keyword_loc, end_keyword_loc, location = Location())
      ForNode.new(index, collection, statements, for_keyword_loc, in_keyword_loc, do_keyword_loc, end_keyword_loc, location)
    end

    # Create a new ForwardingArgumentsNode node
    def ForwardingArgumentsNode(location = Location())
      ForwardingArgumentsNode.new(location)
    end

    # Create a new ForwardingParameterNode node
    def ForwardingParameterNode(location = Location())
      ForwardingParameterNode.new(location)
    end

    # Create a new ForwardingSuperNode node
    def ForwardingSuperNode(block, location = Location())
      ForwardingSuperNode.new(block, location)
    end

    # Create a new GlobalVariableOperatorAndWriteNode node
    def GlobalVariableOperatorAndWriteNode(name_loc, operator_loc, value, location = Location())
      GlobalVariableOperatorAndWriteNode.new(name_loc, operator_loc, value, location)
    end

    # Create a new GlobalVariableOperatorOrWriteNode node
    def GlobalVariableOperatorOrWriteNode(name_loc, operator_loc, value, location = Location())
      GlobalVariableOperatorOrWriteNode.new(name_loc, operator_loc, value, location)
    end

    # Create a new GlobalVariableOperatorWriteNode node
    def GlobalVariableOperatorWriteNode(name_loc, operator_loc, value, operator, location = Location())
      GlobalVariableOperatorWriteNode.new(name_loc, operator_loc, value, operator, location)
    end

    # Create a new GlobalVariableReadNode node
    def GlobalVariableReadNode(location = Location())
      GlobalVariableReadNode.new(location)
    end

    # Create a new GlobalVariableWriteNode node
    def GlobalVariableWriteNode(name_loc, operator_loc, value, location = Location())
      GlobalVariableWriteNode.new(name_loc, operator_loc, value, location)
    end

    # Create a new HashNode node
    def HashNode(opening_loc, elements, closing_loc, location = Location())
      HashNode.new(opening_loc, elements, closing_loc, location)
    end

    # Create a new HashPatternNode node
    def HashPatternNode(constant, assocs, kwrest, opening_loc, closing_loc, location = Location())
      HashPatternNode.new(constant, assocs, kwrest, opening_loc, closing_loc, location)
    end

    # Create a new IfNode node
    def IfNode(if_keyword_loc, predicate, statements, consequent, end_keyword_loc, location = Location())
      IfNode.new(if_keyword_loc, predicate, statements, consequent, end_keyword_loc, location)
    end

    # Create a new ImaginaryNode node
    def ImaginaryNode(numeric, location = Location())
      ImaginaryNode.new(numeric, location)
    end

    # Create a new InNode node
    def InNode(pattern, statements, in_loc, then_loc, location = Location())
      InNode.new(pattern, statements, in_loc, then_loc, location)
    end

    # Create a new InstanceVariableOperatorAndWriteNode node
    def InstanceVariableOperatorAndWriteNode(name_loc, operator_loc, value, location = Location())
      InstanceVariableOperatorAndWriteNode.new(name_loc, operator_loc, value, location)
    end

    # Create a new InstanceVariableOperatorOrWriteNode node
    def InstanceVariableOperatorOrWriteNode(name_loc, operator_loc, value, location = Location())
      InstanceVariableOperatorOrWriteNode.new(name_loc, operator_loc, value, location)
    end

    # Create a new InstanceVariableOperatorWriteNode node
    def InstanceVariableOperatorWriteNode(name_loc, operator_loc, value, operator, location = Location())
      InstanceVariableOperatorWriteNode.new(name_loc, operator_loc, value, operator, location)
    end

    # Create a new InstanceVariableReadNode node
    def InstanceVariableReadNode(location = Location())
      InstanceVariableReadNode.new(location)
    end

    # Create a new InstanceVariableWriteNode node
    def InstanceVariableWriteNode(name_loc, value, operator_loc, location = Location())
      InstanceVariableWriteNode.new(name_loc, value, operator_loc, location)
    end

    # Create a new IntegerNode node
    def IntegerNode(location = Location())
      IntegerNode.new(location)
    end

    # Create a new InterpolatedRegularExpressionNode node
    def InterpolatedRegularExpressionNode(opening_loc, parts, closing_loc, flags, location = Location())
      InterpolatedRegularExpressionNode.new(opening_loc, parts, closing_loc, flags, location)
    end

    # Create a new InterpolatedStringNode node
    def InterpolatedStringNode(opening_loc, parts, closing_loc, location = Location())
      InterpolatedStringNode.new(opening_loc, parts, closing_loc, location)
    end

    # Create a new InterpolatedSymbolNode node
    def InterpolatedSymbolNode(opening_loc, parts, closing_loc, location = Location())
      InterpolatedSymbolNode.new(opening_loc, parts, closing_loc, location)
    end

    # Create a new InterpolatedXStringNode node
    def InterpolatedXStringNode(opening_loc, parts, closing_loc, location = Location())
      InterpolatedXStringNode.new(opening_loc, parts, closing_loc, location)
    end

    # Create a new KeywordHashNode node
    def KeywordHashNode(elements, location = Location())
      KeywordHashNode.new(elements, location)
    end

    # Create a new KeywordParameterNode node
    def KeywordParameterNode(name_loc, value, location = Location())
      KeywordParameterNode.new(name_loc, value, location)
    end

    # Create a new KeywordRestParameterNode node
    def KeywordRestParameterNode(operator_loc, name_loc, location = Location())
      KeywordRestParameterNode.new(operator_loc, name_loc, location)
    end

    # Create a new LambdaNode node
    def LambdaNode(locals, opening_loc, parameters, statements, location = Location())
      LambdaNode.new(locals, opening_loc, parameters, statements, location)
    end

    # Create a new LocalVariableOperatorAndWriteNode node
    def LocalVariableOperatorAndWriteNode(name_loc, operator_loc, value, constant_id, location = Location())
      LocalVariableOperatorAndWriteNode.new(name_loc, operator_loc, value, constant_id, location)
    end

    # Create a new LocalVariableOperatorOrWriteNode node
    def LocalVariableOperatorOrWriteNode(name_loc, operator_loc, value, constant_id, location = Location())
      LocalVariableOperatorOrWriteNode.new(name_loc, operator_loc, value, constant_id, location)
    end

    # Create a new LocalVariableOperatorWriteNode node
    def LocalVariableOperatorWriteNode(name_loc, operator_loc, value, constant_id, operator_id, location = Location())
      LocalVariableOperatorWriteNode.new(name_loc, operator_loc, value, constant_id, operator_id, location)
    end

    # Create a new LocalVariableReadNode node
    def LocalVariableReadNode(constant_id, depth, location = Location())
      LocalVariableReadNode.new(constant_id, depth, location)
    end

    # Create a new LocalVariableWriteNode node
    def LocalVariableWriteNode(constant_id, depth, value, name_loc, operator_loc, location = Location())
      LocalVariableWriteNode.new(constant_id, depth, value, name_loc, operator_loc, location)
    end

    # Create a new MatchPredicateNode node
    def MatchPredicateNode(value, pattern, operator_loc, location = Location())
      MatchPredicateNode.new(value, pattern, operator_loc, location)
    end

    # Create a new MatchRequiredNode node
    def MatchRequiredNode(value, pattern, operator_loc, location = Location())
      MatchRequiredNode.new(value, pattern, operator_loc, location)
    end

    # Create a new MissingNode node
    def MissingNode(location = Location())
      MissingNode.new(location)
    end

    # Create a new ModuleNode node
    def ModuleNode(locals, module_keyword_loc, constant_path, statements, end_keyword_loc, location = Location())
      ModuleNode.new(locals, module_keyword_loc, constant_path, statements, end_keyword_loc, location)
    end

    # Create a new MultiWriteNode node
    def MultiWriteNode(targets, operator_loc, value, lparen_loc, rparen_loc, location = Location())
      MultiWriteNode.new(targets, operator_loc, value, lparen_loc, rparen_loc, location)
    end

    # Create a new NextNode node
    def NextNode(arguments, keyword_loc, location = Location())
      NextNode.new(arguments, keyword_loc, location)
    end

    # Create a new NilNode node
    def NilNode(location = Location())
      NilNode.new(location)
    end

    # Create a new NoKeywordsParameterNode node
    def NoKeywordsParameterNode(operator_loc, keyword_loc, location = Location())
      NoKeywordsParameterNode.new(operator_loc, keyword_loc, location)
    end

    # Create a new NumberedReferenceReadNode node
    def NumberedReferenceReadNode(location = Location())
      NumberedReferenceReadNode.new(location)
    end

    # Create a new OptionalParameterNode node
    def OptionalParameterNode(constant_id, name_loc, operator_loc, value, location = Location())
      OptionalParameterNode.new(constant_id, name_loc, operator_loc, value, location)
    end

    # Create a new OrNode node
    def OrNode(left, right, operator_loc, location = Location())
      OrNode.new(left, right, operator_loc, location)
    end

    # Create a new ParametersNode node
    def ParametersNode(requireds, optionals, posts, rest, keywords, keyword_rest, block, location = Location())
      ParametersNode.new(requireds, optionals, posts, rest, keywords, keyword_rest, block, location)
    end

    # Create a new ParenthesesNode node
    def ParenthesesNode(statements, opening_loc, closing_loc, location = Location())
      ParenthesesNode.new(statements, opening_loc, closing_loc, location)
    end

    # Create a new PinnedExpressionNode node
    def PinnedExpressionNode(expression, operator_loc, lparen_loc, rparen_loc, location = Location())
      PinnedExpressionNode.new(expression, operator_loc, lparen_loc, rparen_loc, location)
    end

    # Create a new PinnedVariableNode node
    def PinnedVariableNode(variable, operator_loc, location = Location())
      PinnedVariableNode.new(variable, operator_loc, location)
    end

    # Create a new PostExecutionNode node
    def PostExecutionNode(statements, keyword_loc, opening_loc, closing_loc, location = Location())
      PostExecutionNode.new(statements, keyword_loc, opening_loc, closing_loc, location)
    end

    # Create a new PreExecutionNode node
    def PreExecutionNode(statements, keyword_loc, opening_loc, closing_loc, location = Location())
      PreExecutionNode.new(statements, keyword_loc, opening_loc, closing_loc, location)
    end

    # Create a new ProgramNode node
    def ProgramNode(locals, statements, location = Location())
      ProgramNode.new(locals, statements, location)
    end

    # Create a new RangeNode node
    def RangeNode(left, right, operator_loc, flags, location = Location())
      RangeNode.new(left, right, operator_loc, flags, location)
    end

    # Create a new RationalNode node
    def RationalNode(numeric, location = Location())
      RationalNode.new(numeric, location)
    end

    # Create a new RedoNode node
    def RedoNode(location = Location())
      RedoNode.new(location)
    end

    # Create a new RegularExpressionNode node
    def RegularExpressionNode(opening_loc, content_loc, closing_loc, unescaped, flags, location = Location())
      RegularExpressionNode.new(opening_loc, content_loc, closing_loc, unescaped, flags, location)
    end

    # Create a new RequiredDestructuredParameterNode node
    def RequiredDestructuredParameterNode(parameters, opening_loc, closing_loc, location = Location())
      RequiredDestructuredParameterNode.new(parameters, opening_loc, closing_loc, location)
    end

    # Create a new RequiredParameterNode node
    def RequiredParameterNode(constant_id, location = Location())
      RequiredParameterNode.new(constant_id, location)
    end

    # Create a new RescueModifierNode node
    def RescueModifierNode(expression, keyword_loc, rescue_expression, location = Location())
      RescueModifierNode.new(expression, keyword_loc, rescue_expression, location)
    end

    # Create a new RescueNode node
    def RescueNode(keyword_loc, exceptions, operator_loc, reference, statements, consequent, location = Location())
      RescueNode.new(keyword_loc, exceptions, operator_loc, reference, statements, consequent, location)
    end

    # Create a new RestParameterNode node
    def RestParameterNode(operator_loc, name_loc, location = Location())
      RestParameterNode.new(operator_loc, name_loc, location)
    end

    # Create a new RetryNode node
    def RetryNode(location = Location())
      RetryNode.new(location)
    end

    # Create a new ReturnNode node
    def ReturnNode(keyword_loc, arguments, location = Location())
      ReturnNode.new(keyword_loc, arguments, location)
    end

    # Create a new SelfNode node
    def SelfNode(location = Location())
      SelfNode.new(location)
    end

    # Create a new SingletonClassNode node
    def SingletonClassNode(locals, class_keyword_loc, operator_loc, expression, statements, end_keyword_loc, location = Location())
      SingletonClassNode.new(locals, class_keyword_loc, operator_loc, expression, statements, end_keyword_loc, location)
    end

    # Create a new SourceEncodingNode node
    def SourceEncodingNode(location = Location())
      SourceEncodingNode.new(location)
    end

    # Create a new SourceFileNode node
    def SourceFileNode(filepath, location = Location())
      SourceFileNode.new(filepath, location)
    end

    # Create a new SourceLineNode node
    def SourceLineNode(location = Location())
      SourceLineNode.new(location)
    end

    # Create a new SplatNode node
    def SplatNode(operator_loc, expression, location = Location())
      SplatNode.new(operator_loc, expression, location)
    end

    # Create a new StatementsNode node
    def StatementsNode(body, location = Location())
      StatementsNode.new(body, location)
    end

    # Create a new StringConcatNode node
    def StringConcatNode(left, right, location = Location())
      StringConcatNode.new(left, right, location)
    end

    # Create a new StringNode node
    def StringNode(opening_loc, content_loc, closing_loc, unescaped, location = Location())
      StringNode.new(opening_loc, content_loc, closing_loc, unescaped, location)
    end

    # Create a new SuperNode node
    def SuperNode(keyword_loc, lparen_loc, arguments, rparen_loc, block, location = Location())
      SuperNode.new(keyword_loc, lparen_loc, arguments, rparen_loc, block, location)
    end

    # Create a new SymbolNode node
    def SymbolNode(opening_loc, value_loc, closing_loc, unescaped, location = Location())
      SymbolNode.new(opening_loc, value_loc, closing_loc, unescaped, location)
    end

    # Create a new TrueNode node
    def TrueNode(location = Location())
      TrueNode.new(location)
    end

    # Create a new UndefNode node
    def UndefNode(names, keyword_loc, location = Location())
      UndefNode.new(names, keyword_loc, location)
    end

    # Create a new UnlessNode node
    def UnlessNode(keyword_loc, predicate, statements, consequent, end_keyword_loc, location = Location())
      UnlessNode.new(keyword_loc, predicate, statements, consequent, end_keyword_loc, location)
    end

    # Create a new UntilNode node
    def UntilNode(keyword_loc, predicate, statements, flags, location = Location())
      UntilNode.new(keyword_loc, predicate, statements, flags, location)
    end

    # Create a new WhenNode node
    def WhenNode(keyword_loc, conditions, statements, location = Location())
      WhenNode.new(keyword_loc, conditions, statements, location)
    end

    # Create a new WhileNode node
    def WhileNode(keyword_loc, predicate, statements, flags, location = Location())
      WhileNode.new(keyword_loc, predicate, statements, flags, location)
    end

    # Create a new XStringNode node
    def XStringNode(opening_loc, content_loc, closing_loc, unescaped, location = Location())
      XStringNode.new(opening_loc, content_loc, closing_loc, unescaped, location)
    end

    # Create a new YieldNode node
    def YieldNode(keyword_loc, lparen_loc, arguments, rparen_loc, location = Location())
      YieldNode.new(keyword_loc, lparen_loc, arguments, rparen_loc, location)
    end
  end
end
