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

Constructor Details

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

Returns a new instance of Statements.



9012
9013
9014
9015
9016
9017
# File 'lib/syntax_tree/node.rb', line 9012

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



9007
9008
9009
# File 'lib/syntax_tree/node.rb', line 9007

def body
  @body
end

#commentsObject (readonly)

Array[ Comment | EmbDoc ]

the comments attached to this node



9010
9011
9012
# File 'lib/syntax_tree/node.rb', line 9010

def comments
  @comments
end

#parserObject (readonly)

SyntaxTree

the parser that is generating this node



9004
9005
9006
# File 'lib/syntax_tree/node.rb', line 9004

def parser
  @parser
end

Instance Method Details

#bind(start_char, end_char) ⇒ Object



9019
9020
9021
9022
9023
9024
9025
9026
9027
9028
9029
9030
9031
9032
9033
9034
9035
9036
9037
9038
9039
9040
9041
9042
# File 'lib/syntax_tree/node.rb', line 9019

def bind(start_char, end_char)
  @location =
    Location.new(
      start_line: location.start_line,
      start_char: start_char,
      end_line: location.end_line,
      end_char: end_char
    )

  if body[0].is_a?(VoidStmt)
    location = body[0].location
    location =
      Location.new(
        start_line: location.start_line,
        start_char: start_char,
        end_line: location.end_line,
        end_char: start_char
      )

    body[0] = VoidStmt.new(location: location)
  end

  attach_comments(start_char, end_char)
end

#bind_end(end_char) ⇒ Object



9044
9045
9046
9047
9048
9049
9050
9051
9052
# File 'lib/syntax_tree/node.rb', line 9044

def bind_end(end_char)
  @location =
    Location.new(
      start_line: location.start_line,
      start_char: location.start_char,
      end_line: location.end_line,
      end_char: end_char
    )
end

#child_nodesObject Also known as: deconstruct



9060
9061
9062
# File 'lib/syntax_tree/node.rb', line 9060

def child_nodes
  body
end

#deconstruct_keys(keys) ⇒ Object



9066
9067
9068
# File 'lib/syntax_tree/node.rb', line 9066

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

#empty?Boolean

Returns:

  • (Boolean)


9054
9055
9056
9057
9058
# File 'lib/syntax_tree/node.rb', line 9054

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

#format(q) ⇒ Object



9070
9071
9072
9073
9074
9075
9076
9077
9078
9079
9080
9081
9082
9083
9084
9085
9086
9087
9088
9089
9090
9091
9092
9093
9094
9095
9096
9097
9098
9099
9100
9101
9102
9103
9104
9105
9106
9107
9108
9109
9110
9111
9112
9113
9114
9115
9116
9117
9118
9119
# File 'lib/syntax_tree/node.rb', line 9070

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

#pretty_print(q) ⇒ Object



9121
9122
9123
9124
9125
9126
9127
9128
9129
9130
# File 'lib/syntax_tree/node.rb', line 9121

def pretty_print(q)
  q.group(2, "(", ")") do
    q.text("statements")

    q.breakable
    q.seplist(body) { |statement| q.pp(statement) }

    q.pp(Comment::List.new(comments))
  end
end

#to_json(*opts) ⇒ Object



9132
9133
9134
9135
9136
# File 'lib/syntax_tree/node.rb', line 9132

def to_json(*opts)
  { type: :statements, body: body, loc: location, cmts: comments }.to_json(
    *opts
  )
end