mutant 0.2.20 → 0.3.0.beta2

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 (201) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +10 -11
  3. data/Changelog.md +93 -38
  4. data/Gemfile +3 -1
  5. data/Gemfile.devtools +16 -20
  6. data/Guardfile +1 -1
  7. data/README.md +36 -16
  8. data/Rakefile +21 -2
  9. data/TODO +11 -7
  10. data/bin/mutant +4 -0
  11. data/bin/zombie +4 -0
  12. data/config/devtools.yml +2 -0
  13. data/config/flay.yml +2 -2
  14. data/config/flog.yml +1 -1
  15. data/config/{site.reek → reek.yml} +94 -70
  16. data/lib/mutant/cli/classifier/method.rb +100 -0
  17. data/lib/mutant/cli/classifier/namespace.rb +47 -0
  18. data/lib/mutant/cli/classifier/scope.rb +35 -0
  19. data/lib/mutant/cli/classifier.rb +141 -0
  20. data/lib/mutant/cli.rb +115 -162
  21. data/lib/mutant/color.rb +2 -2
  22. data/lib/mutant/config.rb +27 -0
  23. data/lib/mutant/constants.rb +32 -17
  24. data/lib/mutant/context/scope.rb +33 -51
  25. data/lib/mutant/context.rb +8 -19
  26. data/lib/mutant/differ.rb +5 -5
  27. data/lib/mutant/helper.rb +2 -17
  28. data/lib/mutant/killer/forked.rb +44 -0
  29. data/lib/mutant/killer/forking.rb +3 -57
  30. data/lib/mutant/killer/rspec.rb +16 -20
  31. data/lib/mutant/killer/static.rb +6 -7
  32. data/lib/mutant/killer.rb +48 -74
  33. data/lib/mutant/loader.rb +6 -6
  34. data/lib/mutant/matcher/chain.rb +4 -25
  35. data/lib/mutant/matcher/method/instance.rb +14 -24
  36. data/lib/mutant/matcher/method/singleton.rb +35 -46
  37. data/lib/mutant/matcher/method.rb +95 -83
  38. data/lib/mutant/matcher/{scope_methods.rb → methods.rb} +53 -76
  39. data/lib/mutant/matcher/namespace.rb +71 -0
  40. data/lib/mutant/matcher/scope.rb +34 -0
  41. data/lib/mutant/matcher.rb +24 -34
  42. data/lib/mutant/mutation/evil.rb +35 -0
  43. data/lib/mutant/mutation/filter/code.rb +7 -28
  44. data/lib/mutant/mutation/filter/regexp.rb +6 -18
  45. data/lib/mutant/mutation/filter/whitelist.rb +5 -4
  46. data/lib/mutant/mutation/filter.rb +10 -9
  47. data/lib/mutant/mutation/neutral.rb +35 -0
  48. data/lib/mutant/mutation.rb +21 -61
  49. data/lib/mutant/mutator/node/argument.rb +88 -0
  50. data/lib/mutant/mutator/node/arguments.rb +52 -0
  51. data/lib/mutant/mutator/node/assignment.rb +34 -38
  52. data/lib/mutant/mutator/node/begin.rb +33 -0
  53. data/lib/mutant/mutator/node/block.rb +14 -14
  54. data/lib/mutant/mutator/node/case.rb +59 -0
  55. data/lib/mutant/mutator/node/define.rb +26 -22
  56. data/lib/mutant/mutator/node/if.rb +31 -71
  57. data/lib/mutant/mutator/node/literal/array.rb +25 -9
  58. data/lib/mutant/mutator/node/literal/boolean.rb +13 -30
  59. data/lib/mutant/mutator/node/literal/dynamic.rb +6 -5
  60. data/lib/mutant/mutator/node/literal/fixnum.rb +18 -7
  61. data/lib/mutant/mutator/node/literal/float.rb +15 -8
  62. data/lib/mutant/mutator/node/literal/hash.rb +33 -52
  63. data/lib/mutant/mutator/node/literal/nil.rb +8 -7
  64. data/lib/mutant/mutator/node/literal/range.rb +25 -50
  65. data/lib/mutant/mutator/node/literal/regex.rb +15 -23
  66. data/lib/mutant/mutator/node/literal/string.rb +7 -6
  67. data/lib/mutant/mutator/node/literal/symbol.rb +7 -6
  68. data/lib/mutant/mutator/node/literal.rb +4 -46
  69. data/lib/mutant/mutator/node/mlhs.rb +27 -0
  70. data/lib/mutant/mutator/node/noop.rb +18 -43
  71. data/lib/mutant/mutator/node/return.rb +8 -8
  72. data/lib/mutant/mutator/node/send/binary.rb +31 -0
  73. data/lib/mutant/mutator/node/send.rb +106 -72
  74. data/lib/mutant/mutator/node/super.rb +15 -20
  75. data/lib/mutant/mutator/node/when.rb +32 -7
  76. data/lib/mutant/mutator/node/while.rb +9 -7
  77. data/lib/mutant/mutator/node.rb +116 -66
  78. data/lib/mutant/mutator/registry.rb +14 -11
  79. data/lib/mutant/mutator/util/array.rb +9 -9
  80. data/lib/mutant/mutator/util/symbol.rb +6 -20
  81. data/lib/mutant/mutator/util.rb +6 -3
  82. data/lib/mutant/mutator.rb +12 -28
  83. data/lib/mutant/node_helpers.rb +28 -0
  84. data/lib/mutant/random.rb +3 -2
  85. data/lib/mutant/reporter/cli/printer/config.rb +174 -0
  86. data/lib/mutant/reporter/cli/printer/killer.rb +42 -0
  87. data/lib/mutant/reporter/cli/printer/mutation.rb +55 -0
  88. data/lib/mutant/reporter/cli/printer/subject.rb +147 -0
  89. data/lib/mutant/reporter/cli/printer.rb +165 -0
  90. data/lib/mutant/reporter/cli.rb +9 -277
  91. data/lib/mutant/reporter/null.rb +6 -30
  92. data/lib/mutant/reporter.rb +6 -73
  93. data/lib/mutant/runner/config.rb +82 -0
  94. data/lib/mutant/runner/mutation.rb +58 -0
  95. data/lib/mutant/runner/subject.rb +81 -0
  96. data/lib/mutant/runner.rb +42 -92
  97. data/lib/mutant/singleton_methods.rb +2 -2
  98. data/lib/mutant/strategy/method_expansion.rb +51 -0
  99. data/lib/mutant/strategy/rspec/dm2/lookup/method.rb +142 -0
  100. data/lib/mutant/strategy/rspec/dm2/lookup.rb +61 -0
  101. data/lib/mutant/strategy/rspec/dm2.rb +22 -0
  102. data/lib/mutant/strategy/rspec.rb +20 -22
  103. data/lib/mutant/strategy/static.rb +18 -0
  104. data/lib/mutant/strategy.rb +15 -50
  105. data/lib/mutant/subject/method.rb +100 -0
  106. data/lib/mutant/subject.rb +18 -49
  107. data/lib/mutant/support/method_object.rb +4 -2
  108. data/lib/mutant.rb +40 -35
  109. data/mutant.gemspec +9 -8
  110. data/spec/integration/mutant/rspec_killer_spec.rb +3 -3
  111. data/spec/integration/mutant/test_mutator_handles_types_spec.rb +9 -0
  112. data/spec/integration/mutant/zombie_spec.rb +1 -1
  113. data/spec/shared/method_matcher_behavior.rb +35 -0
  114. data/spec/shared/mutator_behavior.rb +63 -32
  115. data/spec/spec_helper.rb +13 -3
  116. data/spec/support/ice_nine_config.rb +8 -0
  117. data/spec/support/rspec.rb +1 -1
  118. data/spec/support/zombie.rb +1 -1
  119. data/spec/unit/mutant/cli/class_methods/new_spec.rb +42 -28
  120. data/spec/unit/mutant/cli/class_methods/run_spec.rb +15 -13
  121. data/spec/unit/mutant/cli/classifier/class_methods/build_spec.rb +44 -0
  122. data/spec/unit/mutant/context/scope/root_spec.rb +4 -4
  123. data/spec/unit/mutant/killer/rspec/class_methods/new_spec.rb +6 -5
  124. data/spec/unit/mutant/killer/success_predicate_spec.rb +28 -0
  125. data/spec/unit/mutant/loader/eval/class_methods/run_spec.rb +1 -1
  126. data/spec/unit/mutant/matcher/chain/each_spec.rb +1 -1
  127. data/spec/unit/mutant/matcher/chain/matchers_spec.rb +1 -1
  128. data/spec/unit/mutant/matcher/method/instance/each_spec.rb +112 -0
  129. data/spec/unit/mutant/matcher/method/singleton/each_spec.rb +93 -0
  130. data/spec/unit/mutant/matcher/methods/instance/each_spec.rb +59 -0
  131. data/spec/unit/mutant/matcher/methods/singleton/each_spec.rb +53 -0
  132. data/spec/unit/mutant/matcher/namespace/each_spec.rb +37 -0
  133. data/spec/unit/mutant/mutator/node/begin/mutation_spec.rb +33 -0
  134. data/spec/unit/mutant/mutator/node/block/mutation_spec.rb +42 -14
  135. data/spec/unit/mutant/mutator/node/case/mutation_spec.rb +319 -0
  136. data/spec/unit/mutant/mutator/node/define/mutation_spec.rb +31 -27
  137. data/spec/unit/mutant/mutator/node/if/mutation_spec.rb +75 -0
  138. data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +1 -1
  139. data/spec/unit/mutant/mutator/node/literal/hash_spec.rb +2 -2
  140. data/spec/unit/mutant/mutator/node/literal/nil_spec.rb +1 -3
  141. data/spec/unit/mutant/mutator/node/literal/regex_spec.rb +1 -9
  142. data/spec/unit/mutant/mutator/node/return/mutation_spec.rb +6 -2
  143. data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +111 -108
  144. data/spec/unit/mutant/mutator/node/super/mutation_spec.rb +0 -33
  145. data/spec/unit/mutant/mutator/node/while/mutation_spec.rb +2 -2
  146. data/spec/unit/mutant/runner/config/subjects_spec.rb +38 -0
  147. data/spec/unit/mutant/runner/config/success_predicate_spec.rb +53 -0
  148. data/spec/unit/mutant/runner/failed_predicte_spec.rb +33 -0
  149. data/spec/unit/mutant/runner/mutation/killer_spec.rb +39 -0
  150. data/spec/unit/mutant/runner/subject/success_predicate_spec.rb +49 -0
  151. data/spec/unit/mutant/strategy/method_expansion/class_methods/run_spec.rb +49 -0
  152. data/spec/unit/mutant/strategy/rspec/dm2/lookup/method/instance/spec_files_spec.rb +52 -0
  153. data/spec/unit/mutant/strategy/rspec/dm2/lookup/method/singleton/spec_files_spec.rb +42 -0
  154. data/spec/unit/mutant/subject/context_spec.rb +6 -3
  155. data/spec/unit/mutant/subject/each_spec.rb +11 -8
  156. data/spec/unit/mutant/subject/node_spec.rb +6 -2
  157. data/test_app/spec/shared/method_filter_parse_behavior.rb +0 -2
  158. data/test_app/spec/shared/method_match_behavior.rb +1 -1
  159. data/test_app/spec/spec_helper.rb +4 -2
  160. metadata +101 -109
  161. data/config/roodi.yml +0 -26
  162. data/lib/mutant/matcher/method/classifier.rb +0 -141
  163. data/lib/mutant/matcher/object_space.rb +0 -114
  164. data/lib/mutant/mutator/node/actual_arguments.rb +0 -25
  165. data/lib/mutant/mutator/node/default_arguments.rb +0 -25
  166. data/lib/mutant/mutator/node/formal_arguments_19/default_mutations.rb +0 -33
  167. data/lib/mutant/mutator/node/formal_arguments_19/pattern_argument_expansion.rb +0 -35
  168. data/lib/mutant/mutator/node/formal_arguments_19/require_defaults.rb +0 -37
  169. data/lib/mutant/mutator/node/formal_arguments_19.rb +0 -41
  170. data/lib/mutant/mutator/node/iter_19.rb +0 -27
  171. data/lib/mutant/mutator/node/literal/empty_array.rb +0 -26
  172. data/lib/mutant/mutator/node/pattern_arguments.rb +0 -41
  173. data/lib/mutant/mutator/node/pattern_variable.rb +0 -23
  174. data/lib/mutant/mutator/node/receiver_case.rb +0 -122
  175. data/lib/mutant/mutator/node/send/binary_operator_method.rb +0 -61
  176. data/lib/mutant/mutator/node/send/with_arguments.rb +0 -81
  177. data/lib/mutant/reporter/stats.rb +0 -120
  178. data/lib/mutant/strategy/rspec/example_lookup.rb +0 -163
  179. data/spec/integration/mutant/method_matching_spec.rb +0 -269
  180. data/spec/shared/method_match_behavior.rb +0 -39
  181. data/spec/unit/mutant/killer/fail_ques_spec.rb +0 -39
  182. data/spec/unit/mutant/matcher/class_methods/from_string_spec.rb +0 -49
  183. data/spec/unit/mutant/matcher/class_methods/parse_spec.rb +0 -12
  184. data/spec/unit/mutant/matcher/method/class_methods/parse_spec.rb +0 -21
  185. data/spec/unit/mutant/matcher/method/classifier/class_methods/run_spec.rb +0 -52
  186. data/spec/unit/mutant/matcher/object_space/class_methods/parse_spec.rb +0 -24
  187. data/spec/unit/mutant/matcher/object_space/each_spec.rb +0 -31
  188. data/spec/unit/mutant/mutator/node/if_statement/mutation_spec.rb +0 -60
  189. data/spec/unit/mutant/mutator/node/receiver_case/mutation_spec.rb +0 -27
  190. data/spec/unit/mutant/strategy/rspec/example_lookup/spec_file_spec.rb +0 -236
  191. data/spec/unit/mutant/subject/class_methods/new_spec.rb +0 -13
  192. data/tasks/metrics/ci.rake +0 -7
  193. data/tasks/metrics/flay.rake +0 -41
  194. data/tasks/metrics/flog.rake +0 -43
  195. data/tasks/metrics/heckle.rake +0 -216
  196. data/tasks/metrics/metric_fu.rake +0 -31
  197. data/tasks/metrics/reek.rake +0 -15
  198. data/tasks/metrics/roodi.rake +0 -15
  199. data/tasks/metrics/yardstick.rake +0 -23
  200. data/tasks/spec.rake +0 -45
  201. data/tasks/yard.rake +0 -9
@@ -2,10 +2,20 @@ module Mutant
2
2
  class Mutator
3
3
  class Node
4
4
  class Literal
5
+
5
6
  # Abstract literal range mutator
6
7
  class Range < self
7
8
  include AbstractType
8
9
 
10
+ MAP = {
11
+ :irange => :erange,
12
+ :erange => :irange
13
+ }.freeze
14
+
15
+ children :start, :_end
16
+
17
+ handle(*MAP.keys)
18
+
9
19
  private
10
20
 
11
21
  # Emit mutants
@@ -16,30 +26,19 @@ module Mutant
16
26
  #
17
27
  def dispatch
18
28
  emit_nil
19
- emit(inverse)
20
- emit_range
29
+ emit_inverse
30
+ emit_start_mutations
31
+ emit_end_mutations
21
32
  end
22
33
 
23
34
  # Return inverse node
24
35
  #
25
- # @return [Rubinius::AST::Node]
36
+ # @return [Parser::AST::Node]
26
37
  #
27
38
  # @api private
28
39
  #
29
- def inverse
30
- node = self.node
31
- new(inverse_class, node.start, node.finish)
32
- end
33
-
34
- # Emit range specific mutants
35
- #
36
- # @return [undefined]
37
- #
38
- # @api private
39
- #
40
- def emit_range
41
- emit_finish_mutations
42
- emit_start_mutations
40
+ def emit_inverse
41
+ emit(s(MAP.fetch(node.type), *children))
43
42
  end
44
43
 
45
44
  # Emit range start mutations
@@ -48,10 +47,9 @@ module Mutant
48
47
  #
49
48
  # @api private
50
49
  #
51
- def emit_finish_mutations
52
- finish = node.finish
50
+ def emit_end_mutations
53
51
  #emit_self(negative_infinity, finish)
54
- emit_self(nan, finish)
52
+ emit_self(NAN, _end)
55
53
  end
56
54
 
57
55
  # Emit start mutations
@@ -61,35 +59,12 @@ module Mutant
61
59
  # @api private
62
60
  #
63
61
  def emit_start_mutations
64
- start = node.start
65
- emit_self(start, infinity)
66
- emit_self(start, nan)
62
+ emit_self(start, INFINITY)
63
+ emit_self(start, NAN)
67
64
  end
68
65
 
69
- # Return inverse AST node class
70
- #
71
- # @return [Class:Rubinius::AST::Node]
72
- #
73
- # @api private
74
- #
75
- def inverse_class
76
- self.class::INVERSE_CLASS
77
- end
78
-
79
- # Mutator for range exclude literals
80
- class Exclude < self
81
- INVERSE_CLASS = Rubinius::AST::Range
82
- handle(Rubinius::AST::RangeExclude)
83
-
84
- end
85
-
86
- # Mutator for range include literals
87
- class Include < self
88
- INVERSE_CLASS = Rubinius::AST::RangeExclude
89
- handle(Rubinius::AST::Range)
90
- end
91
- end
92
- end
93
- end
94
- end
95
- end
66
+ end # Range
67
+ end # Literal
68
+ end # Node
69
+ end # Mutator
70
+ end # Mutant
@@ -5,7 +5,14 @@ module Mutant
5
5
  # Mutator for regexp literals
6
6
  class Regex < self
7
7
 
8
- handle(Rubinius::AST::RegexLiteral)
8
+ handle(:regexp)
9
+
10
+ EMPTY_STRING = ''.freeze
11
+
12
+ # No input can ever be matched with this
13
+ NULL_REGEXP_SOURCE = 'a\A'.freeze
14
+
15
+ children :source, :options
9
16
 
10
17
  private
11
18
 
@@ -17,27 +24,12 @@ module Mutant
17
24
  #
18
25
  def dispatch
19
26
  emit_nil
20
- emit_self('') # match all
21
- emit_self('a\A') # match nothing
22
- emit_new { new_self(Random.hex_string) }
27
+ emit_self(s(:str, EMPTY_STRING), options)
28
+ emit_self(s(:str, NULL_REGEXP_SOURCE), options)
23
29
  end
24
30
 
25
- # Return new Rubinius::AST::Regex
26
- #
27
- # @param [String] source
28
- #
29
- # @param [Integer] options
30
- # options of regexp, defaults to mutation subject node options
31
- #
32
- # @return [undefined]
33
- #
34
- # @api private
35
- #
36
- def new_self(source,options=nil)
37
- super(source,options || node.options)
38
- end
39
- end
40
- end
41
- end
42
- end
43
- end
31
+ end # Regex
32
+ end # Literal
33
+ end # Node
34
+ end # Mutator
35
+ end # Mutant
@@ -5,7 +5,7 @@ module Mutant
5
5
  # Mutator for string literals
6
6
  class String < self
7
7
 
8
- handle(Rubinius::AST::StringLiteral)
8
+ handle(:str)
9
9
 
10
10
  private
11
11
 
@@ -19,8 +19,9 @@ module Mutant
19
19
  emit_nil
20
20
  emit_new { new_self(Random.hex_string) }
21
21
  end
22
- end
23
- end
24
- end
25
- end
26
- end
22
+
23
+ end # String
24
+ end # Literal
25
+ end # Node
26
+ end # Mutator
27
+ end # Mutant
@@ -5,7 +5,7 @@ module Mutant
5
5
  # Mutator for symbol literals
6
6
  class Symbol < self
7
7
 
8
- handle(Rubinius::AST::SymbolLiteral)
8
+ handle(:sym)
9
9
 
10
10
  private
11
11
 
@@ -19,8 +19,9 @@ module Mutant
19
19
  emit_nil
20
20
  emit_new { new_self(('s'+Random.hex_string).to_sym) }
21
21
  end
22
- end
23
- end
24
- end
25
- end
26
- end
22
+
23
+ end # Symbol
24
+ end # Literal
25
+ end # Node
26
+ end # Mutator
27
+ end # Mutant
@@ -7,18 +7,6 @@ module Mutant
7
7
 
8
8
  private
9
9
 
10
- # Return new float literal
11
- #
12
- # @param [#to_f] value
13
- #
14
- # @return [Rubinius::Node::FloatLiteral]
15
- #
16
- # @api private
17
- #
18
- def new_float(value)
19
- new(Rubinius::AST::FloatLiteral, value)
20
- end
21
-
22
10
  # Emit a new node with wrapping class for each entry in values
23
11
  #
24
12
  # @param [Array] values
@@ -33,37 +21,7 @@ module Mutant
33
21
  end
34
22
  end
35
23
 
36
- # Return AST representing NaN
37
- #
38
- # @return [Rubinius::Node::AST]
39
- #
40
- # @api private
41
- #
42
- def nan
43
- zero_float = new_float(0)
44
- new_send_with_arguments(zero_float, :/, zero_float)
45
- end
46
-
47
- # Return AST representing negative infinity
48
- #
49
- # @return [Rubinius::Node::AST]
50
- #
51
- # @api private
52
- #
53
- def negative_infinity
54
- new_send_with_arguments(new_float(-1), :/, new_float(0))
55
- end
56
-
57
- # Return AST representing infinity
58
- #
59
- # @return [Rubinius::Node::AST]
60
- #
61
- # @api private
62
- #
63
- def infinity
64
- new_send_with_arguments(new_float(1), :/, new_float(0))
65
- end
66
- end
67
- end
68
- end
69
- end
24
+ end # Literal
25
+ end # Node
26
+ end # Mutator
27
+ end # Mutant
@@ -0,0 +1,27 @@
1
+ module Mutant
2
+ class Mutator
3
+ class Node
4
+ # Mutator for multiple assignment left hand side nodes
5
+ class MLHS < self
6
+
7
+ handle(:mlhs)
8
+
9
+ private
10
+
11
+ # Emit mutations
12
+ #
13
+ # @return [undefined]
14
+ #
15
+ # @api private
16
+ #
17
+ def dispatch
18
+ children.each_index do |index|
19
+ mutate_child(index)
20
+ delete_child(index)
21
+ end
22
+ end
23
+
24
+ end # MLHS
25
+ end # Node
26
+ end # Mutator
27
+ end # Mutant
@@ -5,45 +5,20 @@ module Mutant
5
5
  class Noop < self
6
6
 
7
7
  # Literal references to self do not need to be mutated?
8
- handle(Rubinius::AST::Self)
8
+ handle(:self)
9
+
10
+ # These nodes still need a mutator, your contribution is that close!
11
+ handle(
12
+ :zsuper, :not, :or, :and, :defined,
13
+ :next, :break, :match, :gvar, :cvar, :ensure,
14
+ :dstr, :dsym, :yield, :rescue, :redo, :defined?,
15
+ :lvar, :splat, :const, :blockarg, :block_pass, :op_asgn, :regopt,
16
+ :ivar, :restarg, :casgn, :masgn, :resbody, :retry, :arg_expr,
17
+ :kwrestarg, :kwoptarg, :kwarg, :undef, :module, :cbase, :empty,
18
+ :alias, :for, :xstr, :back_ref, :nth_ref, :class, :sclass, :match_with_lvasgn,
19
+ :match_current_line, :or_asgn
20
+ )
9
21
 
10
- # Currently unhandled node classes. Feel free to contribute your mutator!
11
- handle(Rubinius::AST::ZSuper)
12
- handle(Rubinius::AST::ElementAssignment)
13
- handle(Rubinius::AST::AttributeAssignment)
14
- handle(Rubinius::AST::Not)
15
- handle(Rubinius::AST::And)
16
- handle(Rubinius::AST::Or)
17
- handle(Rubinius::AST::Defined)
18
- handle(Rubinius::AST::Super)
19
- handle(Rubinius::AST::Next)
20
- handle(Rubinius::AST::Break)
21
- handle(Rubinius::AST::Match3)
22
- handle(Rubinius::AST::ZSuper)
23
- handle(Rubinius::AST::MultipleAssignment)
24
- handle(Rubinius::AST::ScopedConstant)
25
- handle(Rubinius::AST::LocalVariableAccess)
26
- handle(Rubinius::AST::InstanceVariableAccess)
27
- handle(Rubinius::AST::GlobalVariableAccess)
28
- handle(Rubinius::AST::ClassVariableAccess)
29
- handle(Rubinius::AST::ToplevelConstant)
30
- handle(Rubinius::AST::Ensure)
31
- handle(Rubinius::AST::Rescue)
32
- handle(Rubinius::AST::DynamicString)
33
- handle(Rubinius::AST::DynamicSymbol)
34
- handle(Rubinius::AST::DynamicRegex)
35
- handle(Rubinius::AST::File)
36
- handle(Rubinius::AST::NthRef)
37
- handle(Rubinius::AST::OpAssignOr19)
38
- handle(Rubinius::AST::BlockPass19)
39
- handle(Rubinius::AST::OpAssign1)
40
- handle(Rubinius::AST::OpAssign2)
41
- handle(Rubinius::AST::SplatValue)
42
- handle(Rubinius::AST::ConstantAccess)
43
- handle(Rubinius::AST::Yield)
44
- handle(Rubinius::AST::Begin)
45
- handle(Rubinius::AST::Rescue)
46
-
47
22
  private
48
23
 
49
24
  # Emit mutations
@@ -53,9 +28,9 @@ module Mutant
53
28
  # @api private
54
29
  #
55
30
  def dispatch
56
- # noop
57
31
  end
58
- end
59
- end
60
- end
61
- end
32
+
33
+ end # Noop
34
+ end # Node
35
+ end # Mutator
36
+ end # Mutant
@@ -4,10 +4,11 @@ module Mutant
4
4
  # Mutator for return statements
5
5
  class Return < self
6
6
 
7
- handle(Rubinius::AST::Return)
7
+ handle(:return)
8
8
 
9
- private
9
+ children :value
10
10
 
11
+ private
11
12
 
12
13
  # Emit mutants
13
14
  #
@@ -16,16 +17,15 @@ module Mutant
16
17
  # @api private
17
18
  #
18
19
  def dispatch
19
- value = node.value
20
20
  if value
21
21
  emit(value)
22
+ emit_value_mutations
22
23
  else
23
24
  emit_nil
24
25
  end
25
26
  end
26
27
 
27
- end
28
- end
29
- end
30
-
31
- end
28
+ end # Return
29
+ end # Node
30
+ end # Mutator
31
+ end # Mutant
@@ -0,0 +1,31 @@
1
+ module Mutant
2
+ class Mutator
3
+ class Node
4
+ class Send
5
+
6
+ # Mutator for sends that correspond to a binary operator
7
+ class Binary < self
8
+
9
+ children :left, :operator, :right
10
+
11
+ private
12
+
13
+ # Emit mutations
14
+ #
15
+ # @return [undefined]
16
+ #
17
+ # @api private
18
+ #
19
+ def dispatch
20
+ emit(left)
21
+ emit_left_mutations
22
+ emit(right) unless right.type == :splat
23
+ emit_right_mutations
24
+ end
25
+
26
+ end # Binary
27
+
28
+ end # Send
29
+ end # Node
30
+ end # Mutator
31
+ end # Mutant
@@ -5,137 +5,171 @@ module Mutant
5
5
  # Namespace for send mutators
6
6
  class Send < self
7
7
 
8
- handle(Rubinius::AST::Send)
8
+ handle(:send)
9
+
10
+ children :receiver, :selector
11
+
12
+ INDEX_REFERENCE = :[]
13
+ INDEX_ASSIGN = :[]=
14
+ ASSIGN_SUFFIX = :'='
15
+
16
+ # Base mutator for index operations
17
+ class Index < self
18
+
19
+ # Mutator for index references
20
+ class Reference < self
21
+
22
+ # Perform dispatch
23
+ #
24
+ # @return [undefined]
25
+ #
26
+ # @api private
27
+ #
28
+ def dispatch
29
+ emit(receiver)
30
+ end
31
+
32
+ end # Reference
33
+
34
+ # Mutator for index assignments
35
+ class Assign < self
36
+
37
+ # Perform dispatch
38
+ #
39
+ # @return [undefined]
40
+ #
41
+ # @api private
42
+ #
43
+ def dispatch
44
+ emit(receiver)
45
+ end
46
+
47
+ end # Assign
48
+ end # Index
9
49
 
10
50
  private
11
51
 
12
- # Emit mutations
52
+ # Perform dispatch
13
53
  #
14
54
  # @return [undefined]
15
55
  #
16
56
  # @api private
17
57
  #
18
58
  def dispatch
19
- emit_receiver
20
- emit_implicit_self_receiver
21
- emit_receiver_mutations
22
- emit_block_mutations
23
- emit_block_absence_mutation
59
+ case selector
60
+ when INDEX_REFERENCE
61
+ run(Index::Reference)
62
+ when INDEX_ASSIGN
63
+ run(Index::Assign)
64
+ else
65
+ non_index_dispatch
66
+ end
24
67
  end
25
68
 
26
- # Emit receiver
69
+ # Perform non index dispatch
27
70
  #
28
71
  # @return [undefined]
29
72
  #
30
73
  # @api private
31
74
  #
32
- def emit_receiver
33
- unless to_self?
34
- emit(receiver)
75
+ def non_index_dispatch
76
+ if binary_operator?
77
+ run(Binary)
78
+ return
35
79
  end
80
+ normal_dispatch
36
81
  end
37
82
 
38
- # Emit block mutations
83
+ # Return arguments
39
84
  #
40
- # @return [undefined]
85
+ # @return [Enumerable<Parser::AST::Node>]
41
86
  #
42
87
  # @api private
43
88
  #
44
- def emit_block_mutations
45
- emit_attribute_mutations(:block) if node.block
46
- end
89
+ alias_method :arguments, :remaining_children
47
90
 
48
- # Emit receiver mutations
91
+ # Perform normal, non special case dispatch
49
92
  #
50
93
  # @return [undefined]
51
94
  #
52
95
  # @api private
53
96
  #
54
- def emit_receiver_mutations
55
- emit_attribute_mutations(:receiver)
97
+ def normal_dispatch
98
+ emit(receiver) if receiver
99
+ mutate_receiver
100
+ emit_argument_propagation
101
+ mutate_arguments
56
102
  end
57
103
 
58
- # Emit block absence mutation
104
+ # Test for binary operator
59
105
  #
60
- # @return [undefined]
106
+ # @return [true]
107
+ # if send is a binary operator
108
+ #
109
+ # @return [false]
110
+ # otherwise
61
111
  #
62
112
  # @api private
63
113
  #
64
- def emit_block_absence_mutation
65
- dup = dup_node
66
- dup.block = nil
67
- emit(dup)
114
+ def binary_operator?
115
+ arguments.one? && BINARY_METHOD_OPERATORS.include?(selector)
68
116
  end
69
117
 
70
- # Return receiver AST node
118
+ # Mutate arguments
71
119
  #
72
- # @return [Rubinius::AST::Node]
120
+ # @return [undefined]
73
121
  #
74
122
  # @api private
75
123
  #
76
- def receiver
77
- node.receiver
124
+ def mutate_arguments
125
+ return if arguments.empty?
126
+ emit_self(receiver, selector)
127
+ remaining_children_with_index.each do |node, index|
128
+ mutate_child(index)
129
+ delete_child(index)
130
+ end
78
131
  end
79
132
 
80
- # Return name of call
133
+ NO_PROPAGATE = [ :splat, :block_pass ].to_set
134
+
135
+ # Emit argument propagation
81
136
  #
82
- # @return [Symbol]
137
+ # @return [undefined]
83
138
  #
84
139
  # @api private
85
140
  #
86
- def name
87
- node.name
141
+ def emit_argument_propagation
142
+ return unless arguments.one?
143
+ node = arguments.first
144
+ return if NO_PROPAGATE.include?(node.type)
145
+ emit(arguments.first)
88
146
  end
89
147
 
90
- # Check if receiver is self
91
- #
92
- # @return [true]
93
- # if receiver is a Rubinius::AST::Self node
148
+ # Emit receiver mutations
94
149
  #
95
- # @return [false]
96
- # return false otherwise
150
+ # @return [undefined]
97
151
  #
98
152
  # @api private
99
153
  #
100
- def to_self?
101
- receiver.kind_of?(Rubinius::AST::Self)
154
+ def mutate_receiver
155
+ return unless receiver
156
+ emit_implicit_self
157
+ emit_receiver_mutations
102
158
  end
103
159
 
104
- # Emit mutation that replaces explicit send to self with implicit send to self
105
- #
106
- # @example:
107
- #
108
- # # This class does use Foo#a with explicitly specifing the receiver self.
109
- # # But an implicit (privately) call should be used as there is no need for
110
- # # specifing en explicit receiver.
111
- #
112
- # class Foo # Mutation
113
- # def print_a # def print_a
114
- # puts self.a # puts a
115
- # end # end
116
- #
117
- # def a
118
- # :bar
119
- # end
120
- # end
121
- #
122
- # There will not be any exception so the mutant is not killed and such calls where
123
- # implicit receiver should be used will be spotted.
160
+ # Emit implicit self mutation
124
161
  #
125
162
  # @return [undefined]
126
163
  #
127
164
  # @api private
128
165
  #
129
- def emit_implicit_self_receiver
130
- unless to_self? and !Mutant::KEYWORDS.include?(node.name)
131
- return
166
+ def emit_implicit_self
167
+ if receiver.type == :self and !KEYWORDS.include?(selector)
168
+ emit_receiver(nil)
132
169
  end
133
-
134
- mutant = dup_node
135
- mutant.privately = true
136
- emit(mutant)
137
170
  end
138
- end
139
- end
140
- end
141
- end
171
+
172
+ end # Send
173
+ end # Node
174
+ end # Mutator
175
+ end # Mutant