deep-cover 0.6.2 → 0.6.3.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.rspec +2 -1
  4. data/.rspec_all +2 -1
  5. data/.rubocop.yml +8 -9
  6. data/Gemfile +2 -0
  7. data/Rakefile +32 -6
  8. data/bin/cov +3 -3
  9. data/deep_cover.gemspec +3 -16
  10. data/exe/deep-cover +5 -0
  11. data/lib/deep_cover/cli/debugger.rb +1 -1
  12. data/lib/deep_cover/cli/exec.rb +1 -1
  13. data/lib/deep_cover/cli/instrumented_clone_reporter.rb +5 -3
  14. data/lib/deep_cover/cli/runner.rb +2 -2
  15. data/lib/deep_cover/{tools/dump_covered_code.rb → dump_covered_code.rb} +2 -0
  16. metadata +10 -203
  17. data/lib/deep-cover.rb +0 -3
  18. data/lib/deep_cover.rb +0 -22
  19. data/lib/deep_cover/analyser.rb +0 -23
  20. data/lib/deep_cover/analyser/base.rb +0 -104
  21. data/lib/deep_cover/analyser/branch.rb +0 -41
  22. data/lib/deep_cover/analyser/covered_code_source.rb +0 -21
  23. data/lib/deep_cover/analyser/function.rb +0 -14
  24. data/lib/deep_cover/analyser/node.rb +0 -54
  25. data/lib/deep_cover/analyser/per_char.rb +0 -38
  26. data/lib/deep_cover/analyser/per_line.rb +0 -41
  27. data/lib/deep_cover/analyser/ruby25_like_branch.rb +0 -211
  28. data/lib/deep_cover/analyser/statement.rb +0 -33
  29. data/lib/deep_cover/analyser/stats.rb +0 -54
  30. data/lib/deep_cover/analyser/subset.rb +0 -27
  31. data/lib/deep_cover/auto_run.rb +0 -71
  32. data/lib/deep_cover/autoload_tracker.rb +0 -215
  33. data/lib/deep_cover/backports.rb +0 -22
  34. data/lib/deep_cover/base.rb +0 -117
  35. data/lib/deep_cover/basics.rb +0 -22
  36. data/lib/deep_cover/builtin_takeover.rb +0 -10
  37. data/lib/deep_cover/config.rb +0 -104
  38. data/lib/deep_cover/config_setter.rb +0 -33
  39. data/lib/deep_cover/core_ext/autoload_overrides.rb +0 -112
  40. data/lib/deep_cover/core_ext/coverage_replacement.rb +0 -61
  41. data/lib/deep_cover/core_ext/exec_callbacks.rb +0 -27
  42. data/lib/deep_cover/core_ext/instruction_sequence_load_iseq.rb +0 -32
  43. data/lib/deep_cover/core_ext/load_overrides.rb +0 -19
  44. data/lib/deep_cover/core_ext/require_overrides.rb +0 -28
  45. data/lib/deep_cover/coverage.rb +0 -125
  46. data/lib/deep_cover/coverage/analysis.rb +0 -42
  47. data/lib/deep_cover/coverage/persistence.rb +0 -84
  48. data/lib/deep_cover/covered_code.rb +0 -145
  49. data/lib/deep_cover/custom_requirer.rb +0 -187
  50. data/lib/deep_cover/flag_comment_associator.rb +0 -68
  51. data/lib/deep_cover/load.rb +0 -66
  52. data/lib/deep_cover/memoize.rb +0 -48
  53. data/lib/deep_cover/module_override.rb +0 -39
  54. data/lib/deep_cover/node.rb +0 -23
  55. data/lib/deep_cover/node/arguments.rb +0 -51
  56. data/lib/deep_cover/node/assignments.rb +0 -273
  57. data/lib/deep_cover/node/base.rb +0 -155
  58. data/lib/deep_cover/node/begin.rb +0 -27
  59. data/lib/deep_cover/node/block.rb +0 -61
  60. data/lib/deep_cover/node/branch.rb +0 -32
  61. data/lib/deep_cover/node/case.rb +0 -113
  62. data/lib/deep_cover/node/collections.rb +0 -31
  63. data/lib/deep_cover/node/const.rb +0 -12
  64. data/lib/deep_cover/node/def.rb +0 -40
  65. data/lib/deep_cover/node/empty_body.rb +0 -32
  66. data/lib/deep_cover/node/exceptions.rb +0 -79
  67. data/lib/deep_cover/node/if.rb +0 -73
  68. data/lib/deep_cover/node/keywords.rb +0 -86
  69. data/lib/deep_cover/node/literals.rb +0 -100
  70. data/lib/deep_cover/node/loops.rb +0 -74
  71. data/lib/deep_cover/node/mixin/can_augment_children.rb +0 -65
  72. data/lib/deep_cover/node/mixin/check_completion.rb +0 -18
  73. data/lib/deep_cover/node/mixin/child_can_be_empty.rb +0 -27
  74. data/lib/deep_cover/node/mixin/executed_after_children.rb +0 -15
  75. data/lib/deep_cover/node/mixin/execution_location.rb +0 -66
  76. data/lib/deep_cover/node/mixin/filters.rb +0 -47
  77. data/lib/deep_cover/node/mixin/flow_accounting.rb +0 -71
  78. data/lib/deep_cover/node/mixin/has_child.rb +0 -145
  79. data/lib/deep_cover/node/mixin/has_child_handler.rb +0 -75
  80. data/lib/deep_cover/node/mixin/has_tracker.rb +0 -46
  81. data/lib/deep_cover/node/mixin/is_statement.rb +0 -20
  82. data/lib/deep_cover/node/mixin/rewriting.rb +0 -35
  83. data/lib/deep_cover/node/mixin/wrapper.rb +0 -15
  84. data/lib/deep_cover/node/module.rb +0 -66
  85. data/lib/deep_cover/node/root.rb +0 -20
  86. data/lib/deep_cover/node/send.rb +0 -161
  87. data/lib/deep_cover/node/short_circuit.rb +0 -42
  88. data/lib/deep_cover/node/splat.rb +0 -15
  89. data/lib/deep_cover/node/variables.rb +0 -16
  90. data/lib/deep_cover/parser_ext/range.rb +0 -21
  91. data/lib/deep_cover/problem_with_diagnostic.rb +0 -63
  92. data/lib/deep_cover/reporter.rb +0 -10
  93. data/lib/deep_cover/reporter/base.rb +0 -68
  94. data/lib/deep_cover/reporter/html.rb +0 -15
  95. data/lib/deep_cover/reporter/html/base.rb +0 -14
  96. data/lib/deep_cover/reporter/html/index.rb +0 -59
  97. data/lib/deep_cover/reporter/html/site.rb +0 -70
  98. data/lib/deep_cover/reporter/html/source.rb +0 -136
  99. data/lib/deep_cover/reporter/html/template/assets/32px.png +0 -0
  100. data/lib/deep_cover/reporter/html/template/assets/40px.png +0 -0
  101. data/lib/deep_cover/reporter/html/template/assets/deep_cover.css.sass +0 -336
  102. data/lib/deep_cover/reporter/html/template/assets/jquery-3.2.1.min.js +0 -4
  103. data/lib/deep_cover/reporter/html/template/assets/jquery-3.2.1.min.map +0 -1
  104. data/lib/deep_cover/reporter/html/template/assets/jstree.css +0 -1108
  105. data/lib/deep_cover/reporter/html/template/assets/jstree.js +0 -8424
  106. data/lib/deep_cover/reporter/html/template/assets/jstreetable.js +0 -1069
  107. data/lib/deep_cover/reporter/html/template/assets/throbber.gif +0 -0
  108. data/lib/deep_cover/reporter/html/template/index.html.erb +0 -75
  109. data/lib/deep_cover/reporter/html/template/source.html.erb +0 -35
  110. data/lib/deep_cover/reporter/istanbul.rb +0 -184
  111. data/lib/deep_cover/reporter/text.rb +0 -58
  112. data/lib/deep_cover/reporter/tree/util.rb +0 -86
  113. data/lib/deep_cover/tools.rb +0 -22
  114. data/lib/deep_cover/tools/blank.rb +0 -25
  115. data/lib/deep_cover/tools/builtin_coverage.rb +0 -55
  116. data/lib/deep_cover/tools/camelize.rb +0 -13
  117. data/lib/deep_cover/tools/content_tag.rb +0 -11
  118. data/lib/deep_cover/tools/covered.rb +0 -9
  119. data/lib/deep_cover/tools/execute_sample.rb +0 -34
  120. data/lib/deep_cover/tools/format.rb +0 -18
  121. data/lib/deep_cover/tools/format_char_cover.rb +0 -19
  122. data/lib/deep_cover/tools/format_generated_code.rb +0 -27
  123. data/lib/deep_cover/tools/indent_string.rb +0 -26
  124. data/lib/deep_cover/tools/merge.rb +0 -16
  125. data/lib/deep_cover/tools/number_lines.rb +0 -22
  126. data/lib/deep_cover/tools/our_coverage.rb +0 -11
  127. data/lib/deep_cover/tools/profiling.rb +0 -68
  128. data/lib/deep_cover/tools/render_template.rb +0 -13
  129. data/lib/deep_cover/tools/require_relative_dir.rb +0 -12
  130. data/lib/deep_cover/tools/scan_match_datas.rb +0 -10
  131. data/lib/deep_cover/tools/silence_warnings.rb +0 -18
  132. data/lib/deep_cover/tools/slice.rb +0 -9
  133. data/lib/deep_cover/tools/strip_heredoc.rb +0 -18
  134. data/lib/deep_cover/tools/truncate_backtrace.rb +0 -32
  135. data/lib/deep_cover/tracker_bucket.rb +0 -50
  136. data/lib/deep_cover/tracker_hits_per_path.rb +0 -35
  137. data/lib/deep_cover/tracker_storage.rb +0 -76
  138. data/lib/deep_cover/tracker_storage_per_path.rb +0 -34
  139. data/lib/deep_cover/version.rb +0 -5
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'subset'
4
-
5
- module DeepCover
6
- class Analyser::Statement < Analyser
7
- include Analyser::Subset
8
- # Returns a map of Range => runs
9
- def results
10
- each_node.map do |node|
11
- [node.expression, node_runs(node)]
12
- end.to_h
13
- end
14
-
15
- private
16
-
17
- def in_subset?(node, parent)
18
- is_statement = node.is_statement
19
- if node.expression.nil?
20
- false
21
- elsif is_statement != :if_incompatible
22
- is_statement
23
- else
24
- !compatible_runs?(node_runs(parent), node_runs(node))
25
- end
26
- end
27
-
28
- def compatible_runs?(expression_runs, sub_expression_runs)
29
- sub_expression_runs.nil? ||
30
- (sub_expression_runs == 0) == (expression_runs == 0)
31
- end
32
- end
33
- end
@@ -1,54 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeepCover
4
- class Analyser::StatsBase
5
- DECIMALS = 2
6
- include Memoize
7
- memoize :to_h, :total
8
-
9
- VALUES = %i[executed not_executed not_executable ignored].freeze # All are exclusive
10
-
11
- attr_reader(*VALUES)
12
-
13
- def to_h
14
- VALUES.map { |val| [val, public_send(val)] }.to_h
15
- end
16
-
17
- def initialize(executed: 0, not_executed: 0, not_executable: 0, ignored: 0)
18
- @executed = executed
19
- @not_executed = not_executed
20
- @not_executable = not_executable
21
- @ignored = ignored
22
- freeze
23
- end
24
-
25
- def +(other)
26
- self.class.new(to_h.merge(other.to_h) { |k, a, b| a + b })
27
- end
28
-
29
- def total
30
- to_h.values.inject(:+)
31
- end
32
-
33
- def with(**values)
34
- self.class.new(to_h.merge(values))
35
- end
36
-
37
- def potentially_executable
38
- total - not_executable
39
- end
40
-
41
- def percent_covered
42
- return 100 if potentially_executable == 0
43
- (100 * (1 - not_executed.fdiv(potentially_executable))).round(DECIMALS)
44
- end
45
- end
46
-
47
- class Analyser::Stats < Analyser::StatsBase
48
- memoize :percent
49
-
50
- def percent
51
- Analyser::StatsBase.new(to_h.transform_values { |v| (100 * v).fdiv(total).round(DECIMALS) })
52
- end
53
- end
54
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeepCover
4
- # A module to create a subset from a criteria called `in_subset?`
5
- # Including classes can refine it, or specify SUBSET_CLASSES
6
- module Analyser::Subset
7
- def node_children(node)
8
- find_children(node)
9
- end
10
-
11
- private
12
-
13
- def find_children(from, parent = from)
14
- @source.node_children(from).flat_map do |node|
15
- if in_subset?(node, parent)
16
- [node]
17
- else
18
- find_children(node, parent)
19
- end
20
- end
21
- end
22
-
23
- def in_subset?(node, _parent)
24
- self.class::SUBSET_CLASSES.any? { |klass| node.is_a?(klass) }
25
- end
26
- end
27
- end
@@ -1,71 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'core_ext/exec_callbacks'
4
-
5
- module DeepCover
6
- module AutoRun
7
- class Runner
8
- def initialize(covered_path)
9
- @covered_path = covered_path
10
- @saved = !(DeepCover.respond_to?(:running?) && DeepCover.running?)
11
- end
12
-
13
- def run!
14
- after_tests { save }
15
- ExecCallbacks.before_exec { save }
16
- self
17
- end
18
-
19
- def report!(**options)
20
- after_tests { puts report(**options) }
21
- self
22
- end
23
-
24
- private
25
-
26
- def saved?
27
- @saved
28
- end
29
-
30
- def coverage
31
- @coverage ||= if saved?
32
- Coverage.load(@covered_path, with_trackers: false)
33
- else
34
- DeepCover.coverage
35
- end
36
- end
37
-
38
- def save
39
- require_relative '../deep_cover'
40
- coverage.save(@covered_path) unless saved?
41
- coverage.save_trackers(@covered_path)
42
- end
43
-
44
- def report(**options)
45
- coverage.report(**options)
46
- end
47
-
48
- def after_tests
49
- use_at_exit = true
50
- if defined?(Minitest)
51
- use_at_exit = false
52
- Minitest.after_run { yield }
53
- end
54
- if defined?(Rspec)
55
- use_at_exit = false
56
- RSpec.configure do |config|
57
- config.after(:suite) { yield }
58
- end
59
- end
60
- if use_at_exit
61
- at_exit { yield }
62
- end
63
- end
64
- end
65
-
66
- def self.run!(covered_path)
67
- @runners ||= {}
68
- @runners[covered_path] ||= Runner.new(covered_path).run!
69
- end
70
- end
71
- end
@@ -1,215 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'weakref'
4
-
5
- # TODO: if a constant is removed, AutoloadEntries should be removed
6
-
7
- module DeepCover
8
- class AutoloadTracker
9
- AutoloadEntry = Struct.new(:weak_mod, :name, :target_path, :interceptor_path) do
10
- # If the ref is dead, will return nil
11
- # If the target is frozen, will warn and return nil
12
- # Otherwise return the target
13
- def mod_if_available
14
- mod = weak_mod.__getobj__
15
- if mod.frozen?
16
- AutoloadTracker.warn_frozen_module(mod)
17
- nil
18
- else
19
- mod
20
- end
21
- rescue WeakRef::RefError
22
- nil
23
- end
24
- end
25
-
26
- attr_reader :autoloads_by_basename, :interceptor_files_by_path
27
- def initialize
28
- @autoloads_by_basename = {}
29
- @interceptor_files_by_path = {}
30
- end
31
-
32
- def autoload_path_for(mod, name, path)
33
- interceptor_path = setup_interceptor_for(mod, name, path)
34
-
35
- if DeepCover.custom_requirer.is_being_required?(path)
36
- already_loaded_feature
37
- else
38
- interceptor_path
39
- end
40
- end
41
-
42
- def possible_autoload_target?(requested_path)
43
- basename = basename_without_extension(requested_path)
44
- autoloads = @autoloads_by_basename[basename]
45
- autoloads && !autoloads.empty?
46
- end
47
-
48
- def wrap_require(requested_path, absolute_path_found) # &block
49
- entries = entries_for_target(requested_path, absolute_path_found)
50
-
51
- begin
52
- entries.each do |entry|
53
- mod = entry.mod_if_available
54
- next unless mod
55
- mod.autoload_without_deep_cover(entry.name, already_loaded_feature)
56
- end
57
-
58
- yield
59
- ensure
60
- entries = entries_for_target(requested_path, absolute_path_found)
61
- entries.each do |entry|
62
- mod = entry.mod_if_available
63
- next unless mod
64
- # Putting the autoloads back back since we couldn't complete the require
65
- mod.autoload_without_deep_cover(entry.name, entry.interceptor_path)
66
- end
67
- end
68
- end
69
-
70
- # This is only used on MRI, so ObjectSpace is alright.
71
- def initialize_autoloaded_paths(mods = ObjectSpace.each_object(Module)) # &do_autoload_block
72
- mods.each do |mod|
73
- # Module's constants are shared with Object. But if you set autoloads directly on Module, they
74
- # appear on multiple classes. So just skip, Object will take care of those.
75
- next if mod == Module
76
-
77
- if mod.frozen?
78
- if mod.constants.any? { |name| mod.autoload?(name) }
79
- self.class.warn_frozen_module(mod)
80
- end
81
- next
82
- end
83
-
84
- mod.constants.each do |name|
85
- path = mod.autoload?(name)
86
- next unless path
87
- interceptor_path = setup_interceptor_for(mod, name, path)
88
- yield mod, name, interceptor_path
89
- end
90
- end
91
- end
92
-
93
- # We need to remove the interceptor hooks, otherwise, the problem if manually requiring
94
- # something that is autoloaded will cause issues.
95
- def remove_interceptors # &do_autoload_block
96
- @autoloads_by_basename.each do |basename, entries|
97
- entries.each do |entry|
98
- mod = entry.mod_if_available
99
- next unless mod
100
- # Module's constants are shared with Object. But if you set autoloads directly on Module, they
101
- # appear on multiple classes. So just skip, Object will take care of those.
102
- next if mod == Module
103
- yield mod, entry.name, entry.target_path
104
- end
105
- end
106
-
107
- @autoloaded_paths = {}
108
- @interceptor_files_by_path = {}
109
- end
110
-
111
- class << self
112
- attr_accessor :warned_for_frozen_module
113
- end
114
- self.warned_for_frozen_module = false
115
-
116
- # Using frozen modules/classes is almost unheard of, but a warning makes things easier if someone does it
117
- def self.warn_frozen_module(mod)
118
- return if warned_for_frozen_module
119
- self.warned_for_frozen_module ||= true
120
- warn "There is an autoload on a frozen module/class: #{mod}, DeepCover cannot handle those, failure is probable. " \
121
- "This warning won't be displayed again (even for different module/class)"
122
- end
123
-
124
- protected
125
-
126
- def setup_interceptor_for(mod, name, path)
127
- interceptor_path = autoload_interceptor_for(path)
128
- entry = AutoloadEntry.new(WeakRef.new(mod), name, path, interceptor_path)
129
-
130
- basename = basename_without_extension(path)
131
-
132
- @autoloads_by_basename[basename] ||= []
133
- @autoloads_by_basename[basename] << entry
134
- interceptor_path
135
- end
136
-
137
- def entries_for_target(requested_path, absolute_path_found)
138
- basename = basename_without_extension(requested_path)
139
- autoloads = @autoloads_by_basename[basename] || []
140
-
141
- if absolute_path_found
142
- autoloads.select { |entry| entry_is_target?(entry, requested_path, absolute_path_found) }
143
- elsif requested_path == File.absolute_path(requested_path)
144
- []
145
- elsif requested_path.start_with?('./', '../')
146
- []
147
- else
148
- # We didn't find a path that goes through the $LOAD_PATH
149
- # It's possible that RubyGems will actually add the $LOAD_PATH and require an actual file
150
- # So we must make a best-guest for possible matches
151
- requested_path_to_compare = without_extension(requested_path)
152
- autoloads.select { |entry| requested_path_to_compare == without_extension(entry.target_path) }
153
- end
154
- end
155
-
156
- def entry_is_target?(entry, requested_path, absolute_path_found)
157
- return true if entry.target_path == requested_path
158
- target_path_rb = with_rb_extension(entry.target_path)
159
- return true if target_path_rb == requested_path
160
-
161
- # Even though this is not efficient, it's safer to resolve entries' target_path each time
162
- # instead of storing the result, in case subsequent changes to $LOAD_PATH gives different results
163
- entry_absolute_path = DeepCover.custom_requirer.resolve_path(entry.target_path)
164
- return true if entry_absolute_path == absolute_path_found
165
- false
166
- end
167
-
168
- def basename_without_extension(path)
169
- without_extension(File.basename(path))
170
- end
171
-
172
- def with_rb_extension(path)
173
- path += '.rb' unless has_supported_extension?(path)
174
- path
175
- end
176
-
177
- def without_extension(path)
178
- path = path[0...-3] if has_supported_extension?(path)
179
- path
180
- end
181
-
182
- def has_supported_extension?(path)
183
- path.end_with?('.rb', '.so')
184
- end
185
-
186
- # It is not possible to simply remove an autoload. So, instead, we must change the
187
- # autoload to an already loaded path.
188
- # The autoload will be set back to what it was once the require returns. This is
189
- # needed in case that required path wasn't the one that fulfilled the autoload, or
190
- # if the constant and $LOADED_FEATURES gets removed, since in that situation,
191
- # the autoload is supposed to be active again.
192
- def already_loaded_feature
193
- $LOADED_FEATURES.first
194
- end
195
-
196
- def autoload_interceptor_for(path)
197
- existing_files = @interceptor_files_by_path[path] || []
198
- reusable_file = existing_files.detect { |f| !$LOADED_FEATURES.include?(f.path) }
199
- return reusable_file.path if reusable_file
200
-
201
- new_file = Tempfile.new([File.basename(path), '.rb'])
202
- # Need to store all the tempfiles so that they are not GCed, which would delete the files themselves.
203
- # Keeping them by path allows us to reuse them.
204
- @interceptor_files_by_path[path] ||= []
205
- @interceptor_files_by_path[path] << new_file
206
- new_file.write(<<-RUBY)
207
- # Intermediary file for ruby's autoload made by deep-cover
208
- require #{path.to_s.inspect}
209
- RUBY
210
- new_file.close
211
-
212
- new_file.path
213
- end
214
- end
215
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # We use a few features newer than our target of Ruby 2.1+:
4
- class Module
5
- public :define_method
6
- end
7
- require 'pathname'
8
- class Pathname
9
- def write(*args)
10
- File.write(to_path, *args)
11
- end unless method_defined? :write
12
- def binwrite(*args)
13
- File.binwrite(to_path, *args)
14
- end unless method_defined? :binwrite
15
- end # nocov
16
- require 'backports/2.4.0/false_class/dup'
17
- require 'backports/2.4.0/true_class/dup'
18
- require 'backports/2.4.0/hash/transform_values'
19
- require 'backports/2.4.0/enumerable/sum'
20
- require 'backports/2.5.0/hash/slice'
21
- require 'backports/2.5.0/hash/transform_keys'
22
- require 'backports/2.5.0/kernel/yield_self'
@@ -1,117 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeepCover
4
- module Base
5
- def running?
6
- @started ||= false # rubocop:disable Naming/MemoizedInstanceVariableName [#5648]
7
- end
8
-
9
- def start
10
- return if running?
11
- if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
12
- # Autoload is not supported in JRuby. We currently need to use binding_of_caller
13
- # and that is not available in JRuby. An extension may be able to replace this requirement.
14
- # require_relative 'core_ext/autoload_overrides'
15
- # AutoloadOverride.active = true
16
- require_relative 'core_ext/load_overrides'
17
- require_relative 'core_ext/require_overrides'
18
- LoadOverride.active = RequireOverride.active = true
19
- elsif RUBY_VERSION >= '2.3.0'
20
- require_relative 'core_ext/instruction_sequence_load_iseq'
21
- else
22
- require_relative 'core_ext/autoload_overrides'
23
- require_relative 'core_ext/load_overrides'
24
- require_relative 'core_ext/require_overrides'
25
- AutoloadOverride.active = LoadOverride.active = RequireOverride.active = true
26
- autoload_tracker.initialize_autoloaded_paths { |mod, name, path| mod.autoload_without_deep_cover(name, path) }
27
- end
28
-
29
- config # actualize configuration
30
- @lookup_paths = nil
31
- @started = true
32
- end
33
-
34
- def stop
35
- if defined? AutoloadOverride
36
- AutoloadOverride.active = false
37
- autoload_tracker.remove_interceptors { |mod, name, path| mod.autoload_without_deep_cover(name, path) }
38
- end
39
- RequireOverride.active = false if defined? RequireOverride
40
-
41
- @started = false
42
- end
43
-
44
- def line_coverage(filename)
45
- coverage.line_coverage(handle_relative_filename(filename), **config.to_h)
46
- end
47
-
48
- def covered_code(filename)
49
- coverage.covered_code(handle_relative_filename(filename))
50
- end
51
-
52
- def cover(paths: nil)
53
- if paths
54
- prev = config.paths
55
- config.paths(paths)
56
- end
57
- start
58
- yield
59
- ensure
60
- stop
61
- config.paths(prev) if paths
62
- end
63
-
64
- def config_changed(what)
65
- case what
66
- when :paths
67
- warn "Changing DeepCover's paths after starting coverage is highly discouraged" if running?
68
- @lookup_paths = nil
69
- when :tracker_global
70
- raise NotImplementedError, "Changing DeepCover's tracker global after starting coverage is not supported" if running?
71
- @coverage = nil
72
- end
73
- end
74
-
75
- def reset
76
- stop if running?
77
- @coverage = @custom_requirer = @autoload_tracker = @lookup_paths = nil
78
- config.reset
79
- self
80
- end
81
-
82
- def coverage
83
- @coverage ||= Coverage.new(tracker_global: config.tracker_global)
84
- end
85
-
86
- def lookup_paths
87
- return @lookup_paths if @lookup_paths
88
- lookup_paths = config.paths || Dir.getwd
89
- lookup_paths = Array(lookup_paths).map { |p| File.expand_path(p) }
90
- lookup_paths = ['/'] if lookup_paths.include?('/')
91
- @lookup_paths = lookup_paths
92
- end
93
-
94
- def within_lookup_paths?(path)
95
- lookup_paths.any? { |lookup_path| path.start_with?(lookup_path) }
96
- end
97
-
98
- def custom_requirer
99
- @custom_requirer ||= CustomRequirer.new
100
- end
101
-
102
- def autoload_tracker
103
- @autoload_tracker ||= AutoloadTracker.new
104
- end
105
-
106
- private
107
-
108
- def handle_relative_filename(filename)
109
- unless Pathname.new(filename).absolute?
110
- relative_to = File.dirname(caller(2..2).first.partition(/\.rb:\d/).first)
111
- filename = File.absolute_path(filename, relative_to)
112
- end
113
- filename += '.rb' unless filename =~ /\.rb$/
114
- filename
115
- end
116
- end
117
- end