deep-cover 0.1.14 → 0.1.15
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|