deep-cover 0.6.2 → 0.6.3.pre

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.
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,65 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeepCover
4
- module Node::Mixin
5
- module CanAugmentChildren
6
- def self.included(base)
7
- base.has_child_handler('remap_%{name}')
8
- base.singleton_class.prepend ClassMethods
9
- end
10
-
11
- # Augment creates a covered node from the child_base_node.
12
- # Caution: receiver is not fully constructed since it is also being augmented.
13
- # don't call `children`
14
- def augment_children(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
18
- end
19
- child_base_nodes.map.with_index do |child, child_index|
20
- child_name = self.class.child_index_to_name(child_index, child_base_nodes.size)
21
- if (klass = remap_child(child, child_name))
22
- klass.new(child, parent: self, index: child_index)
23
- else
24
- child
25
- end
26
- end
27
- end
28
- private :augment_children
29
-
30
- def remap_child(child, name = nil)
31
- return unless child.is_a?(Parser::AST::Node)
32
- class_name = Tools.camelize(child.type)
33
- Node.const_defined?(class_name) ? Node.const_get(class_name) : Node
34
- end
35
-
36
- module ClassMethods
37
- # This handles the following shortcuts:
38
- # has_child foo: {type: NodeClass, ...}
39
- # same as:
40
- # has_child foo: [], remap: {type: NodeClass, ...}
41
- # same as:
42
- # has_child foo: [NodeClass, ...], remap: {type: NodeClass, ...}
43
- #
44
- def has_child(remap: nil, **args)
45
- name, types = args.first
46
- if types.is_a? Hash
47
- raise 'Use either remap or a hash as type but not both' if remap
48
- remap = types
49
- args[name] = types = []
50
- end
51
- if remap.is_a? Hash
52
- type_map = remap
53
- remap = ->(child) do
54
- klass = type_map[child.type] if child.respond_to? :type
55
- klass ||= type_map[child.class]
56
- klass
57
- end
58
- types.concat(type_map.values).uniq!
59
- end
60
- super(**args, remap: remap)
61
- end
62
- end
63
- end
64
- end
65
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'executed_after_children'
4
-
5
- module DeepCover
6
- module Node::Mixin
7
- module CheckCompletion
8
- def check_completion(outer: '(%{node})', inner: '(%{node})')
9
- has_tracker :completion
10
- include ExecutedAfterChildren
11
- alias_method :flow_completion_count, :completion_tracker_hits
12
- pre, post = outer.split('%{node}')
13
- # The local=local is to avoid Ruby warning about "Possible use of value in void context"
14
- define_method(:rewrite) { "#{pre}(%{local}=#{inner};%{completion_tracker};%{local}=%{local})#{post}" }
15
- end
16
- end
17
- end
18
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeepCover
4
- module Node::Mixin
5
- module ChildCanBeEmpty
6
- class << self
7
- attr_accessor :last_empty_position # Ugly hack to pass info from Handler to constructor
8
- def included(base)
9
- base.has_child_handler('%{name}_can_be_empty')
10
- end
11
- end
12
-
13
- def remap_child(child, name)
14
- if child == nil
15
- if (ChildCanBeEmpty.last_empty_position = child_can_be_empty(child, name))
16
- return Node::EmptyBody
17
- end
18
- end
19
- super
20
- end
21
-
22
- def child_can_be_empty(_child, _name = nil)
23
- false
24
- end
25
- end
26
- end
27
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeepCover
4
- module Node::Mixin
5
- # By default, nodes are considered executed if they are entered.
6
- # Some are considered executed only if their arguments complete.
7
- module ExecutedAfterChildren
8
- def execution_count
9
- last = children_nodes_in_flow_order.last
10
- return last.flow_completion_count if last
11
- super
12
- end
13
- end
14
- end
15
- end
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeepCover
4
- module Node::Mixin
5
- module ExecutionLocation
6
- def self.included(base)
7
- base.extend ClassMethods
8
- base.has_child_handler('%{name}_executed_loc_keys')
9
- end
10
-
11
- module ClassMethods
12
- # Macro to define the executed_loc_keys
13
- def executed_loc_keys(*loc_keys)
14
- # #flatten allows passing an empty array to be explicit
15
- loc_keys = loc_keys.flatten
16
- define_method :executed_loc_keys do
17
- loc_keys
18
- end
19
- end
20
- end
21
-
22
- def executed_loc_keys
23
- return [] unless executable?
24
- loc_hash.keys - [:expression]
25
- end
26
-
27
- def child_executed_loc_keys(_child, _child_name)
28
- nil
29
- end
30
-
31
- def executed_loc_hash
32
- h = Tools.slice(loc_hash, *executed_loc_keys)
33
- if (keys = parent.child_executed_loc_keys(self))
34
- h.merge!(Tools.slice(parent.loc_hash, *keys))
35
- end
36
- h.reject { |k, v| v.nil? }
37
- end
38
-
39
- def executed_locs
40
- executed_loc_hash.values
41
- end
42
-
43
- def loc_hash
44
- base_node.respond_to?(:location) ? base_node.location.to_hash : {}
45
- end
46
-
47
- def expression
48
- loc_hash[:expression]
49
- end
50
-
51
- def source
52
- expression.source if expression
53
- end
54
-
55
- def diagnostic_expression
56
- expression || parent.diagnostic_expression
57
- end
58
-
59
- # Returns an array of character numbers (in the original buffer) that
60
- # pertain exclusively to this node (and thus not to any children).
61
- def proper_range
62
- executed_locs.map(&:to_a).inject([], :+).uniq
63
- end
64
- end
65
- end
66
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeepCover
4
- module Node::Mixin
5
- module Filters
6
- module ClassMethods
7
- def filter_to_method_name(kind)
8
- :"is_#{kind}?"
9
- end
10
-
11
- def create_filter(name, &block)
12
- Filters.define_method(filter_to_method_name(name), &block)
13
- OPTIONALLY_COVERED << name
14
- end
15
-
16
- def unique_filter
17
- (1..Float::INFINITY).each do |i|
18
- name = :"custom_filter_#{i}"
19
- return name unless Filters.method_defined?(filter_to_method_name(name))
20
- end
21
- end
22
- end
23
-
24
- RAISING_MESSAGES = %i[raise exit].freeze
25
- def is_raise?
26
- is_a?(Node::Send) && RAISING_MESSAGES.include?(message) && receiver == nil
27
- end
28
-
29
- def is_warn?
30
- is_a?(Node::Send) && message == :warn
31
- end
32
-
33
- def is_default_argument?
34
- parent.is_a?(Node::Optarg) && simple_literal?
35
- end
36
-
37
- def is_case_implicit_else?
38
- is_a?(Node::EmptyBody) && parent.is_a?(Node::Case) && !parent.has_else?
39
- end
40
-
41
- def is_trivial_if?
42
- # Supports only node being a branch or the fork itself
43
- parent.is_a?(Node::If) && parent.condition.simple_literal?
44
- end
45
- end
46
- end
47
- end
@@ -1,71 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeepCover
4
- module Node::Mixin
5
- module FlowAccounting
6
- def self.included(base)
7
- base.has_child_handler('%{name}_flow_entry_count')
8
- end
9
-
10
- # Returns true iff it is executable and if was successfully executed
11
- def was_executed?
12
- # There is a rare case of non executable nodes that have important data in flow_entry_count / flow_completion_count,
13
- # like `if cond; end`, so make sure it's actually executable first...
14
- executable? && execution_count > 0
15
- end
16
-
17
- # Returns the control flow entered the node.
18
- # The control flow can then either complete normally or be interrupted
19
- #
20
- # Implementation: This is always the responsibility of the parent; Nodes should not override.
21
- def flow_entry_count
22
- parent.child_flow_entry_count(self)
23
- end
24
-
25
- # Returns the number of times it changed the usual control flow (e.g. raised, returned, ...)
26
- # Implementation: This is always deduced; Nodes should not override.
27
- def flow_interrupt_count
28
- flow_entry_count - flow_completion_count
29
- end
30
-
31
- ### These are refined by subclasses
32
-
33
- # Returns true iff it is executable. Keywords like `end` are not executable, but literals like `42` are executable.
34
- def executable?
35
- true
36
- end
37
-
38
- # Returns number of times the node itself was "executed". Definition of executed depends on the node.
39
- # For now at least, don't return `nil`, instead return `false` in `executable?`
40
- def execution_count
41
- flow_entry_count
42
- end
43
-
44
- # Returns the number of times the control flow succesfully left the node.
45
- # This is the responsability of the child Node, never of the parent.
46
- # Must be refined if the child node may have an impact on control flow (raising, branching, ...)
47
- def flow_completion_count
48
- last = children_nodes_in_flow_order.last
49
- return last.flow_completion_count if last
50
- flow_entry_count
51
- end
52
-
53
- # Returns the number of time the control flow entered this child_node.
54
- # This is the responsability of the Node, not of the child.
55
- # Must be refined if the parent node may have an impact on control flow (raising, branching, ...)
56
- def child_flow_entry_count(child, _name = nil)
57
- prev = child.previous_sibling
58
- if prev
59
- prev.flow_completion_count
60
- else
61
- flow_entry_count
62
- end
63
- end
64
-
65
- # Returns the counts in a hash
66
- def counts
67
- {flow_entry: flow_entry_count, flow_completion: flow_completion_count, execution: execution_count}
68
- end
69
- end
70
- end
71
- end
@@ -1,145 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeepCover
4
- module Node::Mixin
5
- module HasChild
6
- def self.included(base)
7
- base.extend ClassMethods
8
- end
9
- CHILDREN = {}.freeze
10
- CHILDREN_TYPES = {}.freeze
11
-
12
- def initialize(*)
13
- super
14
- self.validate_children_types(children)
15
- end
16
-
17
- def validate_children_types(nodes)
18
- mismatches = self.class.check_children_types(nodes)
19
- unless mismatches.empty?
20
- raise TypeError, "Invalid children types for #{self.class}(type: #{self.type}): #{mismatches}"
21
- end
22
- end
23
-
24
- def child_index_to_name(index)
25
- self.class.child_index_to_name(index, children.size)
26
- end
27
-
28
- module ClassMethods
29
- def has_child(rest_: false, refine_: false, **args)
30
- raise "Needs exactly one custom named argument, got #{args.size}" if args.size != 1
31
- name, types = args.first
32
- raise TypeError, "Expect a Symbol for name, got a #{name.class} (#{name.inspect})" unless name.is_a?(Symbol)
33
- update_children_const(name, rest: rest_) unless refine_
34
- define_accessor(name) unless refine_
35
- add_runtime_check(name, types)
36
- self
37
- end
38
-
39
- def has_extra_children(**args)
40
- has_child(**args, rest_: true)
41
- end
42
-
43
- def refine_child(child_name = nil, **args)
44
- if child_name
45
- args = {child_name => self::CHILDREN_TYPES.fetch(child_name), **args}
46
- end
47
- has_child(**args, refine_: true)
48
- end
49
-
50
- def child_index_to_name(index, nb_children)
51
- self::CHILDREN.each do |name, i|
52
- return name if i == index || (i == index - nb_children) ||
53
- (i.is_a?(Range) && i.begin <= index && i.end + nb_children >= index)
54
- end
55
- raise IndexError, "index #{index} does not correspond to any child of #{self}"
56
- end
57
-
58
- def check_children_types(nodes)
59
- types = expected_types(nodes)
60
- nodes_mismatches(nodes, types)
61
- end
62
-
63
- def min_children
64
- self::CHILDREN.values.grep(Integer).size
65
- end
66
-
67
- private
68
-
69
- def expected_types(nodes)
70
- self::CHILDREN.flat_map do |name, i|
71
- type = self::CHILDREN_TYPES[name]
72
- Array.new(nodes.values_at(i).size, type)
73
- end
74
- end
75
-
76
- def nodes_mismatches(nodes, types)
77
- nodes = nodes.dup
78
- nodes[nodes.size...types.size] = nil
79
- nodes.zip(types).reject do |node, type|
80
- node_matches_type?(node, type)
81
- end
82
- end
83
-
84
- def node_matches_type?(node, expected)
85
- case expected
86
- when :any
87
- true
88
- when nil
89
- node.nil?
90
- when Array
91
- expected.any? { |exp| node_matches_type?(node, exp) }
92
- when Class
93
- node.is_a?(expected)
94
- when Symbol
95
- node.is_a?(Node) && node.type == expected
96
- else
97
- raise "Unrecognized expected type #{expected}"
98
- end
99
- end
100
-
101
- def inherited(subclass)
102
- subclass.const_set :CHILDREN, self::CHILDREN.dup
103
- subclass.const_set :CHILDREN_TYPES, self::CHILDREN_TYPES.dup
104
- super
105
- end
106
-
107
- def update_children_const(name, rest: false)
108
- children_map = self::CHILDREN
109
- already_has_rest = false
110
- children_map.each do |key, value|
111
- if value.is_a? Range
112
- children_map[key] = children_map[key].begin..(children_map[key].end - 1)
113
- already_has_rest = key
114
- elsif value < 0
115
- children_map[key] -= 1
116
- end
117
- end
118
- children_map[name] = if rest
119
- if already_has_rest
120
- raise "Class #{self} can't have extra children '#{name}' because it already has '#{name}' (#{children_map})"
121
- end
122
- children_map.size..-1
123
- elsif already_has_rest
124
- -1
125
- else
126
- children_map.size
127
- end
128
- end
129
-
130
- def define_accessor(name)
131
- warn "child name '#{name}' conflicts with existing method for #{self}" if method_defined? name
132
- class_eval <<-EVAL, __FILE__, __LINE__ + 1
133
- def #{name}
134
- children[CHILDREN.fetch(#{name.inspect})]
135
- end
136
- EVAL
137
- end
138
-
139
- def add_runtime_check(name, type)
140
- self::CHILDREN_TYPES[name] = type
141
- end
142
- end
143
- end
144
- end
145
- end