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

#pretty_print, #to_json

Constructor Details

#initialize(parser, body:, location:, comments: []) ⇒ Statements

Returns a new instance of Statements.



7819
7820
7821
7822
7823
7824
# File 'lib/syntax_tree/node.rb', line 7819

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

Instance Attribute Details

#bodyObject (readonly)

Array[ untyped ]

the list of expressions contained within this node



7814
7815
7816
# File 'lib/syntax_tree/node.rb', line 7814

def body
  @body
end

#commentsObject (readonly)

Array[ Comment | EmbDoc ]

the comments attached to this node



7817
7818
7819
# File 'lib/syntax_tree/node.rb', line 7817

def comments
  @comments
end

#parserObject (readonly)

SyntaxTree

the parser that is generating this node



7811
7812
7813
# File 'lib/syntax_tree/node.rb', line 7811

def parser
  @parser
end

Instance Method Details

#accept(visitor) ⇒ Object



7873
7874
7875
# File 'lib/syntax_tree/node.rb', line 7873

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

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



7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
# File 'lib/syntax_tree/node.rb', line 7826

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



7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
# File 'lib/syntax_tree/node.rb', line 7855

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



7877
7878
7879
# File 'lib/syntax_tree/node.rb', line 7877

def child_nodes
  body
end

#deconstruct_keys(keys) ⇒ Object



7883
7884
7885
# File 'lib/syntax_tree/node.rb', line 7883

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

#empty?Boolean

Returns:

  • (Boolean)


7867
7868
7869
7870
7871
# File 'lib/syntax_tree/node.rb', line 7867

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

#format(q) ⇒ Object



7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
# File 'lib/syntax_tree/node.rb', line 7887

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

  access_controls =
    Hash.new do |hash, node|
      hash[node] = node.is_a?(VCall) &&
        %w[private protected public].include?(node.value.value)
    end

  body.each_with_index do |statement, index|
    next if statement.is_a?(VoidStmt)

    if line.nil?
      q.format(statement)
    elsif (statement.location.start_line - line) > 1
      q.breakable(force: true)
      q.breakable(force: true)
      q.format(statement)
    elsif access_controls[statement] || access_controls[body[index - 1]]
      q.breakable(force: true)
      q.breakable(force: true)
      q.format(statement)
    elsif statement.location.start_line != line
      q.breakable(force: true)
      q.format(statement)
    elsif !q.parent.is_a?(StringEmbExpr)
      q.breakable(force: true)
      q.format(statement)
    else
      q.text("; ")
      q.format(statement)
    end

    line = statement.location.end_line
  end
end