diff options
Diffstat (limited to 'spec/ruby/language/method_spec.rb')
| -rw-r--r-- | spec/ruby/language/method_spec.rb | 538 |
1 files changed, 183 insertions, 355 deletions
diff --git a/spec/ruby/language/method_spec.rb b/spec/ruby/language/method_spec.rb index 9abe4cde20..ca939dbab6 100644 --- a/spec/ruby/language/method_spec.rb +++ b/spec/ruby/language/method_spec.rb @@ -1,4 +1,4 @@ -require_relative '../spec_helper' +require File.expand_path('../../spec_helper', __FILE__) describe "A method send" do evaluate <<-ruby do @@ -40,7 +40,7 @@ describe "A method send" do x = mock("splat argument") x.should_receive(:to_a).and_return(1) - -> { m(*x) }.should raise_error(TypeError) + lambda { m(*x) }.should raise_error(TypeError) end end @@ -74,7 +74,7 @@ describe "A method send" do x = mock("splat argument") x.should_receive(:to_a).and_return(1) - -> { m(*x, 2, 3) }.should raise_error(TypeError) + lambda { m(*x, 2, 3) }.should raise_error(TypeError) end end @@ -108,7 +108,7 @@ describe "A method send" do x = mock("splat argument") x.should_receive(:to_a).and_return(1) - -> { m(1, *x, 2, 3) }.should raise_error(TypeError) + lambda { m(1, *x, 2, 3) }.should raise_error(TypeError) end it "copies the splatted array" do @@ -153,27 +153,7 @@ describe "A method send" do x = mock("splat argument") x.should_receive(:to_a).and_return(1) - -> { m(1, 2, *x) }.should raise_error(TypeError) - end - end - - context "with a block argument" do - before :all do - def m(x) - if block_given? - [true, yield(x + 'b')] - else - [false] - end - end - end - - it "that refers to a proc passes the proc as the block" do - m('a', &-> y { y + 'c'}).should == [true, 'abc'] - end - - it "that is nil passes no block" do - m('a', &nil).should == [false] + lambda { m(1, 2, *x) }.should raise_error(TypeError) end end end @@ -217,7 +197,7 @@ describe "An element assignment method send" do x = mock("splat argument") x.should_receive(:to_a).and_return(1) - -> { @o[*x] = 1 }.should raise_error(TypeError) + lambda { @o[*x] = 1 }.should raise_error(TypeError) end end @@ -255,7 +235,7 @@ describe "An element assignment method send" do x = mock("splat argument") x.should_receive(:to_a).and_return(1) - -> { @o[*x, 2, 3] = 4 }.should raise_error(TypeError) + lambda { @o[*x, 2, 3] = 4 }.should raise_error(TypeError) end end @@ -293,7 +273,7 @@ describe "An element assignment method send" do x = mock("splat argument") x.should_receive(:to_a).and_return(1) - -> { @o[1, 2, *x, 3] = 4 }.should raise_error(TypeError) + lambda { @o[1, 2, *x, 3] = 4 }.should raise_error(TypeError) end end @@ -331,7 +311,7 @@ describe "An element assignment method send" do x = mock("splat argument") x.should_receive(:to_a).and_return(1) - -> { @o[1, 2, 3, *x] = 4 }.should raise_error(TypeError) + lambda { @o[1, 2, 3, *x] = 4 }.should raise_error(TypeError) end end end @@ -368,7 +348,7 @@ describe "An attribute assignment method send" do x = mock("splat argument") x.should_receive(:to_a).and_return(1) - -> { @o.send :m=, *x, 1 }.should raise_error(TypeError) + lambda { @o.send :m=, *x, 1 }.should raise_error(TypeError) end end @@ -403,7 +383,7 @@ describe "An attribute assignment method send" do x = mock("splat argument") x.should_receive(:to_a).and_return(1) - -> { @o.send :m=, *x, 2, 3, 4 }.should raise_error(TypeError) + lambda { @o.send :m=, *x, 2, 3, 4 }.should raise_error(TypeError) end end @@ -438,7 +418,7 @@ describe "An attribute assignment method send" do x = mock("splat argument") x.should_receive(:to_a).and_return(1) - -> { @o.send :m=, 1, 2, *x, 3, 4 }.should raise_error(TypeError) + lambda { @o.send :m=, 1, 2, *x, 3, 4 }.should raise_error(TypeError) end end @@ -473,7 +453,7 @@ describe "An attribute assignment method send" do x = mock("splat argument") x.should_receive(:to_a).and_return(1) - -> { @o.send :m=, 1, 2, 3, *x, 4 }.should raise_error(TypeError) + lambda { @o.send :m=, 1, 2, 3, *x, 4 }.should raise_error(TypeError) end end end @@ -532,15 +512,6 @@ describe "A method" do end evaluate <<-ruby do - def m() end - ruby - - m().should be_nil - m(*[]).should be_nil - m(**{}).should be_nil - end - - evaluate <<-ruby do def m(*) end ruby @@ -556,26 +527,15 @@ describe "A method" do m().should == [] m(1).should == [1] m(1, 2, 3).should == [1, 2, 3] - m(*[]).should == [] - m(**{}).should == [] end evaluate <<-ruby do def m(a:) a end ruby - -> { m() }.should raise_error(ArgumentError) + lambda { m() }.should raise_error(ArgumentError) m(a: 1).should == 1 - suppress_keyword_warning do - -> { m("a" => 1, a: 1) }.should raise_error(ArgumentError) - end - end - - evaluate <<-ruby do - def m(a:, **kw) [a, kw] end - ruby - - -> { m(b: 1) }.should raise_error(ArgumentError) + lambda { m("a" => 1, a: 1) }.should raise_error(ArgumentError) end evaluate <<-ruby do @@ -592,7 +552,7 @@ describe "A method" do m().should be_nil m(a: 1, b: 2).should be_nil - -> { m(1) }.should raise_error(ArgumentError) + lambda { m(1) }.should raise_error(ArgumentError) end evaluate <<-ruby do @@ -601,19 +561,7 @@ describe "A method" do m().should == {} m(a: 1, b: 2).should == { a: 1, b: 2 } - m(*[]).should == {} - m(**{}).should == {} - suppress_warning { - eval "m(**{a: 1, b: 2}, **{a: 4, c: 7})" - }.should == { a: 4, b: 2, c: 7 } - -> { m(2) }.should raise_error(ArgumentError) - end - - evaluate <<-ruby do - def m(**k); k end; - ruby - - m("a" => 1).should == { "a" => 1 } + lambda { m(2) }.should raise_error(ArgumentError) end evaluate <<-ruby do @@ -652,7 +600,7 @@ describe "A method" do m(2, 3).should be_nil m([2, 3, 4], [5, 6]).should be_nil - -> { m a: 1 }.should raise_error(ArgumentError) + lambda { m a: 1 }.should raise_error(ArgumentError) end evaluate <<-ruby do @@ -744,9 +692,7 @@ describe "A method" do ruby m(1, b: 2).should == [1, 2] - suppress_keyword_warning do - -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError) - end + lambda { m("a" => 1, b: 2) }.should raise_error(ArgumentError) end evaluate <<-ruby do @@ -755,7 +701,7 @@ describe "A method" do m(2).should == [2, 1] m(1, b: 2).should == [1, 2] - -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError) + m("a" => 1, b: 2).should == [{"a" => 1, b: 2}, 1] end evaluate <<-ruby do @@ -764,7 +710,7 @@ describe "A method" do m(1).should == 1 m(1, a: 2, b: 3).should == 1 - -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError) + m("a" => 1, b: 2).should == {"a" => 1, b: 2} end evaluate <<-ruby do @@ -773,7 +719,7 @@ describe "A method" do m(1).should == [1, {}] m(1, a: 2, b: 3).should == [1, {a: 2, b: 3}] - -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError) + m("a" => 1, b: 2).should == [{"a" => 1, b: 2}, {}] end evaluate <<-ruby do @@ -848,8 +794,8 @@ describe "A method" do def m(a=1, (*b), (*c)) [a, b, c] end ruby - -> { m() }.should raise_error(ArgumentError) - -> { m(2) }.should raise_error(ArgumentError) + lambda { m() }.should raise_error(ArgumentError) + lambda { m(2) }.should raise_error(ArgumentError) m(2, 3).should == [1, [2], [3]] m(2, [3, 4], [5, 6]).should == [2, [3, 4], [5, 6]] end @@ -890,7 +836,7 @@ describe "A method" do m(b: 2).should == [1, 2] m(2, b: 1).should == [2, 1] - -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError) + m("a" => 1, b: 2).should == [{"a" => 1}, 2] end evaluate <<-ruby do @@ -900,7 +846,7 @@ describe "A method" do m().should == [1, 2] m(2).should == [2, 2] m(b: 3).should == [1, 3] - -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError) + m("a" => 1, b: 2).should == [{"a" => 1}, 2] end evaluate <<-ruby do @@ -909,7 +855,7 @@ describe "A method" do m().should == 1 m(2, a: 1, b: 0).should == 2 - m("a" => 1, a: 2).should == 1 + m("a" => 1, a: 2).should == {"a" => 1} end evaluate <<-ruby do @@ -950,6 +896,151 @@ describe "A method" do end evaluate <<-ruby do + def m(*, a:) a end + ruby + + m(a: 1).should == 1 + m(1, 2, a: 3).should == 3 + m("a" => 1, a: 2).should == 2 + 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] + m("a" => 1, b: 2).should == [[{"a" => 1}], 2] + 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 + m("a" => 1, a: 2).should == 2 + 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] + m("a" => 1, b: 2).should == [[{"a" => 1}], 2] + + 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}) + m(h).should be_nil + + h = mock("keyword splat") + error = RuntimeError.new("error while converting to a hash") + h.should_receive(:to_hash).and_raise(error) + lambda { 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) + lambda { 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 + + evaluate <<-ruby do def m(*, &b) b end ruby @@ -972,9 +1063,7 @@ describe "A method" do ruby m(a: 1, b: 2).should == [1, 2] - suppress_keyword_warning do - -> { m("a" => 1, a: 1, b: 2) }.should raise_error(ArgumentError) - end + lambda { m("a" => 1, a: 1, b: 2) }.should raise_error(ArgumentError) end evaluate <<-ruby do @@ -983,9 +1072,7 @@ describe "A method" do m(a: 1).should == [1, 1] m(a: 1, b: 2).should == [1, 2] - suppress_keyword_warning do - -> { m("a" => 1, a: 1, b: 2) }.should raise_error(ArgumentError) - end + lambda { m("a" => 1, a: 1, b: 2) }.should raise_error(ArgumentError) end evaluate <<-ruby do @@ -994,7 +1081,7 @@ describe "A method" do m(a: 1).should == 1 m(a: 1, b: 2).should == 1 - m("a" => 1, a: 1, b: 2).should == 1 + lambda { m("a" => 1, a: 1, b: 2) }.should raise_error(ArgumentError) end evaluate <<-ruby do @@ -1003,7 +1090,7 @@ describe "A method" do 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}] + lambda { m("a" => 1, a: 1, b: 2) }.should raise_error(ArgumentError) end evaluate <<-ruby do @@ -1101,78 +1188,21 @@ describe "A method" do end 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 raise_error(ArgumentError, 'no keywords accepted') - -> { m(**{a: 1}) }.should raise_error(ArgumentError, 'no keywords accepted') - -> { m("a" => 1) }.should raise_error(ArgumentError, 'no keywords accepted') - end - - evaluate <<-ruby do def m(a, b = nil, c = nil, d, e: nil, **f) [a, b, c, d, e, f] end - ruby + ruby result = m(1, 2) result.should == [1, nil, nil, 2, nil, {}] result = m(1, 2, {foo: :bar}) - result.should == [1, 2, nil, {foo: :bar}, nil, {}] + result.should == [1, nil, nil, 2, nil, {foo: :bar}] result = m(1, {foo: :bar}) result.should == [1, nil, nil, {foo: :bar}, nil, {}] end end - - 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 - end - - 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 = {} - - -> do - m(**h).should == {} - end.should raise_error(ArgumentError) - end - end - - context "raises ArgumentError if passing hash as keyword arguments" do - evaluate <<-ruby do - def m(a: nil); a; end - ruby - - options = {a: 1}.freeze - -> do - m(options) - end.should raise_error(ArgumentError) - end - end - - it "assigns the last Hash to the last optional argument if the Hash contains non-Symbol keys and is not passed as keywords" do - def m(a = nil, b = {}, v: false) - [a, b, v] - end - - h = { "key" => "value" } - m(:a, h).should == [:a, h, false] - m(:a, h, v: true).should == [:a, h, true] - m(v: true).should == [nil, {}, true] - end end describe "A method call with a space between method name and parentheses" do @@ -1193,48 +1223,20 @@ describe "A method call with a space between method name and parentheses" do end end - context "when a single argument is provided" do - it "assigns a simple expression" do - args = m (1) - args.should == [1] - end - - it "assigns an expression consisting of multiple statements" do - args = m ((0; 1)) - args.should == [1] - end - - it "assigns one single statement, without the need of parentheses" do + context "when a single argument provided" do + it "assigns it" do args = m (1 == 1 ? true : false) args.should == [true] end - - ruby_version_is "3.3" do - it "supports multiple statements" do - eval("m (1; 2)").should == [2] - end - end end - context "when multiple arguments are provided" do - it "assigns simple expressions" do - args = m (1), (2) - args.should == [1, 2] - end - - it "assigns expressions consisting of multiple statements" do - args = m ((0; 1)), ((2; 3)) - args.should == [1, 3] - end - end - - context "when the argument looks like an argument list" do + context "when 2+ arguments provided" do it "raises a syntax error" do - -> { + lambda { eval("m (1, 2)") }.should raise_error(SyntaxError) - -> { + lambda { eval("m (1, 2, 3)") }.should raise_error(SyntaxError) end @@ -1292,177 +1294,3 @@ describe "An array-dereference method ([])" do end end end - -describe "An endless method definition" do - context "without arguments" do - evaluate <<-ruby do - def m() = 42 - ruby - - m.should == 42 - end - - context "without parenthesis" do - evaluate <<-ruby do - def m = 42 - ruby - - m.should == 42 - end - end - end - - context "with arguments" do - evaluate <<-ruby do - def m(a, b) = a + b - ruby - - m(1, 4).should == 5 - end - end - - context "with multiline body" do - evaluate <<-ruby do - def m(n) = - if n > 2 - m(n - 2) + m(n - 1) - else - 1 - end - ruby - - m(6).should == 8 - end - end - - # tested more thoroughly in language/delegation_spec.rb - context "with args forwarding" do - evaluate <<-ruby do - def mm(word, num:) - word * num - end - - def m(...) = mm(...) + mm(...) - ruby - - m("meow", num: 2).should == "meow" * 4 - end - end -end - -describe "Keyword arguments are now separated from positional arguments" do - context "when the method has only positional parameters" do - it "treats incoming keyword arguments as positional for compatibility" do - def foo(a, b, c, hsh) - hsh[:key] - end - - foo(1, 2, 3, key: 42).should == 42 - end - end - - context "when the method takes a ** parameter" do - it "captures the passed literal keyword arguments" do - def foo(a, b, c, **hsh) - hsh[:key] - end - - foo(1, 2, 3, key: 42).should == 42 - end - - it "captures the passed ** keyword arguments" do - def foo(a, b, c, **hsh) - hsh[:key] - end - - h = { key: 42 } - foo(1, 2, 3, **h).should == 42 - end - - it "does not convert a positional Hash to keyword arguments" do - def foo(a, b, c, **hsh) - hsh[:key] - end - - -> { - foo(1, 2, 3, { key: 42 }) - }.should raise_error(ArgumentError, 'wrong number of arguments (given 4, expected 3)') - end - end - - context "when the method takes a key: parameter" do - context "when it's called with a positional Hash and no **" do - it "raises ArgumentError" do - def foo(a, b, c, key: 1) - key - end - - -> { - foo(1, 2, 3, { key: 42 }) - }.should raise_error(ArgumentError, 'wrong number of arguments (given 4, expected 3)') - end - end - - context "when it's called with **" do - it "captures the passed keyword arguments" do - def foo(a, b, c, key: 1) - key - end - - h = { key: 42 } - foo(1, 2, 3, **h).should == 42 - end - end - end -end - -ruby_version_is "3.1" do - describe "kwarg with omitted value in a method call" do - context "accepts short notation 'kwarg' in method call" do - evaluate <<-ruby do - def call(*args, **kwargs) = [args, kwargs] - ruby - - a, b, c = 1, 2, 3 - arr, h = eval('call a:') - h.should == {a: 1} - arr.should == [] - - arr, h = eval('call(a:, b:, c:)') - h.should == {a: 1, b: 2, c: 3} - arr.should == [] - - arr, h = eval('call(a:, b: 10, c:)') - h.should == {a: 1, b: 10, c: 3} - arr.should == [] - end - end - - context "with methods and local variables" do - evaluate <<-ruby do - def call(*args, **kwargs) = [args, kwargs] - - def bar - "baz" - end - - def foo(val) - call bar:, val: - end - ruby - - foo(1).should == [[], {bar: "baz", val: 1}] - end - end - end - - describe "Inside 'endless' method definitions" do - it "allows method calls without parenthesis" do - eval <<-ruby - def greet(person) = "Hi, ".dup.concat person - ruby - - greet("Homer").should == "Hi, Homer" - end - end -end |
