Imported File#ftype spec from rubyspecs.
[rbx.git] / lib / missing.rb
blobc1bf3547cbd14e1b0000c1b64bdeca579cfbeda2
1 # Records missing calls and dumps them at the end.
2 # Execute with 
3 #   -rmissing -e '$early = true' script.rb
4 # to have it raise NoMethodError, otherwise it continues,
5 # passing a mock down, gathering up missing behavior.
6
7 unless defined? $early
8   $early = false
9 end
11 MissedCalls = []
13 class MissedCall
14   def initialize(recv, name, args)
15     @recv, @name = recv.inspect, name
16     if args.empty?
17       @args = nil
18     else
19       @args = args.map { |i| i.inspect }.join(", ")
20     end
21     @sub_calls = []
22   end
23   
24   def method_missing(meth, *args)
25     if args.empty?
26       args = nil
27     else
28       args = args.map { |i| i.inspect }.join(", ")
29     end
30     
31     @sub_calls << [meth, args]
32     self
33   end
34   
35   def show
36     print "#{@recv}.#{@name}"
37     if @args
38       puts ": #{@args}" 
39     else
40       puts " (no args)"
41     end
42     
43     @sub_calls.each do |meth, args|
44       print "  #{meth}"
45       if args
46         puts ": #{args}"
47       else
48         puts " (no args)"
49       end
50     end
51   end
52 end
54 class Object
55   def method_missing(meth, *args)
56     obj = MissedCall.new(self, meth, args)
57     MissedCalls << obj
58     if $early
59       raise NoMethodError, "Couldn't find a '#{meth}' on a #{self.inspect}"
60     end
61     obj
62   end
63 end
65 at_exit do
66   print "\nDetected #{MissedCalls.size} missed calls.\n\n"
67   MissedCalls.each { |c| c.show }
68 end