aboutsummaryrefslogtreecommitdiffstats
path: root/spec/ruby/language
diff options
context:
space:
mode:
authorBenoit Daloze <eregontp@gmail.com>2022-04-25 14:53:54 +0200
committerBenoit Daloze <eregontp@gmail.com>2022-04-25 14:53:54 +0200
commit45cf4f218728a15eb36d14a6c9912086525f5e3f (patch)
tree2aa93fadcb904c226f722dde47827098b87a9846 /spec/ruby/language
parent6ae81d49b52563a6720d666a6118ffa6e484f398 (diff)
downloadruby-45cf4f218728a15eb36d14a6c9912086525f5e3f.tar.gz
Update to ruby/spec@3affe1e
Diffstat (limited to 'spec/ruby/language')
-rw-r--r--spec/ruby/language/alias_spec.rb13
-rw-r--r--spec/ruby/language/block_spec.rb52
-rw-r--r--spec/ruby/language/comment_spec.rb16
-rw-r--r--spec/ruby/language/def_spec.rb33
-rw-r--r--spec/ruby/language/defined_spec.rb14
-rw-r--r--spec/ruby/language/delegation_spec.rb61
-rw-r--r--spec/ruby/language/fixtures/defined.rb3
-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_two_literals.rb2
-rw-r--r--spec/ruby/language/hash_spec.rb15
-rw-r--r--spec/ruby/language/heredoc_spec.rb18
-rw-r--r--spec/ruby/language/keyword_arguments_spec.rb57
-rw-r--r--spec/ruby/language/lambda_spec.rb64
-rw-r--r--spec/ruby/language/method_spec.rb274
-rw-r--r--spec/ruby/language/numbered_parameters_spec.rb184
-rw-r--r--spec/ruby/language/pattern_matching_spec.rb2246
-rw-r--r--spec/ruby/language/predefined_spec.rb54
-rw-r--r--spec/ruby/language/proc_spec.rb8
-rw-r--r--spec/ruby/language/range_spec.rb8
-rw-r--r--spec/ruby/language/rescue_spec.rb10
-rw-r--r--spec/ruby/language/return_spec.rb46
-rw-r--r--spec/ruby/language/safe_spec.rb94
-rw-r--r--spec/ruby/language/send_spec.rb18
-rw-r--r--spec/ruby/language/string_spec.rb22
-rw-r--r--spec/ruby/language/yield_spec.rb2
24 files changed, 1470 insertions, 1844 deletions
diff --git a/spec/ruby/language/alias_spec.rb b/spec/ruby/language/alias_spec.rb
index d1d06e3fac..c353390679 100644
--- a/spec/ruby/language/alias_spec.rb
+++ b/spec/ruby/language/alias_spec.rb
@@ -243,6 +243,19 @@ describe "The alias keyword" do
e.class.should == NameError
}
end
+
+ it "defines the method on the aliased class when the original method is from a parent class" do
+ parent = Class.new do
+ def parent_method
+ end
+ end
+ child = Class.new(parent) do
+ alias parent_method_alias parent_method
+ end
+
+ child.instance_method(:parent_method_alias).owner.should == child
+ child.instance_methods(false).should include(:parent_method_alias)
+ end
end
describe "The alias keyword" do
diff --git a/spec/ruby/language/block_spec.rb b/spec/ruby/language/block_spec.rb
index f213d68ba1..42652152a1 100644
--- a/spec/ruby/language/block_spec.rb
+++ b/spec/ruby/language/block_spec.rb
@@ -101,17 +101,7 @@ describe "A block yielded a single" do
end
end
- ruby_version_is ""..."2.7" do
- it "calls #to_hash on the argument and uses resulting hash as first argument when optional argument and keyword argument accepted" do
- obj = mock("coerce block keyword arguments")
- obj.should_receive(:to_hash).and_return({"a" => 1, "b" => 2})
-
- result = m([obj]) { |a=nil, **b| [a, b] }
- result.should == [{"a" => 1, "b" => 2}, {}]
- end
- end
-
- ruby_version_is "2.7"...'3.0' do
+ ruby_version_is ""...'3.0' do
it "calls #to_hash on the argument but ignores result when optional argument and keyword argument accepted" do
obj = mock("coerce block keyword arguments")
obj.should_receive(:to_hash).and_return({"a" => 1, "b" => 2})
@@ -958,38 +948,18 @@ describe "Post-args" do
end
describe "with a circular argument reference" do
- ruby_version_is ''...'2.7' do
- it "warns and uses a nil value when there is an existing local variable with same name" do
- a = 1
- -> {
- @proc = eval "proc { |a=a| a }"
- }.should complain(/circular argument reference/)
- @proc.call.should == nil
- end
-
- it "warns and uses a nil value when there is an existing method with same name" do
- def a; 1; end
- -> {
- @proc = eval "proc { |a=a| a }"
- }.should complain(/circular argument reference/)
- @proc.call.should == nil
- end
+ it "raises a SyntaxError if using an existing local with the same name as the argument" do
+ a = 1
+ -> {
+ @proc = eval "proc { |a=a| a }"
+ }.should raise_error(SyntaxError)
end
- ruby_version_is '2.7' do
- it "raises a SyntaxError if using an existing local with the same name as the argument" do
- a = 1
- -> {
- @proc = eval "proc { |a=a| a }"
- }.should raise_error(SyntaxError)
- end
-
- it "raises a SyntaxError if there is an existing method with the same name as the argument" do
- def a; 1; end
- -> {
- @proc = eval "proc { |a=a| a }"
- }.should raise_error(SyntaxError)
- end
+ it "raises a SyntaxError if there is an existing method with the same name as the argument" do
+ def a; 1; end
+ -> {
+ @proc = eval "proc { |a=a| a }"
+ }.should raise_error(SyntaxError)
end
it "calls an existing method with the same name as the argument if explicitly using ()" do
diff --git a/spec/ruby/language/comment_spec.rb b/spec/ruby/language/comment_spec.rb
index 690e844dc0..dd788e681c 100644
--- a/spec/ruby/language/comment_spec.rb
+++ b/spec/ruby/language/comment_spec.rb
@@ -1,15 +1,13 @@
require_relative '../spec_helper'
describe "The comment" do
- ruby_version_is "2.7" do
- it "can be placed between fluent dot now" do
- code = <<~CODE
- 10
- # some comment
- .to_s
- CODE
+ it "can be placed between fluent dot now" do
+ code = <<~CODE
+ 10
+ # some comment
+ .to_s
+ CODE
- eval(code).should == '10'
- end
+ eval(code).should == '10'
end
end
diff --git a/spec/ruby/language/def_spec.rb b/spec/ruby/language/def_spec.rb
index d72f8fa888..c8531343c0 100644
--- a/spec/ruby/language/def_spec.rb
+++ b/spec/ruby/language/def_spec.rb
@@ -197,32 +197,15 @@ describe "An instance method with a default argument" do
foo(2,3,3).should == [2,3,[3]]
end
- ruby_version_is ''...'2.7' do
- it "warns and uses a nil value when there is an existing local method with same name" do
- def bar
- 1
- end
- -> {
- eval "def foo(bar = bar)
- bar
- end"
- }.should complain(/circular argument reference/)
- foo.should == nil
- foo(2).should == 2
- end
- end
-
- ruby_version_is '2.7' do
- it "raises a SyntaxError when there is an existing method with the same name as the local variable" do
- def bar
- 1
- end
- -> {
- eval "def foo(bar = bar)
- bar
- end"
- }.should raise_error(SyntaxError)
+ it "raises a SyntaxError when there is an existing method with the same name as the local variable" do
+ def bar
+ 1
end
+ -> {
+ eval "def foo(bar = bar)
+ bar
+ end"
+ }.should raise_error(SyntaxError)
end
it "calls a method with the same name as the local when explicitly using ()" do
diff --git a/spec/ruby/language/defined_spec.rb b/spec/ruby/language/defined_spec.rb
index 38345c3727..ae2bf45bda 100644
--- a/spec/ruby/language/defined_spec.rb
+++ b/spec/ruby/language/defined_spec.rb
@@ -48,6 +48,20 @@ describe "The defined? keyword for literals" do
end
describe "The defined? keyword when called with a method name" do
+ before :each do
+ ScratchPad.clear
+ end
+
+ it "does not call the method" do
+ defined?(DefinedSpecs.side_effects).should == "method"
+ ScratchPad.recorded.should != :defined_specs_side_effects
+ end
+
+ it "does not execute the arguments" do
+ defined?(DefinedSpecs.any_args(DefinedSpecs.side_effects)).should == "method"
+ ScratchPad.recorded.should != :defined_specs_side_effects
+ end
+
describe "without a receiver" do
it "returns 'method' if the method is defined" do
ret = defined?(puts)
diff --git a/spec/ruby/language/delegation_spec.rb b/spec/ruby/language/delegation_spec.rb
index 8e4183cbcc..3f24a79d5c 100644
--- a/spec/ruby/language/delegation_spec.rb
+++ b/spec/ruby/language/delegation_spec.rb
@@ -1,42 +1,40 @@
require_relative '../spec_helper'
require_relative 'fixtures/delegation'
-ruby_version_is "2.7" do
- describe "delegation with def(...)" do
- it "delegates rest and kwargs" do
- a = Class.new(DelegationSpecs::Target)
- a.class_eval(<<-RUBY)
- def delegate(...)
- target(...)
- end
- RUBY
+describe "delegation with def(...)" do
+ it "delegates rest and kwargs" do
+ a = Class.new(DelegationSpecs::Target)
+ a.class_eval(<<-RUBY)
+ def delegate(...)
+ target(...)
+ end
+ RUBY
- a.new.delegate(1, b: 2).should == [[1], {b: 2}]
- end
+ a.new.delegate(1, b: 2).should == [[1], {b: 2}]
+ end
- it "delegates block" do
- a = Class.new(DelegationSpecs::Target)
- a.class_eval(<<-RUBY)
- def delegate_block(...)
- target_block(...)
- end
- RUBY
+ it "delegates block" do
+ a = Class.new(DelegationSpecs::Target)
+ a.class_eval(<<-RUBY)
+ def delegate_block(...)
+ target_block(...)
+ end
+ RUBY
- a.new.delegate_block(1, b: 2) { |x| x }.should == [{b: 2}, [1]]
- end
+ a.new.delegate_block(1, b: 2) { |x| x }.should == [{b: 2}, [1]]
+ end
- it "parses as open endless Range when brackets are omitted" do
- a = Class.new(DelegationSpecs::Target)
- suppress_warning do
- a.class_eval(<<-RUBY)
- def delegate(...)
- target ...
- end
- RUBY
- end
+ it "parses as open endless Range when brackets are omitted" do
+ a = Class.new(DelegationSpecs::Target)
+ suppress_warning do
+ a.class_eval(<<-RUBY)
+ def delegate(...)
+ target ...
+ end
+ RUBY
+ end
- a.new.delegate(1, b: 2).should == Range.new([[], {}], nil, true)
- end
+ a.new.delegate(1, b: 2).should == Range.new([[], {}], nil, true)
end
end
@@ -63,6 +61,5 @@ ruby_version_is "2.7.3" do
a.new.delegate_block(0, 1, b: 2) { |x| x }.should == [{b: 2}, [1]]
end
-
end
end
diff --git a/spec/ruby/language/fixtures/defined.rb b/spec/ruby/language/fixtures/defined.rb
index 8b6004c19f..a9552619bf 100644
--- a/spec/ruby/language/fixtures/defined.rb
+++ b/spec/ruby/language/fixtures/defined.rb
@@ -19,6 +19,9 @@ module DefinedSpecs
DefinedSpecs
end
+ def self.any_args(*)
+ end
+
class Basic
A = 42
diff --git a/spec/ruby/language/fixtures/freeze_magic_comment_two_literals.rb b/spec/ruby/language/fixtures/freeze_magic_comment_two_literals.rb
index a4d655ad02..cccc5969bd 100644
--- a/spec/ruby/language/fixtures/freeze_magic_comment_two_literals.rb
+++ b/spec/ruby/language/fixtures/freeze_magic_comment_two_literals.rb
@@ -1,3 +1,3 @@
# frozen_string_literal: true
-p "abc".object_id == "abc".object_id
+p "abc".equal?("abc")
diff --git a/spec/ruby/language/hash_spec.rb b/spec/ruby/language/hash_spec.rb
index 2f8b97199a..c84564d3ea 100644
--- a/spec/ruby/language/hash_spec.rb
+++ b/spec/ruby/language/hash_spec.rb
@@ -148,18 +148,9 @@ describe "Hash literal" do
{a: 1, **obj, c: 3}.should == {a:1, b: 2, c: 3, d: 4}
end
- ruby_version_is ""..."2.7" do
- it "raises a TypeError if any splatted elements keys are not symbols" do
- h = {1 => 2, b: 3}
- -> { {a: 1, **h} }.should raise_error(TypeError)
- end
- end
-
- ruby_version_is "2.7" do
- it "allows splatted elements keys that are not symbols" do
- h = {1 => 2, b: 3}
- {a: 1, **h}.should == {a: 1, 1 => 2, b: 3}
- end
+ it "allows splatted elements keys that are not symbols" do
+ h = {1 => 2, b: 3}
+ {a: 1, **h}.should == {a: 1, 1 => 2, b: 3}
end
it "raises a TypeError if #to_hash does not return a Hash" do
diff --git a/spec/ruby/language/heredoc_spec.rb b/spec/ruby/language/heredoc_spec.rb
index 61a27ad8e0..b3b160fd11 100644
--- a/spec/ruby/language/heredoc_spec.rb
+++ b/spec/ruby/language/heredoc_spec.rb
@@ -59,20 +59,10 @@ HERE
s.encoding.should == Encoding::US_ASCII
end
- ruby_version_is "2.7" do
- 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)
- end
- end
-
- ruby_version_is ""..."2.7" do
- it 'prints a warning if quoted HEREDOC identifier is ending not on same line' do
- -> {
- eval %{<<"HERE\n"\nit warns\nHERE}
- }.should complain(/here document identifier ends with a newline/)
- 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)
end
it "allows HEREDOC with <<~'identifier', allowing to indent identifier and content" do
diff --git a/spec/ruby/language/keyword_arguments_spec.rb b/spec/ruby/language/keyword_arguments_spec.rb
index 66e37915a2..0c72f59d38 100644
--- a/spec/ruby/language/keyword_arguments_spec.rb
+++ b/spec/ruby/language/keyword_arguments_spec.rb
@@ -302,6 +302,63 @@ ruby_version_is "3.0" do
m(a: 1).should == [[{a: 1}], {}]
m({a: 1}).should == [[{a: 1}], {}]
end
+
+ ruby_version_is "3.2" do
+ it "does not work with call(*ruby2_keyword_args) with missing ruby2_keywords in between" do
+ class << self
+ def n(*args) # Note the missing ruby2_keywords here
+ target(*args)
+ end
+
+ ruby2_keywords def m(*args)
+ n(*args)
+ end
+ end
+
+ empty = {}
+ m(**empty).should == [[], {}]
+ m(empty).should == [[{}], {}]
+
+ m(a: 1).should == [[{a: 1}], {}]
+ m({a: 1}).should == [[{a: 1}], {}]
+ end
+ end
+
+ ruby_version_is ""..."3.2" do
+ # https://bugs.ruby-lang.org/issues/18625
+ it "works with call(*ruby2_keyword_args) with missing ruby2_keywords in between due to CRuby bug #18625" do
+ class << self
+ def n(*args) # Note the missing ruby2_keywords here
+ target(*args)
+ end
+
+ ruby2_keywords def m(*args)
+ n(*args)
+ end
+ end
+
+ empty = {}
+ m(**empty).should == [[], {}]
+ Hash.ruby2_keywords_hash?(empty).should == false
+ m(empty).should == [[{}], {}]
+ Hash.ruby2_keywords_hash?(empty).should == false
+
+ m(a: 1).should == [[], {a: 1}]
+ m({a: 1}).should == [[{a: 1}], {}]
+
+ kw = {a: 1}
+
+ m(**kw).should == [[], {a: 1}]
+ m(**kw)[1].should == kw
+ m(**kw)[1].should_not.equal?(kw)
+ Hash.ruby2_keywords_hash?(kw).should == false
+ Hash.ruby2_keywords_hash?(m(**kw)[1]).should == false
+
+ m(kw).should == [[{a: 1}], {}]
+ m(kw)[0][0].should.equal?(kw)
+ Hash.ruby2_keywords_hash?(kw).should == false
+ end
+ end
end
end
end
diff --git a/spec/ruby/language/lambda_spec.rb b/spec/ruby/language/lambda_spec.rb
index 6393fb5c47..a3f01ec04b 100644
--- a/spec/ruby/language/lambda_spec.rb
+++ b/spec/ruby/language/lambda_spec.rb
@@ -281,38 +281,18 @@ describe "A lambda literal -> () { }" do
end
describe "with circular optional argument reference" do
- ruby_version_is ''...'2.7' do
- it "warns and uses a nil value when there is an existing local variable with same name" do
- a = 1
- -> {
- @proc = eval "-> (a=a) { a }"
- }.should complain(/circular argument reference/)
- @proc.call.should == nil
- end
-
- it "warns and uses a nil value when there is an existing method with same name" do
- def a; 1; end
- -> {
- @proc = eval "-> (a=a) { a }"
- }.should complain(/circular argument reference/)
- @proc.call.should == nil
- end
+ it "raises a SyntaxError if using an existing local with the same name as the argument" do
+ a = 1
+ -> {
+ @proc = eval "-> (a=a) { a }"
+ }.should raise_error(SyntaxError)
end
- ruby_version_is '2.7' do
- it "raises a SyntaxError if using an existing local with the same name as the argument" do
- a = 1
- -> {
- @proc = eval "-> (a=a) { a }"
- }.should raise_error(SyntaxError)
- end
-
- it "raises a SyntaxError if there is an existing method with the same name as the argument" do
- def a; 1; end
- -> {
- @proc = eval "-> (a=a) { a }"
- }.should raise_error(SyntaxError)
- end
+ it "raises a SyntaxError if there is an existing method with the same name as the argument" do
+ def a; 1; end
+ -> {
+ @proc = eval "-> (a=a) { a }"
+ }.should raise_error(SyntaxError)
end
it "calls an existing method with the same name as the argument if explicitly using ()" do
@@ -360,26 +340,12 @@ describe "A lambda expression 'lambda { ... }'" do
def meth; lambda; end
end
- ruby_version_is ""..."2.7" do
- it "can be created" do
- implicit_lambda = nil
+ it "raises ArgumentError" do
+ implicit_lambda = nil
+ suppress_warning do
-> {
- implicit_lambda = meth { 1 }
- }.should complain(/tried to create Proc object without a block/)
-
- implicit_lambda.lambda?.should be_true
- implicit_lambda.call.should == 1
- end
- end
-
- ruby_version_is "2.7" do
- it "raises ArgumentError" do
- implicit_lambda = nil
- suppress_warning do
- -> {
- meth { 1 }
- }.should raise_error(ArgumentError, /tried to create Proc object without a block/)
- end
+ meth { 1 }
+ }.should raise_error(ArgumentError, /tried to create Proc object without a block/)
end
end
end
diff --git a/spec/ruby/language/method_spec.rb b/spec/ruby/language/method_spec.rb
index 0a5bb99d0b..d464e79403 100644
--- a/spec/ruby/language/method_spec.rb
+++ b/spec/ruby/language/method_spec.rb
@@ -602,13 +602,11 @@ describe "A method" do
-> { m(2) }.should raise_error(ArgumentError)
end
- ruby_version_is "2.7" do
- evaluate <<-ruby do
- def m(**k); k end;
- ruby
+ evaluate <<-ruby do
+ def m(**k); k end;
+ ruby
- m("a" => 1).should == { "a" => 1 }
- end
+ m("a" => 1).should == { "a" => 1 }
end
evaluate <<-ruby do
@@ -962,26 +960,13 @@ describe "A method" do
end
end
- ruby_version_is ""..."2.7" do
- evaluate <<-ruby do
- def m(a=1, **) a end
- ruby
-
- m().should == 1
- m(2, a: 1, b: 0).should == 2
- m("a" => 1, a: 2).should == {"a" => 1}
- end
- end
-
- ruby_version_is "2.7" do
- evaluate <<-ruby do
- def m(a=1, **) a end
- ruby
+ evaluate <<-ruby do
+ def m(a=1, **) a end
+ ruby
- m().should == 1
- m(2, a: 1, b: 0).should == 2
- m("a" => 1, a: 2).should == 1
- end
+ m().should == 1
+ m(2, a: 1, b: 0).should == 2
+ m("a" => 1, a: 2).should == 1
end
evaluate <<-ruby do
@@ -1021,164 +1006,7 @@ describe "A method" do
m(1, 2, 3).should == [[1, 2], 3]
end
- ruby_version_is ""..."2.7" do
- evaluate <<-ruby do
- def m(*, a:) a end
- ruby
-
- m(a: 1).should == 1
- m(1, 2, a: 3).should == 3
- suppress_keyword_warning do
- m("a" => 1, a: 2).should == 2
- end
- end
-
- evaluate <<-ruby do
- def m(*a, b:) [a, b] end
- ruby
-
- m(b: 1).should == [[], 1]
- m(1, 2, b: 3).should == [[1, 2], 3]
- suppress_keyword_warning do
- m("a" => 1, b: 2).should == [[{"a" => 1}], 2]
- end
- end
-
- evaluate <<-ruby do
- def m(*, a: 1) a end
- ruby
-
- m().should == 1
- m(1, 2).should == 1
- m(a: 2).should == 2
- m(1, a: 2).should == 2
- suppress_keyword_warning do
- m("a" => 1, a: 2).should == 2
- end
- end
-
- evaluate <<-ruby do
- def m(*a, b: 1) [a, b] end
- ruby
-
- m().should == [[], 1]
- m(1, 2, 3, b: 4).should == [[1, 2, 3], 4]
- suppress_keyword_warning do
- m("a" => 1, b: 2).should == [[{"a" => 1}], 2]
- end
-
- a = mock("splat")
- a.should_not_receive(:to_ary)
- m(*a).should == [[a], 1]
- end
-
- evaluate <<-ruby do
- def m(*, **) end
- ruby
-
- m().should be_nil
- m(a: 1, b: 2).should be_nil
- m(1, 2, 3, a: 4, b: 5).should be_nil
-
- h = mock("keyword splat")
- h.should_receive(:to_hash).and_return({a: 1})
- suppress_keyword_warning do
- m(h).should be_nil
- end
-
- h = mock("keyword splat")
- error = RuntimeError.new("error while converting to a hash")
- h.should_receive(:to_hash).and_raise(error)
- -> { m(h) }.should raise_error(error)
- end
-
- evaluate <<-ruby do
- def m(*a, **) a end
- ruby
-
- m().should == []
- m(1, 2, 3, a: 4, b: 5).should == [1, 2, 3]
- m("a" => 1, a: 1).should == [{"a" => 1}]
- m(1, **{a: 2}).should == [1]
-
- h = mock("keyword splat")
- h.should_receive(:to_hash)
- -> { m(**h) }.should raise_error(TypeError)
- end
-
- evaluate <<-ruby do
- def m(*, **k) k end
- ruby
-
- m().should == {}
- m(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5}
- m("a" => 1, a: 1).should == {a: 1}
-
- h = mock("keyword splat")
- h.should_receive(:to_hash).and_return({a: 1})
- m(h).should == {a: 1}
- end
-
- evaluate <<-ruby do
- def m(a = nil, **k) [a, k] end
- ruby
-
- m().should == [nil, {}]
- m("a" => 1).should == [{"a" => 1}, {}]
- m(a: 1).should == [nil, {a: 1}]
- m("a" => 1, a: 1).should == [{"a" => 1}, {a: 1}]
- m({ "a" => 1 }, a: 1).should == [{"a" => 1}, {a: 1}]
- m({a: 1}, {}).should == [{a: 1}, {}]
-
- h = {"a" => 1, b: 2}
- m(h).should == [{"a" => 1}, {b: 2}]
- h.should == {"a" => 1, b: 2}
-
- h = {"a" => 1}
- m(h).first.should == h
-
- h = {}
- r = m(h)
- r.first.should be_nil
- r.last.should == {}
-
- hh = {}
- h = mock("keyword splat empty hash")
- h.should_receive(:to_hash).and_return(hh)
- r = m(h)
- r.first.should be_nil
- r.last.should == {}
-
- h = mock("keyword splat")
- h.should_receive(:to_hash).and_return({"a" => 1, a: 2})
- m(h).should == [{"a" => 1}, {a: 2}]
- end
-
- evaluate <<-ruby do
- def m(*a, **k) [a, k] end
- ruby
-
- m().should == [[], {}]
- m(1).should == [[1], {}]
- m(a: 1, b: 2).should == [[], {a: 1, b: 2}]
- m(1, 2, 3, a: 2).should == [[1, 2, 3], {a: 2}]
-
- m("a" => 1).should == [[{"a" => 1}], {}]
- m(a: 1).should == [[], {a: 1}]
- m("a" => 1, a: 1).should == [[{"a" => 1}], {a: 1}]
- m({ "a" => 1 }, a: 1).should == [[{"a" => 1}], {a: 1}]
- m({a: 1}, {}).should == [[{a: 1}], {}]
- m({a: 1}, {"a" => 1}).should == [[{a: 1}, {"a" => 1}], {}]
-
- bo = BasicObject.new
- def bo.to_a; [1, 2, 3]; end
- def bo.to_hash; {:b => 2, :c => 3}; end
-
- m(*bo, **bo).should == [[1, 2, 3], {:b => 2, :c => 3}]
- end
- end
-
- ruby_version_is "2.7"...'3.0' do
+ ruby_version_is ""...'3.0' do
evaluate <<-ruby do
def m(*, a:) a end
ruby
@@ -1503,44 +1331,22 @@ describe "A method" do
end
end
- ruby_version_is ''...'2.7' do
- evaluate <<-ruby do
- def m(a:, **) a end
- ruby
-
- m(a: 1).should == 1
- m(a: 1, b: 2).should == 1
- -> { m("a" => 1, a: 1, b: 2) }.should raise_error(ArgumentError)
- end
-
- evaluate <<-ruby do
- def m(a:, **k) [a, k] end
- ruby
+ evaluate <<-ruby do
+ def m(a:, **) a end
+ ruby
- m(a: 1).should == [1, {}]
- m(a: 1, b: 2, c: 3).should == [1, {b: 2, c: 3}]
- -> { m("a" => 1, a: 1, b: 2) }.should raise_error(ArgumentError)
- end
+ m(a: 1).should == 1
+ m(a: 1, b: 2).should == 1
+ m("a" => 1, a: 1, b: 2).should == 1
end
- ruby_version_is '2.7' do
- evaluate <<-ruby do
- def m(a:, **) a end
- ruby
-
- m(a: 1).should == 1
- m(a: 1, b: 2).should == 1
- m("a" => 1, a: 1, b: 2).should == 1
- end
-
- evaluate <<-ruby do
- def m(a:, **k) [a, k] end
- ruby
+ evaluate <<-ruby do
+ def m(a:, **k) [a, k] end
+ ruby
- m(a: 1).should == [1, {}]
- m(a: 1, b: 2, c: 3).should == [1, {b: 2, c: 3}]
- m("a" => 1, a: 1, b: 2).should == [1, {"a" => 1, b: 2}]
- end
+ m(a: 1).should == [1, {}]
+ m(a: 1, b: 2, c: 3).should == [1, {b: 2, c: 3}]
+ m("a" => 1, a: 1, b: 2).should == [1, {"a" => 1, b: 2}]
end
evaluate <<-ruby do
@@ -1637,18 +1443,16 @@ describe "A method" do
result.should == [1, 1, [], 2, 3, 2, 4, { h: 5, i: 6 }, l]
end
- ruby_version_is "2.7" do
- evaluate <<-ruby do
- def m(a, **nil); a end;
- ruby
+ evaluate <<-ruby do
+ def m(a, **nil); a end;
+ ruby
- m({a: 1}).should == {a: 1}
- m({"a" => 1}).should == {"a" => 1}
+ m({a: 1}).should == {a: 1}
+ m({"a" => 1}).should == {"a" => 1}
- -> { m(a: 1) }.should raise_error(ArgumentError)
- -> { m(**{a: 1}) }.should raise_error(ArgumentError)
- -> { m("a" => 1) }.should raise_error(ArgumentError)
- end
+ -> { m(a: 1) }.should raise_error(ArgumentError)
+ -> { m(**{a: 1}) }.should raise_error(ArgumentError)
+ -> { m("a" => 1) }.should raise_error(ArgumentError)
end
ruby_version_is ''...'3.0' do
@@ -1690,19 +1494,17 @@ describe "A method" do
end
end
- ruby_version_is '2.7' do
- context 'when passing an empty keyword splat to a method that does not accept keywords' do
- evaluate <<-ruby do
- def m(*a); a; end
- ruby
+ context 'when passing an empty keyword splat to a method that does not accept keywords' do
+ evaluate <<-ruby do
+ def m(*a); a; end
+ ruby
- h = {}
- m(**h).should == []
- end
+ h = {}
+ m(**h).should == []
end
end
- ruby_version_is '2.7'...'3.0' do
+ ruby_version_is ''...'3.0' do
context 'when passing an empty keyword splat to a method that does not accept keywords' do
evaluate <<-ruby do
def m(a); a; end
diff --git a/spec/ruby/language/numbered_parameters_spec.rb b/spec/ruby/language/numbered_parameters_spec.rb
index 838822b2d6..424d7a06e3 100644
--- a/spec/ruby/language/numbered_parameters_spec.rb
+++ b/spec/ruby/language/numbered_parameters_spec.rb
@@ -1,120 +1,118 @@
require_relative '../spec_helper'
-ruby_version_is "2.7" do
- describe "Numbered parameters" do
- it "provides default parameters _1, _2, ... in a block" do
- -> { _1 }.call("a").should == "a"
- proc { _1 }.call("a").should == "a"
- lambda { _1 }.call("a").should == "a"
- ["a"].map { _1 }.should == ["a"]
- end
+describe "Numbered parameters" do
+ it "provides default parameters _1, _2, ... in a block" do
+ -> { _1 }.call("a").should == "a"
+ proc { _1 }.call("a").should == "a"
+ lambda { _1 }.call("a").should == "a"
+ ["a"].map { _1 }.should == ["a"]
+ end
- it "assigns nil to not passed parameters" do
- proc { [_1, _2] }.call("a").should == ["a", nil]
- proc { [_1, _2] }.call("a", "b").should == ["a", "b"]
- end
+ it "assigns nil to not passed parameters" do
+ proc { [_1, _2] }.call("a").should == ["a", nil]
+ proc { [_1, _2] }.call("a", "b").should == ["a", "b"]
+ end
- it "supports variables _1-_9 only for the first 9 passed parameters" do
- block = proc { [_1, _2, _3, _4, _5, _6, _7, _8, _9] }
- result = block.call(1, 2, 3, 4, 5, 6, 7, 8, 9)
- result.should == [1, 2, 3, 4, 5, 6, 7, 8, 9]
- end
+ it "supports variables _1-_9 only for the first 9 passed parameters" do
+ block = proc { [_1, _2, _3, _4, _5, _6, _7, _8, _9] }
+ result = block.call(1, 2, 3, 4, 5, 6, 7, 8, 9)
+ result.should == [1, 2, 3, 4, 5, 6, 7, 8, 9]
+ end
- it "does not support more than 9 parameters" do
- -> {
- proc { [_10] }.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
- }.should raise_error(NameError, /undefined local variable or method `_10'/)
- end
+ it "does not support more than 9 parameters" do
+ -> {
+ proc { [_10] }.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ }.should raise_error(NameError, /undefined local variable or method `_10'/)
+ end
- it "can not be used in both outer and nested blocks at the same time" do
- -> {
- eval("-> { _1; -> { _2 } }")
- }.should raise_error(SyntaxError, /numbered parameter is already used in/m)
- end
+ it "can not be used in both outer and nested blocks at the same time" do
+ -> {
+ eval("-> { _1; -> { _2 } }")
+ }.should raise_error(SyntaxError, /numbered parameter is already used in/m)
+ end
- ruby_version_is '2.7'...'3.0' do
- it "can be overwritten with local variable" do
- suppress_warning do
- eval <<~CODE
- _1 = 0
- proc { _1 }.call("a").should == 0
- CODE
- end
+ ruby_version_is ''...'3.0' do
+ it "can be overwritten with local variable" do
+ suppress_warning do
+ eval <<~CODE
+ _1 = 0
+ proc { _1 }.call("a").should == 0
+ CODE
end
+ end
- it "warns when numbered parameter is overwritten with local variable" do
- -> {
- eval("_1 = 0")
- }.should complain(/warning: `_1' is reserved for numbered parameter; consider another name/)
- end
+ it "warns when numbered parameter is overwritten with local variable" do
+ -> {
+ eval("_1 = 0")
+ }.should complain(/warning: `_1' is reserved for numbered parameter; consider another name/)
end
+ end
- ruby_version_is '3.0' do
- it "cannot be overwritten with local variable" do
- -> {
- eval <<~CODE
- _1 = 0
- proc { _1 }.call("a").should == 0
- CODE
- }.should raise_error(SyntaxError, /_1 is reserved for numbered parameter/)
- end
+ ruby_version_is '3.0' do
+ it "cannot be overwritten with local variable" do
+ -> {
+ eval <<~CODE
+ _1 = 0
+ proc { _1 }.call("a").should == 0
+ CODE
+ }.should raise_error(SyntaxError, /_1 is reserved for numbered parameter/)
+ end
- it "errors when numbered parameter is overwritten with local variable" do
- -> {
- eval("_1 = 0")
- }.should raise_error(SyntaxError, /_1 is reserved for numbered parameter/)
- end
+ it "errors when numbered parameter is overwritten with local variable" do
+ -> {
+ eval("_1 = 0")
+ }.should raise_error(SyntaxError, /_1 is reserved for numbered parameter/)
end
+ end
- it "raises SyntaxError when block parameters are specified explicitly" do
- -> { eval("-> () { _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
- -> { eval("-> (x) { _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ it "raises SyntaxError when block parameters are specified explicitly" do
+ -> { eval("-> () { _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ -> { eval("-> (x) { _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
- -> { eval("proc { || _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
- -> { eval("proc { |x| _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ -> { eval("proc { || _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ -> { eval("proc { |x| _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
- -> { eval("lambda { || _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
- -> { eval("lambda { |x| _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ -> { eval("lambda { || _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ -> { eval("lambda { |x| _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
- -> { eval("['a'].map { || _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
- -> { eval("['a'].map { |x| _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
- end
+ -> { eval("['a'].map { || _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ -> { eval("['a'].map { |x| _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ end
- describe "assigning to a numbered parameter" do
- ruby_version_is '2.7'...'3.0' do
- it "warns" do
- -> { eval("proc { _1 = 0 }") }.should complain(/warning: `_1' is reserved for numbered parameter; consider another name/)
- end
+ describe "assigning to a numbered parameter" do
+ ruby_version_is ''...'3.0' do
+ it "warns" do
+ -> { eval("proc { _1 = 0 }") }.should complain(/warning: `_1' is reserved for numbered parameter; consider another name/)
end
+ end
- ruby_version_is '3.0' do
- it "raises SyntaxError" do
- -> { eval("proc { _1 = 0 }") }.should raise_error(SyntaxError, /_1 is reserved for numbered parameter/)
- end
+ ruby_version_is '3.0' do
+ it "raises SyntaxError" do
+ -> { eval("proc { _1 = 0 }") }.should raise_error(SyntaxError, /_1 is reserved for numbered parameter/)
end
end
+ end
- it "affects block arity" do
- -> { _1 }.arity.should == 1
- -> { _2 }.arity.should == 2
- -> { _3 }.arity.should == 3
- -> { _4 }.arity.should == 4
- -> { _5 }.arity.should == 5
- -> { _6 }.arity.should == 6
- -> { _7 }.arity.should == 7
- -> { _8 }.arity.should == 8
- -> { _9 }.arity.should == 9
-
- -> { _9 }.arity.should == 9
- proc { _9 }.arity.should == 9
- lambda { _9 }.arity.should == 9
- end
+ it "affects block arity" do
+ -> { _1 }.arity.should == 1
+ -> { _2 }.arity.should == 2
+ -> { _3 }.arity.should == 3
+ -> { _4 }.arity.should == 4
+ -> { _5 }.arity.should == 5
+ -> { _6 }.arity.should == 6
+ -> { _7 }.arity.should == 7
+ -> { _8 }.arity.should == 8
+ -> { _9 }.arity.should == 9
+
+ -> { _9 }.arity.should == 9
+ proc { _9 }.arity.should == 9
+ lambda { _9 }.arity.should == 9
+ end
- it "does not work in methods" do
- obj = Object.new
- def obj.foo; _1 end
+ it "does not work in methods" do
+ obj = Object.new
+ def obj.foo; _1 end
- -> { obj.foo("a") }.should raise_error(ArgumentError, /wrong number of arguments/)
- end
+ -> { obj.foo("a") }.should raise_error(ArgumentError, /wrong number of arguments/)
end
end
diff --git a/spec/ruby/language/pattern_matching_spec.rb b/spec/ruby/language/pattern_matching_spec.rb
index c68b6caa34..f3cc86fa0b 100644
--- a/spec/ruby/language/pattern_matching_spec.rb
+++ b/spec/ruby/language/pattern_matching_spec.rb
@@ -1,240 +1,356 @@
require_relative '../spec_helper'
-ruby_version_is "2.7" do
- describe "Pattern matching" do
- # TODO: Remove excessive eval calls when support of previous version
- # Ruby 2.6 will be dropped
+describe "Pattern matching" do
+ # TODO: Remove excessive eval calls when Ruby 3 is the minimum version.
+ # It is best to keep the eval's longer if other Ruby impls cannot parse pattern matching yet.
- before :each do
- ScratchPad.record []
+ before :each do
+ ScratchPad.record []
+ end
+
+ ruby_version_is "3.0" do
+ it "can be standalone assoc operator that deconstructs value" do
+ suppress_warning do
+ eval(<<-RUBY).should == [0, 1]
+ [0, 1] => [a, b]
+ [a, b]
+ RUBY
+ end
end
- ruby_version_is "3.0" do
- it "can be standalone assoc operator that deconstructs value" do
- suppress_warning do
- eval(<<-RUBY).should == [0, 1]
- [0, 1] => [a, b]
- [a, b]
- RUBY
- end
+ describe "find pattern" do
+ it "captures preceding elements to the pattern" do
+ eval(<<~RUBY).should == [0, 1]
+ case [0, 1, 2, 3]
+ in [*pre, 2, 3]
+ pre
+ else
+ false
+ end
+ RUBY
end
- describe "find pattern" do
- it "captures preceding elements to the pattern" do
- eval(<<~RUBY).should == [0, 1]
- case [0, 1, 2, 3]
- in [*pre, 2, 3]
- pre
- else
- false
- end
- RUBY
- end
-
- it "captures following elements to the pattern" do
- eval(<<~RUBY).should == [2, 3]
- case [0, 1, 2, 3]
- in [0, 1, *post]
- post
- else
- false
- end
- RUBY
- end
-
- it "captures both preceding and following elements to the pattern" do
- eval(<<~RUBY).should == [[0, 1], [3, 4]]
- case [0, 1, 2, 3, 4]
- in [*pre, 2, *post]
- [pre, post]
- else
- false
- end
- RUBY
- end
-
- it "can capture the entirety of the pattern" do
- eval(<<~RUBY).should == [0, 1, 2, 3, 4]
- case [0, 1, 2, 3, 4]
- in [*everything]
- everything
- else
- false
- end
- RUBY
- end
-
- it "will match an empty Array-like structure" do
- eval(<<~RUBY).should == []
- case []
- in [*everything]
- everything
- else
- false
- end
- RUBY
- end
-
- it "can be nested" do
- eval(<<~RUBY).should == [[0, [2, 4, 6]], [[4, 16, 64]], 27]
- case [0, [2, 4, 6], [3, 9, 27], [4, 16, 64]]
- in [*pre, [*, 9, a], *post]
- [pre, post, a]
- else
- false
- end
- RUBY
- end
-
- it "can be nested with an array pattern" do
- eval(<<~RUBY).should == [[4, 16, 64]]
- case [0, [2, 4, 6], [3, 9, 27], [4, 16, 64]]
- in [_, _, [*, 9, *], *post]
- post
- else
- false
- end
- RUBY
- end
-
- it "can be nested within a hash pattern" do
- eval(<<~RUBY).should == [27]
- case {a: [3, 9, 27]}
- in {a: [*, 9, *post]}
- post
- else
- false
- end
- RUBY
- end
-
- it "can nest hash and array patterns" do
- eval(<<~RUBY).should == [42, 2]
- case [0, {a: 42, b: [0, 1]}, {a: 42, b: [1, 2]}]
- in [*, {a:, b: [1, c]}, *]
- [a, c]
- else
- false
- end
- RUBY
- end
+ it "captures following elements to the pattern" do
+ eval(<<~RUBY).should == [2, 3]
+ case [0, 1, 2, 3]
+ in [0, 1, *post]
+ post
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "captures both preceding and following elements to the pattern" do
+ eval(<<~RUBY).should == [[0, 1], [3, 4]]
+ case [0, 1, 2, 3, 4]
+ in [*pre, 2, *post]
+ [pre, post]
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "can capture the entirety of the pattern" do
+ eval(<<~RUBY).should == [0, 1, 2, 3, 4]
+ case [0, 1, 2, 3, 4]
+ in [*everything]
+ everything
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "will match an empty Array-like structure" do
+ eval(<<~RUBY).should == []
+ case []
+ in [*everything]
+ everything
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "can be nested" do
+ eval(<<~RUBY).should == [[0, [2, 4, 6]], [[4, 16, 64]], 27]
+ case [0, [2, 4, 6], [3, 9, 27], [4, 16, 64]]
+ in [*pre, [*, 9, a], *post]
+ [pre, post, a]
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "can be nested with an array pattern" do
+ eval(<<~RUBY).should == [[4, 16, 64]]
+ case [0, [2, 4, 6], [3, 9, 27], [4, 16, 64]]
+ in [_, _, [*, 9, *], *post]
+ post
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "can be nested within a hash pattern" do
+ eval(<<~RUBY).should == [27]
+ case {a: [3, 9, 27]}
+ in {a: [*, 9, *post]}
+ post
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "can nest hash and array patterns" do
+ eval(<<~RUBY).should == [42, 2]
+ case [0, {a: 42, b: [0, 1]}, {a: 42, b: [1, 2]}]
+ in [*, {a:, b: [1, c]}, *]
+ [a, c]
+ else
+ false
+ end
+ RUBY
end
end
+ end
- it "extends case expression with case/in construction" do
- eval(<<~RUBY).should == :bar
- case [0, 1]
- in [0]
- :foo
- in [0, 1]
- :bar
- end
- RUBY
+ it "extends case expression with case/in construction" do
+ eval(<<~RUBY).should == :bar
+ case [0, 1]
+ in [0]
+ :foo
+ in [0, 1]
+ :bar
+ end
+ RUBY
+ end
+
+ it "allows using then operator" do
+ eval(<<~RUBY).should == :bar
+ case [0, 1]
+ in [0] then :foo
+ in [0, 1] then :bar
+ end
+ RUBY
+ end
+
+ describe "warning" do
+ before :each do
+ @experimental, Warning[:experimental] = Warning[:experimental], true
end
- it "allows using then operator" do
- eval(<<~RUBY).should == :bar
- case [0, 1]
- in [0] then :foo
- in [0, 1] then :bar
- end
- RUBY
+ after :each do
+ Warning[:experimental] = @experimental
end
- describe "warning" do
+ context 'when regular form' do
before :each do
- @experimental, Warning[:experimental] = Warning[:experimental], true
+ @src = 'case [0, 1]; in [a, b]; end'
+ end
+
+ ruby_version_is ""..."3.0" do
+ it "warns about pattern matching is experimental feature" do
+ -> { eval @src }.should complain(/pattern matching is experimental, and the behavior may change in future versions of Ruby!/i)
+ end
end
- after :each do
- Warning[:experimental] = @experimental
+ ruby_version_is "3.0" do
+ it "does not warn about pattern matching is experimental feature" do
+ -> { eval @src }.should_not complain
+ end
end
+ end
- context 'when regular form' do
+ context 'when one-line form' do
+ ruby_version_is '3.0' do
before :each do
- @src = 'case [0, 1]; in [a, b]; end'
+ @src = '[0, 1] => [a, b]'
end
- ruby_version_is ""..."3.0" do
+ ruby_version_is ""..."3.1" do
it "warns about pattern matching is experimental feature" do
-> { eval @src }.should complain(/pattern matching is experimental, and the behavior may change in future versions of Ruby!/i)
end
end
- ruby_version_is "3.0" do
+ ruby_version_is "3.1" do
it "does not warn about pattern matching is experimental feature" do
-> { eval @src }.should_not complain
end
end
end
+ end
+ end
- context 'when one-line form' do
- ruby_version_is '3.0' do
- before :each do
- @src = '[0, 1] => [a, b]'
- end
+ it "binds variables" do
+ eval(<<~RUBY).should == 1
+ case [0, 1]
+ in [0, a]
+ a
+ end
+ RUBY
+ end
- ruby_version_is ""..."3.1" do
- it "warns about pattern matching is experimental feature" do
- -> { eval @src }.should complain(/pattern matching is experimental, and the behavior may change in future versions of Ruby!/i)
- end
- end
+ it "cannot mix in and when operators" do
+ -> {
+ eval <<~RUBY
+ case []
+ when 1 == 1
+ in []
+ end
+ RUBY
+ }.should raise_error(SyntaxError, /syntax error, unexpected `in'/)
- ruby_version_is "3.1" do
- it "does not warn about pattern matching is experimental feature" do
- -> { eval @src }.should_not complain
- end
- end
+ -> {
+ eval <<~RUBY
+ case []
+ in []
+ when 1 == 1
end
+ RUBY
+ }.should raise_error(SyntaxError, /syntax error, unexpected `when'/)
+ end
+
+ it "checks patterns until the first matching" do
+ eval(<<~RUBY).should == :bar
+ case [0, 1]
+ in [0]
+ :foo
+ in [0, 1]
+ :bar
+ in [0, 1]
+ :baz
+ end
+ RUBY
+ end
+
+ it "executes else clause if no pattern matches" do
+ eval(<<~RUBY).should == false
+ case [0, 1]
+ in [0]
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "raises NoMatchingPatternError if no pattern matches and no else clause" do
+ -> {
+ eval <<~RUBY
+ case [0, 1]
+ in [0]
+ end
+ RUBY
+ }.should raise_error(NoMatchingPatternError, /\[0, 1\]/)
+ end
+
+ it "does not allow calculation or method calls in a pattern" do
+ -> {
+ eval <<~RUBY
+ case 0
+ in 1 + 1
+ true
+ end
+ RUBY
+ }.should raise_error(SyntaxError, /unexpected/)
+ end
+
+ it "evaluates the case expression once for multiple patterns, caching the result" do
+ eval(<<~RUBY).should == true
+ case (ScratchPad << :foo; 1)
+ in 0
+ false
+ in 1
+ true
end
+ RUBY
+
+ ScratchPad.recorded.should == [:foo]
+ end
+
+ describe "guards" do
+ it "supports if guard" do
+ eval(<<~RUBY).should == false
+ case 0
+ in 0 if false
+ true
+ else
+ false
+ end
+ RUBY
+
+ eval(<<~RUBY).should == true
+ case 0
+ in 0 if true
+ true
+ else
+ false
+ end
+ RUBY
end
- it "binds variables" do
- eval(<<~RUBY).should == 1
+ it "supports unless guard" do
+ eval(<<~RUBY).should == false
+ case 0
+ in 0 unless true
+ true
+ else
+ false
+ end
+ RUBY
+
+ eval(<<~RUBY).should == true
+ case 0
+ in 0 unless false
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "makes bound variables visible in guard" do
+ eval(<<~RUBY).should == true
case [0, 1]
- in [0, a]
- a
+ in [a, 1] if a >= 0
+ true
end
RUBY
end
- it "cannot mix in and when operators" do
- -> {
- eval <<~RUBY
- case []
- when 1 == 1
- in []
- end
- RUBY
- }.should raise_error(SyntaxError, /syntax error, unexpected `in'/)
+ it "does not evaluate guard if pattern does not match" do
+ eval <<~RUBY
+ case 0
+ in 1 if (ScratchPad << :foo) || true
+ else
+ end
+ RUBY
- -> {
- eval <<~RUBY
- case []
- in []
- when 1 == 1
- end
- RUBY
- }.should raise_error(SyntaxError, /syntax error, unexpected `when'/)
+ ScratchPad.recorded.should == []
end
- it "checks patterns until the first matching" do
+ it "takes guards into account when there are several matching patterns" do
eval(<<~RUBY).should == :bar
- case [0, 1]
- in [0]
+ case 0
+ in 0 if false
:foo
- in [0, 1]
+ in 0 if true
:bar
- in [0, 1]
- :baz
end
RUBY
end
- it "executes else clause if no pattern matches" do
+ it "executes else clause if no guarded pattern matches" do
eval(<<~RUBY).should == false
- case [0, 1]
- in [0]
+ case 0
+ in 0 if false
true
else
false
@@ -242,1164 +358,1046 @@ ruby_version_is "2.7" do
RUBY
end
- it "raises NoMatchingPatternError if no pattern matches and no else clause" do
+ it "raises NoMatchingPatternError if no guarded pattern matches and no else clause" do
-> {
eval <<~RUBY
case [0, 1]
- in [0]
+ in [0, 1] if false
end
RUBY
}.should raise_error(NoMatchingPatternError, /\[0, 1\]/)
end
+ end
- it "does not allow calculation or method calls in a pattern" do
- -> {
- eval <<~RUBY
- case 0
- in 1 + 1
- true
- end
- RUBY
- }.should raise_error(SyntaxError, /unexpected/)
- end
-
- it "evaluates the case expression once for multiple patterns, caching the result" do
+ describe "value pattern" do
+ it "matches an object such that pattern === object" do
eval(<<~RUBY).should == true
- case (ScratchPad << :foo; 1)
+ case 0
in 0
- false
- in 1
true
end
RUBY
- ScratchPad.recorded.should == [:foo]
- end
-
- describe "guards" do
- it "supports if guard" do
- eval(<<~RUBY).should == false
- case 0
- in 0 if false
- true
- else
- false
- end
- RUBY
-
- eval(<<~RUBY).should == true
- case 0
- in 0 if true
- true
- else
- false
- end
- RUBY
- end
-
- it "supports unless guard" do
- eval(<<~RUBY).should == false
- case 0
- in 0 unless true
- true
- else
- false
- end
- RUBY
-
- eval(<<~RUBY).should == true
- case 0
- in 0 unless false
- true
- else
- false
- end
- RUBY
- end
-
- it "makes bound variables visible in guard" do
- eval(<<~RUBY).should == true
- case [0, 1]
- in [a, 1] if a >= 0
- true
- end
- RUBY
- end
-
- it "does not evaluate guard if pattern does not match" do
- eval <<~RUBY
- case 0
- in 1 if (ScratchPad << :foo) || true
- else
- end
- RUBY
-
- ScratchPad.recorded.should == []
- end
+ eval(<<~RUBY).should == true
+ case 0
+ in (-1..1)
+ true
+ end
+ RUBY
- it "takes guards into account when there are several matching patterns" do
- eval(<<~RUBY).should == :bar
- case 0
- in 0 if false
- :foo
- in 0 if true
- :bar
- end
- RUBY
- end
+ eval(<<~RUBY).should == true
+ case 0
+ in Integer
+ true
+ end
+ RUBY
- it "executes else clause if no guarded pattern matches" do
- eval(<<~RUBY).should == false
- case 0
- in 0 if false
- true
- else
- false
- end
- RUBY
- end
+ eval(<<~RUBY).should == true
+ case "0"
+ in /0/
+ true
+ end
+ RUBY
- it "raises NoMatchingPatternError if no guarded pattern matches and no else clause" do
- -> {
- eval <<~RUBY
- case [0, 1]
- in [0, 1] if false
- end
- RUBY
- }.should raise_error(NoMatchingPatternError, /\[0, 1\]/)
- end
+ eval(<<~RUBY).should == true
+ case "0"
+ in ->(s) { s == "0" }
+ true
+ end
+ RUBY
end
- describe "value pattern" do
- it "matches an object such that pattern === object" do
- eval(<<~RUBY).should == true
- case 0
- in 0
- true
- end
- RUBY
+ it "allows string literal with interpolation" do
+ x = "x"
- eval(<<~RUBY).should == true
- case 0
- in (-1..1)
- true
- end
- RUBY
-
- eval(<<~RUBY).should == true
- case 0
- in Integer
- true
- end
- RUBY
-
- eval(<<~RUBY).should == true
- case "0"
- in /0/
- true
- end
- RUBY
+ eval(<<~RUBY).should == true
+ case "x"
+ in "#{x + ""}"
+ true
+ end
+ RUBY
+ end
+ end
- eval(<<~RUBY).should == true
- case "0"
- in ->(s) { s == "0" }
- true
- end
- RUBY
- end
+ describe "variable pattern" do
+ it "matches a value and binds variable name to this value" do
+ eval(<<~RUBY).should == 0
+ case 0
+ in a
+ a
+ end
+ RUBY
+ end
- it "allows string literal with interpolation" do
- x = "x"
+ it "makes bounded variable visible outside a case statement scope" do
+ eval(<<~RUBY).should == 0
+ case 0
+ in a
+ end
- eval(<<~RUBY).should == true
- case "x"
- in "#{x + ""}"
- true
- end
- RUBY
- end
+ a
+ RUBY
end
- describe "variable pattern" do
- it "matches a value and binds variable name to this value" do
- eval(<<~RUBY).should == 0
- case 0
- in a
- a
- end
- RUBY
- end
+ it "create local variables even if a pattern doesn't match" do
+ eval(<<~RUBY).should == [0, nil, nil]
+ case 0
+ in a
+ in b
+ in c
+ end
- it "makes bounded variable visible outside a case statement scope" do
- eval(<<~RUBY).should == 0
- case 0
- in a
- end
+ [a, b, c]
+ RUBY
+ end
+ it "allow using _ name to drop values" do
+ eval(<<~RUBY).should == 0
+ case [0, 1]
+ in [a, _]
a
- RUBY
- end
-
- it "create local variables even if a pattern doesn't match" do
- eval(<<~RUBY).should == [0, nil, nil]
- case 0
- in a
- in b
- in c
- end
-
- [a, b, c]
- RUBY
- end
+ end
+ RUBY
+ end
- it "allow using _ name to drop values" do
- eval(<<~RUBY).should == 0
- case [0, 1]
- in [a, _]
- a
- end
- RUBY
- end
+ it "supports using _ in a pattern several times" do
+ eval(<<~RUBY).should == true
+ case [0, 1, 2]
+ in [0, _, _]
+ true
+ end
+ RUBY
+ end
- it "supports using _ in a pattern several times" do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in [0, _, _]
- true
- end
- RUBY
- end
+ it "supports using any name with _ at the beginning in a pattern several times" do
+ eval(<<~RUBY).should == true
+ case [0, 1, 2]
+ in [0, _x, _x]
+ true
+ end
+ RUBY
- it "supports using any name with _ at the beginning in a pattern several times" do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in [0, _x, _x]
- true
- end
- RUBY
+ eval(<<~RUBY).should == true
+ case {a: 0, b: 1, c: 2}
+ in {a: 0, b: _x, c: _x}
+ true
+ end
+ RUBY
+ end
- eval(<<~RUBY).should == true
- case {a: 0, b: 1, c: 2}
- in {a: 0, b: _x, c: _x}
- true
+ it "does not support using variable name (except _) several times" do
+ -> {
+ eval <<~RUBY
+ case [0]
+ in [a, a]
end
RUBY
- end
+ }.should raise_error(SyntaxError, /duplicated variable name/)
+ end
- it "does not support using variable name (except _) several times" do
- -> {
- eval <<~RUBY
- case [0]
- in [a, a]
- end
- RUBY
- }.should raise_error(SyntaxError, /duplicated variable name/)
- end
+ it "supports existing variables in a pattern specified with ^ operator" do
+ a = 0
- it "supports existing variables in a pattern specified with ^ operator" do
- a = 0
+ eval(<<~RUBY).should == true
+ case 0
+ in ^a
+ true
+ end
+ RUBY
+ end
- eval(<<~RUBY).should == true
- case 0
- in ^a
- true
- end
- RUBY
- end
+ it "allows applying ^ operator to bound variables" do
+ eval(<<~RUBY).should == 1
+ case [1, 1]
+ in [n, ^n]
+ n
+ end
+ RUBY
- it "allows applying ^ operator to bound variables" do
- eval(<<~RUBY).should == 1
- case [1, 1]
- in [n, ^n]
- n
- end
- RUBY
+ eval(<<~RUBY).should == false
+ case [1, 2]
+ in [n, ^n]
+ true
+ else
+ false
+ end
+ RUBY
+ end
- eval(<<~RUBY).should == false
+ it "requires bound variable to be specified in a pattern before ^ operator when it relies on a bound variable" do
+ -> {
+ eval <<~RUBY
case [1, 2]
- in [n, ^n]
+ in [^n, n]
true
else
false
end
RUBY
- end
-
- it "requires bound variable to be specified in a pattern before ^ operator when it relies on a bound variable" do
- -> {
- eval <<~RUBY
- case [1, 2]
- in [^n, n]
- true
- else
- false
- end
- RUBY
- }.should raise_error(SyntaxError, /n: no such local variable/)
- end
+ }.should raise_error(SyntaxError, /n: no such local variable/)
end
+ end
- describe "alternative pattern" do
- it "matches if any of patterns matches" do
- eval(<<~RUBY).should == true
- case 0
- in 0 | 1 | 2
- true
- end
- RUBY
- end
-
- it "does not support variable binding" do
- -> {
- eval <<~RUBY
- case [0, 1]
- in [0, 0] | [0, a]
- end
- RUBY
- }.should raise_error(SyntaxError, /illegal variable in alternative pattern/)
- end
+ describe "alternative pattern" do
+ it "matches if any of patterns matches" do
+ eval(<<~RUBY).should == true
+ case 0
+ in 0 | 1 | 2
+ true
+ end
+ RUBY
+ end
- it "support underscore prefixed variables in alternation" do
- eval(<<~RUBY).should == true
+ it "does not support variable binding" do
+ -> {
+ eval <<~RUBY
case [0, 1]
- in [1, _]
- false
- in [0, 0] | [0, _a]
- true
+ in [0, 0] | [0, a]
end
RUBY
- end
-
- it "can be used as a nested pattern" do
- eval(<<~RUBY).should == true
- case [[1], ["2"]]
- in [[0] | nil, _]
- false
- in [[1], [1]]
- false
- in [[1], [2 | "2"]]
- true
- end
- RUBY
-
- eval(<<~RUBY).should == true
- case [1, 2]
- in [0, _] | {a: 0}
- false
- in {a: 1, b: 2} | [1, 2]
- true
- end
- RUBY
- end
+ }.should raise_error(SyntaxError, /illegal variable in alternative pattern/)
end
- describe "AS pattern" do
- it "binds a variable to a value if pattern matches" do
- eval(<<~RUBY).should == 0
- case 0
- in Integer => n
- n
- end
- RUBY
- end
-
- it "can be used as a nested pattern" do
- eval(<<~RUBY).should == [2, 3]
- case [1, [2, 3]]
- in [1, Array => ary]
- ary
- end
- RUBY
- end
+ it "support underscore prefixed variables in alternation" do
+ eval(<<~RUBY).should == true
+ case [0, 1]
+ in [1, _]
+ false
+ in [0, 0] | [0, _a]
+ true
+ end
+ RUBY
end
- describe "Array pattern" do
- it "supports form Constant(pat, pat, ...)" do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in Array(0, 1, 2)
+ it "can be used as a nested pattern" do
+ eval(<<~RUBY).should == true
+ case [[1], ["2"]]
+ in [[0] | nil, _]
+ false
+ in [[1], [1]]
+ false
+ in [[1], [2 | "2"]]
true
- end
- RUBY
- end
+ end
+ RUBY
- it "supports form Constant[pat, pat, ...]" do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in Array[0, 1, 2]
+ eval(<<~RUBY).should == true
+ case [1, 2]
+ in [0, _] | {a: 0}
+ false
+ in {a: 1, b: 2} | [1, 2]
true
- end
- RUBY
- end
+ end
+ RUBY
+ end
+ end
- it "supports form [pat, pat, ...]" do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in [0, 1, 2]
- true
- end
- RUBY
- end
+ describe "AS pattern" do
+ it "binds a variable to a value if pattern matches" do
+ eval(<<~RUBY).should == 0
+ case 0
+ in Integer => n
+ n
+ end
+ RUBY
+ end
- it "supports form pat, pat, ..." do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in 0, 1, 2
- true
- end
- RUBY
+ it "can be used as a nested pattern" do
+ eval(<<~RUBY).should == [2, 3]
+ case [1, [2, 3]]
+ in [1, Array => ary]
+ ary
+ end
+ RUBY
+ end
+ end
- eval(<<~RUBY).should == 1
- case [0, 1, 2]
- in 0, a, 2
- a
- end
- RUBY
+ describe "Array pattern" do
+ it "supports form Constant(pat, pat, ...)" do
+ eval(<<~RUBY).should == true
+ case [0, 1, 2]
+ in Array(0, 1, 2)
+ true
+ end
+ RUBY
+ end
- eval(<<~RUBY).should == [1, 2]
- case [0, 1, 2]
- in 0, *rest
- rest
- end
- RUBY
- end
+ it "supports form Constant[pat, pat, ...]" do
+ eval(<<~RUBY).should == true
+ case [0, 1, 2]
+ in Array[0, 1, 2]
+ true
+ end
+ RUBY
+ end
- it "matches an object with #deconstruct method which returns an array and each element in array matches element in pattern" do
- obj = Object.new
- def obj.deconstruct; [0, 1] end
+ it "supports form [pat, pat, ...]" do
+ eval(<<~RUBY).should == true
+ case [0, 1, 2]
+ in [0, 1, 2]
+ true
+ end
+ RUBY
+ end
- eval(<<~RUBY).should == true
- case obj
- in [Integer, Integer]
- true
- end
- RUBY
- end
+ it "supports form pat, pat, ..." do
+ eval(<<~RUBY).should == true
+ case [0, 1, 2]
+ in 0, 1, 2
+ true
+ end
+ RUBY
- ruby_version_is "3.0" do
- it "calls #deconstruct once for multiple patterns, caching the result" do
- obj = Object.new
+ eval(<<~RUBY).should == 1
+ case [0, 1, 2]
+ in 0, a, 2
+ a
+ end
+ RUBY
- def obj.deconstruct
- ScratchPad << :deconstruct
- [0, 1]
- end
+ eval(<<~RUBY).should == [1, 2]
+ case [0, 1, 2]
+ in 0, *rest
+ rest
+ end
+ RUBY
+ end
- eval(<<~RUBY).should == true
- case obj
- in [1, 2]
- false
- in [0, 1]
- true
- end
- RUBY
+ it "matches an object with #deconstruct method which returns an array and each element in array matches element in pattern" do
+ obj = Object.new
+ def obj.deconstruct; [0, 1] end
- ScratchPad.recorded.should == [:deconstruct]
+ eval(<<~RUBY).should == true
+ case obj
+ in [Integer, Integer]
+ true
end
- end
+ RUBY
+ end
+
+ ruby_version_is "3.0" do
+ it "calls #deconstruct once for multiple patterns, caching the result" do
+ obj = Object.new
- it "calls #deconstruct even on objects that are already an array" do
- obj = [1, 2]
def obj.deconstruct
ScratchPad << :deconstruct
- [3, 4]
+ [0, 1]
end
eval(<<~RUBY).should == true
case obj
- in [3, 4]
- true
- else
+ in [1, 2]
false
+ in [0, 1]
+ true
end
RUBY
ScratchPad.recorded.should == [:deconstruct]
end
+ end
- it "does not match object if Constant === object returns false" do
- eval(<<~RUBY).should == false
- case [0, 1, 2]
- in String[0, 1, 2]
- true
- else
- false
- end
- RUBY
+ it "calls #deconstruct even on objects that are already an array" do
+ obj = [1, 2]
+ def obj.deconstruct
+ ScratchPad << :deconstruct
+ [3, 4]
end
- it "does not match object without #deconstruct method" do
- obj = Object.new
- obj.should_receive(:respond_to?).with(:deconstruct)
-
- eval(<<~RUBY).should == false
- case obj
- in Object[]
- true
- else
- false
- end
- RUBY
- end
+ eval(<<~RUBY).should == true
+ case obj
+ in [3, 4]
+ true
+ else
+ false
+ end
+ RUBY
- it "raises TypeError if #deconstruct method does not return array" do
- obj = Object.new
- def obj.deconstruct; "" end
-
- -> {
- eval <<~RUBY
- case obj
- in Object[]
- else
- end
- RUBY
- }.should raise_error(TypeError, /deconstruct must return Array/)
- end
+ ScratchPad.recorded.should == [:deconstruct]
+ end
- it "accepts a subclass of Array from #deconstruct" do
- obj = Object.new
- def obj.deconstruct
- subarray = Class.new(Array).new(2)
- def subarray.[](n)
- n
- end
- subarray
+ it "does not match object if Constant === object returns false" do
+ eval(<<~RUBY).should == false
+ case [0, 1, 2]
+ in String[0, 1, 2]
+ true
+ else
+ false
end
+ RUBY
+ end
- eval(<<~RUBY).should == true
- case obj
- in [1, 2]
- false
- in [0, 1]
- true
- end
- RUBY
- end
+ it "does not match object without #deconstruct method" do
+ obj = Object.new
+ obj.should_receive(:respond_to?).with(:deconstruct)
- it "does not match object if elements of array returned by #deconstruct method does not match elements in pattern" do
- obj = Object.new
- def obj.deconstruct; [1] end
+ eval(<<~RUBY).should == false
+ case obj
+ in Object[]
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "raises TypeError if #deconstruct method does not return array" do
+ obj = Object.new
+ def obj.deconstruct; "" end
- eval(<<~RUBY).should == false
+ -> {
+ eval <<~RUBY
case obj
- in Object[0]
- true
+ in Object[]
else
- false
end
RUBY
- end
+ }.should raise_error(TypeError, /deconstruct must return Array/)
+ end
- it "binds variables" do
- eval(<<~RUBY).should == [0, 1, 2]
- case [0, 1, 2]
- in [a, b, c]
- [a, b, c]
- end
- RUBY
+ it "accepts a subclass of Array from #deconstruct" do
+ obj = Object.new
+ def obj.deconstruct
+ subarray = Class.new(Array).new(2)
+ def subarray.[](n)
+ n
+ end
+ subarray
end
- it "supports splat operator *rest" do
- eval(<<~RUBY).should == [1, 2]
- case [0, 1, 2]
- in [0, *rest]
- rest
- end
- RUBY
- end
+ eval(<<~RUBY).should == true
+ case obj
+ in [1, 2]
+ false
+ in [0, 1]
+ true
+ end
+ RUBY
+ end
- it "does not match partially by default" do
- eval(<<~RUBY).should == false
- case [0, 1, 2, 3]
- in [1, 2]
- true
- else
- false
- end
- RUBY
- end
+ it "does not match object if elements of array returned by #deconstruct method does not match elements in pattern" do
+ obj = Object.new
+ def obj.deconstruct; [1] end
- it "does match partially from the array beginning if list + , syntax used" do
- eval(<<~RUBY).should == true
- case [0, 1, 2, 3]
- in [0, 1,]
- true
- end
- RUBY
+ eval(<<~RUBY).should == false
+ case obj
+ in Object[0]
+ true
+ else
+ false
+ end
+ RUBY
+ end
- eval(<<~RUBY).should == true
- case [0, 1, 2, 3]
- in 0, 1,;
- true
- end
- RUBY
- end
+ it "binds variables" do
+ eval(<<~RUBY).should == [0, 1, 2]
+ case [0, 1, 2]
+ in [a, b, c]
+ [a, b, c]
+ end
+ RUBY
+ end
- it "matches [] with []" do
- eval(<<~RUBY).should == true
- case []
- in []
- true
- end
- RUBY
- end
+ it "supports splat operator *rest" do
+ eval(<<~RUBY).should == [1, 2]
+ case [0, 1, 2]
+ in [0, *rest]
+ rest
+ end
+ RUBY
+ end
- it "matches anything with *" do
- eval(<<~RUBY).should == true
- case [0, 1]
- in *;
- true
- end
- RUBY
- end
+ it "does not match partially by default" do
+ eval(<<~RUBY).should == false
+ case [0, 1, 2, 3]
+ in [1, 2]
+ true
+ else
+ false
+ end
+ RUBY
+ end
- it "can be used as a nested pattern" do
- eval(<<~RUBY).should == true
- case [[1], ["2"]]
- in [[0] | nil, _]
- false
- in [[1], [1]]
- false
- in [[1], [2 | "2"]]
- true
- end
- RUBY
+ it "does match partially from the array beginning if list + , syntax used" do
+ eval(<<~RUBY).should == true
+ case [0, 1, 2, 3]
+ in [0, 1,]
+ true
+ end
+ RUBY
- eval(<<~RUBY).should == true
- case [1, 2]
- in [0, _] | {a: 0}
- false
- in {a: 1, b: 2} | [1, 2]
- true
- end
- RUBY
- end
+ eval(<<~RUBY).should == true
+ case [0, 1, 2, 3]
+ in 0, 1,;
+ true
+ end
+ RUBY
end
- describe "Hash pattern" do
- it "supports form Constant(id: pat, id: pat, ...)" do
- eval(<<~RUBY).should == true
- case {a: 0, b: 1}
- in Hash(a: 0, b: 1)
- true
- end
- RUBY
- end
+ it "matches [] with []" do
+ eval(<<~RUBY).should == true
+ case []
+ in []
+ true
+ end
+ RUBY
+ end
- it "supports form Constant[id: pat, id: pat, ...]" do
- eval(<<~RUBY).should == true
- case {a: 0, b: 1}
- in Hash[a: 0, b: 1]
- true
- end
- RUBY
- end
+ it "matches anything with *" do
+ eval(<<~RUBY).should == true
+ case [0, 1]
+ in *;
+ true
+ end
+ RUBY
+ end
- it "supports form {id: pat, id: pat, ...}" do
- eval(<<~RUBY).should == true
- case {a: 0, b: 1}
- in {a: 0, b: 1}
+ it "can be used as a nested pattern" do
+ eval(<<~RUBY).should == true
+ case [[1], ["2"]]
+ in [[0] | nil, _]
+ false
+ in [[1], [1]]
+ false
+ in [[1], [2 | "2"]]
true
- end
- RUBY
- end
+ end
+ RUBY
- it "supports form id: pat, id: pat, ..." do
- eval(<<~RUBY).should == true
- case {a: 0, b: 1}
- in a: 0, b: 1
+ eval(<<~RUBY).should == true
+ case [1, 2]
+ in [0, _] | {a: 0}
+ false
+ in {a: 1, b: 2} | [1, 2]
true
- end
- RUBY
-
- eval(<<~RUBY).should == [0, 1]
- case {a: 0, b: 1}
- in a: a, b: b
- [a, b]
- end
- RUBY
-
- eval(<<~RUBY).should == { b: 1, c: 2 }
- case {a: 0, b: 1, c: 2}
- in a: 0, **rest
- rest
- end
- RUBY
- end
-
- it "supports a: which means a: a" do
- eval(<<~RUBY).should == [0, 1]
- case {a: 0, b: 1}
- in Hash(a:, b:)
- [a, b]
- end
- RUBY
-
- a = b = nil
- eval(<<~RUBY).should == [0, 1]
- case {a: 0, b: 1}
- in Hash[a:, b:]
- [a, b]
- end
- RUBY
+ end
+ RUBY
+ end
+ end
- a = b = nil
- eval(<<~RUBY).should == [0, 1]
- case {a: 0, b: 1}
- in {a:, b:}
- [a, b]
- end
- RUBY
+ describe "Hash pattern" do
+ it "supports form Constant(id: pat, id: pat, ...)" do
+ eval(<<~RUBY).should == true
+ case {a: 0, b: 1}
+ in Hash(a: 0, b: 1)
+ true
+ end
+ RUBY
+ end
- a = nil
- eval(<<~RUBY).should == [0, {b: 1, c: 2}]
- case {a: 0, b: 1, c: 2}
- in {a:, **rest}
- [a, rest]
- end
- RUBY
+ it "supports form Constant[id: pat, id: pat, ...]" do
+ eval(<<~RUBY).should == true
+ case {a: 0, b: 1}
+ in Hash[a: 0, b: 1]
+ true
+ end
+ RUBY
+ end
- a = b = nil
- eval(<<~RUBY).should == [0, 1]
- case {a: 0, b: 1}
- in a:, b:
- [a, b]
- end
- RUBY
- end
+ it "supports form {id: pat, id: pat, ...}" do
+ eval(<<~RUBY).should == true
+ case {a: 0, b: 1}
+ in {a: 0, b: 1}
+ true
+ end
+ RUBY
+ end
- it "can mix key (a:) and key-value (a: b) declarations" do
- eval(<<~RUBY).should == [0, 1]
- case {a: 0, b: 1}
- in Hash(a:, b: x)
- [a, x]
- end
- RUBY
- end
+ it "supports form id: pat, id: pat, ..." do
+ eval(<<~RUBY).should == true
+ case {a: 0, b: 1}
+ in a: 0, b: 1
+ true
+ end
+ RUBY
- it "supports 'string': key literal" do
- eval(<<~RUBY).should == true
- case {a: 0}
- in {"a": 0}
- true
- end
- RUBY
- end
+ eval(<<~RUBY).should == [0, 1]
+ case {a: 0, b: 1}
+ in a: a, b: b
+ [a, b]
+ end
+ RUBY
- it "does not support non-symbol keys" do
- -> {
- eval <<~RUBY
- case {a: 1}
- in {"a" => 1}
- end
- RUBY
- }.should raise_error(SyntaxError, /unexpected/)
- end
+ eval(<<~RUBY).should == { b: 1, c: 2 }
+ case {a: 0, b: 1, c: 2}
+ in a: 0, **rest
+ rest
+ end
+ RUBY
+ end
- it "does not support string interpolation in keys" do
- x = "a"
+ it "supports a: which means a: a" do
+ eval(<<~RUBY).should == [0, 1]
+ case {a: 0, b: 1}
+ in Hash(a:, b:)
+ [a, b]
+ end
+ RUBY
- -> {
- eval <<~'RUBY'
- case {a: 1}
- in {"#{x}": 1}
- end
- RUBY
- }.should raise_error(SyntaxError, /symbol literal with interpolation is not allowed/)
- end
+ a = b = nil
+ eval(<<~RUBY).should == [0, 1]
+ case {a: 0, b: 1}
+ in Hash[a:, b:]
+ [a, b]
+ end
+ RUBY
- it "raise SyntaxError when keys duplicate in pattern" do
- -> {
- eval <<~RUBY
- case {a: 1}
- in {a: 1, b: 2, a: 3}
- end
- RUBY
- }.should raise_error(SyntaxError, /duplicated key name/)
- end
+ a = b = nil
+ eval(<<~RUBY).should == [0, 1]
+ case {a: 0, b: 1}
+ in {a:, b:}
+ [a, b]
+ end
+ RUBY
- it "matches an object with #deconstruct_keys method which returns a Hash with equal keys and each value in Hash matches value in pattern" do
- obj = Object.new
- def obj.deconstruct_keys(*); {a: 1} end
+ a = nil
+ eval(<<~RUBY).should == [0, {b: 1, c: 2}]
+ case {a: 0, b: 1, c: 2}
+ in {a:, **rest}
+ [a, rest]
+ end
+ RUBY
- eval(<<~RUBY).should == true
- case obj
- in {a: 1}
- true
- end
- RUBY
- end
+ a = b = nil
+ eval(<<~RUBY).should == [0, 1]
+ case {a: 0, b: 1}
+ in a:, b:
+ [a, b]
+ end
+ RUBY
+ end
- it "calls #deconstruct_keys per pattern" do
- obj = Object.new
+ it "can mix key (a:) and key-value (a: b) declarations" do
+ eval(<<~RUBY).should == [0, 1]
+ case {a: 0, b: 1}
+ in Hash(a:, b: x)
+ [a, x]
+ end
+ RUBY
+ end
- def obj.deconstruct_keys(*)
- ScratchPad << :deconstruct_keys
- {a: 1}
+ it "supports 'string': key literal" do
+ eval(<<~RUBY).should == true
+ case {a: 0}
+ in {"a": 0}
+ true
end
+ RUBY
+ end
- eval(<<~RUBY).should == true
- case obj
- in {b: 1}
- false
- in {a: 1}
- true
+ it "does not support non-symbol keys" do
+ -> {
+ eval <<~RUBY
+ case {a: 1}
+ in {"a" => 1}
end
RUBY
+ }.should raise_error(SyntaxError, /unexpected/)
+ end
- ScratchPad.recorded.should == [:deconstruct_keys, :deconstruct_keys]
- end
+ it "does not support string interpolation in keys" do
+ x = "a"
- it "does not match object if Constant === object returns false" do
- eval(<<~RUBY).should == false
+ -> {
+ eval <<~'RUBY'
case {a: 1}
- in String[a: 1]
- true
- else
- false
+ in {"#{x}": 1}
end
RUBY
- end
-
- it "does not match object without #deconstruct_keys method" do
- obj = Object.new
- obj.should_receive(:respond_to?).with(:deconstruct_keys)
+ }.should raise_error(SyntaxError, /symbol literal with interpolation is not allowed/)
+ end
- eval(<<~RUBY).should == false
- case obj
- in Object[a: 1]
- true
- else
- false
+ it "raise SyntaxError when keys duplicate in pattern" do
+ -> {
+ eval <<~RUBY
+ case {a: 1}
+ in {a: 1, b: 2, a: 3}
end
RUBY
- end
-
- it "does not match object if #deconstruct_keys method does not return Hash" do
- obj = Object.new
- def obj.deconstruct_keys(*); "" end
-
- -> {
- eval <<~RUBY
- case obj
- in Object[a: 1]
- end
- RUBY
- }.should raise_error(TypeError, /deconstruct_keys must return Hash/)
- end
+ }.should raise_error(SyntaxError, /duplicated key name/)
+ end
- it "does not match object if #deconstruct_keys method returns Hash with non-symbol keys" do
- obj = Object.new
- def obj.deconstruct_keys(*); {"a" => 1} end
+ it "matches an object with #deconstruct_keys method which returns a Hash with equal keys and each value in Hash matches value in pattern" do
+ obj = Object.new
+ def obj.deconstruct_keys(*); {a: 1} end
- eval(<<~RUBY).should == false
- case obj
- in Object[a: 1]
- true
- else
- false
- end
- RUBY
- end
+ eval(<<~RUBY).should == true
+ case obj
+ in {a: 1}
+ true
+ end
+ RUBY
+ end
- it "does not match object if elements of Hash returned by #deconstruct_keys method does not match values in pattern" do
- obj = Object.new
- def obj.deconstruct_keys(*); {a: 1} end
+ it "calls #deconstruct_keys per pattern" do
+ obj = Object.new
- eval(<<~RUBY).should == false
- case obj
- in Object[a: 2]
- true
- else
- false
- end
- RUBY
+ def obj.deconstruct_keys(*)
+ ScratchPad << :deconstruct_keys
+ {a: 1}
end
- it "passes keys specified in pattern as arguments to #deconstruct_keys method" do
- obj = Object.new
-
- def obj.deconstruct_keys(*args)
- ScratchPad << args
- {a: 1, b: 2, c: 3}
+ eval(<<~RUBY).should == true
+ case obj
+ in {b: 1}
+ false
+ in {a: 1}
+ true
end
+ RUBY
- eval <<~RUBY
- case obj
- in Object[a: 1, b: 2, c: 3]
- end
- RUBY
+ ScratchPad.recorded.should == [:deconstruct_keys, :deconstruct_keys]
+ end
- ScratchPad.recorded.sort.should == [[[:a, :b, :c]]]
- end
+ it "does not match object if Constant === object returns false" do
+ eval(<<~RUBY).should == false
+ case {a: 1}
+ in String[a: 1]
+ true
+ else
+ false
+ end
+ RUBY
+ end
- it "passes keys specified in pattern to #deconstruct_keys method if pattern contains double splat operator **" do
- obj = Object.new
+ it "does not match object without #deconstruct_keys method" do
+ obj = Object.new
+ obj.should_receive(:respond_to?).with(:deconstruct_keys)
- def obj.deconstruct_keys(*args)
- ScratchPad << args
- {a: 1, b: 2, c: 3}
+ eval(<<~RUBY).should == false
+ case obj
+ in Object[a: 1]
+ true
+ else
+ false
end
+ RUBY
+ end
+ it "does not match object if #deconstruct_keys method does not return Hash" do
+ obj = Object.new
+ def obj.deconstruct_keys(*); "" end
+
+ -> {
eval <<~RUBY
case obj
- in Object[a: 1, b: 2, **]
+ in Object[a: 1]
end
RUBY
+ }.should raise_error(TypeError, /deconstruct_keys must return Hash/)
+ end
- ScratchPad.recorded.sort.should == [[[:a, :b]]]
- end
-
- it "passes nil to #deconstruct_keys method if pattern contains double splat operator **rest" do
- obj = Object.new
+ it "does not match object if #deconstruct_keys method returns Hash with non-symbol keys" do
+ obj = Object.new
+ def obj.deconstruct_keys(*); {"a" => 1} end
- def obj.deconstruct_keys(*args)
- ScratchPad << args
- {a: 1, b: 2}
+ eval(<<~RUBY).should == false
+ case obj
+ in Object[a: 1]
+ true
+ else
+ false
end
+ RUBY
+ end
- eval <<~RUBY
- case obj
- in Object[a: 1, **rest]
- end
- RUBY
+ it "does not match object if elements of Hash returned by #deconstruct_keys method does not match values in pattern" do
+ obj = Object.new
+ def obj.deconstruct_keys(*); {a: 1} end
- ScratchPad.recorded.should == [[nil]]
- end
+ eval(<<~RUBY).should == false
+ case obj
+ in Object[a: 2]
+ true
+ else
+ false
+ end
+ RUBY
+ end
- it "binds variables" do
- eval(<<~RUBY).should == [0, 1, 2]
- case {a: 0, b: 1, c: 2}
- in {a: x, b: y, c: z}
- [x, y, z]
- end
- RUBY
- end
+ it "passes keys specified in pattern as arguments to #deconstruct_keys method" do
+ obj = Object.new
- it "supports double splat operator **rest" do
- eval(<<~RUBY).should == {b: 1, c: 2}
- case {a: 0, b: 1, c: 2}
- in {a: 0, **rest}
- rest
- end
- RUBY
+ def obj.deconstruct_keys(*args)
+ ScratchPad << args
+ {a: 1, b: 2, c: 3}
end
- it "treats **nil like there should not be any other keys in a matched Hash" do
- eval(<<~RUBY).should == true
- case {a: 1, b: 2}
- in {a: 1, b: 2, **nil}
- true
- end
- RUBY
+ eval <<~RUBY
+ case obj
+ in Object[a: 1, b: 2, c: 3]
+ end
+ RUBY
- eval(<<~RUBY).should == false
- case {a: 1, b: 2}
- in {a: 1, **nil}
- true
- else
- false
- end
- RUBY
- end
+ ScratchPad.recorded.sort.should == [[[:a, :b, :c]]]
+ end
- it "can match partially" do
- eval(<<~RUBY).should == true
- case {a: 1, b: 2}
- in {a: 1}
- true
- end
- RUBY
- end
+ it "passes keys specified in pattern to #deconstruct_keys method if pattern contains double splat operator **" do
+ obj = Object.new
- it "matches {} with {}" do
- eval(<<~RUBY).should == true
- case {}
- in {}
- true
- end
- RUBY
+ def obj.deconstruct_keys(*args)
+ ScratchPad << args
+ {a: 1, b: 2, c: 3}
end
- it "matches anything with **" do
- eval(<<~RUBY).should == true
- case {a: 1}
- in **;
- true
- end
- RUBY
- end
+ eval <<~RUBY
+ case obj
+ in Object[a: 1, b: 2, **]
+ end
+ RUBY
- it "can be used as a nested pattern" do
- eval(<<~RUBY).should == true
- case {a: {a: 1, b: 1}, b: {a: 1, b: 2}}
- in {a: {a: 0}}
- false
- in {a: {a: 1}, b: {b: 1}}
- false
- in {a: {a: 1}, b: {b: 2}}
- true
- end
- RUBY
+ ScratchPad.recorded.sort.should == [[[:a, :b]]]
+ end
- eval(<<~RUBY).should == true
- case [{a: 1, b: [1]}, {a: 1, c: ["2"]}]
- in [{a:, c:},]
- false
- in [{a: 1, b:}, {a: 1, c: [Integer]}]
- false
- in [_, {a: 1, c: [String]}]
- true
- end
- RUBY
+ it "passes nil to #deconstruct_keys method if pattern contains double splat operator **rest" do
+ obj = Object.new
+
+ def obj.deconstruct_keys(*args)
+ ScratchPad << args
+ {a: 1, b: 2}
end
- end
- describe "refinements" do
- it "are used for #deconstruct" do
- refinery = Module.new do
- refine Array do
- def deconstruct
- [0]
- end
- end
+ eval <<~RUBY
+ case obj
+ in Object[a: 1, **rest]
end
+ RUBY
- result = nil
- Module.new do
- using refinery
+ ScratchPad.recorded.should == [[nil]]
+ end
- result = eval(<<~RUBY)
- case []
- in [0]
- true
- end
- RUBY
+ it "binds variables" do
+ eval(<<~RUBY).should == [0, 1, 2]
+ case {a: 0, b: 1, c: 2}
+ in {a: x, b: y, c: z}
+ [x, y, z]
end
+ RUBY
+ end
- result.should == true
- end
-
- it "are used for #deconstruct_keys" do
- refinery = Module.new do
- refine Hash do
- def deconstruct_keys(_)
- {a: 0}
- end
- end
+ it "supports double splat operator **rest" do
+ eval(<<~RUBY).should == {b: 1, c: 2}
+ case {a: 0, b: 1, c: 2}
+ in {a: 0, **rest}
+ rest
end
+ RUBY
+ end
- result = nil
- Module.new do
- using refinery
+ it "treats **nil like there should not be any other keys in a matched Hash" do
+ eval(<<~RUBY).should == true
+ case {a: 1, b: 2}
+ in {a: 1, b: 2, **nil}
+ true
+ end
+ RUBY
- result = eval(<<~RUBY)
- case {}
- in a: 0
- true
- end
- RUBY
+ eval(<<~RUBY).should == false
+ case {a: 1, b: 2}
+ in {a: 1, **nil}
+ true
+ else
+ false
end
+ RUBY
+ end
- result.should == true
- end
+ it "can match partially" do
+ eval(<<~RUBY).should == true
+ case {a: 1, b: 2}
+ in {a: 1}
+ true
+ end
+ RUBY
+ end
- it "are used for #=== in constant pattern" do
- refinery = Module.new do
- refine Array.singleton_class do
- def ===(obj)
- obj.is_a?(Hash)
- end
- end
+ it "matches {} with {}" do
+ eval(<<~RUBY).should == true
+ case {}
+ in {}
+ true
end
+ RUBY
+ end
- result = nil
- Module.new do
- using refinery
+ it "matches anything with **" do
+ eval(<<~RUBY).should == true
+ case {a: 1}
+ in **;
+ true
+ end
+ RUBY
+ end
- result = eval(<<~RUBY)
- case {}
- in Array
- true
- end
- RUBY
+ it "can be used as a nested pattern" do
+ eval(<<~RUBY).should == true
+ case {a: {a: 1, b: 1}, b: {a: 1, b: 2}}
+ in {a: {a: 0}}
+ false
+ in {a: {a: 1}, b: {b: 1}}
+ false
+ in {a: {a: 1}, b: {b: 2}}
+ true
end
+ RUBY
- result.should == true
- end
+ eval(<<~RUBY).should == true
+ case [{a: 1, b: [1]}, {a: 1, c: ["2"]}]
+ in [{a:, c:},]
+ false
+ in [{a: 1, b:}, {a: 1, c: [Integer]}]
+ false
+ in [_, {a: 1, c: [String]}]
+ true
+ end
+ RUBY
end
+ end
- ruby_version_is "3.1" do
- it "can omit parentheses in one line pattern matching" do
- eval(<<~RUBY).should == [1, 2]
- [1, 2] => a, b
- [a, b]
- RUBY
-
- eval(<<~RUBY).should == 1
- {a: 1} => a:
- a
- RUBY
+ describe "refinements" do
+ it "are used for #deconstruct" do
+ refinery = Module.new do
+ refine Array do
+ def deconstruct
+ [0]
+ end
+ end
end
- it "supports pinning instance variables" do
- eval(<<~RUBY).should == true
- @a = /a/
- case 'abc'
- in ^@a
+ result = nil
+ Module.new do
+ using refinery
+
+ result = eval(<<~RUBY)
+ case []
+ in [0]
true
end
RUBY
end
- it "supports pinning class variables" do
- result = nil
- Module.new do
- result = module_eval(<<~RUBY)
- @@a = 0..10
+ result.should == true
+ end
- case 2
- in ^@@a
- true
- end
- RUBY
+ it "are used for #deconstruct_keys" do
+ refinery = Module.new do
+ refine Hash do
+ def deconstruct_keys(_)
+ {a: 0}
+ end
end
-
- result.should == true
end
- it "supports pinning global variables" do
- eval(<<~RUBY).should == true
- $a = /a/
- case 'abc'
- in ^$a
+ result = nil
+ Module.new do
+ using refinery
+
+ result = eval(<<~RUBY)
+ case {}
+ in a: 0
true
end
RUBY
end
- it "supports pinning expressions" do
- eval(<<~RUBY).should == true
- case 'abc'
- in ^(/a/)
- true
+ result.should == true
+ end
+
+ it "are used for #=== in constant pattern" do
+ refinery = Module.new do
+ refine Array.singleton_class do
+ def ===(obj)
+ obj.is_a?(Hash)
end
- RUBY
+ end
+ end
- eval(<<~RUBY).should == true
- case {name: '2.6', released_at: Time.new(2018, 12, 25)}
- in {released_at: ^(Time.new(2010)..Time.new(2020))}
+ result = nil
+ Module.new do
+ using refinery
+
+ result = eval(<<~RUBY)
+ case {}
+ in Array
true
end
RUBY
+ end
- eval(<<~RUBY).should == true
- case 0
- in ^(0+0)
+ result.should == true
+ end
+ end
+
+ ruby_version_is "3.1" do
+ it "can omit parentheses in one line pattern matching" do
+ eval(<<~RUBY).should == [1, 2]
+ [1, 2] => a, b
+ [a, b]
+ RUBY
+
+ eval(<<~RUBY).should == 1
+ {a: 1} => a:
+ a
+ RUBY
+ end
+
+ it "supports pinning instance variables" do
+ eval(<<~RUBY).should == true
+ @a = /a/
+ case 'abc'
+ in ^@a
+ true
+ end
+ RUBY
+ end
+
+ it "supports pinning class variables" do
+ result = nil
+ Module.new do
+ result = module_eval(<<~RUBY)
+ @@a = 0..10
+
+ case 2
+ in ^@@a
true
end
RUBY
end
+
+ result.should == true
+ end
+
+ it "supports pinning global variables" do
+ eval(<<~RUBY).should == true
+ $a = /a/
+ case 'abc'
+ in ^$a
+ true
+ end
+ RUBY
+ end
+
+ it "supports pinning expressions" do
+ eval(<<~RUBY).should == true
+ case 'abc'
+ in ^(/a/)
+ true
+ end
+ RUBY
+
+ eval(<<~RUBY).should == true
+ case {name: '2.6', released_at: Time.new(2018, 12, 25)}
+ in {released_at: ^(Time.new(2010)..Time.new(2020))}
+ true
+ end
+ RUBY
+
+ eval(<<~RUBY).should == true
+ case 0
+ in ^(0+0)
+ true
+ end
+ RUBY
end
end
end
diff --git a/spec/ruby/language/predefined_spec.rb b/spec/ruby/language/predefined_spec.rb
index d04dfcf251..b5eda7f789 100644
--- a/spec/ruby/language/predefined_spec.rb
+++ b/spec/ruby/language/predefined_spec.rb
@@ -654,10 +654,8 @@ describe "Predefined global $," do
-> { $, = Object.new }.should raise_error(TypeError)
end
- ruby_version_is "2.7" do
- it "warns if assigned non-nil" do
- -> { $, = "_" }.should complain(/warning: `\$,' is deprecated/)
- end
+ it "warns if assigned non-nil" do
+ -> { $, = "_" }.should complain(/warning: `\$,' is deprecated/)
end
end
@@ -693,10 +691,8 @@ describe "Predefined global $;" do
$; = nil
end
- ruby_version_is "2.7" do
- it "warns if assigned non-nil" do
- -> { $; = "_" }.should complain(/warning: `\$;' is deprecated/)
- end
+ it "warns if assigned non-nil" do
+ -> { $; = "_" }.should complain(/warning: `\$;' is deprecated/)
end
end
@@ -1316,33 +1312,31 @@ describe "The predefined global constant" do
end
end
-ruby_version_is "2.7" do
- describe "$LOAD_PATH.resolve_feature_path" do
- it "returns what will be loaded without actual loading, .rb file" do
- extension, path = $LOAD_PATH.resolve_feature_path('set')
- extension.should == :rb
- path.should.end_with?('/set.rb')
- end
+describe "$LOAD_PATH.resolve_feature_path" do
+ it "returns what will be loaded without actual loading, .rb file" do
+ extension, path = $LOAD_PATH.resolve_feature_path('set')
+ extension.should == :rb
+ path.should.end_with?('/set.rb')
+ end
- it "returns what will be loaded without actual loading, .so file" do
- require 'rbconfig'
- skip "no dynamically loadable standard extension" if RbConfig::CONFIG["EXTSTATIC"] == "static"
+ it "returns what will be loaded without actual loading, .so file" do
+ require 'rbconfig'
+ skip "no dynamically loadable standard extension" if RbConfig::CONFIG["EXTSTATIC"] == "static"
- extension, path = $LOAD_PATH.resolve_feature_path('etc')
- extension.should == :so
- path.should.end_with?("/etc.#{RbConfig::CONFIG['DLEXT']}")
- end
+ extension, path = $LOAD_PATH.resolve_feature_path('etc')
+ extension.should == :so
+ path.should.end_with?("/etc.#{RbConfig::CONFIG['DLEXT']}")
+ end
- ruby_version_is "2.7"..."3.1" do
- it "raises LoadError if feature cannot be found" do
- -> { $LOAD_PATH.resolve_feature_path('noop') }.should raise_error(LoadError)
- end
+ ruby_version_is ""..."3.1" do
+ it "raises LoadError if feature cannot be found" do
+ -> { $LOAD_PATH.resolve_feature_path('noop') }.should raise_error(LoadError)
end
+ end
- ruby_version_is "3.1" do
- it "return nil if feature cannot be found" do
- $LOAD_PATH.resolve_feature_path('noop').should be_nil
- end
+ ruby_version_is "3.1" do
+ it "return nil if feature cannot be found" do
+ $LOAD_PATH.resolve_feature_path('noop').should be_nil
end
end
end
diff --git a/spec/ruby/language/proc_spec.rb b/spec/ruby/language/proc_spec.rb
index ef4a43bed6..8360967ec8 100644
--- a/spec/ruby/language/proc_spec.rb
+++ b/spec/ruby/language/proc_spec.rb
@@ -223,13 +223,7 @@ describe "A Proc" do
@p = proc { |*a, **kw| [a, kw] }
end
- ruby_version_is ""..."2.7" do
- it 'autosplats keyword arguments' do
- @p.call([1, {a: 1}]).should == [[1], {a: 1}]
- end
- end
-
- ruby_version_is "2.7"..."3.0" do
+ ruby_version_is ""..."3.0" do
it 'autosplats keyword arguments and warns' do
-> {
@p.call([1, {a: 1}]).should == [[1], {a: 1}]
diff --git a/spec/ruby/language/range_spec.rb b/spec/ruby/language/range_spec.rb
index 79500c6b33..55dc65882a 100644
--- a/spec/ruby/language/range_spec.rb
+++ b/spec/ruby/language/range_spec.rb
@@ -15,10 +15,8 @@ describe "Literal Ranges" do
(1...).should == Range.new(1, nil, true)
end
- ruby_version_is "2.7" do
- it "creates beginless ranges" do
- eval("(..1)").should == Range.new(nil, 1)
- eval("(...1)").should == Range.new(nil, 1, true)
- end
+ it "creates beginless ranges" do
+ (..1).should == Range.new(nil, 1)
+ (...1).should == Range.new(nil, 1, true)
end
end
diff --git a/spec/ruby/language/rescue_spec.rb b/spec/ruby/language/rescue_spec.rb
index fcd9ae0de9..b91b52fa0f 100644
--- a/spec/ruby/language/rescue_spec.rb
+++ b/spec/ruby/language/rescue_spec.rb
@@ -504,14 +504,12 @@ describe "The rescue keyword" do
}.should raise_error(Exception)
end
- ruby_version_is "2.7" do
- it "rescues with multiple assignment" do
+ it "rescues with multiple assignment" do
- a, b = raise rescue [1, 2]
+ a, b = raise rescue [1, 2]
- a.should == 1
- b.should == 2
- end
+ a.should == 1
+ b.should == 2
end
end
end
diff --git a/spec/ruby/language/return_spec.rb b/spec/ruby/language/return_spec.rb
index d8506834c8..94c15b697e 100644
--- a/spec/ruby/language/return_spec.rb
+++ b/spec/ruby/language/return_spec.rb
@@ -422,18 +422,16 @@ describe "The return keyword" do
end
describe "within a block within a class" do
- ruby_version_is "2.7" do
- it "is not allowed" do
- File.write(@filename, <<-END_OF_CODE)
- class ReturnSpecs::A
- ScratchPad << "before return"
- 1.times { return }
- ScratchPad << "after return"
- end
- END_OF_CODE
-
- -> { load @filename }.should raise_error(LocalJumpError)
- end
+ it "is not allowed" do
+ File.write(@filename, <<-END_OF_CODE)
+ class ReturnSpecs::A
+ ScratchPad << "before return"
+ 1.times { return }
+ ScratchPad << "after return"
+ end
+ END_OF_CODE
+
+ -> { load @filename }.should raise_error(LocalJumpError)
end
end
@@ -464,25 +462,13 @@ describe "The return keyword" do
end
describe "return with argument" do
- ruby_version_is ""..."2.7" do
- it "does not affect exit status" do
- ruby_exe(<<-END_OF_CODE).should == ""
- return 10
- END_OF_CODE
-
- $?.exitstatus.should == 0
- end
- end
-
- ruby_version_is "2.7" do
- it "warns but does not affect exit status" do
- err = ruby_exe(<<-END_OF_CODE, args: "2>&1")
- return 10
- END_OF_CODE
- $?.exitstatus.should == 0
+ it "warns but does not affect exit status" do
+ err = ruby_exe(<<-END_OF_CODE, args: "2>&1")
+ return 10
+ END_OF_CODE
+ $?.exitstatus.should == 0
- err.should =~ /warning: argument of top-level return is ignored/
- end
+ err.should =~ /warning: argument of top-level return is ignored/
end
end
end
diff --git a/spec/ruby/language/safe_spec.rb b/spec/ruby/language/safe_spec.rb
index 89830a2069..ee5c1b3ccc 100644
--- a/spec/ruby/language/safe_spec.rb
+++ b/spec/ruby/language/safe_spec.rb
@@ -1,99 +1,7 @@
require_relative '../spec_helper'
describe "The $SAFE variable" do
- ruby_version_is ""..."2.7" do
- after :each do
- $SAFE = 0
- end
-
- it "is 0 by default" do
- $SAFE.should == 0
- proc {
- $SAFE.should == 0
- }.call
- end
-
- it "can be set to 0" do
- proc {
- $SAFE = 0
- $SAFE.should == 0
- }.call
- end
-
- it "can be set to 1" do
- proc {
- $SAFE = 1
- $SAFE.should == 1
- }.call
- end
-
- [2, 3, 4].each do |n|
- it "cannot be set to #{n}" do
- -> {
- proc {
- $SAFE = n
- }.call
- }.should raise_error(ArgumentError, /\$SAFE=2 to 4 are obsolete/)
- end
- end
-
- it "raises ArgumentError when set to values below 0" do
- -> {
- proc {
- $SAFE = -100
- }.call
- }.should raise_error(ArgumentError, "$SAFE should be >= 0")
- end
-
- it "cannot be set to values above 4" do
- -> {
- proc {
- $SAFE = 100
- }.call
- }.should raise_error(ArgumentError, /\$SAFE=2 to 4 are obsolete/)
- end
-
- it "can be manually lowered" do
- $SAFE = 1
- $SAFE = 0
- $SAFE.should == 0
- end
-
- it "is not Proc local" do
- $SAFE.should == 0
- proc {
- $SAFE = 1
- }.call
- $SAFE.should == 1
- end
-
- it "is not lambda local" do
- $SAFE.should == 0
- -> {
- $SAFE = 1
- }.call
- $SAFE.should == 1
- end
-
- it "is global like regular global variables" do
- Thread.new { $SAFE }.value.should == 0
- $SAFE = 1
- Thread.new { $SAFE }.value.should == 1
- end
-
- it "can be read when default from Thread#safe_level" do
- Thread.current.safe_level.should == 0
- end
-
- it "can be read when modified from Thread#safe_level" do
- proc {
- $SAFE = 1
- Thread.current.safe_level.should == 1
- }.call
- end
- end
-
- ruby_version_is "2.7"..."3.0" do
+ ruby_version_is ""..."3.0" do
it "warn when access" do
-> {
$SAFE
diff --git a/spec/ruby/language/send_spec.rb b/spec/ruby/language/send_spec.rb
index e57e2c65dc..5999079d58 100644
--- a/spec/ruby/language/send_spec.rb
+++ b/spec/ruby/language/send_spec.rb
@@ -258,20 +258,10 @@ describe "Invoking a private setter method" do
end
describe "Invoking a private getter method" do
- ruby_version_is ""..."2.7" do
- it "does not permit self as a receiver" do
- receiver = LangSendSpecs::PrivateGetter.new
- -> { receiver.call_self_foo }.should raise_error(NoMethodError)
- -> { receiver.call_self_foo_or_equals(6) }.should raise_error(NoMethodError)
- end
- end
-
- ruby_version_is "2.7" do
- it "permits self as a receiver" do
- receiver = LangSendSpecs::PrivateGetter.new
- receiver.call_self_foo_or_equals(6)
- receiver.call_self_foo.should == 6
- end
+ it "permits self as a receiver" do
+ receiver = LangSendSpecs::PrivateGetter.new
+ receiver.call_self_foo_or_equals(6)
+ receiver.call_self_foo.should == 6
end
end
diff --git a/spec/ruby/language/string_spec.rb b/spec/ruby/language/string_spec.rb
index ce4941569e..02e3488a1f 100644
--- a/spec/ruby/language/string_spec.rb
+++ b/spec/ruby/language/string_spec.rb
@@ -56,28 +56,6 @@ describe "Ruby character strings" do
"#\$".should == '#$'
end
- ruby_version_is ''...'2.7' do
- it "taints the result of interpolation when an interpolated value is tainted" do
- "#{"".taint}".tainted?.should be_true
-
- @ip.taint
- "#@ip".tainted?.should be_true
-
- $ip.taint
- "#$ip".tainted?.should be_true
- end
-
- it "untrusts the result of interpolation when an interpolated value is untrusted" do
- "#{"".untrust}".untrusted?.should be_true
-
- @ip.untrust
- "#@ip".untrusted?.should be_true
-
- $ip.untrust
- "#$ip".untrusted?.should be_true
- end
- end
-
it "allows using non-alnum characters as string delimiters" do
%(hey #{@ip}).should == "hey xxx"
%[hey #{@ip}].should == "hey xxx"
diff --git a/spec/ruby/language/yield_spec.rb b/spec/ruby/language/yield_spec.rb
index 3db6d353a9..85bd5af25b 100644
--- a/spec/ruby/language/yield_spec.rb
+++ b/spec/ruby/language/yield_spec.rb
@@ -186,7 +186,7 @@ describe "The yield call" do
end
describe "Using yield in a singleton class literal" do
- ruby_version_is "2.7"..."3.0" do
+ ruby_version_is ""..."3.0" do
it 'emits a deprecation warning' do
code = <<~RUBY
def m