deep-cover 0.1.14 → 0.1.15
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 +4 -4
- data/.rubocop.yml +227 -0
- data/Gemfile +5 -2
- data/Rakefile +9 -6
- data/bin/console +3 -3
- data/bin/cov +8 -8
- data/bin/gemcov +2 -2
- data/bin/selfcov +5 -5
- data/bin/test_gems +11 -10
- data/bin/testall +6 -6
- data/deep_cover.gemspec +26 -21
- data/exe/deep-cover +1 -0
- data/lib/deep-cover.rb +2 -0
- data/lib/deep_cover.rb +3 -0
- data/lib/deep_cover/analyser.rb +2 -0
- data/lib/deep_cover/analyser/base.rb +2 -0
- data/lib/deep_cover/analyser/branch.rb +4 -2
- data/lib/deep_cover/analyser/covered_code_source.rb +3 -1
- data/lib/deep_cover/analyser/function.rb +3 -1
- data/lib/deep_cover/analyser/ignore_uncovered.rb +6 -4
- data/lib/deep_cover/analyser/node.rb +3 -0
- data/lib/deep_cover/analyser/optionally_covered.rb +12 -7
- data/lib/deep_cover/analyser/per_char.rb +7 -6
- data/lib/deep_cover/analyser/per_line.rb +9 -8
- data/lib/deep_cover/analyser/statement.rb +2 -0
- data/lib/deep_cover/analyser/subset.rb +4 -1
- data/lib/deep_cover/auto_run.rb +3 -0
- data/lib/deep_cover/autoload_tracker.rb +6 -3
- data/lib/deep_cover/backports.rb +2 -0
- data/lib/deep_cover/base.rb +11 -2
- data/lib/deep_cover/builtin_takeover.rb +2 -0
- data/lib/deep_cover/cli/debugger.rb +55 -30
- data/lib/deep_cover/cli/deep_cover.rb +17 -11
- data/lib/deep_cover/cli/instrumented_clone_reporter.rb +16 -14
- data/lib/deep_cover/config.rb +29 -16
- data/lib/deep_cover/core_ext/autoload_overrides.rb +2 -0
- data/lib/deep_cover/core_ext/coverage_replacement.rb +2 -0
- data/lib/deep_cover/core_ext/load_overrides.rb +5 -6
- data/lib/deep_cover/core_ext/require_overrides.rb +6 -7
- data/lib/deep_cover/coverage.rb +21 -18
- data/lib/deep_cover/covered_code.rb +22 -12
- data/lib/deep_cover/custom_requirer.rb +82 -35
- data/lib/deep_cover/memoize.rb +48 -0
- data/lib/deep_cover/module_override.rb +2 -0
- data/lib/deep_cover/node.rb +14 -1
- data/lib/deep_cover/node/arguments.rb +2 -0
- data/lib/deep_cover/node/assignments.rb +32 -30
- data/lib/deep_cover/node/base.rb +30 -29
- data/lib/deep_cover/node/begin.rb +3 -1
- data/lib/deep_cover/node/block.rb +5 -2
- data/lib/deep_cover/node/branch.rb +2 -1
- data/lib/deep_cover/node/case.rb +15 -13
- data/lib/deep_cover/node/collections.rb +2 -0
- data/lib/deep_cover/node/const.rb +2 -0
- data/lib/deep_cover/node/def.rb +10 -8
- data/lib/deep_cover/node/empty_body.rb +2 -0
- data/lib/deep_cover/node/exceptions.rb +3 -1
- data/lib/deep_cover/node/if.rb +3 -1
- data/lib/deep_cover/node/keywords.rb +4 -2
- data/lib/deep_cover/node/literals.rb +2 -0
- data/lib/deep_cover/node/loops.rb +5 -3
- data/lib/deep_cover/node/mixin/can_augment_children.rb +8 -7
- data/lib/deep_cover/node/mixin/check_completion.rb +3 -1
- data/lib/deep_cover/node/mixin/child_can_be_empty.rb +4 -2
- data/lib/deep_cover/node/mixin/executed_after_children.rb +2 -0
- data/lib/deep_cover/node/mixin/execution_location.rb +4 -2
- data/lib/deep_cover/node/mixin/flow_accounting.rb +2 -0
- data/lib/deep_cover/node/mixin/has_child.rb +22 -18
- data/lib/deep_cover/node/mixin/has_child_handler.rb +10 -8
- data/lib/deep_cover/node/mixin/has_tracker.rb +4 -2
- data/lib/deep_cover/node/mixin/is_statement.rb +3 -1
- data/lib/deep_cover/node/mixin/rewriting.rb +5 -3
- data/lib/deep_cover/node/mixin/wrapper.rb +2 -0
- data/lib/deep_cover/node/module.rb +11 -9
- data/lib/deep_cover/node/root.rb +2 -0
- data/lib/deep_cover/node/send.rb +4 -2
- data/lib/deep_cover/node/short_circuit.rb +4 -2
- data/lib/deep_cover/node/splat.rb +2 -0
- data/lib/deep_cover/node/variables.rb +2 -0
- data/lib/deep_cover/parser_ext/range.rb +3 -1
- data/lib/deep_cover/problem_with_diagnostic.rb +11 -9
- data/lib/deep_cover/reporter.rb +2 -0
- data/lib/deep_cover/reporter/istanbul.rb +28 -24
- data/lib/deep_cover/tools.rb +2 -0
- data/lib/deep_cover/tools/builtin_coverage.rb +6 -4
- data/lib/deep_cover/tools/camelize.rb +3 -1
- data/lib/deep_cover/tools/dasherize.rb +3 -1
- data/lib/deep_cover/tools/dump_covered_code.rb +7 -6
- data/lib/deep_cover/tools/execute_sample.rb +13 -13
- data/lib/deep_cover/tools/format.rb +3 -1
- data/lib/deep_cover/tools/format_char_cover.rb +4 -2
- data/lib/deep_cover/tools/format_generated_code.rb +3 -1
- data/lib/deep_cover/tools/number_lines.rb +2 -0
- data/lib/deep_cover/tools/our_coverage.rb +5 -3
- data/lib/deep_cover/tools/profiling.rb +66 -0
- data/lib/deep_cover/tools/require_relative_dir.rb +3 -1
- data/lib/deep_cover/tools/silence_warnings.rb +4 -1
- data/lib/deep_cover/tools/slice.rb +3 -1
- data/lib/deep_cover/tools/truncate_backtrace.rb +2 -0
- data/lib/deep_cover/version.rb +3 -1
- metadata +47 -30
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DeepCover
|
2
4
|
class Node
|
3
5
|
class Begin < Node
|
@@ -16,7 +18,7 @@ module DeepCover
|
|
16
18
|
when 'else', '#{'
|
17
19
|
%i[begin end]
|
18
20
|
else
|
19
|
-
warn
|
21
|
+
warn 'Unknown context for Begin node'
|
20
22
|
[]
|
21
23
|
end
|
22
24
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'send'
|
2
4
|
require_relative 'keywords'
|
3
5
|
|
@@ -32,8 +34,9 @@ module DeepCover
|
|
32
34
|
class Block < Node
|
33
35
|
check_completion
|
34
36
|
has_tracker :body
|
35
|
-
has_child call: {
|
36
|
-
|
37
|
+
has_child call: {send: SendWithBlock, csend: CsendWithBlock,
|
38
|
+
zsuper: SuperWithBlock, super: SuperWithBlock,
|
39
|
+
}
|
37
40
|
has_child args: Args
|
38
41
|
has_child body: Node,
|
39
42
|
can_be_empty: -> { base_node.loc.end.begin },
|
data/lib/deep_cover/node/case.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'branch'
|
2
4
|
|
3
5
|
module DeepCover
|
@@ -14,8 +16,8 @@ module DeepCover
|
|
14
16
|
# See https://github.com/jruby/jruby/issues/4804
|
15
17
|
# This is solved in jruby 9.2.0.0, better keep the workaround
|
16
18
|
# for compatibility.
|
17
|
-
has_child condition: Node, rewrite:
|
18
|
-
|
19
|
+
has_child condition: Node, rewrite: '(((%{entry_tracker}) && %{node}))',
|
20
|
+
flow_entry_count: :entry_tracker_hits
|
19
21
|
executed_loc_keys []
|
20
22
|
|
21
23
|
def flow_entry_count
|
@@ -43,18 +45,18 @@ module DeepCover
|
|
43
45
|
|
44
46
|
class When < Node
|
45
47
|
has_tracker :body_entry
|
46
|
-
has_extra_children matches: {
|
48
|
+
has_extra_children matches: {splat: WhenSplatCondition, Parser::AST::Node => WhenCondition}
|
47
49
|
has_child body: Node,
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
50
|
+
can_be_empty: -> {
|
51
|
+
if (after_then = base_node.loc.begin)
|
52
|
+
after_then.end
|
53
|
+
else
|
54
|
+
base_node.loc.expression.end
|
55
|
+
end
|
56
|
+
},
|
57
|
+
rewrite: ';%{body_entry_tracker};%{local}=nil;%{node}',
|
58
|
+
is_statement: true,
|
59
|
+
flow_entry_count: :body_entry_tracker_hits
|
58
60
|
|
59
61
|
def flow_entry_count
|
60
62
|
matches.first.flow_entry_count
|
data/lib/deep_cover/node/def.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'arguments'
|
2
4
|
|
3
5
|
module DeepCover
|
@@ -7,10 +9,10 @@ module DeepCover
|
|
7
9
|
has_child method_name: Symbol
|
8
10
|
has_child signature: Args
|
9
11
|
has_child body: Node,
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
rewrite: '%{method_call_tracker};%{local}=nil;%{node}',
|
13
|
+
can_be_empty: -> { base_node.loc.end.begin },
|
14
|
+
is_statement: true,
|
15
|
+
flow_entry_count: :method_call_tracker_hits
|
14
16
|
executed_loc_keys :keyword, :name
|
15
17
|
|
16
18
|
def children_nodes_in_flow_order
|
@@ -25,10 +27,10 @@ module DeepCover
|
|
25
27
|
has_child method_name: Symbol
|
26
28
|
has_child signature: Args
|
27
29
|
has_child body: Node,
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
rewrite: '%{method_call_tracker};%{local}=nil;%{node}',
|
31
|
+
can_be_empty: -> { base_node.loc.end.begin },
|
32
|
+
is_statement: true,
|
33
|
+
flow_entry_count: :method_call_tracker_hits
|
32
34
|
executed_loc_keys :keyword, :name, :operator
|
33
35
|
|
34
36
|
def children_nodes_in_flow_order
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'variables'
|
2
4
|
require_relative 'collections'
|
3
5
|
|
@@ -51,7 +53,7 @@ module DeepCover
|
|
51
53
|
if prev.equal? watched_body
|
52
54
|
prev.flow_entry_count - prev.flow_completion_count
|
53
55
|
else # RESBODIES
|
54
|
-
if prev.exception
|
56
|
+
if prev.exception # rubocop:disable Style/IfInsideElse
|
55
57
|
prev.exception.flow_completion_count - prev.execution_count
|
56
58
|
else
|
57
59
|
prev.flow_entry_count - prev.execution_count
|
data/lib/deep_cover/node/if.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'branch'
|
2
4
|
|
3
5
|
module DeepCover
|
@@ -19,7 +21,7 @@ module DeepCover
|
|
19
21
|
executed_loc_keys :keyword, :question
|
20
22
|
|
21
23
|
def branches
|
22
|
-
[
|
24
|
+
[true_branch, false_branch]
|
23
25
|
end
|
24
26
|
|
25
27
|
def execution_count
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'variables'
|
2
4
|
require_relative 'literals'
|
3
5
|
|
@@ -31,7 +33,7 @@ module DeepCover
|
|
31
33
|
|
32
34
|
class Break < Node
|
33
35
|
has_extra_children arguments: Node
|
34
|
-
# TODO Anything special needed for the arguments?
|
36
|
+
# TODO: Anything special needed for the arguments?
|
35
37
|
|
36
38
|
def flow_completion_count
|
37
39
|
0
|
@@ -40,7 +42,7 @@ module DeepCover
|
|
40
42
|
|
41
43
|
class Next < Node
|
42
44
|
has_extra_children arguments: Node
|
43
|
-
# TODO Anything special needed for the arguments?
|
45
|
+
# TODO: Anything special needed for the arguments?
|
44
46
|
|
45
47
|
def flow_completion_count
|
46
48
|
0
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DeepCover
|
2
4
|
class Node
|
3
5
|
class For < Node
|
@@ -5,9 +7,9 @@ module DeepCover
|
|
5
7
|
has_child assignments: [Mlhs, VariableAssignment], flow_entry_count: -> { body.flow_entry_count if body }
|
6
8
|
has_child iterable: [Node], flow_entry_count: -> { flow_entry_count }
|
7
9
|
has_child body: Node,
|
8
|
-
|
9
|
-
|
10
|
-
|
10
|
+
can_be_empty: -> { base_node.loc.end.begin },
|
11
|
+
flow_entry_count: :body_tracker_hits,
|
12
|
+
rewrite: '((%{body_tracker};%{local}=nil;%{node}))'
|
11
13
|
check_completion
|
12
14
|
|
13
15
|
def execution_count
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DeepCover
|
2
4
|
module Node::Mixin
|
3
5
|
module CanAugmentChildren
|
@@ -10,9 +12,9 @@ module DeepCover
|
|
10
12
|
# Caution: receiver is not fully constructed since it is also being augmented.
|
11
13
|
# don't call `children`
|
12
14
|
def augment_children(child_base_nodes)
|
13
|
-
|
14
|
-
|
15
|
-
child_base_nodes = [
|
15
|
+
if child_base_nodes.size < (sz = self.class.min_children)
|
16
|
+
child_base_nodes = child_base_nodes.dup
|
17
|
+
child_base_nodes[sz..-1] = [] # Fill with nil
|
16
18
|
end
|
17
19
|
child_base_nodes.map.with_index do |child, child_index|
|
18
20
|
child_name = self.class.child_index_to_name(child_index, child_base_nodes.size)
|
@@ -25,14 +27,13 @@ module DeepCover
|
|
25
27
|
end
|
26
28
|
private :augment_children
|
27
29
|
|
28
|
-
def remap_child(child, name=nil)
|
30
|
+
def remap_child(child, name = nil)
|
29
31
|
return unless child.is_a?(Parser::AST::Node)
|
30
32
|
class_name = Tools.camelize(child.type)
|
31
33
|
Node.const_defined?(class_name) ? Node.const_get(class_name) : Node
|
32
34
|
end
|
33
35
|
|
34
36
|
module ClassMethods
|
35
|
-
|
36
37
|
# This handles the following shortcuts:
|
37
38
|
# has_child foo: {type: NodeClass, ...}
|
38
39
|
# same as:
|
@@ -43,13 +44,13 @@ module DeepCover
|
|
43
44
|
def has_child(remap: nil, **h)
|
44
45
|
name, types = h.first
|
45
46
|
if types.is_a? Hash
|
46
|
-
raise
|
47
|
+
raise 'Use either remap or a hash as type but not both' if remap
|
47
48
|
remap = types
|
48
49
|
h[name] = types = []
|
49
50
|
end
|
50
51
|
if remap.is_a? Hash
|
51
52
|
type_map = remap
|
52
|
-
remap = ->
|
53
|
+
remap = ->(child) do
|
53
54
|
klass = type_map[child.type] if child.respond_to? :type
|
54
55
|
klass ||= type_map[child.class]
|
55
56
|
klass
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'executed_after_children'
|
2
4
|
|
3
5
|
module DeepCover
|
4
6
|
module Node::Mixin
|
5
7
|
module CheckCompletion
|
6
|
-
def check_completion(outer:'(%{node})', inner:'(%{node})')
|
8
|
+
def check_completion(outer: '(%{node})', inner: '(%{node})')
|
7
9
|
has_tracker :completion
|
8
10
|
include ExecutedAfterChildren
|
9
11
|
alias_method :flow_completion_count, :completion_tracker_hits
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DeepCover
|
2
4
|
module Node::Mixin
|
3
5
|
module ChildCanBeEmpty
|
@@ -8,7 +10,7 @@ module DeepCover
|
|
8
10
|
end
|
9
11
|
end
|
10
12
|
|
11
|
-
def remap_child(child, name=raise)
|
13
|
+
def remap_child(child, name = raise)
|
12
14
|
if child == nil
|
13
15
|
if (ChildCanBeEmpty.last_empty_position = child_can_be_empty(child, name))
|
14
16
|
return Node::EmptyBody
|
@@ -17,7 +19,7 @@ module DeepCover
|
|
17
19
|
super
|
18
20
|
end
|
19
21
|
|
20
|
-
def child_can_be_empty(_child, _name=nil)
|
22
|
+
def child_can_be_empty(_child, _name = nil)
|
21
23
|
false
|
22
24
|
end
|
23
25
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DeepCover
|
2
4
|
module Node::Mixin
|
3
5
|
module ExecutionLocation
|
@@ -30,7 +32,7 @@ module DeepCover
|
|
30
32
|
if (keys = parent.child_executed_loc_keys(self))
|
31
33
|
h.merge!(Tools.slice(parent.loc_hash, *keys))
|
32
34
|
end
|
33
|
-
h.reject{|k, v| v.nil? }
|
35
|
+
h.reject { |k, v| v.nil? }
|
34
36
|
end
|
35
37
|
|
36
38
|
def executed_locs
|
@@ -38,7 +40,7 @@ module DeepCover
|
|
38
40
|
end
|
39
41
|
|
40
42
|
def loc_hash
|
41
|
-
|
43
|
+
base_node.respond_to?(:location) ? base_node.location.to_hash : {}
|
42
44
|
end
|
43
45
|
|
44
46
|
def expression
|
@@ -1,11 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DeepCover
|
2
4
|
module Node::Mixin
|
3
5
|
module HasChild
|
4
6
|
def self.included(base)
|
5
7
|
base.extend ClassMethods
|
6
8
|
end
|
7
|
-
CHILDREN = {}
|
8
|
-
CHILDREN_TYPES = {}
|
9
|
+
CHILDREN = {}.freeze
|
10
|
+
CHILDREN_TYPES = {}.freeze
|
9
11
|
|
10
12
|
def initialize(*)
|
11
13
|
super
|
@@ -20,31 +22,31 @@ module DeepCover
|
|
20
22
|
end
|
21
23
|
|
22
24
|
module ClassMethods
|
23
|
-
def has_child(
|
25
|
+
def has_child(rest_: false, refine_: false, **h)
|
24
26
|
raise "Needs exactly one custom named argument, got #{h.size}" if h.size != 1
|
25
27
|
name, types = h.first
|
26
28
|
raise TypeError, "Expect a Symbol for name, got a #{name.class} (#{name.inspect})" unless name.is_a?(Symbol)
|
27
|
-
update_children_const(name, rest:
|
28
|
-
define_accessor(name) unless
|
29
|
+
update_children_const(name, rest: rest_) unless refine_
|
30
|
+
define_accessor(name) unless refine_
|
29
31
|
add_runtime_check(name, types)
|
30
32
|
self
|
31
33
|
end
|
32
34
|
|
33
35
|
def has_extra_children(**h)
|
34
|
-
has_child(**h,
|
36
|
+
has_child(**h, rest_: true)
|
35
37
|
end
|
36
38
|
|
37
39
|
def refine_child(child_name = nil, **h)
|
38
40
|
if child_name
|
39
41
|
h = {child_name => self::CHILDREN_TYPES.fetch(child_name), **h}
|
40
42
|
end
|
41
|
-
has_child(**h,
|
43
|
+
has_child(**h, refine_: true)
|
42
44
|
end
|
43
45
|
|
44
46
|
def child_index_to_name(index, nb_children)
|
45
47
|
self::CHILDREN.each do |name, i|
|
46
48
|
return name if i == index || (i == index - nb_children) ||
|
47
|
-
|
49
|
+
(i.is_a?(Range) && i.begin <= index && i.end + nb_children >= index)
|
48
50
|
end
|
49
51
|
raise IndexError, "index #{index} does not correspond to any child of #{self}"
|
50
52
|
end
|
@@ -82,7 +84,7 @@ module DeepCover
|
|
82
84
|
when nil
|
83
85
|
node.nil?
|
84
86
|
when Array
|
85
|
-
expected.any? {|exp| node_matches_type?(node, exp) }
|
87
|
+
expected.any? { |exp| node_matches_type?(node, exp) }
|
86
88
|
when Class
|
87
89
|
node.is_a?(expected)
|
88
90
|
when Symbol
|
@@ -110,22 +112,24 @@ module DeepCover
|
|
110
112
|
end
|
111
113
|
end
|
112
114
|
children_map[name] = if rest
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
115
|
+
if already_has_rest
|
116
|
+
raise "Class #{self} can't have extra children '#{name}' because it already has '#{name}' (#{children_map})"
|
117
|
+
end
|
118
|
+
children_map.size..-1
|
119
|
+
elsif already_has_rest
|
120
|
+
-1
|
121
|
+
else
|
122
|
+
children_map.size
|
123
|
+
end
|
120
124
|
end
|
121
125
|
|
122
126
|
def define_accessor(name)
|
123
127
|
warn "child name '#{name}' conflicts with existing method for #{self}" if method_defined? name
|
124
|
-
class_eval <<-
|
128
|
+
class_eval <<-EVAL, __FILE__, __LINE__ + 1
|
125
129
|
def #{name}
|
126
130
|
children[CHILDREN.fetch(#{name.inspect})]
|
127
131
|
end
|
128
|
-
|
132
|
+
EVAL
|
129
133
|
end
|
130
134
|
|
131
135
|
def add_runtime_check(name, type)
|