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.



7919
7920
7921
7922
7923
7924
# File 'lib/syntax_tree/node.rb', line 7919

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



7914
7915
7916
# File 'lib/syntax_tree/node.rb', line 7914

def body
  @body
end

#commentsObject (readonly)

Array[ Comment | EmbDoc ]

the comments attached to this node



7917
7918
7919
# File 'lib/syntax_tree/node.rb', line 7917

def comments
  @comments
end

#parserObject (readonly)

SyntaxTree

the parser that is generating this node



7911
7912
7913
# File 'lib/syntax_tree/node.rb', line 7911

def parser
  @parser
end

Instance Method Details

#accept(visitor) ⇒ Object



7973
7974
7975
# File 'lib/syntax_tree/node.rb', line 7973

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

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



7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952
7953
# File 'lib/syntax_tree/node.rb', line 7926

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



7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
# File 'lib/syntax_tree/node.rb', line 7955

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



7977
7978
7979
# File 'lib/syntax_tree/node.rb', line 7977

def child_nodes
  body
end

#deconstruct_keys(_keys) ⇒ Object



7983
7984
7985
# File 'lib/syntax_tree/node.rb', line 7983

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

#empty?Boolean

Returns:

  • (Boolean)


7967
7968
7969
7970
7971
# File 'lib/syntax_tree/node.rb', line 7967

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

#format(q) ⇒ Object



7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
# File 'lib/syntax_tree/node.rb', line 7987

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