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.



10762
10763
10764
10765
10766
10767
# File 'lib/syntax_tree.rb', line 10762

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



10754
10755
10756
# File 'lib/syntax_tree.rb', line 10754

def body
  @body
end

#commentsObject (readonly)

Array[ Comment | EmbDoc ]

the comments attached to this node



10760
10761
10762
# File 'lib/syntax_tree.rb', line 10760

def comments
  @comments
end

#locationObject (readonly)

Location

the location of this node



10757
10758
10759
# File 'lib/syntax_tree.rb', line 10757

def location
  @location
end

#parserObject (readonly)

SyntaxTree

the parser that is generating this node



10751
10752
10753
# File 'lib/syntax_tree.rb', line 10751

def parser
  @parser
end

Instance Method Details

#bind(start_char, end_char) ⇒ Object



10769
10770
10771
10772
10773
10774
10775
10776
10777
10778
10779
10780
10781
10782
10783
10784
10785
10786
10787
10788
10789
10790
10791
10792
# File 'lib/syntax_tree.rb', line 10769

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



10794
10795
10796
10797
10798
10799
10800
10801
10802
# File 'lib/syntax_tree.rb', line 10794

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



10810
10811
10812
# File 'lib/syntax_tree.rb', line 10810

def child_nodes
  body
end

#empty?Boolean

Returns:

  • (Boolean)


10804
10805
10806
10807
10808
# File 'lib/syntax_tree.rb', line 10804

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

#format(q) ⇒ Object



10814
10815
10816
10817
10818
10819
10820
10821
10822
10823
10824
10825
10826
10827
10828
10829
10830
10831
10832
10833
10834
10835
10836
10837
10838
10839
10840
10841
10842
10843
10844
10845
10846
10847
10848
10849
10850
10851
10852
10853
10854
10855
10856
10857
10858
10859
10860
10861
10862
10863
# File 'lib/syntax_tree.rb', line 10814

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



10865
10866
10867
10868
10869
10870
10871
10872
10873
10874
# File 'lib/syntax_tree.rb', line 10865

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



10876
10877
10878
10879
10880
# File 'lib/syntax_tree.rb', line 10876

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