Class: MethodTracer::Tracer

Inherits:
Object
  • Object
show all
Defined in:
lib/method_tracer/tracer.rb

Constant Summary collapse

UNCOOPERATIVE_NAMES =
[
  # Some classes don't behave well when we try to hook them, at least with
  # the methods currently used.
  'CGI',    # Waits for input from stdin when opening rails console
  'RSpec'   # RSpec doesn't run
].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(target) ⇒ Tracer

Returns a new instance of Tracer.



10
11
12
13
14
15
16
17
# File 'lib/method_tracer/tracer.rb', line 10

def initialize(target)
  @target_path = target

  find_methods!

  add_hooks_to_class_methods
  add_hooks_to_instance_methods
end

Class Method Details

.outfileObject



34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/method_tracer/tracer.rb', line 34

def self.outfile
  @outfile ||= begin
                 output_file = Config.output_file
                 if output_file.instance_of?(IO) || output_file.instance_of?(StringIO)
                   output_file
                 elsif output_file.instance_of?(String)
                   File.open(output_file, 'a')
                 else
                   raise "Unhandled output_file type: #{output_file}"
                 end
               end
end

.record_and_call_original(unbound_m, receiver, *args, &block) ⇒ Object



24
25
26
27
28
29
30
31
32
# File 'lib/method_tracer/tracer.rb', line 24

def self.record_and_call_original(unbound_m, receiver, *args, &block)
  outfile.write "#{receiver}.#{unbound_m.name} called from:\n"
  caller_locations.select { |loc| loc.path.start_with?(Config.app_path) }
                  .each do |loc|
                    outfile.write "#{loc.path}:#{loc.lineno}\n"
                  end

  unbound_m.bind(receiver).call(*args, &block)
end

.uncooperative_class?(class_name) ⇒ Boolean

Returns:

  • (Boolean)


19
20
21
22
# File 'lib/method_tracer/tracer.rb', line 19

def self.uncooperative_class?(class_name)
  !class_name.nil? &&
    UNCOOPERATIVE_NAMES.any? { |bad_name| class_name.include?(bad_name) }
end