load_tracer 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bdcf72ff4eb8378b4450689b64b9b6bf5a97a679baa47709414834ecb87f705b
4
- data.tar.gz: 387db21e56a184a66f308b59b761641f3142702f29a3e47d3dbbdef65db5cf85
3
+ metadata.gz: 8506eef88908cad86610b5a6d6741ff697acc77172067fb41e162939eb6df5b7
4
+ data.tar.gz: 03dc7508cecc0b9fa08c1fbf3f4157b88196eb704fbb0664b14ae8e480b384ba
5
5
  SHA512:
6
- metadata.gz: c3458986d97707e5e4324095d16c51e1c157b437efca8664cdc0cd269dac08676494c8d420934dee9fb101dbdcce145c09d095afa17ea3504c1a35f058d44dcf
7
- data.tar.gz: 73ebe3f5d161787a283bfe3e65f91d77a42841e386d303055ca1fb719723c4006639a80d90d27c64a366b53e29d3ab5a76b030adb087a1adba5bcde5094d8151
6
+ metadata.gz: 125417a2ee92c559509bcc15e7e0a3229fd1e5b99f96835d3e9aa6b9d32ebcf926825abe1b6316dafca424f1adf6af62e0992366f80b5b96c59b7f0e7ab592e0
7
+ data.tar.gz: a6c8d3b5900e8f990ed07e63a38c3f4bcfa0dc879bf169854b2a9f4914c66723264829d92c62a1325d90eee59290d4824a25e46872f0bef4959b634c10bf7784
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- load_tracer (0.3.0)
4
+ load_tracer (0.4.0)
5
5
  binding_of_caller (~> 0.8.0)
6
6
 
7
7
  GEM
data/lib/load_tracer.rb CHANGED
@@ -2,6 +2,7 @@ require 'binding_of_caller'
2
2
  require 'load_tracer/formatter/default'
3
3
  require 'load_tracer/formatter/dot'
4
4
  require 'load_tracer/formatter/json'
5
+ require 'load_tracer/static_checker'
5
6
  require 'load_tracer/version'
6
7
 
7
8
  module Kernel
@@ -43,21 +44,27 @@ class LoadTracer
43
44
 
44
45
  LOAD_METHODS = %i(require require_relative load autoload)
45
46
 
46
- def self.trace(format: nil, exclude_files: [])
47
- instance = new(exclude_files: exclude_files)
48
- instance.tracer.enable { yield }
49
- instance.report(format: format)
47
+ def self.trace(format: nil, exclude_files: [], &block)
48
+ new(exclude_files: exclude_files).trace(format: format, &block)
50
49
  end
51
50
 
52
- def initialize(exclude_files: [])
51
+ def initialize(format: nil, exclude_files: [])
52
+ @exclude_files = exclude_files
53
+ end
54
+
55
+ def trace(format: nil)
53
56
  @dependencies = Hash.new { |hash, key| hash[key] = [] }
54
57
  @reverse_dependencies = Hash.new { |hash, key| hash[key] = [] }
55
- @exclude_files = exclude_files
58
+ @load_checked_features = Hash.new
56
59
  @not_found_features = []
60
+
61
+ tracer.enable { yield }
62
+
63
+ report(format: format, dependencies: @dependencies, reverse_dependencies: @reverse_dependencies)
57
64
  end
58
65
 
59
66
  def tracer
60
- TracePoint.new(:call) do |tp|
67
+ TracePoint.new(:return) do |tp|
61
68
  next unless LOAD_METHODS.include?(tp.method_id)
62
69
  next if tp.defined_class != ::Kernel
63
70
  next if tp.path != __FILE__
@@ -78,26 +85,37 @@ class LoadTracer
78
85
  next
79
86
  end
80
87
 
88
+ @load_checked_features[bl.absolute_path] = true
89
+
81
90
  @dependencies[bl.absolute_path] << path
82
91
  @reverse_dependencies[path] << bl.absolute_path
92
+
93
+ if !tp.return_value && !@load_checked_features[path]
94
+ file_specs = StaticChecker.parse_file(path)
95
+
96
+ file_specs.each do |fs|
97
+ @dependencies[fs.path] |= fs.dependencies
98
+ @reverse_dependencies[fs.path] |= fs.reverse_dependencies
99
+ end
100
+ end
83
101
  end
84
102
  end
85
103
 
86
- def report(format:)
104
+ def report(format:, dependencies:, reverse_dependencies:)
87
105
  case format
88
106
  when :dot
89
107
  DotFormatter.export(
90
- dependencies: @dependencies
108
+ dependencies: dependencies
91
109
  )
92
110
  when :json
93
111
  JsonFormatter.export(
94
- dependencies: @dependencies,
95
- reverse_dependencies: @reverse_dependencies
112
+ dependencies: dependencies,
113
+ reverse_dependencies: reverse_dependencies
96
114
  )
97
115
  else
98
116
  DefaultFormatter.export(
99
- dependencies: @dependencies,
100
- reverse_dependencies: @reverse_dependencies
117
+ dependencies: dependencies,
118
+ reverse_dependencies: reverse_dependencies
101
119
  )
102
120
  end
103
121
  end
@@ -0,0 +1,80 @@
1
+ class LoadTracer
2
+ class StaticChecker < LoadTracer
3
+ def self.parse_file(path)
4
+ new(path).trace
5
+ end
6
+
7
+ def initialize(path)
8
+ @path = path
9
+ end
10
+
11
+ def trace(format: nil)
12
+ @dependencies = Hash.new { |hash, key| hash[key] = [] }
13
+ @reverse_dependencies = Hash.new { |hash, key| hash[key] = [] }
14
+ @load_checked_features = Hash.new
15
+ @not_found_features = []
16
+
17
+ traverse(path: @path)
18
+
19
+ report(format: format, dependencies: @dependencies, reverse_dependencies: @reverse_dependencies)
20
+ end
21
+
22
+ def traverse(path:)
23
+ return if @load_checked_features[path]
24
+ return if File.extname(path) != '.rb'
25
+
26
+ @load_checked_features[path] = true
27
+ ast = RubyVM::AbstractSyntaxTree.parse_file(path)
28
+ features = search_load_features(ast: ast)
29
+
30
+ features.each do |feature|
31
+ feature_path = find_path(feature) || find_path(File.expand_path(feature, File.dirname(path)))
32
+
33
+ if feature_path.nil?
34
+ @not_found_features << feature
35
+ next
36
+ end
37
+
38
+ traverse(path: feature_path)
39
+
40
+ @dependencies[path] << feature_path
41
+ @reverse_dependencies[feature_path] << path
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def inspector(ast:, &block)
48
+ ast.children.each do |child|
49
+ next unless child.instance_of?(RubyVM::AbstractSyntaxTree::Node)
50
+
51
+ yield child
52
+
53
+ inspector(ast: child, &block)
54
+ end
55
+ end
56
+
57
+ def search_load_features(ast:)
58
+ features = []
59
+
60
+ inspector(ast: ast) do |node|
61
+ next if node.type != :FCALL
62
+
63
+ method_id = node.children[0]
64
+
65
+ next unless LOAD_METHODS.include?(method_id)
66
+
67
+ feature = case method_id
68
+ when :require, :require_relative, :load
69
+ node.children[1].children[0].children[0]
70
+ when :autoload
71
+ node.children[1].children[1].children[0]
72
+ end
73
+
74
+ features << feature if feature.instance_of?(String)
75
+ end
76
+
77
+ features
78
+ end
79
+ end
80
+ end
@@ -1,3 +1,3 @@
1
1
  class LoadTracer
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: load_tracer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shuichi Tamayose
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-03-02 00:00:00.000000000 Z
11
+ date: 2019-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: binding_of_caller
@@ -92,6 +92,7 @@ files:
92
92
  - lib/load_tracer/formatter/dot.rb
93
93
  - lib/load_tracer/formatter/json.rb
94
94
  - lib/load_tracer/formatter/templates/default.dot.erb
95
+ - lib/load_tracer/static_checker.rb
95
96
  - lib/load_tracer/version.rb
96
97
  - load_tracer.gemspec
97
98
  homepage: https://github.com/siman-man/load_tracer
@@ -113,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
114
  - !ruby/object:Gem::Version
114
115
  version: '0'
115
116
  requirements: []
116
- rubygems_version: 3.0.2
117
+ rubygems_version: 3.0.3
117
118
  signing_key:
118
119
  specification_version: 4
119
120
  summary: This gem can check the dependency files.