class SyntaxTree::Statements

Everything that has a block of code inside of it has a list of statements. Normally we would just track those as a node that has an array body, but we have some special handling in order to handle empty statement lists. They need to have the right location information, so all of the parent node of stmts nodes will report back down the location information. We then propagate that onto void_stmt nodes inside the stmts in order to make sure all comments get printed appropriately.

Attributes

body[R]
Array[ Node ]

the list of expressions contained within this node

comments[R]
Array[ Comment | EmbDoc ]

the comments attached to this node

Public Class Methods

new(body:, location:) click to toggle source
# File lib/syntax_tree/node.rb, line 9874
def initialize(body:, location:)
  @body = body
  @location = location
  @comments = []
end

Public Instance Methods

===(other) click to toggle source
# File lib/syntax_tree/node.rb, line 10000
def ===(other)
  other.is_a?(Statements) && ArrayMatch.call(body, other.body)
end
accept(visitor) click to toggle source
# File lib/syntax_tree/node.rb, line 9927
def accept(visitor)
  visitor.visit_statements(self)
end
bind(parser, start_char, start_column, end_char, end_column) click to toggle source
# File lib/syntax_tree/node.rb, line 9880
def bind(parser, start_char, start_column, end_char, end_column)
  @location =
    Location.new(
      start_line: location.start_line,
      start_char: start_char,
      start_column: start_column,
      end_line: location.end_line,
      end_char: end_char,
      end_column: end_column
    )

  if (void_stmt = body[0]).is_a?(VoidStmt)
    location = void_stmt.location
    location =
      Location.new(
        start_line: location.start_line,
        start_char: start_char,
        start_column: start_column,
        end_line: location.end_line,
        end_char: start_char,
        end_column: end_column
      )

    body[0] = VoidStmt.new(location: location)
  end

  attach_comments(parser, start_char, end_char)
end
bind_end(end_char, end_column) click to toggle source
# File lib/syntax_tree/node.rb, line 9909
def bind_end(end_char, end_column)
  @location =
    Location.new(
      start_line: location.start_line,
      start_char: location.start_char,
      start_column: location.start_column,
      end_line: location.end_line,
      end_char: end_char,
      end_column: end_column
    )
end
child_nodes() click to toggle source
# File lib/syntax_tree/node.rb, line 9931
def child_nodes
  body
end
Also aliased as: deconstruct
copy(body: nil, location: nil) click to toggle source
# File lib/syntax_tree/node.rb, line 9935
def copy(body: nil, location: nil)
  node =
    Statements.new(
      body: body || self.body,
      location: location || self.location
    )

  node.comments.concat(comments.map(&:copy))
  node
end
deconstruct()
Alias for: child_nodes
deconstruct_keys(_keys) click to toggle source
# File lib/syntax_tree/node.rb, line 9948
def deconstruct_keys(_keys)
  { body: body, location: location, comments: comments }
end
empty?() click to toggle source
# File lib/syntax_tree/node.rb, line 9921
def empty?
  body.all? do |statement|
    statement.is_a?(VoidStmt) && statement.comments.empty?
  end
end
format(q) click to toggle source
# File lib/syntax_tree/node.rb, line 9952
def format(q)
  line = nil

  # This handles a special case where you've got a block of statements where
  # the only value is a comment. In that case a lot of nodes like
  # brace_block will attempt to format as a single line, but since that
  # wouldn't work with a comment, we intentionally break the parent group.
  if body.length == 2
    void_stmt, comment = body

    if void_stmt.is_a?(VoidStmt) && comment.is_a?(Comment)
      q.format(comment)
      q.break_parent
      return
    end
  end

  previous = nil
  body.each do |statement|
    next if statement.is_a?(VoidStmt)

    if line.nil?
      q.format(statement)
    elsif (statement.location.start_line - line) > 1
      q.breakable_force
      q.breakable_force
      q.format(statement)
    elsif (statement.is_a?(VCall) && statement.access_control?) ||
          (previous.is_a?(VCall) && previous.access_control?)
      q.breakable_force
      q.breakable_force
      q.format(statement)
    elsif statement.location.start_line != line
      q.breakable_force
      q.format(statement)
    elsif !q.parent.is_a?(StringEmbExpr)
      q.breakable_force
      q.format(statement)
    else
      q.text("; ")
      q.format(statement)
    end

    line = statement.location.end_line
    previous = statement
  end
end