ruby/test/error_highlight/test_error_highlight.rb

1353 строки
25 KiB
Ruby

require "test/unit"
require "error_highlight"
require "tempfile"
class ErrorHighlightTest < Test::Unit::TestCase
class DummyFormatter
def self.message_for(corrections)
""
end
end
def setup
if defined?(DidYouMean)
@did_you_mean_old_formatter = DidYouMean.formatter
DidYouMean.formatter = DummyFormatter
end
end
def teardown
if defined?(DidYouMean)
DidYouMean.formatter = @did_you_mean_old_formatter
end
end
if Exception.method_defined?(:detailed_message)
def assert_error_message(klass, expected_msg, &blk)
omit unless klass < ErrorHighlight::CoreExt
err = assert_raise(klass, &blk)
assert_equal(expected_msg.chomp, err.detailed_message(highlight: false).sub(/ \((?:NoMethod|Name)Error\)/, ""))
end
else
def assert_error_message(klass, expected_msg, &blk)
omit unless klass < ErrorHighlight::CoreExt
err = assert_raise(klass, &blk)
assert_equal(expected_msg.chomp, err.message)
end
end
if begin; 1.time; rescue; $!.message.end_with?("an instance of Integer"); end
# new message format
NEW_MESSAGE_FORMAT = true
NIL_RECV_MESSAGE = "nil"
ONE_RECV_MESSAGE = "an instance of Integer"
else
NEW_MESSAGE_FORMAT = false
NIL_RECV_MESSAGE = "nil:NilClass"
ONE_RECV_MESSAGE = "1:Integer"
end
def test_CALL_noarg_1
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ NIL_RECV_MESSAGE }
nil.foo + 1
^^^^
END
nil.foo + 1
end
end
def test_CALL_noarg_2
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ NIL_RECV_MESSAGE }
.foo + 1
^^^^
END
nil
.foo + 1
end
end
def test_CALL_noarg_3
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ NIL_RECV_MESSAGE }
foo + 1
^^^
END
nil.
foo + 1
end
end
def test_CALL_noarg_4
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ NIL_RECV_MESSAGE }
(nil).foo + 1
^^^^
END
(nil).foo + 1
end
end
def test_CALL_arg_1
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ NIL_RECV_MESSAGE }
nil.foo (42)
^^^^
END
nil.foo (42)
end
end
def test_CALL_arg_2
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ NIL_RECV_MESSAGE }
.foo (
^^^^
END
nil
.foo (
42
)
end
end
def test_CALL_arg_3
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ NIL_RECV_MESSAGE }
foo (
^^^
END
nil.
foo (
42
)
end
end
def test_CALL_arg_4
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ NIL_RECV_MESSAGE }
nil.foo(42)
^^^^
END
nil.foo(42)
end
end
def test_CALL_arg_5
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ NIL_RECV_MESSAGE }
.foo(
^^^^
END
nil
.foo(
42
)
end
end
def test_CALL_arg_6
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ NIL_RECV_MESSAGE }
foo(
^^^
END
nil.
foo(
42
)
end
end
def test_QCALL_1
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ ONE_RECV_MESSAGE }
1&.foo
^^^^^
END
1&.foo
end
end
def test_QCALL_2
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ ONE_RECV_MESSAGE }
1&.foo(42)
^^^^^
END
1&.foo(42)
end
end
def test_CALL_aref_1
assert_error_message(NoMethodError, <<~END) do
undefined method `[]' for #{ NIL_RECV_MESSAGE }
nil [ ]
^^^
END
nil [ ]
end
end
def test_CALL_aref_2
assert_error_message(NoMethodError, <<~END) do
undefined method `[]' for #{ NIL_RECV_MESSAGE }
nil [0]
^^^
END
nil [0]
end
end
def test_CALL_aref_3
assert_error_message(NoMethodError, <<~END) do
undefined method `[]' for #{ NIL_RECV_MESSAGE }
END
nil [
0
]
end
end
def test_CALL_aref_4
v = Object.new
recv = NEW_MESSAGE_FORMAT ? "an instance of Object" : v.inspect
assert_error_message(NoMethodError, <<~END) do
undefined method `[]' for #{ recv }
v &.[](0)
^^^^
END
v &.[](0)
end
end
def test_CALL_aref_5
assert_error_message(NoMethodError, <<~END) do
undefined method `[]' for #{ NIL_RECV_MESSAGE }
(nil)[ ]
^^^
END
(nil)[ ]
end
end
def test_CALL_aset
assert_error_message(NoMethodError, <<~END) do
undefined method `[]=' for #{ NIL_RECV_MESSAGE }
nil.[]=
^^^^
END
nil.[]=
end
end
def test_CALL_op_asgn
v = nil
assert_error_message(NoMethodError, <<~END) do
undefined method `+' for #{ NIL_RECV_MESSAGE }
v += 42
^
END
v += 42
end
end
def test_CALL_special_call_1
assert_error_message(NoMethodError, <<~END) do
undefined method `call' for #{ NIL_RECV_MESSAGE }
END
nil.()
end
end
def test_CALL_special_call_2
assert_error_message(NoMethodError, <<~END) do
undefined method `call' for #{ NIL_RECV_MESSAGE }
END
nil.(42)
end
end
def test_CALL_send
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ NIL_RECV_MESSAGE }
nil.send(:foo, 42)
^^^^^
END
nil.send(:foo, 42)
end
end
def test_ATTRASGN_1
assert_error_message(NoMethodError, <<~END) do
undefined method `[]=' for #{ NIL_RECV_MESSAGE }
nil [ ] = 42
^^^^^
END
nil [ ] = 42
end
end
def test_ATTRASGN_2
assert_error_message(NoMethodError, <<~END) do
undefined method `[]=' for #{ NIL_RECV_MESSAGE }
nil [0] = 42
^^^^^
END
nil [0] = 42
end
end
def test_ATTRASGN_3
assert_error_message(NoMethodError, <<~END) do
undefined method `foo=' for #{ NIL_RECV_MESSAGE }
nil.foo = 42
^^^^^^
END
nil.foo = 42
end
end
def test_ATTRASGN_4
assert_error_message(NoMethodError, <<~END) do
undefined method `[]=' for #{ NIL_RECV_MESSAGE }
(nil)[0] = 42
^^^^^
END
(nil)[0] = 42
end
end
def test_ATTRASGN_5
assert_error_message(NoMethodError, <<~END) do
undefined method `foo=' for #{ NIL_RECV_MESSAGE }
(nil).foo = 42
^^^^^^
END
(nil).foo = 42
end
end
def test_OPCALL_binary_1
assert_error_message(NoMethodError, <<~END) do
undefined method `+' for #{ NIL_RECV_MESSAGE }
nil + 42
^
END
nil + 42
end
end
def test_OPCALL_binary_2
assert_error_message(NoMethodError, <<~END) do
undefined method `+' for #{ NIL_RECV_MESSAGE }
nil + # comment
^
END
nil + # comment
42
end
end
def test_OPCALL_binary_3
assert_error_message(NoMethodError, <<~END) do
undefined method `+' for #{ NIL_RECV_MESSAGE }
(nil) + 42
^
END
(nil) + 42
end
end
def test_OPCALL_unary_1
assert_error_message(NoMethodError, <<~END) do
undefined method `+@' for #{ NIL_RECV_MESSAGE }
+ nil
^
END
+ nil
end
end
def test_OPCALL_unary_2
assert_error_message(NoMethodError, <<~END) do
undefined method `+@' for #{ NIL_RECV_MESSAGE }
+(nil)
^
END
+(nil)
end
end
def test_FCALL_1
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ NIL_RECV_MESSAGE }
nil.instance_eval { foo() }
^^^
END
nil.instance_eval { foo() }
end
end
def test_FCALL_2
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ NIL_RECV_MESSAGE }
nil.instance_eval { foo(42) }
^^^
END
nil.instance_eval { foo(42) }
end
end
def test_VCALL_2
assert_error_message(NameError, <<~END) do
undefined local variable or method `foo' for #{ NIL_RECV_MESSAGE }
nil.instance_eval { foo }
^^^
END
nil.instance_eval { foo }
end
end
def test_OP_ASGN1_aref_1
v = nil
assert_error_message(NoMethodError, <<~END) do
undefined method `[]' for #{ NIL_RECV_MESSAGE }
v [0] += 42
^^^
END
v [0] += 42
end
end
def test_OP_ASGN1_aref_2
v = nil
assert_error_message(NoMethodError, <<~END) do
undefined method `[]' for #{ NIL_RECV_MESSAGE }
v [0] += # comment
^^^
END
v [0] += # comment
42
end
end
def test_OP_ASGN1_aref_3
v = nil
assert_error_message(NoMethodError, <<~END) do
undefined method `[]' for #{ NIL_RECV_MESSAGE }
END
v [
0
] += # comment
42
end
end
def test_OP_ASGN1_aref_4
v = nil
assert_error_message(NoMethodError, <<~END) do
undefined method `[]' for #{ NIL_RECV_MESSAGE }
(v)[0] += 42
^^^
END
(v)[0] += 42
end
end
def test_OP_ASGN1_op_1
v = Object.new
def v.[](x); nil; end
assert_error_message(NoMethodError, <<~END) do
undefined method `+' for #{ NIL_RECV_MESSAGE }
v [0] += 42
^
END
v [0] += 42
end
end
def test_OP_ASGN1_op_2
v = Object.new
def v.[](x); nil; end
assert_error_message(NoMethodError, <<~END) do
undefined method `+' for #{ NIL_RECV_MESSAGE }
v [0 ] += # comment
^
END
v [0 ] += # comment
42
end
end
def test_OP_ASGN1_op_3
v = Object.new
def v.[](x); nil; end
assert_error_message(NoMethodError, <<~END) do
undefined method `+' for #{ NIL_RECV_MESSAGE }
END
v [
0
] +=
42
end
end
def test_OP_ASGN1_op_4
v = Object.new
def v.[](x); nil; end
assert_error_message(NoMethodError, <<~END) do
undefined method `+' for #{ NIL_RECV_MESSAGE }
(v)[0] += 42
^
END
(v)[0] += 42
end
end
def test_OP_ASGN1_aset_1
v = Object.new
def v.[](x); 1; end
assert_error_message(NoMethodError, <<~END) do
undefined method `[]=' for #{ v.inspect }
v [0] += 42
^^^^^^
END
v [0] += 42
end
end
def test_OP_ASGN1_aset_2
v = Object.new
def v.[](x); 1; end
assert_error_message(NoMethodError, <<~END) do
undefined method `[]=' for #{ v.inspect }
v [0] += # comment
^^^^^^
END
v [0] += # comment
42
end
end
def test_OP_ASGN1_aset_3
v = Object.new
def v.[](x); 1; end
assert_error_message(NoMethodError, <<~END) do
undefined method `[]=' for #{ v.inspect }
END
v [
0
] +=
42
end
end
def test_OP_ASGN1_aset_4
v = Object.new
def v.[](x); 1; end
assert_error_message(NoMethodError, <<~END) do
undefined method `[]=' for #{ v.inspect }
(v)[0] += 42
^^^^^^
END
(v)[0] += 42
end
end
def test_OP_ASGN2_read_1
v = nil
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ NIL_RECV_MESSAGE }
v.foo += 42
^^^^
END
v.foo += 42
end
end
def test_OP_ASGN2_read_2
v = nil
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ NIL_RECV_MESSAGE }
v.foo += # comment
^^^^
END
v.foo += # comment
42
end
end
def test_OP_ASGN2_read_3
v = nil
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ NIL_RECV_MESSAGE }
(v).foo += 42
^^^^
END
(v).foo += 42
end
end
def test_OP_ASGN2_op_1
v = Object.new
def v.foo; nil; end
assert_error_message(NoMethodError, <<~END) do
undefined method `+' for #{ NIL_RECV_MESSAGE }
v.foo += 42
^
END
v.foo += 42
end
end
def test_OP_ASGN2_op_2
v = Object.new
def v.foo; nil; end
assert_error_message(NoMethodError, <<~END) do
undefined method `+' for #{ NIL_RECV_MESSAGE }
v.foo += # comment
^
END
v.foo += # comment
42
end
end
def test_OP_ASGN2_op_3
v = Object.new
def v.foo; nil; end
assert_error_message(NoMethodError, <<~END) do
undefined method `+' for #{ NIL_RECV_MESSAGE }
(v).foo += 42
^
END
(v).foo += 42
end
end
def test_OP_ASGN2_write_1
v = Object.new
def v.foo; 1; end
assert_error_message(NoMethodError, <<~END) do
undefined method `foo=' for #{ v.inspect }
v.foo += 42
^^^^^^^
END
v.foo += 42
end
end
def test_OP_ASGN2_write_2
v = Object.new
def v.foo; 1; end
assert_error_message(NoMethodError, <<~END) do
undefined method `foo=' for #{ v.inspect }
v.foo += # comment
^^^^^^^
END
v.foo += # comment
42
end
end
def test_OP_ASGN2_write_3
v = Object.new
def v.foo; 1; end
assert_error_message(NoMethodError, <<~END) do
undefined method `foo=' for #{ v.inspect }
(v).foo += 42
^^^^^^^
END
(v).foo += 42
end
end
def test_CONST
assert_error_message(NameError, <<~END) do
uninitialized constant ErrorHighlightTest::NotDefined
1 + NotDefined + 1
^^^^^^^^^^
END
1 + NotDefined + 1
end
end
def test_COLON2_1
assert_error_message(NameError, <<~END) do
uninitialized constant ErrorHighlightTest::NotDefined
ErrorHighlightTest::NotDefined
^^^^^^^^^^^^
END
ErrorHighlightTest::NotDefined
end
end
def test_COLON2_2
assert_error_message(NameError, <<~END) do
uninitialized constant ErrorHighlightTest::NotDefined
NotDefined
^^^^^^^^^^
END
ErrorHighlightTest::
NotDefined
end
end
def test_COLON2_3
assert_error_message(NameError, <<~END) do
uninitialized constant ErrorHighlightTest::NotDefined
ErrorHighlightTest::NotDefined::Foo
^^^^^^^^^^^^
END
ErrorHighlightTest::NotDefined::Foo
end
end
def test_COLON2_4
assert_error_message(NameError, <<~END) do
uninitialized constant ErrorHighlightTest::NotDefined
::ErrorHighlightTest::NotDefined::Foo
^^^^^^^^^^^^
END
::ErrorHighlightTest::NotDefined::Foo
end
end
if ErrorHighlight.const_get(:Spotter).const_get(:OPT_GETCONSTANT_PATH)
def test_COLON2_5
# Unfortunately, we cannot identify which `NotDefined` caused the NameError
assert_error_message(NameError, <<~END) do
uninitialized constant ErrorHighlightTest::NotDefined
END
ErrorHighlightTest::NotDefined::NotDefined
end
end
else
def test_COLON2_5
assert_error_message(NameError, <<~END) do
uninitialized constant ErrorHighlightTest::NotDefined
ErrorHighlightTest::NotDefined::NotDefined
^^^^^^^^^^^^
END
ErrorHighlightTest::NotDefined::NotDefined
end
end
end
def test_COLON3
assert_error_message(NameError, <<~END) do
uninitialized constant NotDefined
::NotDefined
^^^^^^^^^^^^
END
::NotDefined
end
end
module OP_CDECL_TEST
Nil = nil
end
def test_OP_CDECL_read_1
assert_error_message(NameError, <<~END) do
uninitialized constant ErrorHighlightTest::OP_CDECL_TEST::NotDefined
OP_CDECL_TEST::NotDefined += 1
^^^^^^^^^^^^
END
OP_CDECL_TEST::NotDefined += 1
end
end
def test_OP_CDECL_read_2
assert_error_message(NameError, <<~END) do
uninitialized constant ErrorHighlightTest::OP_CDECL_TEST::NotDefined
OP_CDECL_TEST::NotDefined += # comment
^^^^^^^^^^^^
END
OP_CDECL_TEST::NotDefined += # comment
1
end
end
def test_OP_CDECL_read_3
assert_error_message(NameError, <<~END) do
uninitialized constant ErrorHighlightTest::OP_CDECL_TEST::NotDefined
END
OP_CDECL_TEST::
NotDefined += 1
end
end
def test_OP_CDECL_op_1
assert_error_message(NoMethodError, <<~END) do
undefined method `+' for #{ NIL_RECV_MESSAGE }
OP_CDECL_TEST::Nil += 1
^
END
OP_CDECL_TEST::Nil += 1
end
end
def test_OP_CDECL_op_2
assert_error_message(NoMethodError, <<~END) do
undefined method `+' for #{ NIL_RECV_MESSAGE }
OP_CDECL_TEST::Nil += # comment
^
END
OP_CDECL_TEST::Nil += # comment
1
end
end
def test_OP_CDECL_op_3
assert_error_message(NoMethodError, <<~END) do
undefined method `+' for #{ NIL_RECV_MESSAGE }
Nil += 1
^
END
OP_CDECL_TEST::
Nil += 1
end
end
def test_OP_CDECL_toplevel_1
assert_error_message(NameError, <<~END) do
uninitialized constant NotDefined
::NotDefined += 1
^^^^^^^^^^^^
END
::NotDefined += 1
end
end
def test_OP_CDECL_toplevel_2
recv = NEW_MESSAGE_FORMAT ? "class ErrorHighlightTest" : "ErrorHighlightTest:Class"
assert_error_message(NoMethodError, <<~END) do
undefined method `+' for #{ recv }
::ErrorHighlightTest += 1
^
END
::ErrorHighlightTest += 1
end
end
def test_explicit_raise_name_error
assert_error_message(NameError, <<~END) do
NameError
raise NameError
^^^^^
END
raise NameError
end
end
def test_explicit_raise_no_method_error
assert_error_message(NoMethodError, <<~END) do
NoMethodError
raise NoMethodError
^^^^^
END
raise NoMethodError
end
end
def test_const_get
assert_error_message(NameError, <<~END) do
uninitialized constant ErrorHighlightTest::NotDefined
ErrorHighlightTest.const_get(:NotDefined)
^^^^^^^^^^
END
ErrorHighlightTest.const_get(:NotDefined)
end
end
def test_local_variable_get
b = binding
assert_error_message(NameError, <<~END) do
local variable `foo' is not defined for #{ b.inspect }
b.local_variable_get(:foo)
^^^^^^^^^^^^^^^^^^^
END
b.local_variable_get(:foo)
end
end
def test_multibyte
assert_error_message(NoMethodError, <<~END) do
undefined method `' for #{ NIL_RECV_MESSAGE }
END
nil.あいうえお
end
end
def test_args_CALL_1
assert_error_message(TypeError, <<~END) do
nil can't be coerced into Integer (TypeError)
1.+(nil)
^^^
END
1.+(nil)
end
end
def test_args_CALL_2
v = []
assert_error_message(TypeError, <<~END) do
no implicit conversion from nil to integer (TypeError)
v[nil]
^^^
END
v[nil]
end
end
def test_args_ATTRASGN_1
v = []
assert_error_message(ArgumentError, <<~END) do
wrong number of arguments (given 1, expected 2..3) (ArgumentError)
v [ ] = 1
^^^^^^
END
v [ ] = 1
end
end
def test_args_ATTRASGN_2
v = []
assert_error_message(TypeError, <<~END) do
no implicit conversion from nil to integer (TypeError)
v [nil] = 1
^^^^^^^^
END
v [nil] = 1
end
end
def test_args_ATTRASGN_3
assert_error_message(TypeError, <<~END) do
no implicit conversion of String into Integer (TypeError)
$stdin.lineno = "str"
^^^^^
END
$stdin.lineno = "str"
end
end
def test_args_OPCALL
assert_error_message(TypeError, <<~END) do
nil can't be coerced into Integer (TypeError)
1 + nil
^^^
END
1 + nil
end
end
def test_args_FCALL_1
assert_error_message(TypeError, <<~END) do
no implicit conversion of Symbol into String (TypeError)
"str".instance_eval { gsub("foo", :sym) }
^^^^^^^^^^^
END
"str".instance_eval { gsub("foo", :sym) }
end
end
def test_args_FCALL_2
assert_error_message(TypeError, <<~END) do
no implicit conversion of Symbol into String (TypeError)
"str".instance_eval { gsub "foo", :sym }
^^^^^^^^^^^
END
"str".instance_eval { gsub "foo", :sym }
end
end
def test_args_OP_ASGN1_aref_1
v = []
assert_error_message(TypeError, <<~END) do
no implicit conversion from nil to integer (TypeError)
v [nil] += 42
^^^^^^^^^^
END
v [nil] += 42
end
end
def test_args_OP_ASGN1_aref_2
v = []
assert_error_message(ArgumentError, <<~END) do
wrong number of arguments (given 0, expected 1..2) (ArgumentError)
v [ ] += 42
^^^^^^^^
END
v [ ] += 42
end
end
def test_args_OP_ASGN1_op
v = [1]
assert_error_message(TypeError, <<~END) do
nil can't be coerced into Integer (TypeError)
v [0] += nil
^^^^^^^^^
END
v [0] += nil
end
end
def test_args_OP_ASGN2
v = Object.new
def v.foo; 1; end
assert_error_message(TypeError, <<~END) do
nil can't be coerced into Integer (TypeError)
v.foo += nil
^^^
END
v.foo += nil
end
end
def test_custom_formatter
custom_formatter = Object.new
def custom_formatter.message_for(spot)
"\n\n" + spot.except(:script_lines).inspect
end
original_formatter, ErrorHighlight.formatter = ErrorHighlight.formatter, custom_formatter
assert_error_message(NoMethodError, <<~END) do
undefined method `time' for #{ ONE_RECV_MESSAGE }
{:first_lineno=>#{ __LINE__ + 3 }, :first_column=>7, :last_lineno=>#{ __LINE__ + 3 }, :last_column=>12, :snippet=>" 1.time {}\\n"}
END
1.time {}
end
ensure
ErrorHighlight.formatter = original_formatter
end
def test_hard_tabs
Tempfile.create(["error_highlight_test", ".rb"], binmode: true) do |tmp|
tmp << "\t \t1.time {}\n"
tmp.close
assert_error_message(NoMethodError, <<~END.gsub("_", "\t")) do
undefined method `time' for #{ ONE_RECV_MESSAGE }
_ _1.time {}
_ _ ^^^^^
END
load tmp.path
end
end
end
def test_no_final_newline
Tempfile.create(["error_highlight_test", ".rb"], binmode: true) do |tmp|
tmp << "1.time {}"
tmp.close
assert_error_message(NoMethodError, <<~END) do
undefined method `time' for #{ ONE_RECV_MESSAGE }
1.time {}
^^^^^
END
load tmp.path
end
end
end
def test_simulate_funcallv_from_embedded_ruby
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for #{ NIL_RECV_MESSAGE }
END
nil.foo + 1
rescue NoMethodError => exc
def exc.backtrace_locations = []
raise
end
end
def test_spoofed_filename
Tempfile.create(["error_highlight_test", ".rb"], binmode: true) do |tmp|
tmp << "module Dummy\nend\n"
tmp.close
recv = NEW_MESSAGE_FORMAT ? "an instance of String" : '"dummy":String'
assert_error_message(NameError, <<~END) do
undefined local variable or method `foo' for #{ recv }
END
"dummy".instance_eval do
eval <<-END, nil, tmp.path
foo
END
end
end
end
end
def raise_name_error
1.time
end
def test_spot_with_backtrace_location
lineno = __LINE__
begin
raise_name_error
rescue NameError => exc
end
spot = ErrorHighlight.spot(exc).except(:script_lines)
assert_equal(lineno - 4, spot[:first_lineno])
assert_equal(lineno - 4, spot[:last_lineno])
assert_equal(5, spot[:first_column])
assert_equal(10, spot[:last_column])
assert_equal(" 1.time\n", spot[:snippet])
spot = ErrorHighlight.spot(exc, backtrace_location: exc.backtrace_locations[1]).except(:script_lines)
assert_equal(lineno + 2, spot[:first_lineno])
assert_equal(lineno + 2, spot[:last_lineno])
assert_equal(6, spot[:first_column])
assert_equal(22, spot[:last_column])
assert_equal(" raise_name_error\n", spot[:snippet])
end
def test_spot_with_node
omit unless RubyVM::AbstractSyntaxTree.respond_to?(:node_id_for_backtrace_location)
begin
raise_name_error
rescue NameError => exc
end
bl = exc.backtrace_locations.first
expected_spot = ErrorHighlight.spot(exc, backtrace_location: bl)
ast = RubyVM::AbstractSyntaxTree.parse_file(__FILE__, keep_script_lines: true)
node_id = RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(bl)
node = find_node_by_id(ast, node_id)
actual_spot = ErrorHighlight.spot(node)
assert_equal expected_spot, actual_spot
end
private
def find_node_by_id(node, node_id)
return node if node.node_id == node_id
node.children.each do |child|
next unless child.is_a?(RubyVM::AbstractSyntaxTree::Node)
found = find_node_by_id(child, node_id)
return found if found
end
return false
end
end