From 80f1817ec850f44a80f7d10fafb79d45c184fab8 Mon Sep 17 00:00:00 2001 From: Alexander Momchilov Date: Tue, 30 Jul 2024 18:50:55 -0400 Subject: [PATCH 1/2] Add `expect_syntax_error` spec helper --- spec_helper.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec_helper.rb b/spec_helper.rb index af1c38587..34bc068a5 100644 --- a/spec_helper.rb +++ b/spec_helper.rb @@ -36,3 +36,7 @@ def report_on_exception=(value) ARGV.unshift $0 MSpecRun.main end + +def expect_syntax_error(ruby_src) + -> { eval(ruby_src) }.should raise_error(SyntaxError) +end From 7849c33e7fff997b90dc662f5f4c2ce363c4a888 Mon Sep 17 00:00:00 2001 From: Alexander Momchilov Date: Tue, 30 Jul 2024 19:25:29 -0400 Subject: [PATCH 2/2] Apply new `expect_syntax_error` helper --- language/BEGIN_spec.rb | 2 +- language/block_spec.rb | 38 +++++++++-------------- language/break_spec.rb | 8 ++--- language/case_spec.rb | 12 +++---- language/def_spec.rb | 10 +++--- language/encoding_spec.rb | 2 +- language/ensure_spec.rb | 14 ++++----- language/file_spec.rb | 2 +- language/hash_spec.rb | 6 ++-- language/heredoc_spec.rb | 4 +-- language/lambda_spec.rb | 4 +-- language/line_spec.rb | 2 +- language/method_spec.rb | 9 ++---- language/next_spec.rb | 4 +-- language/numbers_spec.rb | 4 +-- language/precedence_spec.rb | 16 +++++----- language/predefined_spec.rb | 8 ++--- language/redo_spec.rb | 4 +-- language/regexp/character_classes_spec.rb | 2 +- language/regexp/escapes_spec.rb | 6 ++-- language/regexp/modifiers_spec.rb | 6 ++-- language/regexp_spec.rb | 8 ++--- language/rescue_spec.rb | 26 +++++++--------- language/retry_spec.rb | 8 ++--- language/safe_navigator_spec.rb | 2 +- language/send_spec.rb | 4 +-- 26 files changed, 87 insertions(+), 124 deletions(-) diff --git a/language/BEGIN_spec.rb b/language/BEGIN_spec.rb index 5aef5a1d7..84966d435 100644 --- a/language/BEGIN_spec.rb +++ b/language/BEGIN_spec.rb @@ -15,7 +15,7 @@ end it "must appear in a top-level context" do - -> { eval "1.times { BEGIN { 1 } }" }.should raise_error(SyntaxError) + expect_syntax_error("1.times { BEGIN { 1 } }") end it "uses top-level for self" do diff --git a/language/block_spec.rb b/language/block_spec.rb index cf0931b68..fedbb9faf 100644 --- a/language/block_spec.rb +++ b/language/block_spec.rb @@ -731,9 +731,9 @@ def obj.to_ary; raise "Exception raised in #to_ary" end describe "taking identically-named arguments" do it "raises a SyntaxError for standard arguments" do - -> { eval "lambda { |x,x| }" }.should raise_error(SyntaxError) - -> { eval "->(x,x) {}" }.should raise_error(SyntaxError) - -> { eval "Proc.new { |x,x| }" }.should raise_error(SyntaxError) + expect_syntax_error("lambda { |x,x| }") + expect_syntax_error("->(x,x) {}") + expect_syntax_error("Proc.new { |x,x| }") end it "accepts unnamed arguments" do @@ -790,29 +790,23 @@ def obj.to_ary; raise "Exception raised in #to_ary" end end it "can not have the same name as one of the standard parameters" do - -> { eval "[1].each {|foo; foo| }" }.should raise_error(SyntaxError) - -> { eval "[1].each {|foo, bar; glark, bar| }" }.should raise_error(SyntaxError) + expect_syntax_error("[1].each {|foo; foo| }") + expect_syntax_error("[1].each {|foo, bar; glark, bar| }") end it "can not be prefixed with an asterisk" do - -> { eval "[1].each {|foo; *bar| }" }.should raise_error(SyntaxError) - -> do - eval "[1].each {|foo, bar; glark, *fnord| }" - end.should raise_error(SyntaxError) + expect_syntax_error("[1].each {|foo; *bar| }") + expect_syntax_error("[1].each {|foo, bar; glark, *fnord| }") end it "can not be prefixed with an ampersand" do - -> { eval "[1].each {|foo; &bar| }" }.should raise_error(SyntaxError) - -> do - eval "[1].each {|foo, bar; glark, &fnord| }" - end.should raise_error(SyntaxError) + expect_syntax_error("[1].each {|foo; &bar| }") + expect_syntax_error("[1].each {|foo, bar; glark, &fnord| }") end it "can not be assigned default values" do - -> { eval "[1].each {|foo; bar=1| }" }.should raise_error(SyntaxError) - -> do - eval "[1].each {|foo, bar; glark, fnord=:fnord| }" - end.should raise_error(SyntaxError) + expect_syntax_error("[1].each {|foo; bar=1| }") + expect_syntax_error("[1].each {|foo, bar; glark, fnord=:fnord| }") end it "need not be preceded by standard parameters" do @@ -821,8 +815,8 @@ def obj.to_ary; raise "Exception raised in #to_ary" end end it "only allow a single semi-colon in the parameter list" do - -> { eval "[1].each {|foo; bar; glark| }" }.should raise_error(SyntaxError) - -> { eval "[1].each {|; bar; glark| }" }.should raise_error(SyntaxError) + expect_syntax_error("[1].each {|foo; bar; glark| }") + expect_syntax_error("[1].each {|; bar; glark| }") end it "override shadowed variables from the outer scope" do @@ -963,9 +957,7 @@ def obj.to_ary; raise "Exception raised in #to_ary" end ruby_version_is ""..."3.4" do it "raises a SyntaxError if using the argument in its default value" do a = 1 - -> { - eval "proc { |a=a| a }" - }.should raise_error(SyntaxError) + expect_syntax_error "proc { |a=a| a }" end end @@ -1011,7 +1003,7 @@ def c(&); yield :non_null end end it "requires the anonymous block parameter to be declared if directly passing a block" do - -> { eval "def a; b(&); end; def b; end" }.should raise_error(SyntaxError) + expect_syntax_error("def a; b(&); end; def b; end") end it "works when it's the only declared parameter" do diff --git a/language/break_spec.rb b/language/break_spec.rb index 7e5b6fb32..3ff6b0090 100644 --- a/language/break_spec.rb +++ b/language/break_spec.rb @@ -254,21 +254,17 @@ def mid(&b) describe "The break statement in a method" do it "is invalid and raises a SyntaxError" do - -> { - eval("def m; break; end") - }.should raise_error(SyntaxError) + expect_syntax_error("def m; break; end") end end describe "The break statement in a module literal" do it "is invalid and raises a SyntaxError" do - code = <<~RUBY + expect_syntax_error <<~RUBY module BreakSpecs:ModuleWithBreak break end RUBY - - -> { eval(code) }.should raise_error(SyntaxError) end end diff --git a/language/case_spec.rb b/language/case_spec.rb index 464d06e46..1d5c1c937 100644 --- a/language/case_spec.rb +++ b/language/case_spec.rb @@ -261,26 +261,22 @@ def bar; @calls << :bar; end end it "raises a SyntaxError when 'else' is used when no 'when' is given" do - -> { - eval <<-CODE + expect_syntax_error <<-CODE case 4 else true end - CODE - }.should raise_error(SyntaxError) + CODE end it "raises a SyntaxError when 'else' is used before a 'when' was given" do - -> { - eval <<-CODE + expect_syntax_error <<-CODE case 4 else true when 4; false end - CODE - }.should raise_error(SyntaxError) + CODE end it "supports nested case statements" do diff --git a/language/def_spec.rb b/language/def_spec.rb index ce8077eb6..2f8a070a2 100644 --- a/language/def_spec.rb +++ b/language/def_spec.rb @@ -133,7 +133,7 @@ def foo(a, b, c, d, e, *f); [a, b, c, d, e, f]; end end it "allows only a single * argument" do - -> { eval 'def foo(a, *b, *c); end' }.should raise_error(SyntaxError) + expect_syntax_error('def foo(a, *b, *c); end') end it "requires the presence of any arguments that precede the *" do @@ -199,11 +199,11 @@ def foo(a, b = 2, *args) ruby_version_is ""..."3.4" do it "raises a SyntaxError if using the argument in its default value" do - -> { - eval "def foo(bar = bar) + expect_syntax_error <<~RUBY + def foo(bar = bar) bar - end" - }.should raise_error(SyntaxError) + end + RUBY end end diff --git a/language/encoding_spec.rb b/language/encoding_spec.rb index e761a53cb..abecc2e23 100644 --- a/language/encoding_spec.rb +++ b/language/encoding_spec.rb @@ -31,6 +31,6 @@ end it "raises a SyntaxError if assigned to" do - -> { eval("__ENCODING__ = 1") }.should raise_error(SyntaxError) + expect_syntax_error("__ENCODING__ = 1") end end diff --git a/language/ensure_spec.rb b/language/ensure_spec.rb index 16e626b4d..4cbe20265 100644 --- a/language/ensure_spec.rb +++ b/language/ensure_spec.rb @@ -240,14 +240,12 @@ class EnsureInClassExample describe "An ensure block inside {} block" do it "is not allowed" do - -> { - eval <<-ruby - lambda { - raise - ensure - } - ruby - }.should raise_error(SyntaxError) + expect_syntax_error <<-ruby + lambda { + raise + ensure + } + ruby end end diff --git a/language/file_spec.rb b/language/file_spec.rb index 59563d964..fd015641c 100644 --- a/language/file_spec.rb +++ b/language/file_spec.rb @@ -4,7 +4,7 @@ describe "The __FILE__ pseudo-variable" do it "raises a SyntaxError if assigned to" do - -> { eval("__FILE__ = 1") }.should raise_error(SyntaxError) + expect_syntax_error("__FILE__ = 1") end ruby_version_is ""..."3.3" do diff --git a/language/hash_spec.rb b/language/hash_spec.rb index 068ac0f39..a29aa41aa 100644 --- a/language/hash_spec.rb +++ b/language/hash_spec.rb @@ -83,7 +83,7 @@ end it "with '==>' in the middle raises SyntaxError" do - -> { eval("{:a ==> 1}") }.should raise_error(SyntaxError) + expect_syntax_error("{:a ==> 1}") end it "recognizes '!' at the end of the key" do @@ -95,7 +95,7 @@ end it "raises a SyntaxError if there is no space between `!` and `=>`" do - -> { eval("{:a!=> 1}") }.should raise_error(SyntaxError) + expect_syntax_error("{:a!=> 1}") end it "recognizes '?' at the end of the key" do @@ -107,7 +107,7 @@ end it "raises a SyntaxError if there is no space between `?` and `=>`" do - -> { eval("{:a?=> 1}") }.should raise_error(SyntaxError) + expect_syntax_error("{:a?=> 1}") end it "constructs a new hash with the given elements" do diff --git a/language/heredoc_spec.rb b/language/heredoc_spec.rb index 47ee9c2c5..33cfd80e5 100644 --- a/language/heredoc_spec.rb +++ b/language/heredoc_spec.rb @@ -60,9 +60,7 @@ end it 'raises SyntaxError if quoted HEREDOC identifier is ending not on same line' do - -> { - eval %{<<"HERE\n"\nraises syntax error\nHERE} - }.should raise_error(SyntaxError) + expect_syntax_error %{<<"HERE\n"\nraises syntax error\nHERE} end it "allows HEREDOC with <<~'identifier', allowing to indent identifier and content" do diff --git a/language/lambda_spec.rb b/language/lambda_spec.rb index ed5a1c69e..2fb222ac5 100644 --- a/language/lambda_spec.rb +++ b/language/lambda_spec.rb @@ -266,9 +266,7 @@ def create_lambda ruby_version_is ""..."3.4" do it "raises a SyntaxError if using the argument in its default value" do a = 1 - -> { - eval "-> (a=a) { a }" - }.should raise_error(SyntaxError) + expect_syntax_error("-> (a=a) { a }") end end diff --git a/language/line_spec.rb b/language/line_spec.rb index fcadaa71d..f234bb3fa 100644 --- a/language/line_spec.rb +++ b/language/line_spec.rb @@ -4,7 +4,7 @@ describe "The __LINE__ pseudo-variable" do it "raises a SyntaxError if assigned to" do - -> { eval("__LINE__ = 1") }.should raise_error(SyntaxError) + expect_syntax_error("__LINE__ = 1") end before :each do diff --git a/language/method_spec.rb b/language/method_spec.rb index 9abe4cde2..60c006788 100644 --- a/language/method_spec.rb +++ b/language/method_spec.rb @@ -1230,13 +1230,8 @@ def n(value, &block) context "when the argument looks like an argument list" do it "raises a syntax error" do - -> { - eval("m (1, 2)") - }.should raise_error(SyntaxError) - - -> { - eval("m (1, 2, 3)") - }.should raise_error(SyntaxError) + expect_syntax_error("m (1, 2)") + expect_syntax_error("m (1, 2, 3)") end end diff --git a/language/next_spec.rb b/language/next_spec.rb index 6fbfc4a54..c981f2c2b 100644 --- a/language/next_spec.rb +++ b/language/next_spec.rb @@ -109,9 +109,7 @@ def self.enclosing_method describe "The next statement" do describe "in a method" do it "is invalid and raises a SyntaxError" do - -> { - eval("def m; next; end") - }.should raise_error(SyntaxError) + expect_syntax_error("def m; next; end") end end end diff --git a/language/numbers_spec.rb b/language/numbers_spec.rb index a8e023efb..13416574a 100644 --- a/language/numbers_spec.rb +++ b/language/numbers_spec.rb @@ -20,8 +20,8 @@ it "must have a digit before the decimal point" do 0.75.should == 0.75 - -> { eval(".75") }.should raise_error(SyntaxError) - -> { eval("-.75") }.should raise_error(SyntaxError) + expect_syntax_error(".75") + expect_syntax_error("-.75") end it "can have an exponent" do diff --git a/language/precedence_spec.rb b/language/precedence_spec.rb index c5adcca2c..e2a7ef377 100644 --- a/language/precedence_spec.rb +++ b/language/precedence_spec.rb @@ -251,12 +251,12 @@ def >=(a); 0; end; end it "<=> == === != =~ !~ are non-associative" do - -> { eval("1 <=> 2 <=> 3") }.should raise_error(SyntaxError) - -> { eval("1 == 2 == 3") }.should raise_error(SyntaxError) - -> { eval("1 === 2 === 3") }.should raise_error(SyntaxError) - -> { eval("1 != 2 != 3") }.should raise_error(SyntaxError) - -> { eval("1 =~ 2 =~ 3") }.should raise_error(SyntaxError) - -> { eval("1 !~ 2 !~ 3") }.should raise_error(SyntaxError) + expect_syntax_error("1 <=> 2 <=> 3") + expect_syntax_error("1 == 2 == 3") + expect_syntax_error("1 === 2 === 3") + expect_syntax_error("1 != 2 != 3") + expect_syntax_error("1 =~ 2 =~ 3") + expect_syntax_error("1 !~ 2 !~ 3") end it "<=> == === != =~ !~ have higher precedence than &&" do @@ -290,8 +290,8 @@ class FalseClass; undef_method :=~; end end it ".. ... are non-associative" do - -> { eval("1..2..3") }.should raise_error(SyntaxError) - -> { eval("1...2...3") }.should raise_error(SyntaxError) + expect_syntax_error("1..2..3") + expect_syntax_error("1...2...3") end it ".. ... have higher precedence than ? :" do diff --git a/language/predefined_spec.rb b/language/predefined_spec.rb index ac28f1e8a..9c2480c13 100644 --- a/language/predefined_spec.rb +++ b/language/predefined_spec.rb @@ -1100,7 +1100,7 @@ def obj.foo2; yield; end end it "raises a SyntaxError if assigned to" do - -> { eval("nil = true") }.should raise_error(SyntaxError) + expect_syntax_error("nil = true") end end @@ -1110,7 +1110,7 @@ def obj.foo2; yield; end end it "raises a SyntaxError if assigned to" do - -> { eval("true = false") }.should raise_error(SyntaxError) + expect_syntax_error("true = false") end end @@ -1120,13 +1120,13 @@ def obj.foo2; yield; end end it "raises a SyntaxError if assigned to" do - -> { eval("false = nil") }.should raise_error(SyntaxError) + expect_syntax_error("false = nil") end end describe "The self pseudo-variable" do it "raises a SyntaxError if assigned to" do - -> { eval("self = 1") }.should raise_error(SyntaxError) + expect_syntax_error("self = 1") end end diff --git a/language/redo_spec.rb b/language/redo_spec.rb index 57532553b..041d9edf6 100644 --- a/language/redo_spec.rb +++ b/language/redo_spec.rb @@ -58,9 +58,7 @@ describe "in a method" do it "is invalid and raises a SyntaxError" do - -> { - eval("def m; redo; end") - }.should raise_error(SyntaxError) + expect_syntax_error("def m; redo; end") end end end diff --git a/language/regexp/character_classes_spec.rb b/language/regexp/character_classes_spec.rb index 98d431a81..26c1e219e 100644 --- a/language/regexp/character_classes_spec.rb +++ b/language/regexp/character_classes_spec.rb @@ -89,7 +89,7 @@ /[^[:lower:]A-C]+/.match("abcABCDEF123def").to_a.should == ["DEF123"] # negated character class /[:alnum:]+/.match("a:l:n:u:m").to_a.should == ["a:l:n:u:m"] # should behave like regular character class composed of the individual letters /[\[:alnum:]+/.match("[:a:l:n:u:m").to_a.should == ["[:a:l:n:u:m"] # should behave like regular character class composed of the individual letters - -> { eval('/[[:alpha:]-[:digit:]]/') }.should raise_error(SyntaxError) # can't use character class as a start value of range + expect_syntax_error('/[[:alpha:]-[:digit:]]/') end it "matches ASCII characters with [[:ascii:]]" do diff --git a/language/regexp/escapes_spec.rb b/language/regexp/escapes_spec.rb index 16a4d8c23..4757ee2be 100644 --- a/language/regexp/escapes_spec.rb +++ b/language/regexp/escapes_spec.rb @@ -120,7 +120,7 @@ /\x0AA/.match("\nA").to_a.should == ["\nA"] /\xAG/.match("\nG").to_a.should == ["\nG"] # Non-matches - -> { eval('/\xG/') }.should raise_error(SyntaxError) + expect_syntax_error('/\xG/') # \x{7HHHHHHH} wide hexadecimal char (character code point value) end @@ -141,9 +141,9 @@ # Parsing precedence /\cJ+/.match("\n\n").to_a.should == ["\n\n"] # Quantifiers apply to entire escape sequence /\\cJ/.match("\\cJ").to_a.should == ["\\cJ"] - -> { eval('/[abc\x]/') }.should raise_error(SyntaxError) # \x is treated as a escape sequence even inside a character class + expect_syntax_error('/[abc\x]/') # \x is treated as a escape sequence even inside a character class # Syntax error - -> { eval('/\c/') }.should raise_error(SyntaxError) + expect_syntax_error('/\c/') # \cx control char (character code point value) # \C-x control char (character code point value) diff --git a/language/regexp/modifiers_spec.rb b/language/regexp/modifiers_spec.rb index 2f5522bc8..17ec168f0 100644 --- a/language/regexp/modifiers_spec.rb +++ b/language/regexp/modifiers_spec.rb @@ -36,7 +36,7 @@ def o.to_s /foo/imox.match("foo").to_a.should == ["foo"] /foo/imoximox.match("foo").to_a.should == ["foo"] - -> { eval('/foo/a') }.should raise_error(SyntaxError) + expect_syntax_error('/foo/a') end it "supports (?~) (absent operator)" do @@ -76,7 +76,7 @@ def o.to_s /(?i-i)foo/.match("FOO").should be_nil /(?ii)foo/.match("FOO").to_a.should == ["FOO"] /(?-)foo/.match("foo").to_a.should == ["foo"] - -> { eval('/(?o)/') }.should raise_error(SyntaxError) + expect_syntax_error('/(?o)/') end it "supports (?imx-imx:expr) (scoped inline modifiers)" do @@ -96,7 +96,7 @@ def o.to_s /(?i-i:foo)/.match("FOO").should be_nil /(?ii:foo)/.match("FOO").to_a.should == ["FOO"] /(?-:)foo/.match("foo").to_a.should == ["foo"] - -> { eval('/(?o:)/') }.should raise_error(SyntaxError) + expect_syntax_error('/(?o:)/') end it "supports . with /m" do diff --git a/language/regexp_spec.rb b/language/regexp_spec.rb index dbf341b19..de0e5af95 100644 --- a/language/regexp_spec.rb +++ b/language/regexp_spec.rb @@ -31,7 +31,7 @@ end it "throws SyntaxError for malformed literals" do - -> { eval('/(/') }.should raise_error(SyntaxError) + expect_syntax_error('/(/') end ############################################################################# @@ -58,7 +58,7 @@ it "disallows first part of paired delimiters to be used as non-paired delimiters" do LanguageSpecs.paired_delimiters.each do |p0, p1| - -> { eval("%r#{p0} foo #{p0}") }.should raise_error(SyntaxError) + expect_syntax_error("%r#{p0} foo #{p0}") end end @@ -69,11 +69,11 @@ end it "disallows alphabets as non-paired delimiter with %r" do - -> { eval('%ra foo a') }.should raise_error(SyntaxError) + expect_syntax_error('%ra foo a') end it "disallows spaces after %r and delimiter" do - -> { eval('%r !foo!') }.should raise_error(SyntaxError) + expect_syntax_error('%r !foo!') end it "allows unescaped / to be used with %r" do diff --git a/language/rescue_spec.rb b/language/rescue_spec.rb index 4dc25a5b4..7455cc5d7 100644 --- a/language/rescue_spec.rb +++ b/language/rescue_spec.rb @@ -530,15 +530,13 @@ class RescueInClassExample end it "does not allow rescue in {} block" do - -> { - eval <<-ruby - lambda { - raise SpecificExampleException - rescue SpecificExampleException - :caught - } - ruby - }.should raise_error(SyntaxError) + expect_syntax_error <<-ruby + lambda { + raise SpecificExampleException + rescue SpecificExampleException + :caught + } + ruby end it "allows rescue in 'do end' block" do @@ -559,7 +557,7 @@ class RescueInClassExample end it "requires the 'rescue' in method arguments to be wrapped in parens" do - -> { eval '1.+(1 rescue 1)' }.should raise_error(SyntaxError) + expect_syntax_error '1.+(1 rescue 1)' eval('1.+((1 rescue 1))').should == 2 end @@ -587,11 +585,9 @@ def foo end it "doesn't except rescue expression" do - -> { - eval <<-ruby - a = 1 rescue RuntimeError 2 - ruby - }.should raise_error(SyntaxError) + expect_syntax_error <<-ruby + a = 1 rescue RuntimeError 2 + ruby end it "rescues only StandardError and its subclasses" do diff --git a/language/retry_spec.rb b/language/retry_spec.rb index 669d5f0ff..70f2ebd16 100644 --- a/language/retry_spec.rb +++ b/language/retry_spec.rb @@ -32,10 +32,10 @@ end it "raises a SyntaxError when used outside of a rescue statement" do - -> { eval 'retry' }.should raise_error(SyntaxError) - -> { eval 'begin; retry; end' }.should raise_error(SyntaxError) - -> { eval 'def m; retry; end' }.should raise_error(SyntaxError) - -> { eval 'module RetrySpecs; retry; end' }.should raise_error(SyntaxError) + expect_syntax_error('retry') + expect_syntax_error('begin; retry; end') + expect_syntax_error('def m; retry; end') + expect_syntax_error('module RetrySpecs; retry; end') end end diff --git a/language/safe_navigator_spec.rb b/language/safe_navigator_spec.rb index b1e28c396..ab378df3a 100644 --- a/language/safe_navigator_spec.rb +++ b/language/safe_navigator_spec.rb @@ -2,7 +2,7 @@ describe "Safe navigator" do it "requires a method name to be provided" do - -> { eval("obj&. {}") }.should raise_error(SyntaxError) + expect_syntax_error("obj&. {}") end context "when context is nil" do diff --git a/language/send_spec.rb b/language/send_spec.rb index aaccdf099..265b64765 100644 --- a/language/send_spec.rb +++ b/language/send_spec.rb @@ -107,9 +107,7 @@ end it "raises a SyntaxError with both a literal block and an object as block" do - -> { - eval "specs.oneb(10, &l){ 42 }" - }.should raise_error(SyntaxError) + expect_syntax_error "specs.oneb(10, &l){ 42 }" end it "with same names as existing variables is ok" do