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,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