класс Prism::Translation::Ripper
Этот класс обеспечивает совместимость между 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
-
Эта таблица содержит все события сканера и их соответствующую арность.
Атрибуты
Текущий номер столбца парсера.
Имя файла исходного кода, который анализируется.
Текущий номер строки парсера.
Исходный код, который анализируется.
Публичные методы класса
Исходный код
# File lib/prism/translation/ripper.rb, line 72
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 для повышения SyntaxError для ошибки в src.
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 ]] Исходный код
# File lib/prism/translation/ripper.rb, line 444 def initialize(source, filename = "(ripper)", lineno = 1) @source = source @filename = filename @lineno = lineno @column = 0 @result = nil end
Создаёт новый объект Translation::Ripper с заданным исходным кодом.
Исходный код
Исходный код
# File lib/prism/translation/ripper.rb, line 381
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-exp. Возвращает более читаемое дерево, а не Ripper.sexp_raw. Этот метод предназначен в основном для разработчиков. Аргумент filename в основном игнорируется. По умолчанию этот метод не обрабатывает синтаксические ошибки в src, возвращая nil в таких случаях. Используйте ключевое слово raise_errors для повышения SyntaxError для ошибки в src.
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]]]] Исходный код
# File lib/prism/translation/ripper.rb, line 416
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-exp. Этот метод предназначен в основном для разработчиков. Аргумент filename в основном игнорируется. По умолчанию этот метод не обрабатывает синтаксические ошибки в src, возвращая nil в таких случаях. Используйте ключевое слово raise_errors для повышения SyntaxError для ошибки в src.
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]]]] Публичные методы экземпляра
Исходный код
# File lib/prism/translation/ripper.rb, line 457 def error? result.failure? end
True, если парсер встретил ошибку во время парсинга.
Исходный код
# File lib/prism/translation/ripper.rb, line 462
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 Разбирает исходный код и возвращает результат.
Исходный код
# File lib/prism/translation/ripper.rb, line 561 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 ^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 551 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 ^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 585 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
^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 605 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 ^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 796 def visit_arguments_node(node) arguments, _ = visit_call_node_arguments(node, nil, false) arguments end
foo(bar)
^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 615
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 -
^^
Исходный код
# File lib/prism/translation/ripper.rb, line 775
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]
^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 803 def visit_assoc_node(node) key = visit(node.key) value = visit(node.value) bounds(node.location) on_assoc_new(key, value) end
{ a: 1 }
^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 816 def visit_assoc_splat_node(node) value = visit(node.value) bounds(node.location) on_assoc_splat(value) end
def foo(**); bar(**); end
^^
{ **foo }
^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 825 def visit_back_reference_read_node(node) bounds(node.location) on_backref(node.slice) end
$+ ^^
Исходный код
# File lib/prism/translation/ripper.rb, line 832 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 ^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 896 def visit_block_argument_node(node) visit(node.expression) end
foo(&bar)
^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 902 def visit_block_local_variable_node(node) bounds(node.location) on_ident(node.name.to_s) end
foo { |; bar| }
^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 908
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 Visit a BlockNode.
Исходный код
# File lib/prism/translation/ripper.rb, line 944
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
^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 958
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 Параметры блока.
Исходный код
# File lib/prism/translation/ripper.rb, line 982
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 ^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1194
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 ^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1002
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 :!
receiver = visit(node.receiver)
bounds(node.location)
on_unary(node.message == "not" ? :not : :!, receiver)
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() {} ^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1172
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 ^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1216
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 ^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1238
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 ^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1263 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
^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1286
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 ^^^^^^^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1273
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 ^^^^^^^^^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1299
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 ^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1352
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 ^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1338
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 ^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1366
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 ^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1317 def visit_class_variable_read_node(node) bounds(node.location) on_var_ref(on_cvar(node.slice)) end
@@foo ^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1380 def visit_class_variable_target_node(node) bounds(node.location) on_var_field(on_cvar(node.name.to_s)) end
@@foo, = bar ^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1327 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 ^^^^^ ^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1422
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 ^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1408
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 ^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1436
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 ^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1523
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 ^^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1457
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 ^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1509
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 ^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1537
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 ^^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1551 def visit_constant_path_target_node(node) visit_constant_path_write_node_target(node) end
Foo::Bar, = baz ^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1480 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 ^^^^^^^^ ^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1387 def visit_constant_read_node(node) bounds(node.location) on_var_ref(on_const(node.name.to_s)) end
Foo ^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1450 def visit_constant_target_node(node) bounds(node.location) on_var_field(on_const(node.name.to_s)) end
Foo, = bar ^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1397 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 ^^^ ^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1560
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 ^^^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1607 def visit_defined_node(node) bounds(node.location) on_defined(visit(node.value)) end
defined? a ^^^^^^^^^^
defined?(a) ^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1614
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
^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1630
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}”
^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1651 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”
^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1662
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.
Исходный код
# File lib/prism/translation/ripper.rb, line 1680
def visit_false_node(node)
bounds(node.location)
on_var_ref(on_kw("false"))
end false ^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1687
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, *]
^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1712
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
^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1726
def visit_float_node(node)
visit_number_node(node) { |text| on_float(text) }
end 1.0 ^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1732
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 ^^^^^^^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1749 def visit_forwarding_arguments_node(node) bounds(node.location) on_args_forward end
def foo(…); bar(…); end
^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1756 def visit_forwarding_parameter_node(node) bounds(node.location) on_args_forward end
def foo(…); end
^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1766
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 {} ^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1815
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 ^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1801
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 ^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1829
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 ^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1780 def visit_global_variable_read_node(node) bounds(node.location) on_var_ref(on_gvar(node.name.to_s)) end
$foo ^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1843 def visit_global_variable_target_node(node) bounds(node.location) on_var_field(on_gvar(node.name.to_s)) end
$foo, = bar ^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1790 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 ^^^^ ^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1850
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 {} ^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1865
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 => {}
^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1907
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 ^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1943
def visit_imaginary_node(node)
visit_number_node(node) { |text| on_imaginary(text) }
end 1i ^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1949 def visit_implicit_node(node) end
{ foo: }
^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1954 def visit_implicit_rest_node(node) bounds(node.location) on_excessed_comma end
foo { |bar,| }
^
Исходный код
# File lib/prism/translation/ripper.rb, line 1961
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 ^^^^^^^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1996
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 ^^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 1979
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 ^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2013
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 ^^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2030 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 ^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2072
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 ^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2058
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 ^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2086
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 ^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2040 def visit_instance_variable_read_node(node) bounds(node.location) on_var_ref(on_ivar(node.name.to_s)) end
@foo ^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2100 def visit_instance_variable_target_node(node) bounds(node.location) on_var_field(on_ivar(node.name.to_s)) end
@foo, = bar ^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2047 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 ^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2107
def visit_integer_node(node)
visit_number_node(node) { |text| on_int(text) }
end 1 ^
Исходный код
# File lib/prism/translation/ripper.rb, line 2113
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
^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2132
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}/ ^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2151
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}” ^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2179
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}” ^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2192
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}` ^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2222 def visit_it_local_variable_read_node(node) bounds(node.location) on_vcall(on_ident(node.slice)) end
-> { it }
^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2229 def visit_it_parameters_node(node) end
-> { it } ^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2234 def visit_keyword_hash_node(node) elements = visit_all(node.elements) bounds(node.location) on_bare_assoc_hash(elements) end
foo(bar: baz)
^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2246
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
^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2260
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 -> {}
Исходный код
# File lib/prism/translation/ripper.rb, line 2352
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 ^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2338
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 ^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2366
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 ^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2320 def visit_local_variable_read_node(node) bounds(node.location) on_var_ref(on_ident(node.slice)) end
foo ^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2380 def visit_local_variable_target_node(node) bounds(node.location) on_var_field(on_ident(node.name.to_s)) end
foo, = bar ^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2327 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 ^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2387 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
^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2402 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 ^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2411 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 ^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2420 def visit_match_write_node(node) visit(node.call) end
/(?<foo>foo)/ =~ bar ^^^^^^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2426 def visit_missing_node(node) raise "Cannot visit missing nodes directly." end
Узел, отсутствующий в синтаксическом дереве. Используется только в случае синтаксической ошибки.
Исходный код
# File lib/prism/translation/ripper.rb, line 2432
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 ^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2449
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 ^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2503
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 ^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2523
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 следующий ^^^^
следующий foo ^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2537
def visit_nil_node(node)
bounds(node.location)
on_var_ref(on_kw("nil"))
end nil ^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2544 def visit_no_keywords_parameter_node(node) bounds(node.location) on_nokw_param(nil) :nil end
def foo(**nil); end
^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2553 def visit_numbered_parameters_node(node) end
-> { _1 + _2 } ^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2558 def visit_numbered_reference_read_node(node) bounds(node.location) on_backref(node.slice) end
$1 ^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2565
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
^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2575 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
^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2585 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 или b ^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2595
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
^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2622
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) ^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2636 def visit_pinned_expression_node(node) expression = visit(node.expression) bounds(node.location) on_begin(expression) end
foo => ^(bar)
^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2645 def visit_pinned_variable_node(node) visit(node.variable) end
foo = 1 и bar => ^foo
^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2651
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 КОНЕЦ {} ^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2666
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 НАЧАЛО {} ^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2680 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
Узел программы верхнего уровня.
Исходный код
# File lib/prism/translation/ripper.rb, line 2691
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 ^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2705
def visit_rational_node(node)
visit_number_node(node) { |text| on_rational(text) }
end 1r ^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2711 def visit_redo_node(node) bounds(node.location) on_redo end
повторить ^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2718
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/ ^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2740
def visit_required_keyword_parameter_node(node)
bounds(node.name_loc)
[on_label("#{node.name}:"), false]
end def foo(bar:); end
^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2747 def visit_required_parameter_node(node) bounds(node.location) on_ident(node.name.to_s) end
def foo(bar); end
^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2754 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 ^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2764
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
^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2822
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
^
Исходный код
# File lib/prism/translation/ripper.rb, line 2834 def visit_retry_node(node) bounds(node.location) on_retry end
повторить ^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2844
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 ^^^^^^
возвратить 1 ^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2858
def visit_self_node(node)
bounds(node.location)
on_var_ref(on_kw("self"))
end self ^^^^
Исходный код
Постоянная величина, доступная для совместного использования.
Исходный код
# File lib/prism/translation/ripper.rb, line 2870 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 ^^^^^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2880
def visit_source_encoding_node(node)
bounds(node.location)
on_var_ref(on_kw("__ENCODING__"))
end __ENCODING__ ^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2887
def visit_source_file_node(node)
bounds(node.location)
on_var_ref(on_kw("__FILE__"))
end __FILE__ ^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2894
def visit_source_line_node(node)
bounds(node.location)
on_var_ref(on_kw("__LINE__"))
end __LINE__ ^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 2907 def visit_splat_node(node) visit(node.expression) end
foo(*bar)
^^^^
def foo((bar, *baz)); end
^^^^
def foo(*); bar(*); end
^
Исходный код
# File lib/prism/translation/ripper.rb, line 2912 def visit_statements_node(node) bounds(node.location) visit_statements_node_body(node.body) end
Список инструкций.
Исходный код
# File lib/prism/translation/ripper.rb, line 2929
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” ^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 3061
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) ^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 3082
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 ^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 3106
def visit_true_node(node)
bounds(node.location)
on_var_ref(on_kw("true"))
end true ^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 3113 def visit_undef_node(node) names = visit_all(node.names) bounds(node.location) on_undef(names) end
undef foo ^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 3125
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 ^^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 3153
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 ^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 3177
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
^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 3198
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 ^^^^^^^^^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 3222
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` ^^^^^
Исходный код
# File lib/prism/translation/ripper.rb, line 3245
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 ^^^^^^^
Методы приватного экземпляра
Исходный код
# File lib/prism/translation/ripper.rb, line 3375 def bounds(location) @lineno = location.start_line @column = location.start_column end
Этот метод отвечает за обновление информации о строке и столбце для отражения текущего узла.
Этот метод можно значительно улучшить с помощью кэширования в начале каждой строки, но пока он достаточно хороший.
Исходный код
# File lib/prism/translation/ripper.rb, line 1163
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, если заданный узел является узлом команды.
Исходный код
# File lib/prism/translation/ripper.rb, line 3413 def compile_error(msg) end
Этот метод вызывается, когда парсер обнаруживает синтаксическую ошибку.
Исходный код
# File lib/prism/translation/ripper.rb, line 3428
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 Этот метод предоставляется расширением C Ripper. Он вызывается, когда строка должна быть деиндентифицирована из-за тильды heredoc. Ожидается, что он изменит строку на месте и вернёт количество байтов, которые были удалены.
Исходный код
# File lib/prism/translation/ripper.rb, line 3271 def result @result ||= Prism.parse(source, partial_script: true) end
Ленивая инициализация результата разбора.
Исходный код
# File lib/prism/translation/ripper.rb, line 3280
def trailing_comma?(left, right)
source.byteslice(left.end_offset...right.start_offset).include?(",")
end Возвращает true, если между двумя местоположениями есть запятая.
Исходный код
# File lib/prism/translation/ripper.rb, line 570
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 Посещение одной стороны узла alias global variable.
Исходный код
# File lib/prism/translation/ripper.rb, line 756
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 Посещение списка элементов, таких как элементы массива или аргументы.
Исходный код
# File lib/prism/translation/ripper.rb, line 840
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.
Исходный код
# File lib/prism/translation/ripper.rb, line 875
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.
Исходный код
# File lib/prism/translation/ripper.rb, line 1136
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 Посещение аргументов и блока узла вызова и возвращение аргументов и блока в соответствии с ожидаемым использованием.
Исходный код
# File lib/prism/translation/ripper.rb, line 1489
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 Посещение константного пути, являющегося частью узла записи.
Исходный код
# File lib/prism/translation/ripper.rb, line 2609
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 Посещение узла деструктурированного позиционного параметра.
Исходный код
# File lib/prism/translation/ripper.rb, line 2980
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 <<~.
Исходный код
# File lib/prism/translation/ripper.rb, line 2955
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 возвращает строку содержимого со снятыми общими отступами. Prism возвращает строку содержимого без экранирования и местоположение для строки содержимого с экранированием. К сожалению, эти функции не работают хорошо вместе, поэтому здесь нам нужно повторно вывести общие отступы.
Исходный код
# File lib/prism/translation/ripper.rb, line 3026
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, представляющего строку.
Исходный код
# File lib/prism/translation/ripper.rb, line 3043
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.
Исходный код
# File lib/prism/translation/ripper.rb, line 2462
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 Посетить целевые узлы узла с несколькими целевыми узлами.
Исходный код
# File lib/prism/translation/ripper.rb, line 3319
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 Посетить узел, представляющий число. Нам необходимо явно обработать унарный оператор -.
Исходный код
# File lib/prism/translation/ripper.rb, line 595
def visit_pattern_node(node)
if node.is_a?(ParenthesesNode)
visit(node.body)
else
visit(node)
end
end Посетить шаблон внутри сопоставления с шаблоном. Это используется для обхода узла скобок, который может использоваться для обертывания шаблонов.
Исходный код
# File lib/prism/translation/ripper.rb, line 2921
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 Посетить список операторов узла операторов. Мы поддерживаем пустые операторы в списке. Обычно это не допускается структурой дерева синтаксического разбора prism, но мы вручную добавляем их сюда, чтобы мы могли отобразить пустой оператор Ripper.
Исходный код
# File lib/prism/translation/ripper.rb, line 2211
def visit_string_content(part)
if part.is_a?(StringNode)
bounds(part.content_loc)
on_tstring_content(part.content)
else
visit(part)
end
end Посетить отдельную часть узла строкового типа.
Исходный код
# File lib/prism/translation/ripper.rb, line 3292
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 Посетить строковое содержимое конкретного узла. Этот метод используется для разделения на различные типы токенов.
Исходный код
# File lib/prism/translation/ripper.rb, line 745
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, содержащее пробел между элементами списковых литералов.
Исходный код
# File lib/prism/translation/ripper.rb, line 3337
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 Посетить узел, представляющий значение записи. Это используется для обработки специального случая неявного массива, который генерируется без скобок.
Исходный код
# File lib/prism/translation/ripper.rb, line 3285 def void_stmt?(left, right, allow_newline) pattern = allow_newline ? /[;\n]/ : /;/ source.byteslice(left.end_offset...right.start_offset).match?(pattern) end
Возвращает true, если между двумя локациями есть точка с запятой.
Исходный код
# File lib/prism/translation/ripper.rb, line 3404 def warn(fmt, *args) end
Этот метод вызывается, когда синтаксическим анализатором генерируется слабое предупреждение. fmt и args имеет стиль printf.
Исходный код
# File lib/prism/translation/ripper.rb, line 3409 def warning(fmt, *args) end
Этот метод вызывается, когда синтаксическим анализатором генерируется сильное предупреждение. fmt и args имеет стиль printf.
Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.