ruby-changes:58956
From: Yusuke <ko1@a...>
Date: Fri, 29 Nov 2019 17:32:48 +0900 (JST)
Subject: [ruby-changes:58956] 191ce5344e (master): Reduce duplicated warnings for the change of Ruby 3 keyword arguments
https://git.ruby-lang.org/ruby.git/commit/?id=191ce5344e From 191ce5344ec42c91571f8f47c85be9138262b1c7 Mon Sep 17 00:00:00 2001 From: Yusuke Endoh <mame@r...> Date: Fri, 13 Sep 2019 17:02:08 +0900 Subject: Reduce duplicated warnings for the change of Ruby 3 keyword arguments By this change, the following code prints only one warning. ``` def foo(**opt); end 100.times { foo({kw:1}) } ``` A global variable `st_table *caller_to_callees` is a map from caller to a set of callee methods. It remembers that a warning is already printed for each pair of caller and callee. [Feature #16289] diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb index 862b673..295b499 100644 --- a/test/ruby/test_keyword.rb +++ b/test/ruby/test_keyword.rb @@ -313,9 +313,19 @@ class TestKeywordArguments < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L313 sc = Class.new c = sc.new - def c.m(*args, **kw) - super + redef = -> do + if defined?(c.m) + class << c + remove_method(:m) + end + end + eval <<-END + def c.m(*args, **kw) + super(*args, **kw) + end + END end + redef[] sc.class_eval do def m(*args) args @@ -350,6 +360,7 @@ class TestKeywordArguments < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L360 assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal(kw, c.m(**{})) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal(kw, c.m(**kw)) end @@ -386,24 +397,31 @@ class TestKeywordArguments < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L397 [arg, args] end end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do c.m(**{}) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do c.m(**kw) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal([h, kw], c.m(**h)) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal([h, kw], c.m(a: 1)) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal([h2, kw], c.m(**h2)) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal([h3, kw], c.m(**h3)) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal([h3, kw], c.m(a: 1, **h2)) end @@ -431,9 +449,19 @@ class TestKeywordArguments < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L449 sc = Class.new c = sc.new - def c.m(*args, **kw) - super(*args, **kw) + redef = -> do + if defined?(c.m) + class << c + remove_method(:m) + end + end + eval <<-END + def c.m(*args, **kw) + super(*args, **kw) + end + END end + redef[] sc.class_eval do def m(*args) args @@ -468,6 +496,7 @@ class TestKeywordArguments < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L496 assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal(kw, c.m(**{})) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal(kw, c.m(**kw)) end @@ -504,24 +533,31 @@ class TestKeywordArguments < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L533 [arg, args] end end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do c.m(**{}) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do c.m(**kw) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal([h, kw], c.m(**h)) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal([h, kw], c.m(a: 1)) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal([h2, kw], c.m(**h2)) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal([h3, kw], c.m(**h3)) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal([h3, kw], c.m(a: 1, **h2)) end @@ -2092,13 +2128,19 @@ class TestKeywordArguments < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L2128 assert_raise(ArgumentError) { c.m(**h3) } assert_raise(ArgumentError) { c.m(a: 1, **h2) } - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, args) - args + redef = -> do + c.singleton_class.remove_method(:method_missing) + eval <<-END + def c.method_missing(_, args) + args + end + END end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `method_missing'/m) do assert_equal(kw, c.m(**{})) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `method_missing'/m) do assert_equal(kw, c.m(**kw)) end @@ -2127,28 +2169,39 @@ class TestKeywordArguments < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L2169 assert_raise(ArgumentError) { c.m(h3) } end - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, arg, **args) - [arg, args] + redef = -> do + c.singleton_class.remove_method(:method_missing) + eval <<-END + def c.method_missing(_, arg, **args) + [arg, args] + end + END end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `method_missing'/m) do assert_equal([kw, kw], c.m(**{})) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `method_missing'/m) do assert_equal([kw, kw], c.m(**kw)) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `method_missing'/m) do assert_equal([h, kw], c.m(**h)) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `method_missing'/m) do assert_equal([h, kw], c.m(a: 1)) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `method_missing'/m) do assert_equal([h2, kw], c.m(**h2)) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `method_missing'/m) do assert_equal([h3, kw], c.m(**h3)) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `method_missing'/m) do assert_equal([h3, kw], c.m(a: 1, **h2)) end @@ -2950,6 +3003,12 @@ class TestKeywordArguments < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L3003 assert_equal([1, h1], o.baz(1, h1)) assert_equal([h1], o.baz(h1, **{})) + c.class_eval do + remove_method(:bar) + def bar(*args, **kw) + [args, kw] + end + end assert_warn(/The last argument is used as the keyword parameter.* for `bar'/m) do assert_equal([[1], h1], o.foo(:pass_bar, 1, :a=>1)) end @@ -4601,13 +4660,19 @@ class TestKeywordArgumentsSymProcRefinements < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L4660 assert_raise(ArgumentError) { c.call(**h3, &:m) } assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m) } - c.singleton_class.remove_method(:m) - def c.m(args) - args + redef = -> do + c.singleton_class.remove_method(:m) + eval <<-END + def c.m(args) + args + end + END end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal(kw, c.call(**{}, &:m)) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal(kw, c.call(**kw, &:m)) end @@ -4636,28 +4701,39 @@ class TestKeywordArgumentsSymProcRefinements < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L4701 assert_raise(ArgumentError) { c.call(h3, &:m) } end - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] + redef = -> do + c.singleton_class.remove_method(:m) + eval <<-END + def c.m(arg, **args) + [arg, args] + end + END end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal([kw, kw], c.call(**{}, &:m)) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal([kw, kw], c.call(**kw, &:m)) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do assert_equal([h, kw], c.call(**h, &:m)) end + redef[] assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/