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.



9738
9739
9740
9741
9742
9743
# File 'lib/syntax_tree/node.rb', line 9738

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



9733
9734
9735
# File 'lib/syntax_tree/node.rb', line 9733

def body
  @body
end

#commentsObject (readonly)

Array[ Comment | EmbDoc ]

the comments attached to this node



9736
9737
9738
# File 'lib/syntax_tree/node.rb', line 9736

def comments
  @comments
end

#parserObject (readonly)

SyntaxTree

the parser that is generating this node



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

def parser
  @parser
end

Instance Method Details

#===(other) ⇒ Object



9866
9867
9868
# File 'lib/syntax_tree/node.rb', line 9866

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

#accept(visitor) ⇒ Object



9792
9793
9794
# File 'lib/syntax_tree/node.rb', line 9792

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

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



9745
9746
9747
9748
9749
9750
9751
9752
9753
9754
9755
9756
9757
9758
9759
9760
9761
9762
9763
9764
9765
9766
9767
9768
9769
9770
9771
9772
# File 'lib/syntax_tree/node.rb', line 9745

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



9774
9775
9776
9777
9778
9779
9780
9781
9782
9783
9784
# File 'lib/syntax_tree/node.rb', line 9774

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



9796
9797
9798
# File 'lib/syntax_tree/node.rb', line 9796

def child_nodes
  body
end

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



9800
9801
9802
9803
9804
9805
9806
9807
9808
9809
9810
# File 'lib/syntax_tree/node.rb', line 9800

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



9814
9815
9816
# File 'lib/syntax_tree/node.rb', line 9814

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

#empty?Boolean

Returns:

  • (Boolean)


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

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

#format(q) ⇒ Object



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
9856
9857
9858
9859
9860
9861
9862
9863
9864
# File 'lib/syntax_tree/node.rb', line 9818

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