-
Notifications
You must be signed in to change notification settings - Fork 0
irb method, class, and definition capturing
Here’s something cool using trace that I’ll make use of in the Ruby 1.9 debugger.
I want to be able to debug and trace methods I type into irb and see nice source listings.
I think this can be done in Ruby 1.9 without this trace module, but there are two advantages to using the trace module.
The biggest reason is that the trace module allows for multiple event hooks. So you can install this trace hook and debug which installs another (and a profiler which might install a 3rd). The second advantage is that this is faster since the event checking is done inside interpreter.
Below you’ll see that when I get the definition for method “foo” it contains entire string for the class it is in A. But this is exactly what I want! That is I don’t want the string for just “foo”. This is because what’s important is to synchronize the line numbers that the VM evaluator may spit out on an exception with the source text, here a string.
Here is a sample trial.
$ irb >> load '/home/rocky/irbplus/irb-hack.rb' >> class A >> def foo >> 5 >> end >> end => nil >> puts CLASSES['A'] class A def foo 5 end end => nil >> puts METHODS['foo'] class A def foo 5 end end => nil >> module M >> CONSTANT=5 >> end => 5 >> puts MODULES['M'] module M CONSTANT=5 end => nil >>Here is the code
require 'irb' require 'trace' include Trace Trace.event_masks = C_CALL_EVENT_MASK trace_filter = TraceFilter.new CLASSES = {} METHODS = {} MODULES = {} def capture_hook(event, frame, arg=nil) methods = %w(define_method method_added CLASS) return unless methods.member?(frame.method) METHODS[$1] = $irb_stmts if $irb_stmts =~ /^\s*def\s+(\S+)(:?\(|\n)/ CLASSES[$1] = $irb_stmts if $irb_stmts =~ /^\s*class\s+(\S+)\s+/ MODULES[$1] = $irb_stmts if $irb_stmts =~ /^\s*module\s+(\S+)\s+/ end # Monkeypatch to save the current IRB statement to be run. # Possibly not needed. class IRB::Context alias original_evaluate evaluate def evaluate(line, line_no) $irb_stmts = line original_evaluate(line, line_no) end end workspace = IRB::WorkSpace.new(binding) irb = IRB::Irb.new(workspace) trace_filter.set_trace_func(method(:capture_hook).to_proc) irb.eval_input