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
@@ -1,57 +1,47 @@
1
1
  module Mutant
2
- # Abstract matcher to find ASTs to mutate
2
+ # Abstract matcher to find subjects to mutate
3
3
  class Matcher
4
4
  include Adamantium::Flat, Enumerable, AbstractType
5
5
  extend DescendantsTracker
6
6
 
7
7
  # Enumerate subjects
8
8
  #
9
- # @api private
10
- #
11
- # @return [undefined]
9
+ # @param [Object] input
12
10
  #
13
- abstract_method :each
14
-
15
- # Return identification
11
+ # @return [self]
12
+ # if block given
16
13
  #
17
- # @return [String
14
+ # @return [Enumerator<Subject>]
18
15
  #
19
16
  # @api private
20
17
  #
21
- abstract_method :identification
18
+ def self.each(input, &block)
19
+ return to_enum(__method__, input) unless block_given?
22
20
 
23
- # Return matcher
24
- #
25
- # @param [String] input
26
- #
27
- # @return [nil]
28
- # returns nil as default implementation
21
+ new(input).each(&block)
22
+
23
+ self
24
+ end
25
+
26
+ # Enumerate subjects
29
27
  #
30
28
  # @api private
31
29
  #
32
- def self.parse(input)
33
- nil
34
- end
35
-
36
- # Return match from string
30
+ # @return [self]
31
+ # if block given
37
32
  #
38
- # @param [String] input
33
+ # @return [Enumerabe<Subject>]
34
+ # otherwise
39
35
  #
40
- # @return [Matcher]
41
- # returns matcher input if successful
36
+ abstract_method :each
37
+
38
+ # Return identification
42
39
  #
43
- # @return [nil]
44
- # returns nil otherwise
40
+ # @return [String
45
41
  #
46
42
  # @api private
47
43
  #
48
- def self.from_string(input)
49
- descendants.each do |descendant|
50
- matcher = descendant.parse(input)
51
- return matcher if matcher
52
- end
44
+ abstract_method :identification
53
45
 
54
- nil
55
- end
56
- end
57
- end
46
+ end # Matcher
47
+ end # Mutant
@@ -0,0 +1,35 @@
1
+ module Mutant
2
+ class Mutation
3
+ # Evul mutation
4
+ class Evil < self
5
+
6
+ # Return identification
7
+ #
8
+ # @return [String]
9
+ #
10
+ # @api private
11
+ #
12
+ def identification
13
+ "evil:#{super}"
14
+ end
15
+ memoize :identification
16
+
17
+ # Test if killer is successful
18
+ #
19
+ # @param [Killer] killer
20
+ #
21
+ # @return [true]
22
+ # if killer killed mutation
23
+ #
24
+ # @return [false]
25
+ # otherwise
26
+ #
27
+ # @api private
28
+ #
29
+ def success?(killer)
30
+ killer.killed?
31
+ end
32
+
33
+ end # Evil
34
+ end # Mutation
35
+ end # Mutant
@@ -1,9 +1,9 @@
1
1
  module Mutant
2
2
  class Mutation
3
- class Filter
3
+ class Filter
4
4
  # Mutation filter that filters on mutation codes
5
5
  class Code < self
6
- include Equalizer.new(:code)
6
+ include Concord::Public.new(:code)
7
7
 
8
8
  # Test for match
9
9
  #
@@ -36,33 +36,12 @@ module Mutant
36
36
  # @api private
37
37
  #
38
38
  def self.handle(notation)
39
- match = PATTERN.match(notation)
39
+ match = PATTERN.match(notation)
40
40
  return unless match
41
41
  new(match[1])
42
42
  end
43
43
 
44
- # Return code
45
- #
46
- # @return [String]
47
- #
48
- # @api private
49
- #
50
- attr_reader :code
51
-
52
- private
53
-
54
- # Initialize code filter
55
- #
56
- # @param [String] code
57
- #
58
- # @return [undefined]
59
- #
60
- # @api private
61
- #
62
- def initialize(code)
63
- @code = code
64
- end
65
- end
66
- end
67
- end
68
- end
44
+ end # Code
45
+ end # Filter
46
+ end # Mutation
47
+ end # Mutant
@@ -3,6 +3,7 @@ module Mutant
3
3
  class Filter
4
4
  # Mutaiton filter filtering in regexp match on mutation identification
5
5
  class Regexp < self
6
+ include Concord::Public.new(:regexp)
6
7
 
7
8
  # Test for match
8
9
  #
@@ -17,23 +18,10 @@ module Mutant
17
18
  # @api private
18
19
  #
19
20
  def match?(mutation)
20
- !!@regexp.match =~ mutation.identification
21
+ !!(regexp =~ mutation.identification)
21
22
  end
22
23
 
23
- private
24
-
25
- # Initialize regexp filter
26
- #
27
- # @param [Regexp] regexp
28
- #
29
- # @return [undefined]
30
- #
31
- # @api private
32
- #
33
- def initialize(regexp)
34
- @regexp = regexp
35
- end
36
- end
37
- end
38
- end
39
- end
24
+ end # Regexp
25
+ end # Filter
26
+ end # Mutation
27
+ end # Mutant
@@ -43,7 +43,8 @@ module Mutant
43
43
  def initialize(whitelist)
44
44
  @whitelist = whitelist
45
45
  end
46
- end
47
- end
48
- end
49
- end
46
+
47
+ end # Whitelist
48
+ end # Filter
49
+ end # Mutation
50
+ end # Mutant
@@ -32,7 +32,7 @@ module Mutant
32
32
  # @api private
33
33
  #
34
34
  def self.build(notation)
35
- descendants.each do |descendant|
35
+ descendants.each do |descendant|
36
36
  filter = descendant.handle(notation)
37
37
  return filter if filter
38
38
  end
@@ -42,34 +42,35 @@ module Mutant
42
42
 
43
43
  # Return filter for handle
44
44
  #
45
- # @param [String] notation
45
+ # @param [String] _notation
46
46
  #
47
47
  # @return [nil]
48
48
  # returns nil
49
49
  #
50
50
  # @api private
51
51
  #
52
- def self.handle(notation)
52
+ def self.handle(_notation)
53
53
  nil
54
54
  end
55
55
 
56
56
  # Mutation filter matching all mutations
57
- Mutant.define_singleton_subclass('ALL', self) do
57
+ Mutant.singleton_subclass_instance('ALL', self) do
58
58
 
59
59
  # Test for match
60
60
  #
61
- # @pram [Mutation] mutation
61
+ # @pram [Mutation] _mutation
62
62
  #
63
63
  # @return [true]
64
64
  # returns true
65
65
  #
66
66
  # @api private
67
67
  #
68
- def match?(mutation)
68
+ def match?(_mutation)
69
69
  true
70
70
  end
71
71
 
72
72
  end
73
- end
74
- end
75
- end
73
+
74
+ end # Filter
75
+ end # Mutation
76
+ end # Mutant
@@ -0,0 +1,35 @@
1
+ module Mutant
2
+ class Mutation
3
+ # Neutral mutation
4
+ class Neutral < self
5
+
6
+ # Return identification
7
+ #
8
+ # @return [String]
9
+ #
10
+ # @api private
11
+ #
12
+ def identification
13
+ "noop:#{super}"
14
+ end
15
+ memoize :identification
16
+
17
+ # Test if killer is successful
18
+ #
19
+ # @param [Killer] killer
20
+ #
21
+ # @return [true]
22
+ # if killer did NOT killed mutation
23
+ #
24
+ # @return [false]
25
+ # otherwise
26
+ #
27
+ # @api private
28
+ #
29
+ def success?(killer)
30
+ !killer.killed?
31
+ end
32
+
33
+ end # Neutral
34
+ end # Mutation
35
+ end # Mutant
@@ -1,42 +1,43 @@
1
1
  module Mutant
2
2
  # Represent a mutated node with its subject
3
3
  class Mutation
4
- include Adamantium::Flat, Equalizer.new(:sha1)
4
+ include AbstractType, Adamantium::Flat, Concord::Public.new(:subject, :node)
5
5
 
6
- # Return mutation subject
6
+ # Return mutated root node
7
7
  #
8
- # @return [Subject]
8
+ # @return [Parser::AST::Node]
9
9
  #
10
10
  # @api private
11
11
  #
12
- attr_reader :subject
12
+ def root
13
+ subject.root(node)
14
+ end
15
+ memoize :root
13
16
 
14
- # Return mutated node
17
+ # Test if killer is successful
15
18
  #
16
- # @return [Rubinius::AST::Node]
19
+ # @param [Killer] killer
17
20
  #
18
- # @api private
21
+ # @return [true]
22
+ # if killer is successful
19
23
  #
20
- attr_reader :node
21
-
22
- # Return mutated root node
23
- #
24
- # @return [Rubinius::AST::Node]
24
+ # @return [false]
25
+ # otherwise
25
26
  #
26
27
  # @api private
27
28
  #
28
- def root
29
- subject.root(node)
30
- end
31
- memoize :root
29
+ abstract_method :success?
32
30
 
33
31
  # Insert mutated node
34
32
  #
33
+ # FIXME: Cache subject visibility in a better way! Ideally dont mutate it.
34
+ #
35
35
  # @return [self]
36
36
  #
37
37
  # @api private
38
38
  #
39
39
  def insert
40
+ subject.public?
40
41
  Loader::Eval.run(root, subject)
41
42
  self
42
43
  end
@@ -70,7 +71,7 @@ module Mutant
70
71
  # @api private
71
72
  #
72
73
  def sha1
73
- Digest::SHA1.hexdigest(subject.identification + source)
74
+ Digest::SHA1.hexdigest(subject.identification + 0.chr + source)
74
75
  end
75
76
  memoize :sha1
76
77
 
@@ -81,7 +82,7 @@ module Mutant
81
82
  # @api private
82
83
  #
83
84
  def source
84
- ToSource.to_source(node)
85
+ Unparser.unparse(node)
85
86
  end
86
87
  memoize :source
87
88
 
@@ -95,46 +96,5 @@ module Mutant
95
96
  subject.source
96
97
  end
97
98
 
98
- private
99
-
100
- # Initialize mutation object
101
- #
102
- # @param [Subject] subject
103
- # @param [Rubinius::Node::AST] node
104
- #
105
- # @return [undefined]
106
- #
107
- # @api private
108
- #
109
- def initialize(subject, node)
110
- @subject, @node = subject, node
111
- end
112
-
113
- # Noop mutation
114
- class Noop < self
115
-
116
- # Initialize object
117
- #
118
- # @param [Subject] subject
119
- #
120
- # @return [undefined]
121
- #
122
- # @api private
123
- #
124
- def initialize(subject)
125
- super(subject, subject.node)
126
- end
127
-
128
- # Return identification
129
- #
130
- # @return [String]
131
- #
132
- # @api private
133
- #
134
- def identification
135
- "noop:#{super}"
136
- end
137
- memoize :identification
138
- end
139
- end
140
- end
99
+ end # Mutation
100
+ end # Mutant
@@ -0,0 +1,88 @@
1
+ module Mutant
2
+ class Mutator
3
+ class Node
4
+
5
+ # Mutator for required arguments
6
+ class Argument < self
7
+ handle(:arg)
8
+
9
+ UNDERSCORE = '_'.freeze
10
+
11
+ children :name
12
+
13
+ private
14
+
15
+ # Perform dispatch
16
+ #
17
+ # @return [undefined]
18
+ #
19
+ # @api private
20
+ #
21
+ def dispatch
22
+ return if skip?
23
+ emit_name_mutation
24
+ end
25
+
26
+ # Emit name mutations
27
+ #
28
+ # @return [undefined]
29
+ #
30
+ # @api private
31
+ #
32
+ def emit_name_mutation
33
+ Mutator::Util::Symbol.each(name) do |name|
34
+ emit_name(name)
35
+ end
36
+ end
37
+
38
+ # Test if argument mutation is skipped
39
+ #
40
+ # @return [true]
41
+ # if argument should not get mutated
42
+ #
43
+ # @return [false]
44
+ # otherwise
45
+ #
46
+ # @api private
47
+ #
48
+ def skip?
49
+ name.to_s.start_with?(UNDERSCORE)
50
+ end
51
+
52
+ # Mutator for optional arguments
53
+ class Optional < self
54
+
55
+ handle(:optarg)
56
+
57
+ children :name, :default
58
+
59
+ private
60
+
61
+ # Perform dispatch
62
+ #
63
+ # @return [undefined]
64
+ #
65
+ # @api private
66
+ #
67
+ def dispatch
68
+ emit_name_mutation
69
+ emit_required_mutation
70
+ emit_default_mutations
71
+ end
72
+
73
+ # Emit required mutation
74
+ #
75
+ # @return [undefined]
76
+ #
77
+ # @api private
78
+ #
79
+ def emit_required_mutation
80
+ emit(s(:arg, name))
81
+ end
82
+
83
+ end # Optional
84
+
85
+ end # Argument
86
+ end # Node
87
+ end # Mutator
88
+ end # Mutant
@@ -0,0 +1,52 @@
1
+ module Mutant
2
+ class Mutator
3
+ class Node
4
+ # Mutator for arguments node
5
+ class Arguments < self
6
+
7
+ handle(:args)
8
+
9
+ private
10
+
11
+ # Perform dispatch
12
+ #
13
+ # @return [undefined]
14
+ #
15
+ # @api private
16
+ #
17
+ def dispatch
18
+ emit_children_mutations
19
+ emit_mlhs_expansion
20
+ end
21
+
22
+ # Emit mlhs expansions
23
+ #
24
+ # @return [undefined]
25
+ #
26
+ # @api private
27
+ #
28
+ def emit_mlhs_expansion
29
+ mlhs_childs_with_index.each do |child, index|
30
+ dup_children = children.dup
31
+ dup_children.delete_at(index)
32
+ dup_children.insert(index, *child.children)
33
+ emit_self(*dup_children)
34
+ end
35
+ end
36
+
37
+ # Return mlhs childs
38
+ #
39
+ # @return [Enumerable<Parser::AST::Node, Fixnum>]
40
+ #
41
+ # @api private
42
+ #
43
+ def mlhs_childs_with_index
44
+ children.each_with_index.select do |child, index|
45
+ child.type == :mlhs
46
+ end
47
+ end
48
+
49
+ end # Arguments
50
+ end # Node
51
+ end # Mutator
52
+ end # Mutant
@@ -1,55 +1,51 @@
1
1
  module Mutant
2
2
  class Mutator
3
3
  class Node
4
-
5
- # Abstract base class for assignment mutators
4
+ # Mutator base class for assignments
6
5
  class Assignment < self
7
6
 
8
- private
9
-
10
- # Abstract base class for variable assignments
7
+ # Mutator for variable assignment
11
8
  class Variable < self
12
9
 
13
- # Emit mutants
10
+ children :name, :value
11
+
12
+ MAP = IceNine.deep_freeze(
13
+ :gvasgn => '$',
14
+ :cvasgn => '@@',
15
+ :ivasgn => '@',
16
+ :lvasgn => ''
17
+ )
18
+
19
+ handle *MAP.keys
20
+
21
+ private
22
+
23
+ # Perform dispatch
14
24
  #
15
25
  # @return [undefined]
16
26
  #
17
27
  # @api private
18
28
  #
19
29
  def dispatch
20
- emit_attribute_mutations(:name) do |mutation|
21
- mutation.name = "#{self.class::PREFIX}#{mutation.name}".to_sym
22
- mutation
23
- end
24
- emit_attribute_mutations(:value)
30
+ mutate_name
31
+ emit_value_mutations
25
32
  end
26
33
 
27
- # Mutator for local variable assignments
28
- class Local < self
29
- PREFIX = ''.freeze
30
- handle(Rubinius::AST::LocalVariableAssignment)
31
- end
32
-
33
- # Mutator for instance variable assignments
34
- class Instance < self
35
- PREFIX = '@'.freeze
36
- handle(Rubinius::AST::InstanceVariableAssignment)
37
- end
38
-
39
- # Mutator for class variable assignments
40
- class Class < self
41
- PREFIX = '@@'.freeze
42
- handle(Rubinius::AST::ClassVariableAssignment)
43
- end
44
-
45
- # Mutator for global variable assignments
46
- class Global < self
47
- PREFIX = '$'.freeze
48
- handle(Rubinius::AST::GlobalVariableAssignment)
34
+ # Emit name mutations
35
+ #
36
+ # @return [undefined]
37
+ #
38
+ # @api private
39
+ #
40
+ def mutate_name
41
+ prefix = MAP.fetch(node.type)
42
+ Mutator::Util::Symbol.each(name) do |name|
43
+ emit_name("#{prefix}#{name}")
44
+ end
49
45
  end
50
46
 
51
- end
52
- end
53
- end
54
- end
55
- end
47
+ end # Variable
48
+ end # Assignment
49
+ end # Node
50
+ end # Mutator
51
+ end # Mutant
@@ -0,0 +1,33 @@
1
+ module Mutant
2
+ class Mutator
3
+ class Node
4
+
5
+ # Mutator for begin nodes
6
+ class Begin < self
7
+
8
+ handle(:begin)
9
+
10
+ private
11
+
12
+ # Emit mutants
13
+ #
14
+ # @return [undefined]
15
+ #
16
+ # @api private
17
+ #
18
+ def dispatch
19
+ Util::Array.each(children) do |children|
20
+ if children.length > 1
21
+ emit_self(*children)
22
+ end
23
+ end
24
+ children.each do |child|
25
+ emit(child)
26
+ end
27
+ emit(nil)
28
+ end
29
+
30
+ end # Block
31
+ end # Node
32
+ end # Mutator
33
+ end # Mutant