123456789_123456789_123456789_123456789_123456789_

Class: IRB::NestingParser::NestingVisitor

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Prism::Visitor
Instance Chain:
self, Prism::Visitor
Inherits: Prism::Visitor
  • ::Object
Defined in: lib/irb/nesting_parser.rb

Class Method Summary

Instance Method Summary

Constructor Details

.newNestingVisitor

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 10

def initialize
  # Array of [column, priority(+1/-1), NestingElem(open) or nil(close)] per line.
  # priority is +1 for open, -1 for close so that close comes before open when sorted.
  # Example:
  #   if cond
  #   else
  #   end
  # `else` closes `if` at column 0 first and then opens `else` at column 0 next.
  @lines = []

  # Array of open heredoc NestingElem per line
  @heredocs = []
end

Instance Method Details

#close(line, column)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 51

def close(line, column)
  (@lines[line - 1] ||= []) << [column, -1]
end

#close_closing_loc(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 77

def close_closing_loc(node)
  close_location(node.closing_loc) if node.closing_loc && !node.closing.empty?
end

#close_end_keyword_loc(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 73

def close_end_keyword_loc(node)
  close_location(node.end_keyword_loc) if node.end_keyword == 'end'
end

#close_location(location)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 65

def close_location(location)
  close(location.end_line, location.end_column)
end

#close_location_start(location)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 69

def close_location_start(location)
  close(location.start_line, location.start_column)
end

#heredoc_open(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 42

def heredoc_open(node)
  elem = NestingElem.new([node.location.start_line, node.location.start_column], :on_heredoc_beg, node.opening)
  (@heredocs[node.location.start_line - 1] ||= []) << elem
end

#heredoc_string_like(node, type)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 219

def heredoc_string_like(node, type)
  if node.opening&.start_with?('<<')
    heredoc_open(node)
    # Heredoc closing contains trailing newline. We need to exclude it
    close_location_start(node.closing_loc) if node.closing_loc && !node.closing.empty?
  elsif node.opening
    open_location(node.location, type, node.opening)
    if node.closing && node.closing != ''
      # Closing of `"#{\n` is "\n". We need to treat it as not-closed.
      close_location_start(node.closing_loc) if node.opening.match?(/\n\z/) || node.closing != "\n"
    end
  end
end

#modifier_node?(node, keyword_loc) ⇒ Boolean

Checks if a node (if, while, etc) is a modifier form that does not need end closing. modifier node: a if b, non-modifier node: if a; b; end

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 57

def modifier_node?(node, keyword_loc)
  !(keyword_loc && node.location.start_line == keyword_loc.start_line && node.location.start_column == keyword_loc.start_column)
end

#nestings

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 24

def nestings
  size = [@lines.size, @heredocs.size].max
  nesting = []
  size.times.map do |line_index|
    @lines[line_index]&.sort_by { |col, pri| [col, pri] }&.each do |col, pri, elem|
      if elem
        nesting << elem
      else
        nesting.pop
      end
    end
    @heredocs[line_index]&.sort_by { |elem| elem.pos[1] }&.reverse_each do |elem|
      nesting << elem
    end
    nesting.dup
  end
end

#open(line, column, elem)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 47

def open(line, column, elem)
  (@lines[line - 1] ||= []) << [column, +1, elem]
end

#open_location(location, type, tok)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 61

def open_location(location, type, tok)
  open(location.start_line, location.start_column, NestingElem.new([location.start_line, location.start_column], type, tok))
end

#visit_array_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 188

def visit_array_node(node)
  super
  type =
    case node.opening
    when nil
      # `x = 1, 2` doesn't have opening
      nil
    when '['
      :bracket
    when /\A%W/
      :on_words_beg
    when /\A%w/
      :on_qwords_beg
    when /\A%I/
      :on_symbols_beg
    when /\A%i/
      :on_qsymbols_beg
    end

  if type
    open_location(node.location, type, node.opening)
    close_closing_loc(node)
  end
end

#visit_begin_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 174

def visit_begin_node(node)
  super
  if node.begin_keyword
    open_location(node.location, :on_kw, 'begin')
    close_end_keyword_loc(node)
  end
end

#visit_block_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 182

def visit_block_node(node)
  super
  open_location(node.location, node.opening == '{' ? :on_lbrace : :on_kw, node.opening)
  close_closing_loc(node)
end

#visit_block_parameters_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 290

def visit_block_parameters_node(node)
  super
  if node.opening == '('
    open_location(node.location, :on_lparen, '(')
    close_closing_loc(node)
  end
end

#visit_call_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 274

def visit_call_node(node)
  super
  type =
    case node.opening
    when '('
      :on_lparen
    when '['
      :on_lbracket
    end

  if type
    open_location(node.opening_loc, type, node.opening)
    close_closing_loc(node)
  end
end

#visit_case_match_node(node)

Alias for #visit_case_node.

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 136

alias visit_case_match_node visit_case_node

#visit_case_node(node) Also known as: #visit_case_match_node

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 127

def visit_case_node(node)
  super
  open_location(node.location, :on_kw, 'case')
  if node.else_clause
    close_location_start(node.else_clause.location)
  else
    close_end_keyword_loc(node)
  end
end

#visit_class_node(node) Also known as: #visit_singleton_class_node

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 328

def visit_class_node(node)
  super
  open_location(node.location, :on_kw, 'class')
  close_end_keyword_loc(node)
end

#visit_def_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 314

def visit_def_node(node)
  super
  open_location(node.location, :on_kw, 'def')
  if node.lparen == '('
    open_location(node.lparen_loc, :on_lparen, '(')
    close_location(node.rparen_loc) if node.rparen == ')'
  end
  if node.equal
    close_location(node.equal_loc)
  else
    close_end_keyword_loc(node)
  end
end

#visit_defined_node(node)

Alias for #visit_super_node.

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 312

alias visit_defined_node visit_super_node

#visit_else_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 150

def visit_else_node(node)
  super
  if node.else_keyword == 'else'
    open_location(node.location, :on_kw, 'else')
    close_end_keyword_loc(node)
  end
end

#visit_embedded_statements_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 233

def visit_embedded_statements_node(node)
  super
  open_location(node.location, :on_embexpr_beg, '#{')
  close_closing_loc(node)
end

#visit_ensure_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 158

def visit_ensure_node(node)
  super
  return if modifier_node?(node, node.ensure_keyword_loc)

  close_location_start(node.location)
  open_location(node.location, :on_kw, 'ensure')
end

#visit_for_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 81

def visit_for_node(node)
  super
  open_location(node.location, :on_kw, 'for')
  close_end_keyword_loc(node)
end

#visit_hash_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 213

def visit_hash_node(node)
  super
  open_location(node.location, :on_lbrace, '{')
  close_closing_loc(node)
end

#visit_if_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 103

def visit_if_node(node)
  super
  return if !node.if_keyword || modifier_node?(node, node.if_keyword_loc)

  open_location(node.location, :on_kw, node.if_keyword)
  if node.subsequent
    close_location_start(node.subsequent.location)
  else
    close_end_keyword_loc(node)
  end
end

#visit_in_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 144

def visit_in_node(node)
  super
  close_location_start(node.location)
  open_location(node.location, :on_kw, 'in')
end

#visit_interpolated_regular_expression_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 266

alias visit_interpolated_regular_expression_node visit_regular_expression_node

#visit_interpolated_string_node(node) Also known as: #visit_string_node

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 239

def visit_interpolated_string_node(node)
  super
  heredoc_string_like(node, :on_tstring_beg)
end

#visit_interpolated_symbol_node(node)

Alias for #visit_symbol_node.

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 259

alias visit_interpolated_symbol_node visit_symbol_node

#visit_interpolated_x_string_node(node) Also known as: #visit_x_string_node

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 245

def visit_interpolated_x_string_node(node)
  super
  heredoc_string_like(node, :on_backtick)
end

#visit_lambda_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 298

def visit_lambda_node(node)
  super
  open_location(node.opening_loc, :on_tlambeg, node.opening)
  close_closing_loc(node)
end

#visit_module_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 335

def visit_module_node(node)
  super
  open_location(node.location, :on_kw, 'module')
  close_end_keyword_loc(node)
end

#visit_parentheses_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 268

def visit_parentheses_node(node)
  super
  open_location(node.location, :on_lparen, '(')
  close_closing_loc(node)
end

#visit_regular_expression_node(node) Also known as: #visit_interpolated_regular_expression_node

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 261

def visit_regular_expression_node(node)
  super
  open_location(node.location, :on_regexp_beg, node.opening)
  close_closing_loc(node)
end

#visit_rescue_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 166

def visit_rescue_node(node)
  super
  return if modifier_node?(node, node.keyword_loc)

  close_location_start(node.location)
  open_location(node.location, :on_kw, 'rescue')
end

#visit_singleton_class_node(node)

Alias for #visit_class_node.

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 333

alias visit_singleton_class_node visit_class_node

#visit_string_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 243

alias visit_string_node visit_interpolated_string_node

#visit_super_node(node) Also known as: #visit_yield_node, #visit_defined_node

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 304

def visit_super_node(node)
  super
  if node.lparen
    open_location(node.lparen_loc, :on_lparen, '(')
    close_location(node.rparen_loc) if node.rparen == ')'
  end
end

#visit_symbol_node(node) Also known as: #visit_interpolated_symbol_node

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 251

def visit_symbol_node(node)
  super
  unless node.opening.nil? || node.opening.empty? || node.opening == ':'
    # :"sym" or %s[sym]
    open_location(node.location, :on_symbeg, node.opening)
    close_closing_loc(node)
  end
end

#visit_unless_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 115

def visit_unless_node(node)
  super
  return if modifier_node?(node, node.keyword_loc)

  open_location(node.location, :on_kw, 'unless')
  if node.else_clause
    close_location_start(node.else_clause.location)
  else
    close_end_keyword_loc(node)
  end
end

#visit_until_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 95

def visit_until_node(node)
  super
  return if modifier_node?(node, node.keyword_loc)

  open_location(node.location, :on_kw, 'until')
  close_closing_loc(node)
end

#visit_when_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 138

def visit_when_node(node)
  super
  close_location_start(node.location)
  open_location(node.location, :on_kw, 'when')
end

#visit_while_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 87

def visit_while_node(node)
  super
  return if modifier_node?(node, node.keyword_loc)

  open_location(node.location, :on_kw, 'while')
  close_closing_loc(node)
end

#visit_x_string_node(node)

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 249

alias visit_x_string_node visit_interpolated_x_string_node

#visit_yield_node(node)

Alias for #visit_super_node.

[ GitHub ]

  
# File 'lib/irb/nesting_parser.rb', line 311

alias visit_yield_node visit_super_node