Spec-Zone.ru › Ruby 3.4
  1. Prism::
  2. Translation::
  3. Ripper

class Prism::Translation::Ripper

Родитель:
Prism::Compiler

Этот класс предоставляет уровень совместимости между prism и Ripper. Сначала он разбирает всё дерево, а затем проходит по нему, вызывая при этом каждый из обратных вызовов Ripper. Чтобы использовать этот класс, работайте с Prism::Translation::Ripper так же, как с классом Ripper.

Обратите внимание, что этот класс охватывает наиболее распространённые сценарии использования, но API Ripper обширен и не документирован. Он опирается на получение сведений о состоянии парсера в любой момент времени. Мы делаем всё возможное, чтобы воспроизвести это поведение, но из-за иной архитектуры невозможно в точности повторить поведение Ripper.

Основное известное отличие заключается в том, что в некоторых случаях мы можем не вызывать некоторые события. Это касается следующих событий:

  • on_assign_error

  • on_comma

  • on_ignored_nl

  • on_ignored_sp

  • on_kw

  • on_label_end

  • on_lbrace

  • on_lbracket

  • on_lparen

  • on_nl

  • on_op

  • on_operator_ambiguous

  • on_rbrace

  • on_rbracket

  • on_rparen

  • on_semicolon

  • on_sp

  • on_symbeg

  • on_tstring_beg

  • on_tstring_end

Константы

BINARY_OPERATORS

Список всех бинарных операторов Ruby.

EVENTS

Этот массив содержит имена всех событий ripper.

KEYWORDS

Список всех ключевых слов Ruby.

PARSER_EVENTS

Этот массив содержит имена событий парсера.

PARSER_EVENT_TABLE

Содержит таблицу всех событий парсера и соответствующих им арностей.

SCANNER_EVENTS

Этот массив содержит имена событий сканера.

SCANNER_EVENT_TABLE

Содержит таблицу всех событий сканера и соответствующих им арностей.

Атрибуты

column [R]

Текущий номер столбца парсера.

filename [R]

Имя файла исходного кода, который разбирается.

lineno [R]

Текущий номер строки парсера.

source [R]

Исходный код, который разбирается.

Открытые методы класса

lex (src, filename = "-", lineno = 1, raise_errors: false) Показать исходный код
# File lib/prism/translation/ripper.rb, line 73
def self.lex(src, filename = "-", lineno = 1, raise_errors: false)
  result = Prism.lex_compat(src, filepath: filename, line: lineno)

  if result.failure? && raise_errors
    raise SyntaxError, result.errors.first.message
  else
    result.value
  end
end

Разбивает программу на Ruby на токены и возвращает массив массивов в формате [[lineno, column], type, token, state]. Аргумент filename в основном игнорируется. По умолчанию этот метод не обрабатывает синтаксические ошибки в src; используйте ключевое слово raise_errors, чтобы при ошибке в src вызвать SyntaxError.

require "ripper"
require "pp"

pp Ripper.lex("def m(a) nil end")
#=> [[[1,  0], :on_kw,     "def", FNAME    ],
     [[1,  3], :on_sp,     " ",   FNAME    ],
     [[1,  4], :on_ident,  "m",   ENDFN    ],
     [[1,  5], :on_lparen, "(",   BEG|LABEL],
     [[1,  6], :on_ident,  "a",   ARG      ],
     [[1,  7], :on_rparen, ")",   ENDFN    ],
     [[1,  8], :on_sp,     " ",   BEG      ],
     [[1,  9], :on_kw,     "nil", END      ],
     [[1, 12], :on_sp,     " ",   END      ],
     [[1, 13], :on_kw,     "end", END      ]]
new (source, filename = "(ripper)", lineno = 1) Показать исходный код
# File lib/prism/translation/ripper.rb, line 445
def initialize(source, filename = "(ripper)", lineno = 1)
  @source = source
  @filename = filename
  @lineno = lineno
  @column = 0
  @result = nil
end

Создаёт объект Translation::Ripper с указанным исходным кодом.

parse (src, filename = "(ripper)", lineno = 1) Показать исходный код
# File lib/prism/translation/ripper.rb, line 47
def self.parse(src, filename = "(ripper)", lineno = 1)
  new(src, filename, lineno).parse
end

Разбирает указанную программу на Ruby, прочитанную из src. src должен быть String, IO или объектом с методом gets.

sexp (src, filename = "-", lineno = 1, raise_errors: false) Показать исходный код
# File lib/prism/translation/ripper.rb, line 382
def self.sexp(src, filename = "-", lineno = 1, raise_errors: false)
  builder = SexpBuilderPP.new(src, filename, lineno)
  sexp = builder.parse
  if builder.error?
    if raise_errors
      raise SyntaxError, builder.error
    end
  else
    sexp
  end
end

Разбирает src и создаёт дерево S-выражения. Возвращает более удобочитаемое дерево, чем Ripper.sexp_raw. Этот метод предназначен главным образом для разработчиков. Аргумент filename в основном игнорируется. По умолчанию этот метод не обрабатывает синтаксические ошибки в src и в таких случаях возвращает nil. Используйте ключевое слово raise_errors, чтобы при ошибке в src вызвать SyntaxError.

require "ripper"
require "pp"

pp Ripper.sexp("def m(a) nil end")
  #=> [:program,
       [[:def,
        [:@ident, "m", [1, 4]],
        [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil, nil, nil, nil]],
        [:bodystmt, [[:var_ref, [:@kw, "nil", [1, 9]]]], nil, nil, nil]]]]
sexp_raw (src, filename = "-", lineno = 1, raise_errors: false) Показать исходный код
# File lib/prism/translation/ripper.rb, line 417
def self.sexp_raw(src, filename = "-", lineno = 1, raise_errors: false)
  builder = SexpBuilder.new(src, filename, lineno)
  sexp = builder.parse
  if builder.error?
    if raise_errors
      raise SyntaxError, builder.error
    end
  else
    sexp
  end
end

Разбирает src и создаёт дерево S-выражения. Этот метод предназначен главным образом для разработчиков. Аргумент filename в основном игнорируется. По умолчанию этот метод не обрабатывает синтаксические ошибки в src и в таких случаях возвращает nil. Используйте ключевое слово raise_errors, чтобы при ошибке в src вызвать SyntaxError.

require "ripper"
require "pp"

pp Ripper.sexp_raw("def m(a) nil end")
  #=> [:program,
       [:stmts_add,
        [:stmts_new],
        [:def,
         [:@ident, "m", [1, 4]],
         [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil]],
         [:bodystmt,
          [:stmts_add, [:stmts_new], [:var_ref, [:@kw, "nil", [1, 9]]]],
          nil,
          nil,
          nil]]]]

Открытые методы экземпляра

error? () Показать исходный код
# File lib/prism/translation/ripper.rb, line 458
def error?
  result.failure?
end

Возвращает true, если при разборе парсер обнаружил ошибку.

parse () Показать исходный код
# File lib/prism/translation/ripper.rb, line 463
def parse
  result.comments.each do |comment|
    location = comment.location
    bounds(location)

    if comment.is_a?(InlineComment)
      on_comment(comment.slice)
    else
      offset = location.start_offset
      lines = comment.slice.lines

      lines.each_with_index do |line, index|
        bounds(location.copy(start_offset: offset))

        if index == 0
          on_embdoc_beg(line)
        elsif index == lines.size - 1
          on_embdoc_end(line)
        else
          on_embdoc(line)
        end

        offset += line.bytesize
      end
    end
  end

  result.magic_comments.each do |magic_comment|
    on_magic_comment(magic_comment.key, magic_comment.value)
  end

  unless result.data_loc.nil?
    on___end__(result.data_loc.slice.each_line.first)
  end

  result.warnings.each do |warning|
    bounds(warning.location)

    if warning.level == :default
      warning(warning.message)
    else
      case warning.type
      when :ambiguous_first_argument_plus
        on_arg_ambiguous("+")
      when :ambiguous_first_argument_minus
        on_arg_ambiguous("-")
      when :ambiguous_slash
        on_arg_ambiguous("/")
      else
        warn(warning.message)
      end
    end
  end

  if error?
    result.errors.each do |error|
      location = error.location
      bounds(location)

      case error.type
      when :alias_argument
        on_alias_error("can't make alias for the number variables", location.slice)
      when :argument_formal_class
        on_param_error("formal argument cannot be a class variable", location.slice)
      when :argument_format_constant
        on_param_error("formal argument cannot be a constant", location.slice)
      when :argument_formal_global
        on_param_error("formal argument cannot be a global variable", location.slice)
      when :argument_formal_ivar
        on_param_error("formal argument cannot be an instance variable", location.slice)
      when :class_name, :module_name
        on_class_name_error("class/module name must be CONSTANT", location.slice)
      else
        on_parse_error(error.message)
      end
    end

    nil
  else
    result.value.accept(self)
  end
end

Разбирает исходный код и возвращает результат.

visit_alias_global_variable_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 562
def visit_alias_global_variable_node(node)
  new_name = visit_alias_global_variable_node_value(node.new_name)
  old_name = visit_alias_global_variable_node_value(node.old_name)

  bounds(node.location)
  on_var_alias(new_name, old_name)
end

alias $foo $bar ^^^^^^^^^^^^^^^

visit_alias_method_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 552
def visit_alias_method_node(node)
  new_name = visit(node.new_name)
  old_name = visit(node.old_name)

  bounds(node.location)
  on_alias(new_name, old_name)
end

alias foo bar ^^^^^^^^^^^^^

visit_alternation_pattern_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 586
def visit_alternation_pattern_node(node)
  left = visit_pattern_node(node.left)
  right = visit_pattern_node(node.right)

  bounds(node.location)
  on_binary(left, :|, right)
end

foo => bar | baz ^^^^^^^^^

visit_and_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 606
def visit_and_node(node)
  left = visit(node.left)
  right = visit(node.right)

  bounds(node.location)
  on_binary(left, node.operator.to_sym, right)
end

a and b ^^^^^^^

visit_arguments_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 797
def visit_arguments_node(node)
  arguments, _ = visit_call_node_arguments(node, nil, false)
  arguments
end

foo(bar) ^^^

visit_array_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 616
def visit_array_node(node)
  case (opening = node.opening)
  when /^%w/
    opening_loc = node.opening_loc
    bounds(opening_loc)
    on_qwords_beg(opening)

    elements = on_qwords_new
    previous = nil

    node.elements.each do |element|
      visit_words_sep(opening_loc, previous, element)

      bounds(element.location)
      elements = on_qwords_add(elements, on_tstring_content(element.content))

      previous = element
    end

    bounds(node.closing_loc)
    on_tstring_end(node.closing)
  when /^%i/
    opening_loc = node.opening_loc
    bounds(opening_loc)
    on_qsymbols_beg(opening)

    elements = on_qsymbols_new
    previous = nil

    node.elements.each do |element|
      visit_words_sep(opening_loc, previous, element)

      bounds(element.location)
      elements = on_qsymbols_add(elements, on_tstring_content(element.value))

      previous = element
    end

    bounds(node.closing_loc)
    on_tstring_end(node.closing)
  when /^%W/
    opening_loc = node.opening_loc
    bounds(opening_loc)
    on_words_beg(opening)

    elements = on_words_new
    previous = nil

    node.elements.each do |element|
      visit_words_sep(opening_loc, previous, element)

      bounds(element.location)
      elements =
        on_words_add(
          elements,
          if element.is_a?(StringNode)
            on_word_add(on_word_new, on_tstring_content(element.content))
          else
            element.parts.inject(on_word_new) do |word, part|
              word_part =
                if part.is_a?(StringNode)
                  bounds(part.location)
                  on_tstring_content(part.content)
                else
                  visit(part)
                end

              on_word_add(word, word_part)
            end
          end
        )

      previous = element
    end

    bounds(node.closing_loc)
    on_tstring_end(node.closing)
  when /^%I/
    opening_loc = node.opening_loc
    bounds(opening_loc)
    on_symbols_beg(opening)

    elements = on_symbols_new
    previous = nil

    node.elements.each do |element|
      visit_words_sep(opening_loc, previous, element)

      bounds(element.location)
      elements =
        on_symbols_add(
          elements,
          if element.is_a?(SymbolNode)
            on_word_add(on_word_new, on_tstring_content(element.value))
          else
            element.parts.inject(on_word_new) do |word, part|
              word_part =
                if part.is_a?(StringNode)
                  bounds(part.location)
                  on_tstring_content(part.content)
                else
                  visit(part)
                end

              on_word_add(word, word_part)
            end
          end
        )

      previous = element
    end

    bounds(node.closing_loc)
    on_tstring_end(node.closing)
  else
    bounds(node.opening_loc)
    on_lbracket(opening)

    elements = visit_arguments(node.elements) unless node.elements.empty?

    bounds(node.closing_loc)
    on_rbracket(node.closing)
  end

  bounds(node.location)
  on_array(elements)
end

[] ^^

visit_array_pattern_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 776
def visit_array_pattern_node(node)
  constant = visit(node.constant)
  requireds = visit_all(node.requireds) if node.requireds.any?
  rest =
    if (rest_node = node.rest).is_a?(SplatNode)
      if rest_node.expression.nil?
        bounds(rest_node.location)
        on_var_field(nil)
      else
        visit(rest_node.expression)
      end
    end

  posts = visit_all(node.posts) if node.posts.any?

  bounds(node.location)
  on_aryptn(constant, requireds, rest, posts)
end

foo => [bar] ^^^^^

visit_assoc_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 804
def visit_assoc_node(node)
  key = visit(node.key)
  value = visit(node.value)

  bounds(node.location)
  on_assoc_new(key, value)
end

{ a: 1 } ^^^^

visit_assoc_splat_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 817
def visit_assoc_splat_node(node)
  value = visit(node.value)

  bounds(node.location)
  on_assoc_splat(value)
end

def foo(); bar(); end ^^

{ **foo } ^^^^^

visit_back_reference_read_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 826
def visit_back_reference_read_node(node)
  bounds(node.location)
  on_backref(node.slice)
end

$+ ^^

visit_begin_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 833
def visit_begin_node(node)
  clauses = visit_begin_node_clauses(node.begin_keyword_loc, node, false)

  bounds(node.location)
  on_begin(clauses)
end

begin end ^^^^^^^^^

visit_block_argument_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 897
def visit_block_argument_node(node)
  visit(node.expression)
end

foo(&bar) ^^^^

visit_block_local_variable_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 903
def visit_block_local_variable_node(node)
  bounds(node.location)
  on_ident(node.name.to_s)
end

foo { |; bar| } ^^^

visit_block_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 909
def visit_block_node(node)
  braces = node.opening == "{"
  parameters = visit(node.parameters)

  body =
    case node.body
    when nil
      bounds(node.location)
      stmts = on_stmts_add(on_stmts_new, on_void_stmt)

      bounds(node.location)
      braces ? stmts : on_bodystmt(stmts, nil, nil, nil)
    when StatementsNode
      stmts = node.body.body
      stmts.unshift(nil) if void_stmt?(node.parameters&.location || node.opening_loc, node.body.location, false)
      stmts = visit_statements_node_body(stmts)

      bounds(node.body.location)
      braces ? stmts : on_bodystmt(stmts, nil, nil, nil)
    when BeginNode
      visit_body_node(node.parameters&.location || node.opening_loc, node.body)
    else
      raise
    end

  if braces
    bounds(node.location)
    on_brace_block(parameters, body)
  else
    bounds(node.location)
    on_do_block(parameters, body)
  end
end

Посетить BlockNode.

visit_block_parameter_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 945
def visit_block_parameter_node(node)
  if node.name_loc.nil?
    bounds(node.location)
    on_blockarg(nil)
  else
    bounds(node.name_loc)
    name = visit_token(node.name.to_s)

    bounds(node.location)
    on_blockarg(name)
  end
end

def foo(&bar); end ^^^^

visit_block_parameters_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 959
def visit_block_parameters_node(node)
  parameters =
    if node.parameters.nil?
      on_params(nil, nil, nil, nil, nil, nil, nil)
    else
      visit(node.parameters)
    end

  locals =
    if node.locals.any?
      visit_all(node.locals)
    else
      false
    end

  bounds(node.location)
  on_block_var(parameters, locals)
end

Параметры блока.

visit_break_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 983
def visit_break_node(node)
  if node.arguments.nil?
    bounds(node.location)
    on_break(on_args_new)
  else
    arguments = visit(node.arguments)

    bounds(node.location)
    on_break(arguments)
  end
end

break ^^^^^

break foo ^^^^^^^^^

visit_call_and_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1205
def visit_call_and_write_node(node)
  receiver = visit(node.receiver)

  bounds(node.call_operator_loc)
  call_operator = visit_token(node.call_operator)

  bounds(node.message_loc)
  message = visit_token(node.message)

  bounds(node.location)
  target = on_field(receiver, call_operator, message)

  bounds(node.operator_loc)
  operator = on_op("&&=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

foo.bar &&= baz ^^^^^^^^^^^^^^^

visit_call_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1003
def visit_call_node(node)
  if node.call_operator_loc.nil?
    case node.name
    when :[]
      receiver = visit(node.receiver)
      arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))

      bounds(node.location)
      call = on_aref(receiver, arguments)

      if block.nil?
        call
      else
        bounds(node.location)
        on_method_add_block(call, block)
      end
    when :[]=
      receiver = visit(node.receiver)

      *arguments, last_argument = node.arguments.arguments
      arguments << node.block if !node.block.nil?

      arguments =
        if arguments.any?
          args = visit_arguments(arguments)

          if !node.block.nil?
            args
          else
            bounds(arguments.first.location)
            on_args_add_block(args, false)
          end
        end

      bounds(node.location)
      call = on_aref_field(receiver, arguments)
      value = visit_write_value(last_argument)

      bounds(last_argument.location)
      on_assign(call, value)
    when :-@, :+@, :~
      receiver = visit(node.receiver)

      bounds(node.location)
      on_unary(node.name, receiver)
    when :!
      if node.message == "not"
        receiver =
          if !node.receiver.is_a?(ParenthesesNode) || !node.receiver.body.nil?
            visit(node.receiver)
          end

        bounds(node.location)
        on_unary(:not, receiver)
      else
        receiver = visit(node.receiver)

        bounds(node.location)
        on_unary(:!, receiver)
      end
    when *BINARY_OPERATORS
      receiver = visit(node.receiver)
      value = visit(node.arguments.arguments.first)

      bounds(node.location)
      on_binary(receiver, node.name, value)
    else
      bounds(node.message_loc)
      message = visit_token(node.message, false)

      if node.variable_call?
        on_vcall(message)
      else
        arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc || node.location))
        call =
          if node.opening_loc.nil? && arguments&.any?
            bounds(node.location)
            on_command(message, arguments)
          elsif !node.opening_loc.nil?
            bounds(node.location)
            on_method_add_arg(on_fcall(message), on_arg_paren(arguments))
          else
            bounds(node.location)
            on_method_add_arg(on_fcall(message), on_args_new)
          end

        if block.nil?
          call
        else
          bounds(node.block.location)
          on_method_add_block(call, block)
        end
      end
    end
  else
    receiver = visit(node.receiver)

    bounds(node.call_operator_loc)
    call_operator = visit_token(node.call_operator)

    message =
      if node.message_loc.nil?
        :call
      else
        bounds(node.message_loc)
        visit_token(node.message, false)
      end

    if node.name.end_with?("=") && !node.message.end_with?("=") && !node.arguments.nil? && node.block.nil?
      value = visit_write_value(node.arguments.arguments.first)

      bounds(node.location)
      on_assign(on_field(receiver, call_operator, message), value)
    else
      arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc || node.location))
      call =
        if node.opening_loc.nil?
          bounds(node.location)

          if node.arguments.nil? && !node.block.is_a?(BlockArgumentNode)
            on_call(receiver, call_operator, message)
          else
            on_command_call(receiver, call_operator, message, arguments)
          end
        else
          bounds(node.opening_loc)
          arguments = on_arg_paren(arguments)

          bounds(node.location)
          on_method_add_arg(on_call(receiver, call_operator, message), arguments)
        end

      if block.nil?
        call
      else
        bounds(node.block.location)
        on_method_add_block(call, block)
      end
    end
  end
end

foo ^^^

foo.bar ^^^^^^^

foo.bar() {} ^^^^^^^^^^^^

visit_call_operator_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1183
def visit_call_operator_write_node(node)
  receiver = visit(node.receiver)

  bounds(node.call_operator_loc)
  call_operator = visit_token(node.call_operator)

  bounds(node.message_loc)
  message = visit_token(node.message)

  bounds(node.location)
  target = on_field(receiver, call_operator, message)

  bounds(node.binary_operator_loc)
  operator = on_op("#{node.binary_operator}=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

foo.bar += baz ^^^^^^^^^^^^^^^

visit_call_or_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1227
def visit_call_or_write_node(node)
  receiver = visit(node.receiver)

  bounds(node.call_operator_loc)
  call_operator = visit_token(node.call_operator)

  bounds(node.message_loc)
  message = visit_token(node.message)

  bounds(node.location)
  target = on_field(receiver, call_operator, message)

  bounds(node.operator_loc)
  operator = on_op("||=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

foo.bar ||= baz ^^^^^^^^^^^^^^^

visit_call_target_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1249
def visit_call_target_node(node)
  if node.call_operator == "::"
    receiver = visit(node.receiver)

    bounds(node.message_loc)
    message = visit_token(node.message)

    bounds(node.location)
    on_const_path_field(receiver, message)
  else
    receiver = visit(node.receiver)

    bounds(node.call_operator_loc)
    call_operator = visit_token(node.call_operator)

    bounds(node.message_loc)
    message = visit_token(node.message)

    bounds(node.location)
    on_field(receiver, call_operator, message)
  end
end

foo.bar, = 1 ^^^^^^^

visit_capture_pattern_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1274
def visit_capture_pattern_node(node)
  value = visit(node.value)
  target = visit(node.target)

  bounds(node.location)
  on_binary(value, :"=>", target)
end

foo => bar => baz ^^^^^^^^^^

visit_case_match_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1297
def visit_case_match_node(node)
  predicate = visit(node.predicate)
  clauses =
    node.conditions.reverse_each.inject(visit(node.else_clause)) do |current, condition|
      on_in(*visit(condition), current)
    end

  bounds(node.location)
  on_case(predicate, clauses)
end

case foo; in bar; end ^^^^^^^^^^^^^^^^^^^^^

visit_case_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1284
def visit_case_node(node)
  predicate = visit(node.predicate)
  clauses =
    node.conditions.reverse_each.inject(visit(node.else_clause)) do |current, condition|
      on_when(*visit(condition), current)
    end

  bounds(node.location)
  on_case(predicate, clauses)
end

case foo; when bar; end ^^^^^^^^^^^^^^^^^^^^^^^

visit_class_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1310
def visit_class_node(node)
  constant_path =
    if node.constant_path.is_a?(ConstantReadNode)
      bounds(node.constant_path.location)
      on_const_ref(on_const(node.constant_path.name.to_s))
    else
      visit(node.constant_path)
    end

  superclass = visit(node.superclass)
  bodystmt = visit_body_node(node.superclass&.location || node.constant_path.location, node.body, node.superclass.nil?)

  bounds(node.location)
  on_class(constant_path, superclass, bodystmt)
end

class Foo; end ^^^^^^^^^^^^^^

visit_class_variable_and_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1363
def visit_class_variable_and_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_cvar(node.name.to_s))

  bounds(node.operator_loc)
  operator = on_op("&&=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

@@foo &&= bar ^^^^^^^^^^^^^

visit_class_variable_operator_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1349
def visit_class_variable_operator_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_cvar(node.name.to_s))

  bounds(node.binary_operator_loc)
  operator = on_op("#{node.binary_operator}=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

@@foo += bar ^^^^^^^^^^^^

visit_class_variable_or_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1377
def visit_class_variable_or_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_cvar(node.name.to_s))

  bounds(node.operator_loc)
  operator = on_op("||=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

@@foo ||= bar ^^^^^^^^^^^^^

visit_class_variable_read_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1328
def visit_class_variable_read_node(node)
  bounds(node.location)
  on_var_ref(on_cvar(node.slice))
end

@@foo ^^^^^

visit_class_variable_target_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1391
def visit_class_variable_target_node(node)
  bounds(node.location)
  on_var_field(on_cvar(node.name.to_s))
end

@@foo, = bar ^^^^^

visit_class_variable_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1338
def visit_class_variable_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_cvar(node.name.to_s))
  value = visit_write_value(node.value)

  bounds(node.location)
  on_assign(target, value)
end

@@foo = 1 ^^^^^^^^^

@@foo, @@bar = 1 ^^^^^ ^^^^^

visit_constant_and_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1433
def visit_constant_and_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_const(node.name.to_s))

  bounds(node.operator_loc)
  operator = on_op("&&=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

Foo &&= bar ^^^^^^^^^^^^

visit_constant_operator_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1419
def visit_constant_operator_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_const(node.name.to_s))

  bounds(node.binary_operator_loc)
  operator = on_op("#{node.binary_operator}=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

Foo += bar ^^^^^^^^^^^

visit_constant_or_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1447
def visit_constant_or_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_const(node.name.to_s))

  bounds(node.operator_loc)
  operator = on_op("||=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

Foo ||= bar ^^^^^^^^^^^^

visit_constant_path_and_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1534
def visit_constant_path_and_write_node(node)
  target = visit_constant_path_write_node_target(node.target)
  value = visit(node.value)

  bounds(node.operator_loc)
  operator = on_op("&&=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

Foo::Bar &&= baz ^^^^^^^^^^^^^^^^

visit_constant_path_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1468
def visit_constant_path_node(node)
  if node.parent.nil?
    bounds(node.name_loc)
    child = on_const(node.name.to_s)

    bounds(node.location)
    on_top_const_ref(child)
  else
    parent = visit(node.parent)

    bounds(node.name_loc)
    child = on_const(node.name.to_s)

    bounds(node.location)
    on_const_path_ref(parent, child)
  end
end

Foo::Bar ^^^^^^^^

visit_constant_path_operator_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1520
def visit_constant_path_operator_write_node(node)
  target = visit_constant_path_write_node_target(node.target)
  value = visit(node.value)

  bounds(node.binary_operator_loc)
  operator = on_op("#{node.binary_operator}=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

Foo::Bar += baz ^^^^^^^^^^^^^^^

visit_constant_path_or_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1548
def visit_constant_path_or_write_node(node)
  target = visit_constant_path_write_node_target(node.target)
  value = visit(node.value)

  bounds(node.operator_loc)
  operator = on_op("||=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

Foo::Bar ||= baz ^^^^^^^^^^^^^^^^

visit_constant_path_target_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1562
def visit_constant_path_target_node(node)
  visit_constant_path_write_node_target(node)
end

Foo::Bar, = baz ^^^^^^^^

visit_constant_path_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1491
def visit_constant_path_write_node(node)
  target = visit_constant_path_write_node_target(node.target)
  value = visit_write_value(node.value)

  bounds(node.location)
  on_assign(target, value)
end

Foo::Bar = 1 ^^^^^^^^^^^^

Foo::Foo, Bar::Bar = 1 ^^^^^^^^ ^^^^^^^^

visit_constant_read_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1398
def visit_constant_read_node(node)
  bounds(node.location)
  on_var_ref(on_const(node.name.to_s))
end

Foo ^^^

visit_constant_target_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1461
def visit_constant_target_node(node)
  bounds(node.location)
  on_var_field(on_const(node.name.to_s))
end

Foo, = bar ^^^

visit_constant_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1408
def visit_constant_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_const(node.name.to_s))
  value = visit_write_value(node.value)

  bounds(node.location)
  on_assign(target, value)
end

Foo = 1 ^^^^^^^

Foo, Bar = 1 ^^^ ^^^

visit_def_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1571
def visit_def_node(node)
  receiver = visit(node.receiver)
  operator =
    if !node.operator_loc.nil?
      bounds(node.operator_loc)
      visit_token(node.operator)
    end

  bounds(node.name_loc)
  name = visit_token(node.name_loc.slice)

  parameters =
    if node.parameters.nil?
      bounds(node.location)
      on_params(nil, nil, nil, nil, nil, nil, nil)
    else
      visit(node.parameters)
    end

  if !node.lparen_loc.nil?
    bounds(node.lparen_loc)
    parameters = on_paren(parameters)
  end

  bodystmt =
    if node.equal_loc.nil?
      visit_body_node(node.rparen_loc || node.end_keyword_loc, node.body)
    else
      body = visit(node.body.body.first)

      bounds(node.body.location)
      on_bodystmt(body, nil, nil, nil)
    end

  bounds(node.location)
  if receiver.nil?
    on_def(name, parameters, bodystmt)
  else
    on_defs(receiver, operator, name, parameters, bodystmt)
  end
end

def foo; end ^^^^^^^^^^^^

def self.foo; end ^^^^^^^^^^^^^^^^^

visit_defined_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1618
def visit_defined_node(node)
  expression = visit(node.value)

  # Very weird circumstances here where something like:
  #
  #     defined?
  #     (1)
  #
  # gets parsed in Ruby as having only the `1` expression but in Ripper it
  # gets parsed as having a parentheses node. In this case we need to
  # synthesize that node to match Ripper's behavior.
  if node.lparen_loc && node.keyword_loc.join(node.lparen_loc).slice.include?("\n")
    bounds(node.lparen_loc.join(node.rparen_loc))
    expression = on_paren(on_stmts_add(on_stmts_new, expression))
  end

  bounds(node.location)
  on_defined(expression)
end

defined? a ^^^^^^^^^^

defined?(a) ^^^^^^^^^^^

visit_else_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1640
def visit_else_node(node)
  statements =
    if node.statements.nil?
      [nil]
    else
      body = node.statements.body
      body.unshift(nil) if void_stmt?(node.else_keyword_loc, node.statements.body[0].location, false)
      body
    end

  bounds(node.location)
  on_else(visit_statements_node_body(statements))
end

if foo then bar else baz end ^^^^^^^^^^^^

visit_embedded_statements_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1656
def visit_embedded_statements_node(node)
  bounds(node.opening_loc)
  on_embexpr_beg(node.opening)

  statements =
    if node.statements.nil?
      bounds(node.location)
      on_stmts_add(on_stmts_new, on_void_stmt)
    else
      visit(node.statements)
    end

  bounds(node.closing_loc)
  on_embexpr_end(node.closing)

  bounds(node.location)
  on_string_embexpr(statements)
end

“foo #{bar}” ^^^^^^

visit_embedded_variable_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1677
def visit_embedded_variable_node(node)
  bounds(node.operator_loc)
  on_embvar(node.operator)

  variable = visit(node.variable)

  bounds(node.location)
  on_string_dvar(variable)
end

“foo #@bar” ^^^^^

visit_ensure_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1688
def visit_ensure_node(node)
  statements =
    if node.statements.nil?
      [nil]
    else
      body = node.statements.body
      body.unshift(nil) if void_stmt?(node.ensure_keyword_loc, body[0].location, false)
      body
    end

  statements = visit_statements_node_body(statements)

  bounds(node.location)
  on_ensure(statements)
end

Посетить узел EnsureNode.

visit_false_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1706
def visit_false_node(node)
  bounds(node.location)
  on_var_ref(on_kw("false"))
end

false ^^^^^

visit_find_pattern_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1713
def visit_find_pattern_node(node)
  constant = visit(node.constant)
  left =
    if node.left.expression.nil?
      bounds(node.left.location)
      on_var_field(nil)
    else
      visit(node.left.expression)
    end

  requireds = visit_all(node.requireds) if node.requireds.any?
  right =
    if node.right.expression.nil?
      bounds(node.right.location)
      on_var_field(nil)
    else
      visit(node.right.expression)
    end

  bounds(node.location)
  on_fndptn(constant, left, requireds, right)
end

foo => [, bar, ] ^^^^^^^^^^^

visit_flip_flop_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1738
def visit_flip_flop_node(node)
  left = visit(node.left)
  right = visit(node.right)

  bounds(node.location)
  if node.exclude_end?
    on_dot3(left, right)
  else
    on_dot2(left, right)
  end
end

if foo .. bar; end ^^^^^^^^^^

visit_float_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1752
def visit_float_node(node)
  visit_number_node(node) { |text| on_float(text) }
end

1.0 ^^^

visit_for_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1758
def visit_for_node(node)
  index = visit(node.index)
  collection = visit(node.collection)
  statements =
    if node.statements.nil?
      bounds(node.location)
      on_stmts_add(on_stmts_new, on_void_stmt)
    else
      visit(node.statements)
    end

  bounds(node.location)
  on_for(index, collection, statements)
end

for foo in bar do end ^^^^^^^^^^^^^^^^^^^^^

visit_forwarding_arguments_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1775
def visit_forwarding_arguments_node(node)
  bounds(node.location)
  on_args_forward
end

def foo(…); bar(…); end ^^^

visit_forwarding_parameter_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1782
def visit_forwarding_parameter_node(node)
  bounds(node.location)
  on_args_forward
end

def foo(…); end ^^^

visit_forwarding_super_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1792
def visit_forwarding_super_node(node)
  if node.block.nil?
    bounds(node.location)
    on_zsuper
  else
    block = visit(node.block)

    bounds(node.location)
    on_method_add_block(on_zsuper, block)
  end
end

super ^^^^^

super {} ^^^^^^^^

visit_global_variable_and_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1841
def visit_global_variable_and_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_gvar(node.name.to_s))

  bounds(node.operator_loc)
  operator = on_op("&&=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

$foo &&= bar ^^^^^^^^^^^^

visit_global_variable_operator_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1827
def visit_global_variable_operator_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_gvar(node.name.to_s))

  bounds(node.binary_operator_loc)
  operator = on_op("#{node.binary_operator}=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

$foo += bar ^^^^^^^^^^^

visit_global_variable_or_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1855
def visit_global_variable_or_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_gvar(node.name.to_s))

  bounds(node.operator_loc)
  operator = on_op("||=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

$foo ||= bar ^^^^^^^^^^^^

visit_global_variable_read_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1806
def visit_global_variable_read_node(node)
  bounds(node.location)
  on_var_ref(on_gvar(node.name.to_s))
end

$foo ^^^^

visit_global_variable_target_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1869
def visit_global_variable_target_node(node)
  bounds(node.location)
  on_var_field(on_gvar(node.name.to_s))
end

$foo, = bar ^^^^

visit_global_variable_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1816
def visit_global_variable_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_gvar(node.name.to_s))
  value = visit_write_value(node.value)

  bounds(node.location)
  on_assign(target, value)
end

$foo = 1 ^^^^^^^^

$foo, $bar = 1 ^^^^ ^^^^

visit_hash_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1876
def visit_hash_node(node)
  elements =
    if node.elements.any?
      args = visit_all(node.elements)

      bounds(node.elements.first.location)
      on_assoclist_from_args(args)
    end

  bounds(node.location)
  on_hash(elements)
end

{} ^^

visit_hash_pattern_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1891
def visit_hash_pattern_node(node)
  constant = visit(node.constant)
  elements =
    if node.elements.any? || !node.rest.nil?
      node.elements.map do |element|
        [
          if (key = element.key).opening_loc.nil?
            visit(key)
          else
            bounds(key.value_loc)
            if (value = key.value).empty?
              on_string_content
            else
              on_string_add(on_string_content, on_tstring_content(value))
            end
          end,
          visit(element.value)
        ]
      end
    end

  rest =
    case node.rest
    when AssocSplatNode
      visit(node.rest.value)
    when NoKeywordsParameterNode
      bounds(node.rest.location)
      on_var_field(visit(node.rest))
    end

  bounds(node.location)
  on_hshptn(constant, elements, rest)
end

foo => {} ^^

visit_if_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1933
def visit_if_node(node)
  if node.then_keyword == "?"
    predicate = visit(node.predicate)
    truthy = visit(node.statements.body.first)
    falsy = visit(node.subsequent.statements.body.first)

    bounds(node.location)
    on_ifop(predicate, truthy, falsy)
  elsif node.statements.nil? || (node.predicate.location.start_offset < node.statements.location.start_offset)
    predicate = visit(node.predicate)
    statements =
      if node.statements.nil?
        bounds(node.location)
        on_stmts_add(on_stmts_new, on_void_stmt)
      else
        visit(node.statements)
      end
    subsequent = visit(node.subsequent)

    bounds(node.location)
    if node.if_keyword == "if"
      on_if(predicate, statements, subsequent)
    else
      on_elsif(predicate, statements, subsequent)
    end
  else
    statements = visit(node.statements.body.first)
    predicate = visit(node.predicate)

    bounds(node.location)
    on_if_mod(predicate, statements)
  end
end

if foo then bar end ^^^^^^^^^^^^^^^^^^^

bar if foo ^^^^^^^^^^

foo ? bar : baz ^^^^^^^^^^^^^^^

visit_imaginary_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1969
def visit_imaginary_node(node)
  visit_number_node(node) { |text| on_imaginary(text) }
end

1i ^^

visit_implicit_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1975
def visit_implicit_node(node)
end

{ foo: } ^^^^

visit_implicit_rest_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1980
def visit_implicit_rest_node(node)
  bounds(node.location)
  on_excessed_comma
end

foo { |bar,| } ^

visit_in_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1987
def visit_in_node(node)
  # This is a special case where we're not going to call on_in directly
  # because we don't have access to the subsequent. Instead, we'll return
  # the component parts and let the parent node handle it.
  pattern = visit_pattern_node(node.pattern)
  statements =
    if node.statements.nil?
      bounds(node.location)
      on_stmts_add(on_stmts_new, on_void_stmt)
    else
      visit(node.statements)
    end

  [pattern, statements]
end

case foo; in bar; end ^^^^^^^^^^^^^^^^^^^^^

visit_index_and_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2022
def visit_index_and_write_node(node)
  receiver = visit(node.receiver)
  arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))

  bounds(node.location)
  target = on_aref_field(receiver, arguments)

  bounds(node.operator_loc)
  operator = on_op("&&=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

foo &&= baz ^^^^^^^^^^^^^^^^

visit_index_operator_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2005
def visit_index_operator_write_node(node)
  receiver = visit(node.receiver)
  arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))

  bounds(node.location)
  target = on_aref_field(receiver, arguments)

  bounds(node.binary_operator_loc)
  operator = on_op("#{node.binary_operator}=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

foo += baz ^^^^^^^^^^^^^^^

visit_index_or_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2039
def visit_index_or_write_node(node)
  receiver = visit(node.receiver)
  arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))

  bounds(node.location)
  target = on_aref_field(receiver, arguments)

  bounds(node.operator_loc)
  operator = on_op("||=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

foo ||= baz ^^^^^^^^^^^^^^^^

visit_index_target_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2056
def visit_index_target_node(node)
  receiver = visit(node.receiver)
  arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))

  bounds(node.location)
  on_aref_field(receiver, arguments)
end

foo, = 1 ^^^^^^^^

visit_instance_variable_and_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2098
def visit_instance_variable_and_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_ivar(node.name.to_s))

  bounds(node.operator_loc)
  operator = on_op("&&=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

@foo &&= bar ^^^^^^^^^^^^

visit_instance_variable_operator_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2084
def visit_instance_variable_operator_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_ivar(node.name.to_s))

  bounds(node.binary_operator_loc)
  operator = on_op("#{node.binary_operator}=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

@foo += bar ^^^^^^^^^^^

visit_instance_variable_or_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2112
def visit_instance_variable_or_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_ivar(node.name.to_s))

  bounds(node.operator_loc)
  operator = on_op("||=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

@foo ||= bar ^^^^^^^^^^^^

visit_instance_variable_read_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2066
def visit_instance_variable_read_node(node)
  bounds(node.location)
  on_var_ref(on_ivar(node.name.to_s))
end

@foo ^^^^

visit_instance_variable_target_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2126
def visit_instance_variable_target_node(node)
  bounds(node.location)
  on_var_field(on_ivar(node.name.to_s))
end

@foo, = bar ^^^^

visit_instance_variable_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2073
def visit_instance_variable_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_ivar(node.name.to_s))
  value = visit_write_value(node.value)

  bounds(node.location)
  on_assign(target, value)
end

@foo = 1 ^^^^^^^^

visit_integer_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2133
def visit_integer_node(node)
  visit_number_node(node) { |text| on_int(text) }
end

1 ^

visit_interpolated_match_last_line_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2139
def visit_interpolated_match_last_line_node(node)
  bounds(node.opening_loc)
  on_regexp_beg(node.opening)

  bounds(node.parts.first.location)
  parts =
    node.parts.inject(on_regexp_new) do |content, part|
      on_regexp_add(content, visit_string_content(part))
    end

  bounds(node.closing_loc)
  closing = on_regexp_end(node.closing)

  bounds(node.location)
  on_regexp_literal(parts, closing)
end

if /foo #{bar}/ then end ^^^^^^^^^^^^

visit_interpolated_regular_expression_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2158
def visit_interpolated_regular_expression_node(node)
  bounds(node.opening_loc)
  on_regexp_beg(node.opening)

  bounds(node.parts.first.location)
  parts =
    node.parts.inject(on_regexp_new) do |content, part|
      on_regexp_add(content, visit_string_content(part))
    end

  bounds(node.closing_loc)
  closing = on_regexp_end(node.closing)

  bounds(node.location)
  on_regexp_literal(parts, closing)
end

/foo #{bar}/ ^^^^^^^^^^^^

visit_interpolated_string_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2177
def visit_interpolated_string_node(node)
  if node.opening&.start_with?("<<~")
    heredoc = visit_heredoc_string_node(node)

    bounds(node.location)
    on_string_literal(heredoc)
  elsif !node.heredoc? && node.parts.length > 1 && node.parts.any? { |part| (part.is_a?(StringNode) || part.is_a?(InterpolatedStringNode)) && !part.opening_loc.nil? }
    first, *rest = node.parts
    rest.inject(visit(first)) do |content, part|
      concat = visit(part)

      bounds(part.location)
      on_string_concat(content, concat)
    end
  else
    bounds(node.parts.first.location)
    parts =
      node.parts.inject(on_string_content) do |content, part|
        on_string_add(content, visit_string_content(part))
      end

    bounds(node.location)
    on_string_literal(parts)
  end
end

“foo #{bar}” ^^^^^^^^^^^^

visit_interpolated_symbol_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2205
def visit_interpolated_symbol_node(node)
  bounds(node.parts.first.location)
  parts =
    node.parts.inject(on_string_content) do |content, part|
      on_string_add(content, visit_string_content(part))
    end

  bounds(node.location)
  on_dyna_symbol(parts)
end

:“foo #{bar}” ^^^^^^^^^^^^^

visit_interpolated_x_string_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2218
def visit_interpolated_x_string_node(node)
  if node.opening.start_with?("<<~")
    heredoc = visit_heredoc_x_string_node(node)

    bounds(node.location)
    on_xstring_literal(heredoc)
  else
    bounds(node.parts.first.location)
    parts =
      node.parts.inject(on_xstring_new) do |content, part|
        on_xstring_add(content, visit_string_content(part))
      end

    bounds(node.location)
    on_xstring_literal(parts)
  end
end

foo #{bar} ^^^^^^^^^^^^

visit_it_local_variable_read_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2248
def visit_it_local_variable_read_node(node)
  bounds(node.location)
  on_vcall(on_ident(node.slice))
end

-> { it } ^^

visit_it_parameters_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2255
def visit_it_parameters_node(node)
end

-> { it } ^^^^^^^^^

visit_keyword_hash_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2260
def visit_keyword_hash_node(node)
  elements = visit_all(node.elements)

  bounds(node.location)
  on_bare_assoc_hash(elements)
end

foo(bar: baz) ^^^^^^^^

visit_keyword_rest_parameter_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2272
def visit_keyword_rest_parameter_node(node)
  if node.name_loc.nil?
    bounds(node.location)
    on_kwrest_param(nil)
  else
    bounds(node.name_loc)
    name = on_ident(node.name.to_s)

    bounds(node.location)
    on_kwrest_param(name)
  end
end

def foo(**bar); end ^^^^^

def foo(**); end ^^

visit_lambda_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2286
def visit_lambda_node(node)
  bounds(node.operator_loc)
  on_tlambda(node.operator)

  parameters =
    if node.parameters.is_a?(BlockParametersNode)
      # Ripper does not track block-locals within lambdas, so we skip
      # directly to the parameters here.
      params =
        if node.parameters.parameters.nil?
          bounds(node.location)
          on_params(nil, nil, nil, nil, nil, nil, nil)
        else
          visit(node.parameters.parameters)
        end

      if node.parameters.opening_loc.nil?
        params
      else
        bounds(node.parameters.opening_loc)
        on_paren(params)
      end
    else
      bounds(node.location)
      on_params(nil, nil, nil, nil, nil, nil, nil)
    end

  braces = node.opening == "{"
  if braces
    bounds(node.opening_loc)
    on_tlambeg(node.opening)
  end

  body =
    case node.body
    when nil
      bounds(node.location)
      stmts = on_stmts_add(on_stmts_new, on_void_stmt)

      bounds(node.location)
      braces ? stmts : on_bodystmt(stmts, nil, nil, nil)
    when StatementsNode
      stmts = node.body.body
      stmts.unshift(nil) if void_stmt?(node.parameters&.location || node.opening_loc, node.body.location, false)
      stmts = visit_statements_node_body(stmts)

      bounds(node.body.location)
      braces ? stmts : on_bodystmt(stmts, nil, nil, nil)
    when BeginNode
      visit_body_node(node.opening_loc, node.body)
    else
      raise
    end

  bounds(node.location)
  on_lambda(parameters, body)
end

-> {}

visit_local_variable_and_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2378
def visit_local_variable_and_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_ident(node.name_loc.slice))

  bounds(node.operator_loc)
  operator = on_op("&&=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

foo &&= bar ^^^^^^^^^^^

visit_local_variable_operator_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2364
def visit_local_variable_operator_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_ident(node.name_loc.slice))

  bounds(node.binary_operator_loc)
  operator = on_op("#{node.binary_operator}=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

foo += bar ^^^^^^^^^^

visit_local_variable_or_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2392
def visit_local_variable_or_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_ident(node.name_loc.slice))

  bounds(node.operator_loc)
  operator = on_op("||=")
  value = visit_write_value(node.value)

  bounds(node.location)
  on_opassign(target, operator, value)
end

foo ||= bar ^^^^^^^^^^^

visit_local_variable_read_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2346
def visit_local_variable_read_node(node)
  bounds(node.location)
  on_var_ref(on_ident(node.slice))
end

foo ^^^

visit_local_variable_target_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2406
def visit_local_variable_target_node(node)
  bounds(node.location)
  on_var_field(on_ident(node.name.to_s))
end

foo, = bar ^^^

visit_local_variable_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2353
def visit_local_variable_write_node(node)
  bounds(node.name_loc)
  target = on_var_field(on_ident(node.name_loc.slice))
  value = visit_write_value(node.value)

  bounds(node.location)
  on_assign(target, value)
end

foo = 1 ^^^^^^^

visit_match_last_line_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2413
def visit_match_last_line_node(node)
  bounds(node.opening_loc)
  on_regexp_beg(node.opening)

  bounds(node.content_loc)
  tstring_content = on_tstring_content(node.content)

  bounds(node.closing_loc)
  closing = on_regexp_end(node.closing)

  on_regexp_literal(on_regexp_add(on_regexp_new, tstring_content), closing)
end

if /foo/ then end ^^^^^

visit_match_predicate_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2428
def visit_match_predicate_node(node)
  value = visit(node.value)
  pattern = on_in(visit_pattern_node(node.pattern), nil, nil)

  on_case(value, pattern)
end

foo in bar ^^^^^^^^^^

visit_match_required_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2437
def visit_match_required_node(node)
  value = visit(node.value)
  pattern = on_in(visit_pattern_node(node.pattern), nil, nil)

  on_case(value, pattern)
end

foo => bar ^^^^^^^^^^

visit_match_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2446
def visit_match_write_node(node)
  visit(node.call)
end

/(?<foo>foo)/ =~ bar ^^^^^^^^^^^^^^^^^^^^

visit_missing_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2452
def visit_missing_node(node)
  raise "Cannot visit missing nodes directly."
end

Узел, отсутствующий в синтаксическом дереве. Используется только в случае синтаксической ошибки.

visit_module_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2458
def visit_module_node(node)
  constant_path =
    if node.constant_path.is_a?(ConstantReadNode)
      bounds(node.constant_path.location)
      on_const_ref(on_const(node.constant_path.name.to_s))
    else
      visit(node.constant_path)
    end

  bodystmt = visit_body_node(node.constant_path.location, node.body, true)

  bounds(node.location)
  on_module(constant_path, bodystmt)
end

module Foo; end ^^^^^^^^^^^^^^^

visit_multi_target_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2475
def visit_multi_target_node(node)
  bounds(node.location)
  targets = visit_multi_target_node_targets(node.lefts, node.rest, node.rights, true)

  if node.lparen_loc.nil?
    targets
  else
    bounds(node.lparen_loc)
    on_mlhs_paren(targets)
  end
end

(foo, bar), bar = qux ^^^^^^^^^^

visit_multi_write_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2529
def visit_multi_write_node(node)
  bounds(node.location)
  targets = visit_multi_target_node_targets(node.lefts, node.rest, node.rights, true)

  unless node.lparen_loc.nil?
    bounds(node.lparen_loc)
    targets = on_mlhs_paren(targets)
  end

  value = visit_write_value(node.value)

  bounds(node.location)
  on_massign(targets, value)
end

foo, bar = baz ^^^^^^^^^^^^^^

visit_next_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2549
def visit_next_node(node)
  if node.arguments.nil?
    bounds(node.location)
    on_next(on_args_new)
  else
    arguments = visit(node.arguments)

    bounds(node.location)
    on_next(arguments)
  end
end

next ^^^^

next foo ^^^^^^^^

visit_nil_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2563
def visit_nil_node(node)
  bounds(node.location)
  on_var_ref(on_kw("nil"))
end

nil ^^^

visit_no_keywords_parameter_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2570
def visit_no_keywords_parameter_node(node)
  bounds(node.location)
  on_nokw_param(nil)

  :nil
end

def foo(**nil); end ^^^^^

visit_numbered_parameters_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2579
def visit_numbered_parameters_node(node)
end

-> { 1 + 2 } ^^^^^^^^^^^^^^

visit_numbered_reference_read_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2584
def visit_numbered_reference_read_node(node)
  bounds(node.location)
  on_backref(node.slice)
end

$1 ^^

visit_optional_keyword_parameter_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2591
def visit_optional_keyword_parameter_node(node)
  bounds(node.name_loc)
  name = on_label("#{node.name}:")
  value = visit(node.value)

  [name, value]
end

def foo(bar: baz); end ^^^^^^^^

visit_optional_parameter_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2601
def visit_optional_parameter_node(node)
  bounds(node.name_loc)
  name = visit_token(node.name.to_s)
  value = visit(node.value)

  [name, value]
end

def foo(bar = 1); end ^^^^^^^

visit_or_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2611
def visit_or_node(node)
  left = visit(node.left)
  right = visit(node.right)

  bounds(node.location)
  on_binary(left, node.operator.to_sym, right)
end

a or b ^^^^^^

visit_parameters_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2621
def visit_parameters_node(node)
  requireds = node.requireds.map { |required| required.is_a?(MultiTargetNode) ? visit_destructured_parameter_node(required) : visit(required) } if node.requireds.any?
  optionals = visit_all(node.optionals) if node.optionals.any?
  rest = visit(node.rest)
  posts = node.posts.map { |post| post.is_a?(MultiTargetNode) ? visit_destructured_parameter_node(post) : visit(post) } if node.posts.any?
  keywords = visit_all(node.keywords) if node.keywords.any?
  keyword_rest = visit(node.keyword_rest)
  block = visit(node.block)

  bounds(node.location)
  on_params(requireds, optionals, rest, posts, keywords, keyword_rest, block)
end

def foo(bar, *baz); end ^^^^^^^^^

visit_parentheses_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2648
def visit_parentheses_node(node)
  body =
    if node.body.nil?
      on_stmts_add(on_stmts_new, on_void_stmt)
    else
      visit(node.body)
    end

  bounds(node.location)
  on_paren(body)
end

() ^^

(1) ^^^

visit_pinned_expression_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2662
def visit_pinned_expression_node(node)
  expression = visit(node.expression)

  bounds(node.location)
  on_begin(expression)
end

foo => ^(bar) ^^^^^^

visit_pinned_variable_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2671
def visit_pinned_variable_node(node)
  visit(node.variable)
end

foo = 1 and bar => ^foo ^^^^

visit_post_execution_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2677
def visit_post_execution_node(node)
  statements =
    if node.statements.nil?
      bounds(node.location)
      on_stmts_add(on_stmts_new, on_void_stmt)
    else
      visit(node.statements)
    end

  bounds(node.location)
  on_END(statements)
end

END {} ^^^^^^

visit_pre_execution_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2692
def visit_pre_execution_node(node)
  statements =
    if node.statements.nil?
      bounds(node.location)
      on_stmts_add(on_stmts_new, on_void_stmt)
    else
      visit(node.statements)
    end

  bounds(node.location)
  on_BEGIN(statements)
end

BEGIN {} ^^^^^^^^

visit_program_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2706
def visit_program_node(node)
  body = node.statements.body
  body << nil if body.empty?
  statements = visit_statements_node_body(body)

  bounds(node.location)
  on_program(statements)
end

Узел программы верхнего уровня.

visit_range_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2717
def visit_range_node(node)
  left = visit(node.left)
  right = visit(node.right)

  bounds(node.location)
  if node.exclude_end?
    on_dot3(left, right)
  else
    on_dot2(left, right)
  end
end

0..5 ^^^^

visit_rational_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2731
def visit_rational_node(node)
  visit_number_node(node) { |text| on_rational(text) }
end

1r ^^

visit_redo_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2737
def visit_redo_node(node)
  bounds(node.location)
  on_redo
end

redo ^^^^

visit_regular_expression_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2744
def visit_regular_expression_node(node)
  bounds(node.opening_loc)
  on_regexp_beg(node.opening)

  if node.content.empty?
    bounds(node.closing_loc)
    closing = on_regexp_end(node.closing)

    on_regexp_literal(on_regexp_new, closing)
  else
    bounds(node.content_loc)
    tstring_content = on_tstring_content(node.content)

    bounds(node.closing_loc)
    closing = on_regexp_end(node.closing)

    on_regexp_literal(on_regexp_add(on_regexp_new, tstring_content), closing)
  end
end

/foo/ ^^^^^

visit_required_keyword_parameter_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2766
def visit_required_keyword_parameter_node(node)
  bounds(node.name_loc)
  [on_label("#{node.name}:"), false]
end

def foo(bar:); end ^^^^

visit_required_parameter_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2773
def visit_required_parameter_node(node)
  bounds(node.location)
  on_ident(node.name.to_s)
end

def foo(bar); end ^^^

visit_rescue_modifier_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2780
def visit_rescue_modifier_node(node)
  expression = visit_write_value(node.expression)
  rescue_expression = visit(node.rescue_expression)

  bounds(node.location)
  on_rescue_mod(expression, rescue_expression)
end

foo rescue bar ^^^^^^^^^^^^^^

visit_rescue_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2790
def visit_rescue_node(node)
  exceptions =
    case node.exceptions.length
    when 0
      nil
    when 1
      if (exception = node.exceptions.first).is_a?(SplatNode)
        bounds(exception.location)
        on_mrhs_add_star(on_mrhs_new, visit(exception))
      else
        [visit(node.exceptions.first)]
      end
    else
      bounds(node.location)
      length = node.exceptions.length

      node.exceptions.each_with_index.inject(on_args_new) do |mrhs, (exception, index)|
        arg = visit(exception)

        bounds(exception.location)
        mrhs = on_mrhs_new_from_args(mrhs) if index == length - 1

        if exception.is_a?(SplatNode)
          if index == length - 1
            on_mrhs_add_star(mrhs, arg)
          else
            on_args_add_star(mrhs, arg)
          end
        else
          if index == length - 1
            on_mrhs_add(mrhs, arg)
          else
            on_args_add(mrhs, arg)
          end
        end
      end
    end

  reference = visit(node.reference)
  statements =
    if node.statements.nil?
      bounds(node.location)
      on_stmts_add(on_stmts_new, on_void_stmt)
    else
      visit(node.statements)
    end

  subsequent = visit(node.subsequent)

  bounds(node.location)
  on_rescue(exceptions, reference, statements, subsequent)
end

begin; rescue; end ^^^^^^^

visit_rest_parameter_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2848
def visit_rest_parameter_node(node)
  if node.name_loc.nil?
    bounds(node.location)
    on_rest_param(nil)
  else
    bounds(node.name_loc)
    on_rest_param(visit_token(node.name.to_s))
  end
end

def foo(*bar); end ^^^^

def foo(*); end ^

visit_retry_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2860
def visit_retry_node(node)
  bounds(node.location)
  on_retry
end

retry ^^^^^

visit_return_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2870
def visit_return_node(node)
  if node.arguments.nil?
    bounds(node.location)
    on_return0
  else
    arguments = visit(node.arguments)

    bounds(node.location)
    on_return(arguments)
  end
end

return ^^^^^^

return 1 ^^^^^^^^

visit_self_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2884
def visit_self_node(node)
  bounds(node.location)
  on_var_ref(on_kw("self"))
end

self ^^^^

visit_shareable_constant_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2890
def visit_shareable_constant_node(node)
  visit(node.write)
end

Константа, доступная для совместного использования.

visit_singleton_class_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2896
def visit_singleton_class_node(node)
  expression = visit(node.expression)
  bodystmt = visit_body_node(node.body&.location || node.end_keyword_loc, node.body)

  bounds(node.location)
  on_sclass(expression, bodystmt)
end

class << self; end ^^^^^^^^^^^^^^^^^^

visit_source_encoding_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2906
def visit_source_encoding_node(node)
  bounds(node.location)
  on_var_ref(on_kw("__ENCODING__"))
end

ENCODING ^^^^^^^^^^^^

visit_source_file_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2913
def visit_source_file_node(node)
  bounds(node.location)
  on_var_ref(on_kw("__FILE__"))
end

FILE ^^^^^^^^

visit_source_line_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2920
def visit_source_line_node(node)
  bounds(node.location)
  on_var_ref(on_kw("__LINE__"))
end

LINE ^^^^^^^^

visit_splat_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2933
def visit_splat_node(node)
  visit(node.expression)
end

foo(*bar) ^^^^

def foo((bar, *baz)); end ^^^^

def foo(); bar(); end ^

visit_statements_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2938
def visit_statements_node(node)
  bounds(node.location)
  visit_statements_node_body(node.body)
end

Список инструкций.

visit_string_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2955
def visit_string_node(node)
  if (content = node.content).empty?
    bounds(node.location)
    on_string_literal(on_string_content)
  elsif (opening = node.opening) == "?"
    bounds(node.location)
    on_CHAR("?#{node.content}")
  elsif opening.start_with?("<<~")
    heredoc = visit_heredoc_string_node(node.to_interpolated)

    bounds(node.location)
    on_string_literal(heredoc)
  else
    bounds(node.content_loc)
    tstring_content = on_tstring_content(content)

    bounds(node.location)
    on_string_literal(on_string_add(on_string_content, tstring_content))
  end
end

“foo” ^^^^^

visit_super_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3087
def visit_super_node(node)
  arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.rparen_loc || node.location))

  if !node.lparen_loc.nil?
    bounds(node.lparen_loc)
    arguments = on_arg_paren(arguments)
  end

  bounds(node.location)
  call = on_super(arguments)

  if block.nil?
    call
  else
    bounds(node.block.location)
    on_method_add_block(call, block)
  end
end

super(foo) ^^^^^^^^^^

visit_symbol_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3108
def visit_symbol_node(node)
  if (opening = node.opening)&.match?(/^%s|['"]:?$/)
    bounds(node.value_loc)
    content = on_string_content

    if !(value = node.value).empty?
      content = on_string_add(content, on_tstring_content(value))
    end

    on_dyna_symbol(content)
  elsif (closing = node.closing) == ":"
    bounds(node.location)
    on_label("#{node.value}:")
  elsif opening.nil? && node.closing_loc.nil?
    bounds(node.value_loc)
    on_symbol_literal(visit_token(node.value))
  else
    bounds(node.value_loc)
    on_symbol_literal(on_symbol(visit_token(node.value)))
  end
end

:foo ^^^^

visit_true_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3132
def visit_true_node(node)
  bounds(node.location)
  on_var_ref(on_kw("true"))
end

true ^^^^

visit_undef_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3139
def visit_undef_node(node)
  names = visit_all(node.names)

  bounds(node.location)
  on_undef(names)
end

undef foo ^^^^^^^^^

visit_unless_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3151
def visit_unless_node(node)
  if node.statements.nil? || (node.predicate.location.start_offset < node.statements.location.start_offset)
    predicate = visit(node.predicate)
    statements =
      if node.statements.nil?
        bounds(node.location)
        on_stmts_add(on_stmts_new, on_void_stmt)
      else
        visit(node.statements)
      end
    else_clause = visit(node.else_clause)

    bounds(node.location)
    on_unless(predicate, statements, else_clause)
  else
    statements = visit(node.statements.body.first)
    predicate = visit(node.predicate)

    bounds(node.location)
    on_unless_mod(predicate, statements)
  end
end

unless foo; bar end ^^^^^^^^^^^^^^^^^^^

bar unless foo ^^^^^^^^^^^^^^

visit_until_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3179
def visit_until_node(node)
  if node.statements.nil? || (node.predicate.location.start_offset < node.statements.location.start_offset)
    predicate = visit(node.predicate)
    statements =
      if node.statements.nil?
        bounds(node.location)
        on_stmts_add(on_stmts_new, on_void_stmt)
      else
        visit(node.statements)
      end

    bounds(node.location)
    on_until(predicate, statements)
  else
    statements = visit(node.statements.body.first)
    predicate = visit(node.predicate)

    bounds(node.location)
    on_until_mod(predicate, statements)
  end
end

until foo; bar end ^^^^^^^^^^^^^^^^^

bar until foo ^^^^^^^^^^^^^

visit_when_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3203
def visit_when_node(node)
  # This is a special case where we're not going to call on_when directly
  # because we don't have access to the subsequent. Instead, we'll return
  # the component parts and let the parent node handle it.
  conditions = visit_arguments(node.conditions)
  statements =
    if node.statements.nil?
      bounds(node.location)
      on_stmts_add(on_stmts_new, on_void_stmt)
    else
      visit(node.statements)
    end

  [conditions, statements]
end

case foo; when bar; end ^^^^^^^^^^^^^

visit_while_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3224
def visit_while_node(node)
  if node.statements.nil? || (node.predicate.location.start_offset < node.statements.location.start_offset)
    predicate = visit(node.predicate)
    statements =
      if node.statements.nil?
        bounds(node.location)
        on_stmts_add(on_stmts_new, on_void_stmt)
      else
        visit(node.statements)
      end

    bounds(node.location)
    on_while(predicate, statements)
  else
    statements = visit(node.statements.body.first)
    predicate = visit(node.predicate)

    bounds(node.location)
    on_while_mod(predicate, statements)
  end
end

while foo; bar end ^^^^^^^^^^^^^^^^^^

bar while foo ^^^^^^^^^^^^^

visit_x_string_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3248
def visit_x_string_node(node)
  if node.unescaped.empty?
    bounds(node.location)
    on_xstring_literal(on_xstring_new)
  elsif node.opening.start_with?("<<~")
    heredoc = visit_heredoc_x_string_node(node.to_interpolated)

    bounds(node.location)
    on_xstring_literal(heredoc)
  else
    bounds(node.content_loc)
    content = on_tstring_content(node.content)

    bounds(node.location)
    on_xstring_literal(on_xstring_add(on_xstring_new, content))
  end
end

foo ^^^^^

visit_yield_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3271
def visit_yield_node(node)
  if node.arguments.nil? && node.lparen_loc.nil?
    bounds(node.location)
    on_yield0
  else
    arguments =
      if node.arguments.nil?
        bounds(node.location)
        on_args_new
      else
        visit(node.arguments)
      end

    unless node.lparen_loc.nil?
      bounds(node.lparen_loc)
      arguments = on_paren(arguments)
    end

    bounds(node.location)
    on_yield(arguments)
  end
end

yield ^^^^^

yield 1 ^^^^^^^

Приватные методы экземпляра

bounds (location) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3401
def bounds(location)
  @lineno = location.start_line
  @column = location.start_column
end

Этот метод обновляет информацию о номере строки и столбце в соответствии с текущим узлом.

Этот метод можно было бы значительно улучшить, добавив кэширование начала каждой строки, но пока и так достаточно хорошо.

command? (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1174
        def command?(node)
  node.is_a?(CallNode) &&
    node.opening_loc.nil? &&
    (!node.arguments.nil? || node.block.is_a?(BlockArgumentNode)) &&
    !BINARY_OPERATORS.include?(node.name)
end

Возвращает true, если указанный узел является узлом команды.

compile_error (msg) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3439
def compile_error(msg)
end

Этот метод вызывается, когда парсер обнаруживает синтаксическую ошибку.

dedent_string (string, width) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3454
def dedent_string(string, width)
  whitespace = 0
  cursor = 0

  while cursor < string.length && string[cursor].match?(/\s/) && whitespace < width
    if string[cursor] == "\t"
      whitespace = ((whitespace / 8 + 1) * 8)
      break if whitespace > width
    else
      whitespace += 1
    end

    cursor += 1
  end

  string.replace(string[cursor..])
  cursor
end

Этот метод предоставляется расширением Ripper на C. Он вызывается, когда строку нужно очистить от отступов из-за heredoc с тильдой. Предполагается, что он изменит строку на месте и вернёт количество удалённых байтов.

result () Показать исходный код
# File lib/prism/translation/ripper.rb, line 3297
def result
  @result ||= Prism.parse(source, partial_script: true)
end

Инициализирует результат разбора по требованию.

trailing_comma? (left, right) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3306
def trailing_comma?(left, right)
  source.byteslice(left.end_offset...right.start_offset).include?(",")
end

Возвращает true, если между двумя позициями есть запятая.

visit_alias_global_variable_node_value (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 571
        def visit_alias_global_variable_node_value(node)
  bounds(node.location)

  case node
  when BackReferenceReadNode
    on_backref(node.slice)
  when GlobalVariableReadNode
    on_gvar(node.name.to_s)
  else
    raise
  end
end

Посещает одну из сторон узла глобальной переменной-псевдонима.

visit_arguments (elements) Показать исходный код
# File lib/prism/translation/ripper.rb, line 757
        def visit_arguments(elements)
  bounds(elements.first.location)
  elements.inject(on_args_new) do |args, element|
    arg = visit(element)
    bounds(element.location)

    case element
    when BlockArgumentNode
      on_args_add_block(args, arg)
    when SplatNode
      on_args_add_star(args, arg)
    else
      on_args_add(args, arg)
    end
  end
end

Посещает список элементов, например элементы массива или аргументы.

visit_begin_node_clauses (location, node, allow_newline) Показать исходный код
# File lib/prism/translation/ripper.rb, line 841
        def visit_begin_node_clauses(location, node, allow_newline)
  statements =
    if node.statements.nil?
      on_stmts_add(on_stmts_new, on_void_stmt)
    else
      body = node.statements.body
      body.unshift(nil) if void_stmt?(location, node.statements.body[0].location, allow_newline)

      bounds(node.statements.location)
      visit_statements_node_body(body)
    end

  rescue_clause = visit(node.rescue_clause)
  else_clause =
    unless (else_clause_node = node.else_clause).nil?
      else_statements =
        if else_clause_node.statements.nil?
          [nil]
        else
          body = else_clause_node.statements.body
          body.unshift(nil) if void_stmt?(else_clause_node.else_keyword_loc, else_clause_node.statements.body[0].location, allow_newline)
          body
        end

      bounds(else_clause_node.location)
      visit_statements_node_body(else_statements)
    end
  ensure_clause = visit(node.ensure_clause)

  bounds(node.location)
  on_bodystmt(statements, rescue_clause, else_clause, ensure_clause)
end

Посещает блоки узла begin, чтобы сформировать вызов on_bodystmt.

visit_body_node (location, node, allow_newline = false) Показать исходный код
# File lib/prism/translation/ripper.rb, line 876
        def visit_body_node(location, node, allow_newline = false)
  case node
  when nil
    bounds(location)
    on_bodystmt(visit_statements_node_body([nil]), nil, nil, nil)
  when StatementsNode
    body = [*node.body]
    body.unshift(nil) if void_stmt?(location, body[0].location, allow_newline)
    stmts = visit_statements_node_body(body)

    bounds(node.body.first.location)
    on_bodystmt(stmts, nil, nil, nil)
  when BeginNode
    visit_begin_node_clauses(location, node, allow_newline)
  else
    raise
  end
end

Посещает тело конструкции, которое может содержать набор инструкций или инструкции, заключённые в rescue/else/ensure.

visit_call_node_arguments (arguments_node, block_node, trailing_comma) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1147
        def visit_call_node_arguments(arguments_node, block_node, trailing_comma)
  arguments = arguments_node&.arguments || []
  block = block_node

  if block.is_a?(BlockArgumentNode)
    arguments << block
    block = nil
  end

  [
    if arguments.length == 1 && arguments.first.is_a?(ForwardingArgumentsNode)
      visit(arguments.first)
    elsif arguments.any?
      args = visit_arguments(arguments)

      if block_node.is_a?(BlockArgumentNode) || arguments.last.is_a?(ForwardingArgumentsNode) || command?(arguments.last) || trailing_comma
        args
      else
        bounds(arguments.first.location)
        on_args_add_block(args, false)
      end
    end,
    visit(block)
  ]
end

Посещает аргументы и блок узла вызова и возвращает их в том виде, в котором они должны использоваться.

visit_constant_path_write_node_target (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 1500
        def visit_constant_path_write_node_target(node)
  if node.parent.nil?
    bounds(node.name_loc)
    child = on_const(node.name.to_s)

    bounds(node.location)
    on_top_const_field(child)
  else
    parent = visit(node.parent)

    bounds(node.name_loc)
    child = on_const(node.name.to_s)

    bounds(node.location)
    on_const_path_field(parent, child)
  end
end

Посещает путь к константе, который является частью узла записи.

visit_destructured_parameter_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2635
        def visit_destructured_parameter_node(node)
  bounds(node.location)
  targets = visit_multi_target_node_targets(node.lefts, node.rest, node.rights, false)

  bounds(node.lparen_loc)
  on_mlhs_paren(targets)
end

Посещает узел деструктурированного позиционного параметра.

visit_heredoc_node (parts, base) { |result, on_tstring_content(map(&:content).join)| ... } Показать исходный код
# File lib/prism/translation/ripper.rb, line 3006
        def visit_heredoc_node(parts, base)
  common_whitespace = visit_heredoc_node_whitespace(parts)

  if common_whitespace == 0
    bounds(parts.first.location)

    string = []
    result = base

    parts.each do |part|
      if part.is_a?(StringNode)
        if string.empty?
          string = [part]
        else
          string << part
        end
      else
        unless string.empty?
          bounds(string[0].location)
          result = yield result, on_tstring_content(string.map(&:content).join)
          string = []
        end

        result = yield result, visit(part)
      end
    end

    unless string.empty?
      bounds(string[0].location)
      result = yield result, on_tstring_content(string.map(&:content).join)
    end

    result
  else
    bounds(parts.first.location)
    result =
      parts.inject(base) do |string_content, part|
        yield string_content, visit_string_content(part)
      end

    bounds(parts.first.location)
    on_heredoc_dedent(result, common_whitespace)
  end
end

Посещает строку, заданную с помощью heredoc <<~.

visit_heredoc_node_whitespace (parts) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2981
        def visit_heredoc_node_whitespace(parts)
  common_whitespace = nil
  dedent_next = true

  parts.each do |part|
    if part.is_a?(StringNode)
      if dedent_next && !(content = part.content).chomp.empty?
        common_whitespace = [
          common_whitespace || Float::INFINITY,
          content[/\A\s*/].each_char.inject(0) do |part_whitespace, char|
            char == "\t" ? ((part_whitespace / 8 + 1) * 8) : (part_whitespace + 1)
          end
        ].min
      end

      dedent_next = true
    else
      dedent_next = false
    end
  end

  common_whitespace || 0
end

Ripper возвращает содержимое строки с обработанными escape-последовательностями, но удаляет общие начальные пробелы. Prism возвращает содержимое строки без обработки escape-последовательностей и позицию содержимого строки с обработанными escape-последовательностями. К сожалению, эти варианты плохо сочетаются, поэтому здесь нужно заново определить общие начальные пробелы.

visit_heredoc_string_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3052
        def visit_heredoc_string_node(node)
  bounds(node.opening_loc)
  on_heredoc_beg(node.opening)

  bounds(node.location)
  result =
    visit_heredoc_node(node.parts, on_string_content) do |parts, part|
      on_string_add(parts, part)
    end

  bounds(node.closing_loc)
  on_heredoc_end(node.closing)

  result
end

Посещает узел heredoc, представляющий строку.

visit_heredoc_x_string_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3069
        def visit_heredoc_x_string_node(node)
  bounds(node.opening_loc)
  on_heredoc_beg(node.opening)

  bounds(node.location)
  result =
    visit_heredoc_node(node.parts, on_xstring_new) do |parts, part|
      on_xstring_add(parts, part)
    end

  bounds(node.closing_loc)
  on_heredoc_end(node.closing)

  result
end

Посещает узел heredoc, представляющий xstring.

visit_multi_target_node_targets (lefts, rest, rights, skippable) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2488
        def visit_multi_target_node_targets(lefts, rest, rights, skippable)
  if skippable && lefts.length == 1 && lefts.first.is_a?(MultiTargetNode) && rest.nil? && rights.empty?
    return visit(lefts.first)
  end

  mlhs = on_mlhs_new

  lefts.each do |left|
    bounds(left.location)
    mlhs = on_mlhs_add(mlhs, visit(left))
  end

  case rest
  when nil
    # do nothing
  when ImplicitRestNode
    # these do not get put into the generated tree
    bounds(rest.location)
    on_excessed_comma
  else
    bounds(rest.location)
    mlhs = on_mlhs_add_star(mlhs, visit(rest))
  end

  if rights.any?
    bounds(rights.first.location)
    post = on_mlhs_new

    rights.each do |right|
      bounds(right.location)
      post = on_mlhs_add(post, visit(right))
    end

    mlhs = on_mlhs_add_post(mlhs, post)
  end

  mlhs
end

Посещает цели узла с несколькими целями.

visit_number_node (node) { |slice| ... } Показать исходный код
# File lib/prism/translation/ripper.rb, line 3345
def visit_number_node(node)
  slice = node.slice
  location = node.location

  if slice[0] == "-"
    bounds(location.copy(start_offset: location.start_offset + 1))
    value = yield slice[1..-1]

    bounds(node.location)
    on_unary(:-@, value)
  else
    bounds(location)
    yield slice
  end
end

Посещает узел, представляющий число. Необходимо явно обработать унарный оператор -.

visit_pattern_node (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 596
        def visit_pattern_node(node)
  if node.is_a?(ParenthesesNode)
    visit(node.body)
  else
    visit(node)
  end
end

Посещает шаблон в сопоставлении с шаблоном. Это позволяет обойти узел скобок, который может использоваться для заключения шаблонов в скобки.

visit_statements_node_body (body) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2947
        def visit_statements_node_body(body)
  body.inject(on_stmts_new) do |stmts, stmt|
    on_stmts_add(stmts, stmt.nil? ? on_void_stmt : visit(stmt))
  end
end

Посещает список инструкций узла инструкций. Мы поддерживаем nil-инструкции в списке. Обычно структура дерева разбора prism не допускает их, но здесь мы добавляем их вручную, чтобы можно было воспроизвести void stmt в Ripper.

visit_string_content (part) Показать исходный код
# File lib/prism/translation/ripper.rb, line 2237
        def visit_string_content(part)
  if part.is_a?(StringNode)
    bounds(part.content_loc)
    on_tstring_content(part.content)
  else
    visit(part)
  end
end

Посещает отдельную часть узла строкового типа.

visit_token (token, allow_keywords = true) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3318
def visit_token(token, allow_keywords = true)
  case token
  when "."
    on_period(token)
  when "`"
    on_backtick(token)
  when *(allow_keywords ? KEYWORDS : [])
    on_kw(token)
  when /^_/
    on_ident(token)
  when /^[[:upper:]]\w*$/
    on_const(token)
  when /^@@/
    on_cvar(token)
  when /^@/
    on_ivar(token)
  when /^\$/
    on_gvar(token)
  when /^[[:punct:]]/
    on_op(token)
  else
    on_ident(token)
  end
end

Посещает строковое содержимое определённого узла. Этот метод используется для разделения на различные типы токенов.

visit_words_sep (opening_loc, previous, current) Показать исходный код
# File lib/prism/translation/ripper.rb, line 746
        def visit_words_sep(opening_loc, previous, current)
  end_offset = (previous.nil? ? opening_loc : previous.location).end_offset
  start_offset = current.location.start_offset

  if end_offset != start_offset
    bounds(current.location.copy(start_offset: end_offset))
    on_words_sep(source.byteslice(end_offset...start_offset))
  end
end

Вызывает событие words_sep, содержащее пробел между элементами литералов списков.

visit_write_value (node) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3363
def visit_write_value(node)
  if node.is_a?(ArrayNode) && node.opening_loc.nil?
    elements = node.elements
    length = elements.length

    bounds(elements.first.location)
    elements.each_with_index.inject((elements.first.is_a?(SplatNode) && length == 1) ? on_mrhs_new : on_args_new) do |args, (element, index)|
      arg = visit(element)
      bounds(element.location)

      if index == length - 1
        if element.is_a?(SplatNode)
          mrhs = index == 0 ? args : on_mrhs_new_from_args(args)
          on_mrhs_add_star(mrhs, arg)
        else
          on_mrhs_add(on_mrhs_new_from_args(args), arg)
        end
      else
        case element
        when BlockArgumentNode
          on_args_add_block(args, arg)
        when SplatNode
          on_args_add_star(args, arg)
        else
          on_args_add(args, arg)
        end
      end
    end
  else
    visit(node)
  end
end

Посещает узел, представляющий значение записи. Это используется для обработки особого случая неявного массива, создаваемого без скобок.

void_stmt? (left, right, allow_newline) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3311
def void_stmt?(left, right, allow_newline)
  pattern = allow_newline ? /[;\n]/ : /;/
  source.byteslice(left.end_offset...right.start_offset).match?(pattern)
end

Возвращает true, если между двумя позициями есть точка с запятой.

warn (fmt, *args) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3430
def warn(fmt, *args)
end

Этот метод вызывается, когда парсер выдаёт предупреждение низкой важности. fmt и args используют формат printf.

warning (fmt, *args) Показать исходный код
# File lib/prism/translation/ripper.rb, line 3435
def warning(fmt, *args)
end

Этот метод вызывается, когда парсер выдаёт предупреждение высокой важности. fmt и args используют формат printf.

Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API