lib/load_tracer.rb in load_tracer-0.3.0 vs lib/load_tracer.rb in load_tracer-0.4.0

- old
+ new

@@ -1,9 +1,10 @@ require 'binding_of_caller' require 'load_tracer/formatter/default' require 'load_tracer/formatter/dot' require 'load_tracer/formatter/json' +require 'load_tracer/static_checker' require 'load_tracer/version' module Kernel unless defined?(__original_require__) alias __original_require__ require @@ -41,25 +42,31 @@ class LoadTracer FileSpec = Struct.new(:name, :path, :dependencies, :reverse_dependencies, keyword_init: true) LOAD_METHODS = %i(require require_relative load autoload) - def self.trace(format: nil, exclude_files: []) - instance = new(exclude_files: exclude_files) - instance.tracer.enable { yield } - instance.report(format: format) + def self.trace(format: nil, exclude_files: [], &block) + new(exclude_files: exclude_files).trace(format: format, &block) end - def initialize(exclude_files: []) + def initialize(format: nil, exclude_files: []) + @exclude_files = exclude_files + end + + def trace(format: nil) @dependencies = Hash.new { |hash, key| hash[key] = [] } @reverse_dependencies = Hash.new { |hash, key| hash[key] = [] } - @exclude_files = exclude_files + @load_checked_features = Hash.new @not_found_features = [] + + tracer.enable { yield } + + report(format: format, dependencies: @dependencies, reverse_dependencies: @reverse_dependencies) end def tracer - TracePoint.new(:call) do |tp| + TracePoint.new(:return) do |tp| next unless LOAD_METHODS.include?(tp.method_id) next if tp.defined_class != ::Kernel next if tp.path != __FILE__ bl = caller_locations[1] @@ -76,29 +83,40 @@ if path.nil? @not_found_features << feature next end + @load_checked_features[bl.absolute_path] = true + @dependencies[bl.absolute_path] << path @reverse_dependencies[path] << bl.absolute_path + + if !tp.return_value && !@load_checked_features[path] + file_specs = StaticChecker.parse_file(path) + + file_specs.each do |fs| + @dependencies[fs.path] |= fs.dependencies + @reverse_dependencies[fs.path] |= fs.reverse_dependencies + end + end end end - def report(format:) + def report(format:, dependencies:, reverse_dependencies:) case format when :dot DotFormatter.export( - dependencies: @dependencies + dependencies: dependencies ) when :json JsonFormatter.export( - dependencies: @dependencies, - reverse_dependencies: @reverse_dependencies + dependencies: dependencies, + reverse_dependencies: reverse_dependencies ) else DefaultFormatter.export( - dependencies: @dependencies, - reverse_dependencies: @reverse_dependencies + dependencies: dependencies, + reverse_dependencies: reverse_dependencies ) end end private