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:, comments: []) ⇒ Statements

Returns a new instance of Statements.



8030
8031
8032
8033
8034
8035
# File 'lib/syntax_tree/node.rb', line 8030

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

Instance Attribute Details

#body ⇒ Object (readonly)

[Array[ untyped ]] the list of expressions contained within this node



8025
8026
8027
# File 'lib/syntax_tree/node.rb', line 8025

def body
  @body
end

#comments ⇒ Object (readonly)

[Array[ Comment | EmbDoc ]] the comments attached to this node



8028
8029
8030
# File 'lib/syntax_tree/node.rb', line 8028

def comments
  @comments
end

#parser ⇒ Object (readonly)

[SyntaxTree] the parser that is generating this node



8022
8023
8024
# File 'lib/syntax_tree/node.rb', line 8022

def parser
  @parser
end

Instance Method Details

#accept(visitor) ⇒ Object



8084
8085
8086
# File 'lib/syntax_tree/node.rb', line 8084

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

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



8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
# File 'lib/syntax_tree/node.rb', line 8037

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



8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
# File 'lib/syntax_tree/node.rb', line 8066

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



8088
8089
8090
# File 'lib/syntax_tree/node.rb', line 8088

def child_nodes
  body
end

#deconstruct_keys(_keys) ⇒ Object



8094
8095
8096
# File 'lib/syntax_tree/node.rb', line 8094

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

#empty? ⇒ Boolean

Returns:

  • (Boolean)


8078
8079
8080
8081
8082
# File 'lib/syntax_tree/node.rb', line 8078

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

#format(q) ⇒ Object



8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
# File 'lib/syntax_tree/node.rb', line 8098

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