diff options
Diffstat (limited to 'lib/method_source/source_location.rb')
-rw-r--r-- | lib/method_source/source_location.rb | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/lib/method_source/source_location.rb b/lib/method_source/source_location.rb new file mode 100644 index 0000000..1878b18 --- /dev/null +++ b/lib/method_source/source_location.rb @@ -0,0 +1,56 @@ +module MethodSource + module SourceLocation + module MethodExtensions + def trace_func(event, file, line, id, binding, classname) + return unless event == 'call' + set_trace_func nil + + @file, @line = file, line + raise :found + end + + # Return the source location of a method for Ruby 1.8. + # @return [Array] A two element array. First element is the + # file, second element is the line in the file where the + # method definition is found. + def source_location + if @file.nil? + args =[*(1..(arity<-1 ? -arity-1 : arity ))] + + set_trace_func method(:trace_func).to_proc + call *args rescue nil + set_trace_func nil + @file = File.expand_path(@file) if @file && File.exist?(File.expand_path(@file)) + end + return [@file, @line] if File.exist?(@file.to_s) + end + end + + module UnboundMethodExtensions + + # Return the source location of an instance method for Ruby 1.8. + # @return [Array] A two element array. First element is the + # file, second element is the line in the file where the + # method definition is found. + def source_location + klass = case owner + when Class + owner + when Module + Class.new.tap { |v| v.send(:include, owner) } + end + + begin + klass.allocate.method(name).source_location + rescue TypeError + + # Assume we are dealing with a Singleton Class: + # 1. Get the instance object + # 2. Forward the source_location lookup to the instance + instance ||= ObjectSpace.each_object(owner).first + instance.method(name).source_location + end + end + end + end +end |