Class: SyntaxTree::Statements

Inherits:
Object
  • Object
show all
Defined in:
lib/syntax_tree.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

Instance Method Summary collapse

Constructor Details

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

Returns a new instance of Statements.



10970
10971
10972
10973
10974
10975
# File 'lib/syntax_tree.rb', line 10970

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



10962
10963
10964
# File 'lib/syntax_tree.rb', line 10962

def body
  @body
end

#commentsObject (readonly)

Array[ Comment | EmbDoc ]

the comments attached to this node



10968
10969
10970
# File 'lib/syntax_tree.rb', line 10968

def comments
  @comments
end

#locationObject (readonly)

Location

the location of this node



10965
10966
10967
# File 'lib/syntax_tree.rb', line 10965

def location
  @location
end

#parserObject (readonly)

SyntaxTree

the parser that is generating this node



10959
10960
10961
# File 'lib/syntax_tree.rb', line 10959

def parser
  @parser
end

Instance Method Details

#bind(start_char, end_char) ⇒ Object



10977
10978
10979
10980
10981
10982
10983
10984
10985
10986
10987
10988
10989
10990
10991
10992
10993
10994
10995
10996
10997
10998
10999
11000
# File 'lib/syntax_tree.rb', line 10977

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



11002
11003
11004
11005
11006
11007
11008
11009
11010
# File 'lib/syntax_tree.rb', line 11002

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



11018
11019
11020
# File 'lib/syntax_tree.rb', line 11018

def child_nodes
  body
end

#empty?Boolean

Returns:

  • (Boolean)


11012
11013
11014
11015
11016
# File 'lib/syntax_tree.rb', line 11012

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

#format(q) ⇒ Object



11022
11023
11024
11025
11026
11027
11028
11029
11030
11031
11032
11033
11034
11035
11036
11037
11038
11039
11040
11041
11042
11043
11044
11045
11046
11047
11048
11049
11050
11051
11052
11053
11054
11055
11056
11057
11058
11059
11060
11061
11062
11063
11064
11065
11066
11067
11068
11069
11070
11071
# File 'lib/syntax_tree.rb', line 11022

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



11073
11074
11075
11076
11077
11078
11079
11080
11081
11082
# File 'lib/syntax_tree.rb', line 11073

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



11084
11085
11086
11087
11088
# File 'lib/syntax_tree.rb', line 11084

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