diff options
author | Yusuke Endoh <[email protected]> | 2021-06-18 17:11:39 +0900 |
---|---|---|
committer | Yusuke Endoh <[email protected]> | 2021-06-29 23:45:49 +0900 |
commit | e94604966572bb43fc887856d54aa54b8e9f7719 (patch) | |
tree | 789d92c232f671c6620af5c4bfd1a3fc0d9d26b3 /test | |
parent | 03dc66449326ce0945c1ccad7f51e57125b2b854 (diff) |
[WIP] add error_squiggle gem
```
$ ./local/bin/ruby -e '1.time {}'
-e:1:in `<main>': undefined method `time' for 1:Integer (NoMethodError)
1.time {}
^^^^^
Did you mean? times
```
https://bugs.ruby-lang.org/issues/17930
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/4586
Diffstat (limited to 'test')
-rw-r--r-- | test/error_squiggle/test_error_squiggle.rb | 984 | ||||
-rw-r--r-- | test/ruby/marshaltestlib.rb | 2 | ||||
-rw-r--r-- | test/ruby/test_marshal.rb | 2 | ||||
-rw-r--r-- | test/ruby/test_module.rb | 2 | ||||
-rw-r--r-- | test/ruby/test_name_error.rb | 2 | ||||
-rw-r--r-- | test/ruby/test_nomethod_error.rb | 2 | ||||
-rw-r--r-- | test/ruby/test_object.rb | 2 |
7 files changed, 990 insertions, 6 deletions
diff --git a/test/error_squiggle/test_error_squiggle.rb b/test/error_squiggle/test_error_squiggle.rb new file mode 100644 index 0000000000..3b44daf74c --- /dev/null +++ b/test/error_squiggle/test_error_squiggle.rb @@ -0,0 +1,984 @@ +require "test/unit" + +require "error_squiggle" + +class ErrorSquiggleTest < Test::Unit::TestCase + class DummyFormatter + def 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 + + def assert_error_message(klass, expected_msg, &blk) + err = assert_raise(klass, &blk) + assert_equal(expected_msg.chomp, err.message) + end + + def test_CALL_noarg_1 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + 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:NilClass + + .foo + 1 + ^^^^ + END + + nil + .foo + 1 + end + end + + def test_CALL_noarg_3 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + foo + 1 + ^^^ + END + + nil. + foo + 1 + end + end + + def test_CALL_arg_1 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + 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:NilClass + + .foo ( + ^^^^ + END + + nil + .foo ( + 42 + ) + end + end + + def test_CALL_arg_3 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + foo ( + ^^^ + END + + nil. + foo ( + 42 + ) + end + end + + def test_CALL_arg_4 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + 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:NilClass + + .foo( + ^^^^ + END + + nil + .foo( + 42 + ) + end + end + + def test_CALL_arg_6 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + foo( + ^^^ + END + + nil. + foo( + 42 + ) + end + end + + def test_QCALL_1 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for 1:Integer + + 1&.foo + ^^^^^ + END + + 1&.foo + end + end + + def test_QCALL_2 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for 1:Integer + + 1&.foo(42) + ^^^^^ + END + + 1&.foo(42) + end + end + + def test_CALL_aref_1 + assert_error_message(NoMethodError, <<~END) do +undefined method `[]' for nil:NilClass + + nil [ ] + ^^^ + END + + nil [ ] + end + end + + def test_CALL_aref_2 + assert_error_message(NoMethodError, <<~END) do +undefined method `[]' for nil:NilClass + + nil [0] + ^^^ + END + + nil [0] + end + end + + def test_CALL_aref_3 + assert_error_message(NoMethodError, <<~END) do +undefined method `[]' for nil:NilClass + END + + nil [ + 0 + ] + end + end + + def test_CALL_aref_4 + v = Object.new + assert_error_message(NoMethodError, <<~END) do +undefined method `[]' for #{ v.inspect } + + v &.[](0) + ^^^^ + END + + v &.[](0) + end + end + + def test_CALL_aset + assert_error_message(NoMethodError, <<~END) do +undefined method `[]=' for nil:NilClass + + nil.[]= + ^^^^ + END + + nil.[]= + end + end + + def test_CALL_op_asgn + v = nil + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for nil:NilClass + + v += 42 + ^ + END + + v += 42 + end + end + + def test_CALL_special_call_1 + assert_error_message(NoMethodError, <<~END) do +undefined method `call' for nil:NilClass + END + + nil.() + end + end + + def test_CALL_special_call_2 + assert_error_message(NoMethodError, <<~END) do +undefined method `call' for nil:NilClass + END + + nil.(42) + end + end + + def test_CALL_send + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + 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:NilClass + + nil [ ] = 42 + ^^^^^ + END + + nil [ ] = 42 + end + end + + def test_ATTRASGN_2 + assert_error_message(NoMethodError, <<~END) do +undefined method `[]=' for nil:NilClass + + nil [0] = 42 + ^^^^^ + END + + nil [0] = 42 + end + end + + def test_ATTRASGN_3 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo=' for nil:NilClass + + nil.foo = 42 + ^^^^^^ + END + + nil.foo = 42 + end + end + + def test_OPCALL_binary_1 + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for nil:NilClass + + nil + 42 + ^ + END + + nil + 42 + end + end + + def test_OPCALL_binary_2 + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for nil:NilClass + + nil + # comment + ^ + END + + nil + # comment + 42 + end + end + + def test_OPCALL_unary + assert_error_message(NoMethodError, <<~END) do +undefined method `+@' for nil:NilClass + + + nil + ^ + END + + + nil + end + end + + def test_FCALL_1 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + 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:NilClass + + 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:NilClass + + 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:NilClass + + 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:NilClass + + 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:NilClass + END + + v [ + 0 + ] += # comment + 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:NilClass + + 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:NilClass + + 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:NilClass + 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_ASGN2_read_1 + v = nil + + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + 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:NilClass + + v.foo += # comment + ^^^^ + END + + v.foo += # comment + 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:NilClass + + 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:NilClass + + v.foo += # comment + ^ + END + + v.foo += # comment + 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_CONST + assert_error_message(NameError, <<~END) do +uninitialized constant ErrorSquiggleTest::NotDefined + + 1 + NotDefined + 1 + ^^^^^^^^^^ + END + + 1 + NotDefined + 1 + end + end + + def test_COLON2_1 + assert_error_message(NameError, <<~END) do +uninitialized constant ErrorSquiggleTest::NotDefined + + ErrorSquiggleTest::NotDefined + ^^^^^^^^^^^^ + END + + ErrorSquiggleTest::NotDefined + end + end + + def test_COLON2_2 + assert_error_message(NameError, <<~END) do +uninitialized constant ErrorSquiggleTest::NotDefined + + NotDefined + ^^^^^^^^^^ + END + + ErrorSquiggleTest:: + NotDefined + 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 ErrorSquiggleTest::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 ErrorSquiggleTest::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 ErrorSquiggleTest::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:NilClass + + 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:NilClass + + 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:NilClass + + 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 + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for ErrorSquiggleTest:Class + + ::ErrorSquiggleTest += 1 + ^ + END + + ::ErrorSquiggleTest += 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 ErrorSquiggleTest::NotDefined + + ErrorSquiggleTest.const_get(:NotDefined) + ^^^^^^^^^^ + END + + ErrorSquiggleTest.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:NilClass + + nil.あいうえお + ^^^^^^ + END + + nil.あいうえお + end + end + + if false + + def test_args_CALL_1 + assert_error_message(TypeError, <<~END) do +nil can't be coerced into Integer + + 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 + + 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) + + 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 + + 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 + + $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 + + 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 + + "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 + + "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 + + 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) + + 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 + + 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 + + v.foo += nil + ^^^ + END + + v.foo += nil + end + end + + end +end diff --git a/test/ruby/marshaltestlib.rb b/test/ruby/marshaltestlib.rb index 5c48a8d853..7f100b7873 100644 --- a/test/ruby/marshaltestlib.rb +++ b/test/ruby/marshaltestlib.rb @@ -112,7 +112,7 @@ module MarshalTestLib marshal_equal(Exception.new('foo')) {|o| o.message} obj = Object.new e = assert_raise(NoMethodError) {obj.no_such_method()} - marshal_equal(e) {|o| o.message} + marshal_equal(e) {|o| o.message.lines.first.chomp} end def test_exception_subclass diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb index d2b4ec169f..5e6891a6a0 100644 --- a/test/ruby/test_marshal.rb +++ b/test/ruby/test_marshal.rb @@ -817,7 +817,7 @@ class TestMarshal < Test::Unit::TestCase nameerror_test rescue NameError => e e2 = Marshal.load(Marshal.dump(e)) - assert_equal(e.message, e2.message) + assert_equal(e.message.lines.first.chomp, e2.message.lines.first) assert_equal(e.name, e2.name) assert_equal(e.backtrace, e2.backtrace) assert_nil(e2.backtrace_locations) # temporal diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb index 84e74693aa..3411c3d701 100644 --- a/test/ruby/test_module.rb +++ b/test/ruby/test_module.rb @@ -267,7 +267,7 @@ class TestModule < Test::Unit::TestCase ].each do |name, msg| expected = "wrong constant name %s" % name msg = "#{msg}#{': ' if msg}wrong constant name #{name.dump}" - assert_raise_with_message(NameError, expected, "#{msg} to #{m}") do + assert_raise_with_message(NameError, Regexp.compile(Regexp.quote(expected)), "#{msg} to #{m}") do yield name end end diff --git a/test/ruby/test_name_error.rb b/test/ruby/test_name_error.rb index 813a976e96..8fcc2dcb26 100644 --- a/test/ruby/test_name_error.rb +++ b/test/ruby/test_name_error.rb @@ -151,6 +151,6 @@ class TestNameError < Test::Unit::TestCase error = assert_raise(NameError) do receiver::FOO end - assert_equal "uninitialized constant #{'A' * 120}::FOO", error.message + assert_match /\Auninitialized constant #{'A' * 120}::FOO$/, error.message end end diff --git a/test/ruby/test_nomethod_error.rb b/test/ruby/test_nomethod_error.rb index 8b81052905..321b7ccab2 100644 --- a/test/ruby/test_nomethod_error.rb +++ b/test/ruby/test_nomethod_error.rb @@ -86,7 +86,7 @@ class TestNoMethodError < Test::Unit::TestCase str = "\u2600" id = :"\u2604" msg = "undefined method `#{id}' for \"#{str}\":String" - assert_raise_with_message(NoMethodError, msg, bug3237) do + assert_raise_with_message(NoMethodError, Regexp.compile(Regexp.quote(msg)), bug3237) do str.__send__(id) end end diff --git a/test/ruby/test_object.rb b/test/ruby/test_object.rb index 774b707742..83208bbcdb 100644 --- a/test/ruby/test_object.rb +++ b/test/ruby/test_object.rb @@ -777,7 +777,7 @@ class TestObject < Test::Unit::TestCase e = assert_raise(NoMethodError) { o.never_defined_test_no_superclass_method } - assert_equal(m1, e.message, bug2312) + assert_equal(m1.lines.first, e.message.lines.first, bug2312) end def test_superclass_method |