Class: SyntaxTree::Statements

Inherits:
Node
  • Object
show all
Defined in:
lib/syntax_tree/node.rb

Overview

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.

Instance Attribute Summary collapse

Attributes inherited from Node

#location

Instance Method Summary collapse

Methods inherited from Node

#construct_keys, #pretty_print, #to_json

Constructor Details

#initialize(parser, body:, location:) ⇒ Statements

Returns a new instance of Statements.



9729
9730
9731
9732
9733
9734
# File 'lib/syntax_tree/node.rb', line 9729

def initialize(parser, body:, location:)
  @parser = parser
  @body = body
  @location = location
  @comments = []
end

Instance Attribute Details

#bodyObject (readonly)

Array[ untyped ]

the list of expressions contained within this node



9724
9725
9726
# File 'lib/syntax_tree/node.rb', line 9724

def body
  @body
end

#commentsObject (readonly)

Array[ Comment | EmbDoc ]

the comments attached to this node



9727
9728
9729
# File 'lib/syntax_tree/node.rb', line 9727

def comments
  @comments
end

#parserObject (readonly)

SyntaxTree

the parser that is generating this node



9721
9722
9723
# File 'lib/syntax_tree/node.rb', line 9721

def parser
  @parser
end

Instance Method Details

#===(other) ⇒ Object



9857
9858
9859
# File 'lib/syntax_tree/node.rb', line 9857

def ===(other)
  other.is_a?(Statements) && ArrayMatch.call(body, other.body)
end

#accept(visitor) ⇒ Object



9783
9784
9785
# File 'lib/syntax_tree/node.rb', line 9783

def accept(visitor)
  visitor.visit_statements(self)
end

#bind(start_char, start_column, end_char, end_column) ⇒ Object



9736
9737
9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
9748
9749
9750
9751
9752
9753
9754
9755
9756
9757
9758
9759
9760
9761
9762
9763
# File 'lib/syntax_tree/node.rb', line 9736

def bind(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 body[0].is_a?(VoidStmt)
    location = body[0].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(start_char, end_char)
end

#bind_end(end_char, end_column) ⇒ Object



9765
9766
9767
9768
9769
9770
9771
9772
9773
9774
9775
# File 'lib/syntax_tree/node.rb', line 9765

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_nodesObject Also known as: deconstruct



9787
9788
9789
# File 'lib/syntax_tree/node.rb', line 9787

def child_nodes
  body
end

#copy(body: nil, location: nil) ⇒ Object



9791
9792
9793
9794
9795
9796
9797
9798
9799
9800
9801
# File 'lib/syntax_tree/node.rb', line 9791

def copy(body: nil, location: nil)
  node =
    Statements.new(
      parser,
      body: body || self.body,
      location: location || self.location
    )

  node.comments.concat(comments.map(&:copy))
  node
end

#deconstruct_keys(_keys) ⇒ Object



9805
9806
9807
# File 'lib/syntax_tree/node.rb', line 9805

def deconstruct_keys(_keys)
  { parser: parser, body: body, location: location, comments: comments }
end

#empty?Boolean

Returns:

  • (Boolean)


9777
9778
9779
9780
9781
# File 'lib/syntax_tree/node.rb', line 9777

def empty?
  body.all? do |statement|
    statement.is_a?(VoidStmt) && statement.comments.empty?
  end
end

#format(q) ⇒ Object



9809
9810
9811
9812
9813
9814
9815
9816
9817
9818
9819
9820
9821
9822
9823
9824
9825
9826
9827
9828
9829
9830
9831
9832
9833
9834
9835
9836
9837
9838
9839
9840
9841
9842
9843
9844
9845
9846
9847
9848
9849
9850
9851
9852
9853
9854
9855
# File 'lib/syntax_tree/node.rb', line 9809

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