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.



9764
9765
9766
9767
9768
9769
# File 'lib/syntax_tree/node.rb', line 9764

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



9759
9760
9761
# File 'lib/syntax_tree/node.rb', line 9759

def body
  @body
end

#commentsObject (readonly)

Array[ Comment | EmbDoc ]

the comments attached to this node



9762
9763
9764
# File 'lib/syntax_tree/node.rb', line 9762

def comments
  @comments
end

#parserObject (readonly)

SyntaxTree

the parser that is generating this node



9756
9757
9758
# File 'lib/syntax_tree/node.rb', line 9756

def parser
  @parser
end

Instance Method Details

#===(other) ⇒ Object



9892
9893
9894
# File 'lib/syntax_tree/node.rb', line 9892

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

#accept(visitor) ⇒ Object



9818
9819
9820
# File 'lib/syntax_tree/node.rb', line 9818

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

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



9771
9772
9773
9774
9775
9776
9777
9778
9779
9780
9781
9782
9783
9784
9785
9786
9787
9788
9789
9790
9791
9792
9793
9794
9795
9796
9797
9798
# File 'lib/syntax_tree/node.rb', line 9771

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



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

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



9822
9823
9824
# File 'lib/syntax_tree/node.rb', line 9822

def child_nodes
  body
end

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



9826
9827
9828
9829
9830
9831
9832
9833
9834
9835
9836
# File 'lib/syntax_tree/node.rb', line 9826

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



9840
9841
9842
# File 'lib/syntax_tree/node.rb', line 9840

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

#empty?Boolean

Returns:

  • (Boolean)


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

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

#format(q) ⇒ Object



9844
9845
9846
9847
9848
9849
9850
9851
9852
9853
9854
9855
9856
9857
9858
9859
9860
9861
9862
9863
9864
9865
9866
9867
9868
9869
9870
9871
9872
9873
9874
9875
9876
9877
9878
9879
9880
9881
9882
9883
9884
9885
9886
9887
9888
9889
9890
# File 'lib/syntax_tree/node.rb', line 9844

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