load_tracer 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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.