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.



8080
8081
8082
8083
8084
8085
# File 'lib/syntax_tree/node.rb', line 8080

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



8075
8076
8077
# File 'lib/syntax_tree/node.rb', line 8075

def body
  @body
end

#commentsObject (readonly)

Array[ Comment | EmbDoc ]

the comments attached to this node



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

def comments
  @comments
end

#parserObject (readonly)

SyntaxTree

the parser that is generating this node



8072
8073
8074
# File 'lib/syntax_tree/node.rb', line 8072

def parser
  @parser
end

Instance Method Details

#accept(visitor) ⇒ Object



8134
8135
8136
# File 'lib/syntax_tree/node.rb', line 8134

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

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



8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
# File 'lib/syntax_tree/node.rb', line 8087

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



8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
# File 'lib/syntax_tree/node.rb', line 8116

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



8138
8139
8140
# File 'lib/syntax_tree/node.rb', line 8138

def child_nodes
  body
end

#deconstruct_keys(_keys) ⇒ Object



8144
8145
8146
# File 'lib/syntax_tree/node.rb', line 8144

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

#empty?Boolean

Returns:

  • (Boolean)


8128
8129
8130
8131
8132
# File 'lib/syntax_tree/node.rb', line 8128

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

#format(q) ⇒ Object



8148
8149
8150
8151
8152
8153
8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166
8167
8168
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193
8194
8195
8196
8197
# File 'lib/syntax_tree/node.rb', line 8148

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