mutant 0.9.8 → 0.9.9

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 (161) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +2 -2
  3. data/Changelog.md +6 -0
  4. data/README.md +63 -23
  5. data/config/reek.yml +1 -0
  6. data/lib/mutant.rb +4 -0
  7. data/lib/mutant/ast.rb +0 -9
  8. data/lib/mutant/ast/find_metaclass_containing.rb +48 -0
  9. data/lib/mutant/ast/meta/send.rb +0 -6
  10. data/lib/mutant/bootstrap.rb +0 -36
  11. data/lib/mutant/cli.rb +5 -49
  12. data/lib/mutant/color.rb +0 -3
  13. data/lib/mutant/config.rb +0 -8
  14. data/lib/mutant/context.rb +0 -3
  15. data/lib/mutant/diff.rb +0 -17
  16. data/lib/mutant/env.rb +0 -6
  17. data/lib/mutant/expression/method.rb +6 -6
  18. data/lib/mutant/expression/methods.rb +6 -6
  19. data/lib/mutant/expression/parser.rb +0 -6
  20. data/lib/mutant/integration.rb +0 -18
  21. data/lib/mutant/isolation/fork.rb +0 -22
  22. data/lib/mutant/license.rb +11 -0
  23. data/lib/mutant/matcher.rb +0 -14
  24. data/lib/mutant/matcher/config.rb +0 -11
  25. data/lib/mutant/matcher/method.rb +0 -31
  26. data/lib/mutant/matcher/method/instance.rb +0 -8
  27. data/lib/mutant/matcher/method/metaclass.rb +86 -0
  28. data/lib/mutant/matcher/method/singleton.rb +0 -25
  29. data/lib/mutant/matcher/methods.rb +17 -28
  30. data/lib/mutant/matcher/namespace.rb +0 -10
  31. data/lib/mutant/matcher/scope.rb +2 -4
  32. data/lib/mutant/meta/example/dsl.rb +0 -21
  33. data/lib/mutant/meta/example/verification.rb +0 -20
  34. data/lib/mutant/mutation.rb +0 -3
  35. data/lib/mutant/mutator.rb +1 -29
  36. data/lib/mutant/mutator/node.rb +1 -66
  37. data/lib/mutant/mutator/node/and_asgn.rb +0 -3
  38. data/lib/mutant/mutator/node/argument.rb +0 -15
  39. data/lib/mutant/mutator/node/arguments.rb +0 -20
  40. data/lib/mutant/mutator/node/begin.rb +0 -3
  41. data/lib/mutant/mutator/node/binary.rb +0 -23
  42. data/lib/mutant/mutator/node/block.rb +0 -15
  43. data/lib/mutant/mutator/node/break.rb +0 -3
  44. data/lib/mutant/mutator/node/case.rb +0 -9
  45. data/lib/mutant/mutator/node/class.rb +0 -3
  46. data/lib/mutant/mutator/node/conditional_loop.rb +0 -3
  47. data/lib/mutant/mutator/node/const.rb +0 -3
  48. data/lib/mutant/mutator/node/define.rb +0 -11
  49. data/lib/mutant/mutator/node/defined.rb +0 -3
  50. data/lib/mutant/mutator/node/dstr.rb +0 -3
  51. data/lib/mutant/mutator/node/dsym.rb +0 -3
  52. data/lib/mutant/mutator/node/generic.rb +0 -3
  53. data/lib/mutant/mutator/node/if.rb +0 -12
  54. data/lib/mutant/mutator/node/index.rb +0 -27
  55. data/lib/mutant/mutator/node/kwbegin.rb +0 -3
  56. data/lib/mutant/mutator/node/literal.rb +0 -3
  57. data/lib/mutant/mutator/node/literal/array.rb +0 -6
  58. data/lib/mutant/mutator/node/literal/boolean.rb +0 -4
  59. data/lib/mutant/mutator/node/literal/float.rb +0 -9
  60. data/lib/mutant/mutator/node/literal/hash.rb +0 -9
  61. data/lib/mutant/mutator/node/literal/integer.rb +0 -9
  62. data/lib/mutant/mutator/node/literal/nil.rb +0 -3
  63. data/lib/mutant/mutator/node/literal/range.rb +0 -6
  64. data/lib/mutant/mutator/node/literal/regex.rb +0 -6
  65. data/lib/mutant/mutator/node/literal/string.rb +0 -3
  66. data/lib/mutant/mutator/node/literal/symbol.rb +0 -3
  67. data/lib/mutant/mutator/node/masgn.rb +0 -3
  68. data/lib/mutant/mutator/node/match_current_line.rb +0 -3
  69. data/lib/mutant/mutator/node/mlhs.rb +0 -3
  70. data/lib/mutant/mutator/node/named_value/access.rb +2 -14
  71. data/lib/mutant/mutator/node/named_value/constant_assignment.rb +0 -9
  72. data/lib/mutant/mutator/node/named_value/variable_assignment.rb +0 -6
  73. data/lib/mutant/mutator/node/next.rb +0 -3
  74. data/lib/mutant/mutator/node/noop.rb +0 -3
  75. data/lib/mutant/mutator/node/nthref.rb +0 -3
  76. data/lib/mutant/mutator/node/op_asgn.rb +0 -3
  77. data/lib/mutant/mutator/node/or_asgn.rb +0 -3
  78. data/lib/mutant/mutator/node/procarg_zero.rb +0 -3
  79. data/lib/mutant/mutator/node/regopt.rb +0 -6
  80. data/lib/mutant/mutator/node/resbody.rb +0 -6
  81. data/lib/mutant/mutator/node/rescue.rb +2 -19
  82. data/lib/mutant/mutator/node/return.rb +0 -3
  83. data/lib/mutant/mutator/node/sclass.rb +20 -0
  84. data/lib/mutant/mutator/node/send.rb +2 -61
  85. data/lib/mutant/mutator/node/send/attribute_assignment.rb +0 -9
  86. data/lib/mutant/mutator/node/send/binary.rb +0 -11
  87. data/lib/mutant/mutator/node/send/conditional.rb +0 -3
  88. data/lib/mutant/mutator/node/splat.rb +0 -3
  89. data/lib/mutant/mutator/node/super.rb +0 -3
  90. data/lib/mutant/mutator/node/when.rb +0 -19
  91. data/lib/mutant/mutator/node/yield.rb +0 -3
  92. data/lib/mutant/mutator/node/zsuper.rb +0 -3
  93. data/lib/mutant/mutator/util/array.rb +0 -6
  94. data/lib/mutant/mutator/util/symbol.rb +0 -3
  95. data/lib/mutant/parallel.rb +0 -13
  96. data/lib/mutant/parallel/driver.rb +0 -10
  97. data/lib/mutant/parallel/worker.rb +0 -22
  98. data/lib/mutant/reporter/cli.rb +0 -5
  99. data/lib/mutant/reporter/cli/format.rb +0 -9
  100. data/lib/mutant/reporter/cli/printer.rb +0 -40
  101. data/lib/mutant/reporter/cli/printer/env_progress.rb +0 -15
  102. data/lib/mutant/reporter/cli/printer/isolation_result.rb +0 -18
  103. data/lib/mutant/reporter/cli/printer/mutation_progress_result.rb +0 -5
  104. data/lib/mutant/reporter/cli/printer/mutation_result.rb +0 -21
  105. data/lib/mutant/reporter/cli/printer/status_progressive.rb +0 -8
  106. data/lib/mutant/reporter/cli/printer/subject_progress.rb +0 -9
  107. data/lib/mutant/repository/diff.rb +1 -13
  108. data/lib/mutant/repository/diff/ranges.rb +0 -11
  109. data/lib/mutant/result.rb +0 -3
  110. data/lib/mutant/runner.rb +0 -18
  111. data/lib/mutant/runner/sink.rb +0 -5
  112. data/lib/mutant/subject.rb +0 -8
  113. data/lib/mutant/subject/method.rb +0 -3
  114. data/lib/mutant/subject/method/instance.rb +0 -5
  115. data/lib/mutant/subject/method/metaclass.rb +30 -0
  116. data/lib/mutant/transform.rb +0 -92
  117. data/lib/mutant/version.rb +1 -1
  118. data/lib/mutant/warnings.rb +0 -6
  119. data/lib/mutant/zombifier.rb +2 -34
  120. data/meta/and.rb +0 -2
  121. data/meta/array.rb +0 -3
  122. data/meta/begin.rb +0 -3
  123. data/meta/block.rb +0 -3
  124. data/meta/break.rb +0 -1
  125. data/meta/case.rb +0 -6
  126. data/meta/casgn.rb +0 -3
  127. data/meta/cvasgn.rb +0 -1
  128. data/meta/def.rb +0 -7
  129. data/meta/ensure.rb +0 -1
  130. data/meta/false.rb +0 -1
  131. data/meta/gvasgn.rb +0 -1
  132. data/meta/hash.rb +0 -4
  133. data/meta/if.rb +0 -5
  134. data/meta/ivasgn.rb +0 -1
  135. data/meta/kwbegin.rb +0 -1
  136. data/meta/lvasgn.rb +0 -1
  137. data/meta/match_current_line.rb +0 -1
  138. data/meta/next.rb +0 -1
  139. data/meta/or.rb +0 -2
  140. data/meta/regexp.rb +0 -1
  141. data/meta/rescue.rb +0 -6
  142. data/meta/sclass.rb +12 -0
  143. data/meta/send.rb +0 -4
  144. data/meta/true.rb +0 -1
  145. data/meta/until.rb +0 -1
  146. data/meta/while.rb +0 -2
  147. data/meta/yield.rb +0 -1
  148. data/mutant.sh +12 -0
  149. data/spec/unit/mutant/ast/find_metaclass_containing_spec.rb +64 -0
  150. data/spec/unit/mutant/expression/methods_spec.rb +7 -2
  151. data/spec/unit/mutant/license_spec.rb +15 -3
  152. data/spec/unit/mutant/matcher/method/metaclass_spec.rb +108 -0
  153. data/spec/unit/mutant/matcher/methods/metaclass_spec.rb +62 -0
  154. data/spec/unit/mutant/matcher/namespace_spec.rb +3 -1
  155. data/spec/unit/mutant/matcher/scope_spec.rb +11 -1
  156. data/spec/unit/mutant/meta/example_spec.rb +3 -3
  157. data/spec/unit/mutant/mutator/node_spec.rb +1 -6
  158. data/spec/unit/mutant/subject/method/metaclass_spec.rb +63 -0
  159. data/test_app/lib/test_app.rb +1 -0
  160. data/test_app/lib/test_app/metaclasses.rb +108 -0
  161. metadata +17 -2
@@ -34,21 +34,9 @@ module Mutant
34
34
 
35
35
  private
36
36
 
37
- # Node to mutate
38
- #
39
- # @return [Parser::AST::Node]
40
- alias_method :node, :input
41
-
42
- # Duplicate of original
43
- #
44
- # @return [Parser::AST::Node]
37
+ alias_method :node, :input
45
38
  alias_method :dup_node, :dup_input
46
39
 
47
- # Dispatch on child index
48
- #
49
- # @param [Integer] index
50
- #
51
- # @return [undefined]
52
40
  def mutate_child(index, &block)
53
41
  block ||= TAUTOLOGY
54
42
  Mutator.mutate(children.fetch(index), self).each do |mutation|
@@ -57,108 +45,55 @@ module Mutant
57
45
  end
58
46
  end
59
47
 
60
- # Emit delete child mutation
61
- #
62
- # @param [Integer] index
63
- #
64
- # @return [undefined]
65
48
  def delete_child(index)
66
49
  dup_children = children.dup
67
50
  dup_children.delete_at(index)
68
51
  emit_type(*dup_children)
69
52
  end
70
53
 
71
- # Emit updated child
72
- #
73
- # @param [Integer] index
74
- # @param [Parser::AST::Node] node
75
- #
76
- # @return [undefined]
77
54
  def emit_child_update(index, node)
78
55
  new_children = children.dup
79
56
  new_children[index] = node
80
57
  emit_type(*new_children)
81
58
  end
82
59
 
83
- # Emit a new AST node with same class as wrapped node
84
- #
85
- # @param [Array<Parser::AST::Node>] children
86
- #
87
- # @return [undefined]
88
60
  def emit_type(*children)
89
61
  emit(::Parser::AST::Node.new(node.type, children))
90
62
  end
91
63
 
92
- # Emit propagation if node can stand alone
93
- #
94
- # @return [undefined]
95
64
  def emit_propagation(node)
96
65
  emit(node) unless AST::Types::NOT_STANDALONE.include?(node.type)
97
66
  end
98
67
 
99
- # Emit singleton literals
100
- #
101
- # @return [undefined]
102
68
  def emit_singletons
103
69
  emit_nil
104
70
  emit_self
105
71
  end
106
72
 
107
- # Emit a literal self
108
- #
109
- # @return [undefined]
110
73
  def emit_self
111
74
  emit(N_SELF)
112
75
  end
113
76
 
114
- # Emit a literal nil
115
- #
116
- # @return [undefined]
117
77
  def emit_nil
118
78
  emit(N_NIL) unless left_assignment?
119
79
  end
120
80
 
121
- # Parent node
122
- #
123
- # @return [Parser::AST::Node] node
124
- # if parent with node is present
125
- #
126
- # @return [nil]
127
- # otherwise
128
81
  def parent_node
129
82
  parent&.node
130
83
  end
131
84
 
132
- # Parent type
133
- #
134
- # @return [Symbol] type
135
- # if parent with type is present
136
- #
137
- # @return [nil]
138
- # otherwise
139
85
  def parent_type
140
86
  parent_node&.type
141
87
  end
142
88
 
143
- # Test if the node is the left of an or_asgn or op_asgn
144
- #
145
- # @return [Boolean]
146
89
  def left_assignment?
147
90
  AST::Types::OP_ASSIGN.include?(parent_type) && parent.node.children.first.equal?(node)
148
91
  end
149
92
 
150
- # Children indices
151
- #
152
- # @param [Range] range
153
- #
154
- # @return [Enumerable<Integer>]
155
93
  def children_indices(range)
156
94
  range.begin.upto(children.length + range.end)
157
95
  end
158
96
 
159
- # Emit single child mutation
160
- #
161
- # @return [undefined]
162
97
  def mutate_single_child
163
98
  children.each_with_index do |child, index|
164
99
  mutate_child(index)
@@ -13,9 +13,6 @@ module Mutant
13
13
 
14
14
  private
15
15
 
16
- # Emit mutations
17
- #
18
- # @return [undefined]
19
16
  def dispatch
20
17
  emit_singletons
21
18
  emit_left_mutations do |node|
@@ -14,24 +14,15 @@ module Mutant
14
14
 
15
15
  private
16
16
 
17
- # Emit mutations
18
- #
19
- # @return [undefined]
20
17
  def dispatch
21
18
  emit_name_mutation
22
19
  end
23
20
 
24
- # Emit name mutations
25
- #
26
- # @return [undefined]
27
21
  def emit_name_mutation
28
22
  return if skip?
29
23
  emit_name(:"#{UNDERSCORE}#{name}")
30
24
  end
31
25
 
32
- # Test if argument mutation is skipped
33
- #
34
- # @return [Boolean]
35
26
  def skip?
36
27
  name.to_s.start_with?(UNDERSCORE)
37
28
  end
@@ -50,18 +41,12 @@ module Mutant
50
41
 
51
42
  private
52
43
 
53
- # Emit mutations
54
- #
55
- # @return [undefined]
56
44
  def dispatch
57
45
  emit_name_mutation
58
46
  emit_required_mutation
59
47
  emit_default_mutations
60
48
  end
61
49
 
62
- # Emit required mutation
63
- #
64
- # @return [undefined]
65
50
  def emit_required_mutation
66
51
  emit(s(TYPE_MAP.fetch(node.type), name))
67
52
  end
@@ -12,18 +12,12 @@ module Mutant
12
12
 
13
13
  private
14
14
 
15
- # Emit mutations
16
- #
17
- # @return [undefined]
18
15
  def dispatch
19
16
  emit_argument_presence
20
17
  emit_argument_mutations
21
18
  emit_mlhs_expansion
22
19
  end
23
20
 
24
- # Emit argument presence mutation
25
- #
26
- # @return [undefined]
27
21
  def emit_argument_presence
28
22
  emit_type
29
23
 
@@ -34,9 +28,6 @@ module Mutant
34
28
  end
35
29
  end
36
30
 
37
- # Emit argument mutations
38
- #
39
- # @return [undefined]
40
31
  def emit_argument_mutations
41
32
  children.each_with_index do |child, index|
42
33
  Mutator.mutate(child).each do |mutant|
@@ -46,18 +37,10 @@ module Mutant
46
37
  end
47
38
  end
48
39
 
49
- # Test if child mutation is allowed
50
- #
51
- # @param [Parser::AST::Node]
52
- #
53
- # @return [Boolean]
54
40
  def invalid_argument_replacement?(mutant, index)
55
41
  n_arg?(mutant) && children[0...index].any?(&method(:n_optarg?))
56
42
  end
57
43
 
58
- # Emit mlhs expansions
59
- #
60
- # @return [undefined]
61
44
  def emit_mlhs_expansion
62
45
  mlhs_childs_with_index.each do |child, index|
63
46
  dup_children = children.dup
@@ -67,9 +50,6 @@ module Mutant
67
50
  end
68
51
  end
69
52
 
70
- # Multiple left hand side childs
71
- #
72
- # @return [Enumerable<Parser::AST::Node, Integer>]
73
53
  def mlhs_childs_with_index
74
54
  children.each_with_index.select do |child,|
75
55
  n_mlhs?(child)
@@ -11,9 +11,6 @@ module Mutant
11
11
 
12
12
  private
13
13
 
14
- # Emit mutations
15
- #
16
- # @return [undefined]
17
14
  def dispatch
18
15
  mutate_single_child do |child|
19
16
  emit(child)
@@ -17,9 +17,6 @@ module Mutant
17
17
 
18
18
  private
19
19
 
20
- # Emit mutations
21
- #
22
- # @return [undefined]
23
20
  def dispatch
24
21
  emit_singletons
25
22
  emit_promotions
@@ -29,35 +26,15 @@ module Mutant
29
26
  emit_right_mutations
30
27
  end
31
28
 
32
- # Emit operator mutations
33
- #
34
- # @return [undefined]
35
29
  def emit_operator_mutations
36
30
  emit(s(INVERSE.fetch(node.type), left, right))
37
31
  end
38
32
 
39
- # Emit promotions
40
- #
41
- # @return [undefined]
42
33
  def emit_promotions
43
34
  emit(left)
44
35
  emit(right)
45
36
  end
46
37
 
47
- # Emit left negation
48
- #
49
- # We do not emit right negation as the `and` and `or` nodes
50
- # in ruby are also used for control flow.
51
- #
52
- # Irrespective of their syntax, aka `||` parses internally to `or`.
53
- #
54
- # `do_a or do_b`. Negating left makes sense, negating right
55
- # only when the result is actually used.
56
- #
57
- # It *would* be possible to emit the right negation in case the use of the result is proved.
58
- # Like parent is an assignment to an {l,i}var. Dunno if we ever get the time to do that.
59
- #
60
- # @return [undefined]
61
38
  def emit_left_negation
62
39
  emit(s(node.type, n_not(left), right))
63
40
  end
@@ -11,9 +11,6 @@ module Mutant
11
11
 
12
12
  private
13
13
 
14
- # Emit mutations
15
- #
16
- # @return [undefined]
17
14
  def dispatch
18
15
  emit_singletons
19
16
  emit(send) unless n_lambda?(send)
@@ -23,9 +20,6 @@ module Mutant
23
20
  mutate_body
24
21
  end
25
22
 
26
- # Emit body mutations
27
- #
28
- # @return [undefined]
29
23
  def mutate_body
30
24
  emit_body(nil)
31
25
  emit_body(N_RAISE)
@@ -37,18 +31,12 @@ module Mutant
37
31
  mutate_body_receiver
38
32
  end
39
33
 
40
- # Test if body has control structures
41
- #
42
- # @return [Boolean]
43
34
  def body_has_control?
44
35
  AST.find_last_path(body) do |node|
45
36
  n_break?(node) || n_next?(node)
46
37
  end.any?
47
38
  end
48
39
 
49
- # Mutate method send in body scope of `send`
50
- #
51
- # @return [undefined]
52
40
  def mutate_body_receiver
53
41
  return if n_lambda?(send) || !n_send?(body)
54
42
 
@@ -57,9 +45,6 @@ module Mutant
57
45
  emit(s(:send, send, body_meta.selector, *body_meta.arguments))
58
46
  end
59
47
 
60
- # Test for valid send mutations
61
- #
62
- # @return [true, false, nil]
63
48
  def valid_send_mutation?(node)
64
49
  return unless n_send?(node)
65
50
 
@@ -11,9 +11,6 @@ module Mutant
11
11
 
12
12
  private
13
13
 
14
- # Emit mutations
15
- #
16
- # @return [undefined]
17
14
  def dispatch
18
15
  super()
19
16
  emit_singletons
@@ -13,9 +13,6 @@ module Mutant
13
13
 
14
14
  private
15
15
 
16
- # Emit mutations
17
- #
18
- # @return [undefined]
19
16
  def dispatch
20
17
  emit_singletons
21
18
  emit_condition_mutations if condition
@@ -23,9 +20,6 @@ module Mutant
23
20
  emit_else_mutations
24
21
  end
25
22
 
26
- # Emit when mutations
27
- #
28
- # @return [undefined]
29
23
  def emit_when_mutations
30
24
  indices = children.each_index.drop(1).take(children.length - 2)
31
25
  one = indices.one?
@@ -35,9 +29,6 @@ module Mutant
35
29
  end
36
30
  end
37
31
 
38
- # Emit else mutations
39
- #
40
- # @return [undefined]
41
32
  def emit_else_mutations
42
33
  else_branch = children.last
43
34
  else_index = children.length - 1
@@ -11,9 +11,6 @@ module Mutant
11
11
 
12
12
  private
13
13
 
14
- # Emit mutations only for class body
15
- #
16
- # @return [undefined]
17
14
  def dispatch
18
15
  emit_body_mutations if body
19
16
  end
@@ -13,9 +13,6 @@ module Mutant
13
13
 
14
14
  private
15
15
 
16
- # Emit mutations
17
- #
18
- # @return [undefined]
19
16
  def dispatch
20
17
  emit_singletons
21
18
  emit_condition_mutations
@@ -11,9 +11,6 @@ module Mutant
11
11
 
12
12
  private
13
13
 
14
- # Emit mutations
15
- #
16
- # @return [undefined]
17
14
  def dispatch
18
15
  emit_singletons unless parent_node && n_const?(parent_node)
19
16
  emit_type(nil, *children.drop(1))
@@ -8,9 +8,6 @@ module Mutant
8
8
 
9
9
  private
10
10
 
11
- # Emit mutations
12
- #
13
- # @return [undefined]
14
11
  def dispatch
15
12
  emit_arguments_mutations
16
13
  emit_optarg_body_assignments
@@ -20,9 +17,6 @@ module Mutant
20
17
  emit_body_mutations if body
21
18
  end
22
19
 
23
- # Emit mutations with optional arguments as assignments in method
24
- #
25
- # @return [undefined]
26
20
  def emit_optarg_body_assignments
27
21
  arguments.children.each do |argument|
28
22
  next unless n_optarg?(argument) && AST::Meta::Optarg.new(argument).used?
@@ -31,11 +25,6 @@ module Mutant
31
25
  end
32
26
  end
33
27
 
34
- # Emit valid body ASTs depending on instance body
35
- #
36
- # @param node [Parser::AST::Node]
37
- #
38
- # @return [undefined]
39
28
  def emit_body_prepend(node)
40
29
  if body
41
30
  emit_body(s(:begin, node, body))