lib/private_please/tracking/trace_point_processor.rb
require 'private_please/config'
require 'private_please/storage/called_methods_memory_store'
require 'private_please/tracking/debug/trace_point_data_logger'
require 'private_please/tracking/result'
require 'private_please/tracking/trace_point_details'
require 'private_please/utils/two_level_stack'
module PrivatePlease
module Tracking
class TracePointProcessor
def initialize(config)
@config = config
@latest_tracepoints = Utils::TwoLevelStack.new
@encountered_method_calls = Storage::CalledMethodsMemoryStore.new
end
def process(tp)
return if untracked_code?(tp.path)
remember_trace_point tp
store_method_call_details if tp.event == :call
end
def result
Result.new(@encountered_method_calls)
end
private
if Debug.enabled?
def remember_trace_point(tp)
tpd = TracePointDetails.from(tp)
@latest_tracepoints.push tpd
Debug.log_to_trace_file tpd
end
else
def remember_trace_point(tp)
@latest_tracepoints.push TracePointDetails.from(tp)
end
end
def untracked_code?(path)
path.start_with?(*untracked_source_dirs)
end
def untracked_source_dirs
@_untracked_source_dirs ||= begin
Utils::RubyUtils.gems_paths +
Array(Utils::RubyUtils.std_lib_home) +
@config.additional_excluded_dirs
end
end
def tp_curr; @latest_tracepoints.curr end
def tp_prev; @latest_tracepoints.prev end
def store_method_call_details
key = tp_curr.method_full_name
if private_call?
@encountered_method_calls.add_private_call(key) unless already_private?
else
@encountered_method_calls.add_public_call(key)
end
end
def private_call?
return unless tp_prev # fails sometime (ex: rspec-core) # UNTESTED
curr_event, prev_event = tp_curr.event, tp_prev.event
(curr_event == :call) &&
[:line, :return, :c_return].include?(prev_event) &&
tp_curr.same_object?(tp_prev)
end
def already_private?
tp_curr._self.private_methods.include?(tp_curr.method_id)
end
end
end
end