From 57b215ff107ef81292376b67c7e55aa7114ba955 Mon Sep 17 00:00:00 2001 From: Mike Dvorkin Date: Fri, 5 Nov 2010 19:45:24 -0700 Subject: [PATCH] Use Method#parameters introduced in Ruby 1.9.2 --- lib/ap/awesome_print.rb | 20 ++++++--- spec/methods_spec.rb | 95 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 102 insertions(+), 13 deletions(-) diff --git a/lib/ap/awesome_print.rb b/lib/ap/awesome_print.rb index 60ec86c..e8c45b6 100755 --- a/lib/ap/awesome_print.rb +++ b/lib/ap/awesome_print.rb @@ -246,11 +246,21 @@ class AwesomePrint # Return [ name, arguments, owner ] tuple for a given method. #------------------------------------------------------------------------------ def method_tuple(method) - # arity: For Ruby methods that take a variable number of arguments, returns -N - 1, - # where N is the number of required arguments. For methods written in C, returns -1 - # if the call takes a variable number of arguments. - args = method.arity.abs.times.map { |i| "arg#{i+1}" } - args[-1] = "*#{args[-1]}" if method.arity < 0 + if method.respond_to?(:parameters) # Ruby 1.9.2+ + # See http://ruby.runpaint.org/methods#method-objects-parameters + args = method.parameters.inject([]) do |arr, (type, name)| + name ||= (type == :block ? 'block' : "arg#{arr.size + 1}") + arr << case type + when :req then name.to_s + when :opt, :rest then "*#{name}" + when :block then "&#{name}" + else '?' + end + end + else # See http://ruby-doc.org/core/classes/Method.html#M001902 + args = method.arity.abs.times.map { |i| "arg#{i+1}" } + args[-1] = "*#{args[-1]}" if method.arity < 0 + end if method.to_s =~ /(Unbound)*Method: (.*?)[#\.]/ owner = "#{$2}#{$1 ? '(unbound)' : ''}".gsub('(', ' (') diff --git a/spec/methods_spec.rb b/spec/methods_spec.rb index e122040..84103dc 100644 --- a/spec/methods_spec.rb +++ b/spec/methods_spec.rb @@ -68,7 +68,11 @@ describe "Single method" do def world(a,b); end end method = Hello.instance_method(:world) - method.ai.should == "\e[1;33mHello (unbound)\e[0m#\e[1;35mworld\e[0m\e[0;37m(arg1, arg2)\e[0m" + if RUBY_VERSION < '1.9.2' + method.ai.should == "\e[1;33mHello (unbound)\e[0m#\e[1;35mworld\e[0m\e[0;37m(arg1, arg2)\e[0m" + else + method.ai.should == "\e[1;33mHello (unbound)\e[0m#\e[1;35mworld\e[0m\e[0;37m(a, b)\e[0m" + end end end @@ -128,7 +132,11 @@ describe "Object methods" do protected def m3(a,b); end end - Hello.new.protected_methods.ai(:plain => true, :index => false).should == "[\n m3(arg1, arg2) Hello\n]" + if RUBY_VERSION < '1.9.2' + Hello.new.protected_methods.ai(:plain => true, :index => false).should == "[\n m3(arg1, arg2) Hello\n]" + else + Hello.new.protected_methods.ai(:plain => true, :index => false).should == "[\n m3(a, b) Hello\n]" + end end end @@ -150,7 +158,11 @@ describe "Object methods" do def m3(a,b); end end out = Hello.new.private_methods.ai(:plain => true).split("\n").grep(/m\d/) - out.first.should =~ /^\s+\[\d+\]\s+m3\(arg1, arg2\)\s+Hello$/ + if RUBY_VERSION < '1.9.2' + out.first.should =~ /^\s+\[\d+\]\s+m3\(arg1, arg2\)\s+Hello$/ + else + out.first.should =~ /^\s+\[\d+\]\s+m3\(a, b\)\s+Hello$/ + end end end @@ -172,7 +184,11 @@ describe "Object methods" do def self.m3(a,b); end end out = Hello.singleton_methods.ai(:plain => true, :index => false).split("\n").grep(/m\d/) - out.first.should =~ /^\s+m3\(arg1, arg2\)\s+Hello$/ + if RUBY_VERSION < '1.9.2' + out.first.should =~ /^\s+m3\(arg1, arg2\)\s+Hello$/ + else + out.first.should =~ /^\s+m3\(a, b\)\s+Hello$/ + end end end end @@ -198,7 +214,11 @@ describe "Class methods" do def m3(a,b); end end out = Hello.instance_methods.ai(:plain => true, :index => false).split("\n").grep(/m\d/) - out.first.should =~ /^\s+m3\(arg1, arg2\)\s+Hello\s\(unbound\)$/ + if RUBY_VERSION < '1.9.2' + out.first.should =~ /^\s+m3\(arg1, arg2\)\s+Hello\s\(unbound\)$/ + else + out.first.should =~ /^\s+m3\(a, b\)\s+Hello\s\(unbound\)$/ + end end end @@ -218,7 +238,11 @@ describe "Class methods" do def m3(a,b); end end out = Hello.public_instance_methods.ai(:plain => true, :index => false).split("\n").grep(/m\d/) - out.first.should =~ /^\s+m3\(arg1, arg2\)\s+Hello\s\(unbound\)$/ + if RUBY_VERSION < '1.9.2' + out.first.should =~ /^\s+m3\(arg1, arg2\)\s+Hello\s\(unbound\)$/ + else + out.first.should =~ /^\s+m3\(a, b\)\s+Hello\s\(unbound\)$/ + end end end @@ -240,7 +264,11 @@ describe "Class methods" do def m3(a,b); end end out = Hello.protected_instance_methods.ai(:plain => true, :index => false).split("\n").grep(/m\d/) - out.first.should =~ /^\s+m3\(arg1, arg2\)\s+Hello\s\(unbound\)$/ + if RUBY_VERSION < '1.9.2' + out.first.should =~ /^\s+m3\(arg1, arg2\)\s+Hello\s\(unbound\)$/ + else + out.first.should =~ /^\s+m3\(a, b\)\s+Hello\s\(unbound\)$/ + end end end @@ -262,8 +290,59 @@ describe "Class methods" do def m3(a,b); end end out = Hello.private_instance_methods.ai(:plain => true, :index => false).split("\n").grep(/m\d/) - out.first.should =~ /^\s+m3\(arg1, arg2\)\s+Hello\s\(unbound\)$/ + if RUBY_VERSION < '1.9.2' + out.first.should =~ /^\s+m3\(arg1, arg2\)\s+Hello\s\(unbound\)$/ + else + out.first.should =~ /^\s+m3\(a, b\)\s+Hello\s\(unbound\)$/ + end end end end +if RUBY_VERSION >= '1.9.2' + describe "Ruby 1.9.2+ Method#parameters" do + after do + Object.instance_eval{ remove_const :Hello } if defined?(Hello) + end + + it "()" do + class Hello + def m1; end + end + out = Hello.new.methods.ai(:plain => true).split("\n").grep(/m1/) + out.first.should =~ /^\s+\[\s*\d+\]\s+m1\(\)\s+Hello$/ + end + + it ":req" do + class Hello + def m1(a, b, c); end + end + out = Hello.new.methods.ai(:plain => true).split("\n").grep(/m1/) + out.first.should =~ /^\s+\[\s*\d+\]\s+m1\(a, b, c\)\s+Hello$/ + end + + it ":opt" do + class Hello + def m1(a, b = 1, c = 2); end # m1(a, *b, *c) + end + out = Hello.new.methods.ai(:plain => true).split("\n").grep(/m1/) + out.first.should =~ /^\s+\[\s*\d+\]\s+m1\(a, \*b, \*c\)\s+Hello$/ + end + + it ":rest" do + class Hello + def m1(*a); end # m1(*a) + end + out = Hello.new.methods.ai(:plain => true).split("\n").grep(/m1/) + out.first.should =~ /^\s+\[\s*\d+\]\s+m1\(\*a\)\s+Hello$/ + end + + it ":block" do + class Hello + def m1(a, b = nil, &blk); end # m1(a, *b, &blk) + end + out = Hello.new.methods.ai(:plain => true).split("\n").grep(/m1/) + out.first.should =~ /^\s+\[\s*\d+\]\s+m1\(a, \*b, &blk\)\s+Hello$/ + end + end +end