mutant 0.1.1 → 0.2.0

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 (225) hide show
  1. data/.gitignore +5 -11
  2. data/.rspec +0 -1
  3. data/.travis.yml +14 -3
  4. data/Changelog.md +3 -0
  5. data/Gemfile +5 -1
  6. data/Gemfile.devtools +49 -0
  7. data/Guardfile +18 -0
  8. data/README.md +67 -0
  9. data/Rakefile +4 -1
  10. data/TODO +13 -0
  11. data/bin/mutant +14 -0
  12. data/bin/zombie +14 -0
  13. data/config/flay.yml +3 -0
  14. data/config/flog.yml +2 -0
  15. data/config/roodi.yml +26 -0
  16. data/config/site.reek +93 -0
  17. data/config/yardstick.yml +2 -0
  18. data/lib/inflector.rb +7 -0
  19. data/lib/inflector/defaults.rb +62 -0
  20. data/lib/inflector/inflections.rb +209 -0
  21. data/lib/inflector/methods.rb +149 -0
  22. data/lib/inflector/version.rb +3 -0
  23. data/lib/mutant.rb +96 -21
  24. data/lib/mutant/cli.rb +309 -0
  25. data/lib/mutant/color.rb +61 -0
  26. data/lib/mutant/context.rb +36 -0
  27. data/lib/mutant/context/scope.rb +138 -0
  28. data/lib/mutant/differ.rb +100 -0
  29. data/lib/mutant/helper.rb +38 -0
  30. data/lib/mutant/killer.rb +136 -0
  31. data/lib/mutant/killer/forking.rb +41 -0
  32. data/lib/mutant/killer/rspec.rb +49 -0
  33. data/lib/mutant/killer/static.rb +19 -0
  34. data/lib/mutant/loader.rb +129 -0
  35. data/lib/mutant/matcher.rb +55 -0
  36. data/lib/mutant/matcher/chain.rb +66 -0
  37. data/lib/mutant/matcher/method.rb +173 -0
  38. data/lib/mutant/matcher/method/classifier.rb +126 -0
  39. data/lib/mutant/matcher/method/instance.rb +67 -0
  40. data/lib/mutant/matcher/method/singleton.rb +141 -0
  41. data/lib/mutant/matcher/object_space.rb +114 -0
  42. data/lib/mutant/matcher/scope_methods.rb +127 -0
  43. data/lib/mutant/mutation.rb +101 -12
  44. data/lib/mutant/mutation/filter.rb +75 -0
  45. data/lib/mutant/mutation/filter/code.rb +68 -0
  46. data/lib/mutant/mutation/filter/regexp.rb +39 -0
  47. data/lib/mutant/mutation/filter/whitelist.rb +47 -0
  48. data/lib/mutant/mutator.rb +134 -30
  49. data/lib/mutant/mutator/node.rb +163 -0
  50. data/lib/mutant/mutator/node/arguments.rb +24 -0
  51. data/lib/mutant/mutator/node/block.rb +24 -0
  52. data/lib/mutant/mutator/node/define.rb +24 -0
  53. data/lib/mutant/mutator/node/if_statement.rb +93 -0
  54. data/lib/mutant/mutator/node/literal.rb +54 -0
  55. data/lib/mutant/mutator/node/literal/array.rb +28 -0
  56. data/lib/mutant/mutator/node/literal/boolean.rb +49 -0
  57. data/lib/mutant/mutator/node/literal/dynamic.rb +24 -0
  58. data/lib/mutant/mutator/node/literal/empty_array.rb +26 -0
  59. data/lib/mutant/mutator/node/literal/fixnum.rb +37 -0
  60. data/lib/mutant/mutator/node/literal/float.rb +48 -0
  61. data/lib/mutant/mutator/node/literal/hash.rb +89 -0
  62. data/lib/mutant/mutator/node/literal/nil.rb +25 -0
  63. data/lib/mutant/mutator/node/literal/range.rb +94 -0
  64. data/lib/mutant/mutator/node/literal/regex.rb +43 -0
  65. data/lib/mutant/mutator/node/literal/string.rb +26 -0
  66. data/lib/mutant/mutator/node/literal/symbol.rb +26 -0
  67. data/lib/mutant/mutator/node/noop.rb +55 -0
  68. data/lib/mutant/mutator/node/receiver_case.rb +140 -0
  69. data/lib/mutant/mutator/node/return.rb +31 -0
  70. data/lib/mutant/mutator/node/send.rb +112 -0
  71. data/lib/mutant/mutator/registry.rb +48 -0
  72. data/lib/mutant/mutator/util.rb +87 -0
  73. data/lib/mutant/random.rb +24 -27
  74. data/lib/mutant/reporter.rb +48 -30
  75. data/lib/mutant/reporter/cli.rb +221 -0
  76. data/lib/mutant/reporter/null.rb +42 -0
  77. data/lib/mutant/reporter/stats.rb +64 -0
  78. data/lib/mutant/runner.rb +112 -0
  79. data/lib/mutant/strategy.rb +42 -0
  80. data/lib/mutant/strategy/rspec.rb +59 -0
  81. data/lib/mutant/strategy/rspec/example_lookup.rb +122 -0
  82. data/lib/mutant/subject.rb +115 -0
  83. data/lib/mutant/support/method_object.rb +31 -0
  84. data/locator.rb +87 -0
  85. data/mutant.gemspec +21 -21
  86. data/spec/integration/mutant/differ_spec.rb +15 -0
  87. data/spec/integration/mutant/loader_spec.rb +21 -0
  88. data/spec/integration/mutant/method_matching_spec.rb +269 -0
  89. data/spec/integration/mutant/rspec_killer_spec.rb +24 -0
  90. data/spec/integration/mutant/runner_spec.rb +26 -0
  91. data/spec/integration/mutant/zombie_spec.rb +8 -0
  92. data/spec/rcov.opts +7 -0
  93. data/spec/shared/command_method_behavior.rb +7 -0
  94. data/spec/shared/each_method_behaviour.rb +15 -0
  95. data/spec/shared/hash_method_behavior.rb +17 -0
  96. data/spec/shared/idempotent_method_behavior.rb +7 -0
  97. data/spec/shared/invertible_method_behaviour.rb +9 -0
  98. data/spec/shared/method_filter_parse_behavior.rb +16 -0
  99. data/spec/shared/method_match_behavior.rb +39 -0
  100. data/spec/shared/mutator_behavior.rb +46 -0
  101. data/spec/spec_helper.rb +11 -14
  102. data/spec/support/compress_helper.rb +10 -0
  103. data/spec/support/rspec.rb +22 -0
  104. data/spec/support/test_app.rb +5 -0
  105. data/spec/support/zombie.rb +141 -0
  106. data/spec/unit/mutant/cli/class_methods/new_spec.rb +87 -0
  107. data/spec/unit/mutant/cli/class_methods/run_spec.rb +38 -0
  108. data/spec/unit/mutant/context/root_spec.rb +11 -0
  109. data/spec/unit/mutant/context/scope/class_methods/build_spec.rb +29 -0
  110. data/spec/unit/mutant/context/scope/root_spec.rb +22 -0
  111. data/spec/unit/mutant/context/scope/unqualified_name_spec.rb +27 -0
  112. data/spec/unit/mutant/killer/fail_ques_spec.rb +39 -0
  113. data/spec/unit/mutant/killer/rspec/class_methods/new_spec.rb +32 -0
  114. data/spec/unit/mutant/loader/eval/class_methods/run_spec.rb +33 -0
  115. data/spec/unit/mutant/loader/rubinius/class_methods/run_spec.rb +42 -0
  116. data/spec/unit/mutant/matcher/chain/each_spec.rb +37 -0
  117. data/spec/unit/mutant/matcher/chain/matchers_spec.rb +12 -0
  118. data/spec/unit/mutant/matcher/class_methods/from_string_spec.rb +49 -0
  119. data/spec/unit/mutant/matcher/class_methods/parse_spec.rb +12 -0
  120. data/spec/unit/mutant/matcher/each_spec.rb +14 -0
  121. data/spec/unit/mutant/matcher/method/class_methods/parse_spec.rb +21 -0
  122. data/spec/unit/mutant/matcher/method/classifier/class_methods/run_spec.rb +34 -0
  123. data/spec/unit/mutant/matcher/method/method_spec.rb +11 -0
  124. data/spec/unit/mutant/matcher/object_space/class_methods/parse_spec.rb +24 -0
  125. data/spec/unit/mutant/matcher/object_space/each_spec.rb +31 -0
  126. data/spec/unit/mutant/mutator/each_spec.rb +25 -0
  127. data/spec/unit/mutant/mutator/emit_new_spec.rb +51 -0
  128. data/spec/unit/mutant/mutator/emit_spec.rb +52 -0
  129. data/spec/unit/mutant/mutator/node/block/mutation_spec.rb +36 -0
  130. data/spec/unit/mutant/mutator/node/define/mutation_spec.rb +47 -0
  131. data/spec/unit/mutant/mutator/node/if_statement/mutation_spec.rb +30 -0
  132. data/spec/unit/mutant/mutator/node/literal/array_spec.rb +30 -0
  133. data/spec/unit/mutant/mutator/node/literal/boolean/mutation_spec.rb +23 -0
  134. data/spec/unit/mutant/mutator/node/literal/empty_array_spec.rb +17 -0
  135. data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +17 -0
  136. data/spec/unit/mutant/mutator/node/literal/float_spec.rb +25 -0
  137. data/spec/unit/mutant/mutator/node/literal/hash_spec.rb +34 -0
  138. data/spec/unit/mutant/mutator/node/literal/nil_spec.rb +13 -0
  139. data/spec/unit/mutant/mutator/node/literal/range_spec.rb +35 -0
  140. data/spec/unit/mutant/mutator/node/literal/regex_spec.rb +23 -0
  141. data/spec/unit/mutant/mutator/node/literal/string_spec.rb +17 -0
  142. data/spec/unit/mutant/mutator/node/literal/symbol_spec.rb +17 -0
  143. data/spec/unit/mutant/mutator/node/receiver_case/mutation_spec.rb +27 -0
  144. data/spec/unit/mutant/mutator/node/return/mutation_spec.rb +21 -0
  145. data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +78 -0
  146. data/spec/unit/mutant/mutator/self_spec.rb +7 -0
  147. data/spec/unit/mutant/subject/class_methods/new_spec.rb +13 -0
  148. data/spec/unit/mutant/subject/context_spec.rb +14 -0
  149. data/spec/unit/mutant/subject/each_spec.rb +35 -0
  150. data/spec/unit/mutant/subject/node_spec.rb +13 -0
  151. data/tasks/metrics/ci.rake +7 -0
  152. data/tasks/metrics/flay.rake +41 -0
  153. data/tasks/metrics/flog.rake +43 -0
  154. data/tasks/metrics/heckle.rake +216 -0
  155. data/tasks/metrics/metric_fu.rake +31 -0
  156. data/tasks/metrics/reek.rake +15 -0
  157. data/tasks/metrics/roodi.rake +15 -0
  158. data/tasks/metrics/yardstick.rake +23 -0
  159. data/tasks/spec.rake +45 -0
  160. data/tasks/yard.rake +9 -0
  161. data/test_app/.rspec +1 -0
  162. data/test_app/lib/test_app.rb +5 -0
  163. data/test_app/lib/test_app/literal.rb +32 -0
  164. data/test_app/spec/shared/command_method_behavior.rb +7 -0
  165. data/test_app/spec/shared/each_method_behaviour.rb +15 -0
  166. data/test_app/spec/shared/hash_method_behavior.rb +17 -0
  167. data/test_app/spec/shared/idempotent_method_behavior.rb +7 -0
  168. data/test_app/spec/shared/invertible_method_behaviour.rb +9 -0
  169. data/test_app/spec/shared/method_filter_parse_behavior.rb +16 -0
  170. data/test_app/spec/shared/method_match_behavior.rb +39 -0
  171. data/test_app/spec/shared/mutator_behavior.rb +44 -0
  172. data/test_app/spec/spec_helper.rb +7 -0
  173. data/test_app/spec/unit/test_app/literal/command_spec.rb +9 -0
  174. data/test_app/spec/unit/test_app/literal/string_spec.rb +9 -0
  175. metadata +346 -124
  176. data/.rvmrc +0 -1
  177. data/Readme.md +0 -13
  178. data/exe/mutate +0 -6
  179. data/lib/mutant/extensions.rb +0 -8
  180. data/lib/mutant/formatter.rb +0 -19
  181. data/lib/mutant/implementation.rb +0 -70
  182. data/lib/mutant/literal.rb +0 -147
  183. data/lib/mutant/method.rb +0 -31
  184. data/lib/mutant/mutatee.rb +0 -61
  185. data/lib/mutant/node.rb +0 -26
  186. data/lib/mutant/runners/rspec.rb +0 -34
  187. data/lib/mutant/version.rb +0 -3
  188. data/spec/functional/class_spec.rb +0 -46
  189. data/spec/functional/instance_method/array_spec.rb +0 -53
  190. data/spec/functional/instance_method/boolean_spec.rb +0 -101
  191. data/spec/functional/instance_method/call_spec.rb +0 -161
  192. data/spec/functional/instance_method/fixnum_spec.rb +0 -53
  193. data/spec/functional/instance_method/float_spec.rb +0 -53
  194. data/spec/functional/instance_method/hash_spec.rb +0 -53
  195. data/spec/functional/instance_method/if_spec.rb +0 -57
  196. data/spec/functional/instance_method/ivar_assign_spec.rb +0 -62
  197. data/spec/functional/instance_method/range_spec.rb +0 -53
  198. data/spec/functional/instance_method/regex_spec.rb +0 -55
  199. data/spec/functional/instance_method/string_spec.rb +0 -53
  200. data/spec/functional/instance_method/symbol_spec.rb +0 -53
  201. data/spec/functional/reporter/method_loaded_spec.rb +0 -62
  202. data/spec/functional/reporter/running_mutations_spec.rb +0 -60
  203. data/spec/functional/runners/rspec_spec.rb +0 -26
  204. data/spec/functional/singleton_method/array_spec.rb +0 -53
  205. data/spec/functional/singleton_method/boolean_spec.rb +0 -101
  206. data/spec/functional/singleton_method/call_spec.rb +0 -161
  207. data/spec/functional/singleton_method/fixnum_spec.rb +0 -53
  208. data/spec/functional/singleton_method/float_spec.rb +0 -53
  209. data/spec/functional/singleton_method/hash_spec.rb +0 -53
  210. data/spec/functional/singleton_method/if_spec.rb +0 -57
  211. data/spec/functional/singleton_method/ivar_assign_spec.rb +0 -60
  212. data/spec/functional/singleton_method/range_spec.rb +0 -53
  213. data/spec/functional/singleton_method/regex_spec.rb +0 -55
  214. data/spec/functional/singleton_method/string_spec.rb +0 -53
  215. data/spec/functional/singleton_method/symbol_spec.rb +0 -53
  216. data/spec/mutant/extensions_spec.rb +0 -13
  217. data/spec/mutant/implementation_spec.rb +0 -223
  218. data/spec/mutant/literal_spec.rb +0 -129
  219. data/spec/mutant/mutatee_spec.rb +0 -28
  220. data/spec/mutant/node_spec.rb +0 -41
  221. data/spec/mutant/random_spec.rb +0 -33
  222. data/spec/mutant/reporter_spec.rb +0 -17
  223. data/spec/mutant_spec.rb +0 -28
  224. data/spec/support/example_group_helpers.rb +0 -11
  225. data/spec/support/example_helpers.rb +0 -5
@@ -0,0 +1,141 @@
1
+ module Mutant
2
+ class Matcher
3
+ class Method
4
+ # Matcher for singleton methods
5
+ class Singleton < self
6
+
7
+ # Return identification
8
+ #
9
+ # @return [String]
10
+ #
11
+ # @api private
12
+ #
13
+ def identification
14
+ "#{scope.name}.#{method_name}"
15
+ end
16
+ memoize :identification
17
+
18
+ # Test if method is public
19
+ #
20
+ # @return [true]
21
+ # if method is public
22
+ #
23
+ # @return [false]
24
+ # otherwise
25
+ #
26
+ # @api private
27
+ #
28
+ def public?
29
+ scope.singleton_class.public_method_defined?(method_name)
30
+ end
31
+ memoize :public?
32
+
33
+
34
+ private
35
+
36
+ # Return method instance
37
+ #
38
+ # @return [UnboundMethod]
39
+ #
40
+ # @api private
41
+ #
42
+ def method
43
+ scope.method(method_name)
44
+ end
45
+ memoize :method, :freezer => :noop
46
+
47
+ # Test for node match
48
+ #
49
+ # @param [Rubinius::AST::Node] node
50
+ #
51
+ # @return [true]
52
+ # returns true if node matches method
53
+ #
54
+ # @return [false]
55
+ # returns false if node NOT matches method
56
+ #
57
+ # @api private
58
+ #
59
+ def match?(node)
60
+ node.class == Rubinius::AST::DefineSingleton &&
61
+ line?(node) &&
62
+ name?(node) &&
63
+ receiver?(node)
64
+ end
65
+
66
+ # Test for line match
67
+ #
68
+ # @param [Rubinius::AST::Node] node
69
+ #
70
+ # @return [true]
71
+ # returns true if node matches source line
72
+ #
73
+ # @return [false]
74
+ # returns false otherwise
75
+ #
76
+ # @api private
77
+ #
78
+ def line?(node)
79
+ node.line == source_line
80
+ end
81
+
82
+ # Test for name match
83
+ #
84
+ # @param [Rubinius::AST::DefineSingleton] node
85
+ #
86
+ # @return [true]
87
+ # returns true if node name matches
88
+ #
89
+ # @return [false]
90
+ # returns false otherwise
91
+ #
92
+ # @api private
93
+ #
94
+ def name?(node)
95
+ node.body.name == method_name
96
+ end
97
+
98
+ # Test for receiver match
99
+ #
100
+ # @param [Rubinius::AST::DefineSingleton] node
101
+ #
102
+ # @return [true]
103
+ # returns true when receiver is self or scope from pattern
104
+ #
105
+ # @return [false]
106
+ # returns false otherwise
107
+ #
108
+ # @api private
109
+ #
110
+ def receiver?(node)
111
+ receiver = node.receiver
112
+ case receiver
113
+ when Rubinius::AST::Self
114
+ true
115
+ when Rubinius::AST::ConstantAccess
116
+ receiver_name?(receiver)
117
+ else
118
+ raise 'Can only match receiver on Rubinius::AST::Self or Rubinius::AST::ConstantAccess'
119
+ end
120
+ end
121
+
122
+ # Test if reciver name matches context
123
+ #
124
+ # @param [Rubinius::AST::Node] node
125
+ #
126
+ # @return [true]
127
+ # returns true when node name matches unqualified scope name
128
+ #
129
+ # @return [false]
130
+ # returns false otherwise
131
+ #
132
+ # @api private
133
+ #
134
+ def receiver_name?(node)
135
+ node.name.to_s == context.unqualified_name
136
+ end
137
+
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,114 @@
1
+ module Mutant
2
+ class Matcher
3
+ # Matcher against object space
4
+ class ObjectSpace < self
5
+ include Equalizer.new(:scope_name_pattern)
6
+
7
+ PATTERN = %r(\A::(.+)\z)
8
+
9
+ # Parse matcher
10
+ #
11
+ # @param [String] input
12
+ #
13
+ # @return [Matcher::ObjectSpace]
14
+ # returns object space matcher if successful
15
+ #
16
+ # @return [nil]
17
+ # returns nil otherwise
18
+ #
19
+ # @api private
20
+ #
21
+ def self.parse(input)
22
+ match = PATTERN.match(input)
23
+ return unless match
24
+
25
+ new(%r(\A#{Regexp.escape(match[1])}(\z|::)))
26
+ end
27
+
28
+ # Enumerate subjects
29
+ #
30
+ # @return [Enumerator<Subject>]
31
+ # returns subject enumerator when no block given
32
+ #
33
+ # @return [self]
34
+ # returns self otherwise
35
+ #
36
+ # @api private
37
+ #
38
+ def each(&block)
39
+ return to_enum unless block_given?
40
+
41
+ scopes.each do |scope|
42
+ emit_scope_matches(scope, &block)
43
+ end
44
+
45
+ self
46
+ end
47
+
48
+ # Return scope name pattern
49
+ #
50
+ # @return [Regexp]
51
+ #
52
+ # @api private
53
+ #
54
+ def scope_name_pattern; @scope_name_pattern; end
55
+
56
+ private
57
+
58
+ # Initialize object space matcher
59
+ #
60
+ # @param [Regexp] scope_name_pattern
61
+ # @param [Enumerable<#each(scope)>] matchers
62
+ #
63
+ # @return [undefined]
64
+ #
65
+ # @api private
66
+ #
67
+ def initialize(scope_name_pattern, matchers = [Matcher::ScopeMethods::Singleton, Matcher::ScopeMethods::Instance])
68
+ @scope_name_pattern, @matchers = scope_name_pattern, @matchers = matchers #[Method::Singleton, Method::Instance]
69
+ end
70
+
71
+ # Yield matchers for scope
72
+ #
73
+ # @param [::Class,::Module] scope
74
+ #
75
+ # @return [undefined]
76
+ #
77
+ # @api private
78
+ #
79
+ def emit_scope_matches(scope, &block)
80
+ @matchers.each do |matcher|
81
+ matcher.new(scope).each(&block)
82
+ end
83
+ end
84
+
85
+ # Return scope enumerator
86
+ #
87
+ # @return [Enumerable<Object>]
88
+ #
89
+ # @api private
90
+ #
91
+ def scopes(&block)
92
+ return to_enum(__method__) unless block_given?
93
+
94
+ ::ObjectSpace.each_object(Module) do |scope|
95
+ emit_scope(scope, &block)
96
+ end
97
+ end
98
+
99
+ # Yield scope if name matches pattern
100
+ #
101
+ # @param [::Module,::Class]
102
+ #
103
+ # @return [undefined]
104
+ #
105
+ # @api private
106
+ #
107
+ def emit_scope(scope)
108
+ if [::Module, ::Class].include?(scope.class) and @scope_name_pattern =~ scope.name
109
+ yield scope
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,127 @@
1
+ module Mutant
2
+ class Matcher
3
+ # Abstract base class for matcher that returns subjects extracted from scope methods
4
+ class ScopeMethods < self
5
+ include AbstractType
6
+
7
+ # Return scope
8
+ #
9
+ # @return [Class,Model]
10
+ #
11
+ # @api private
12
+ #
13
+ attr_reader :scope
14
+
15
+ # Enumerate subjects
16
+ #
17
+ # @return [self]
18
+ # if block given
19
+ #
20
+ # @return [Enumerator<Subject>]
21
+ # otherwise
22
+ #
23
+ # @api private
24
+ #
25
+ def each(&block)
26
+ return to_enum unless block_given?
27
+ methods.each do |method|
28
+ emit_matches(method, &block)
29
+ end
30
+
31
+ self
32
+ end
33
+
34
+ private
35
+
36
+ # Initialize object
37
+ #
38
+ # @param [Class,Module] scope
39
+ #
40
+ # @return [undefined]
41
+ #
42
+ # @api private
43
+ #
44
+ def initialize(scope)
45
+ @scope = scope
46
+ end
47
+
48
+ # Emit matches for method
49
+ #
50
+ # @param [UnboundMethod] method
51
+ #
52
+ # @return [undefined]
53
+ #
54
+ # @api private
55
+ #
56
+ def emit_matches(method)
57
+ matcher.new(scope, method).each do |subject|
58
+ yield subject
59
+ end
60
+ end
61
+
62
+
63
+ abstract_method :methods
64
+
65
+ # Return method matcher class
66
+ #
67
+ # @return [Class:Matcher::Method]
68
+ #
69
+ # @api private
70
+ #
71
+ def matcher
72
+ self.class::MATCHER
73
+ end
74
+
75
+ class Singleton < self
76
+ MATCHER = Mutant::Matcher::Method::Singleton
77
+
78
+ private
79
+
80
+ # Return singleton methods defined on scope
81
+ #
82
+ # @param [Class|Module] scope
83
+ #
84
+ # @return [Enumerable<Symbol>]
85
+ #
86
+ # @api private
87
+ #
88
+ def methods
89
+ singleton_class = scope.singleton_class
90
+
91
+ names =
92
+ singleton_class.public_instance_methods(false) +
93
+ singleton_class.private_instance_methods(false) +
94
+ singleton_class.protected_instance_methods(false)
95
+
96
+ names.map(&:to_sym).sort.reject do |name|
97
+ name.to_sym == :__class_init__
98
+ end
99
+ end
100
+ end
101
+
102
+ class Instance < self
103
+ MATCHER = Mutant::Matcher::Method::Instance
104
+
105
+ private
106
+
107
+ # Return instance methods names of scope
108
+ #
109
+ # @param [Class|Module] scope
110
+ #
111
+ # @return [Enumerable<Symbol>]
112
+ #
113
+ def methods
114
+ scope = self.scope
115
+ return [] unless scope.kind_of?(Module)
116
+
117
+ names =
118
+ scope.public_instance_methods(false) +
119
+ scope.private_instance_methods(false) +
120
+ scope.protected_instance_methods(false)
121
+
122
+ names.uniq.map(&:to_sym).sort
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -1,24 +1,113 @@
1
1
  module Mutant
2
+ # Represent a mutated node with its subject
2
3
  class Mutation
3
- extend Forwardable
4
+ include Adamantium::Flat, Equalizer.new(:sha1)
4
5
 
5
- attr_reader :array
6
+ # Return mutation subject
7
+ #
8
+ # @return [Subject]
9
+ #
10
+ # @api private
11
+ #
12
+ attr_reader :subject
6
13
 
7
- def initialize(node, array)
8
- @node = node
9
- @array = array
10
- @mutated = false
14
+ # Return mutated node
15
+ #
16
+ # @return [Rubinius::AST::Node]
17
+ #
18
+ # @api private
19
+ #
20
+ attr_reader :node
21
+
22
+ # Return mutated root node
23
+ #
24
+ # @return [Rubinius::AST::Node]
25
+ #
26
+ # @api private
27
+ #
28
+ def root
29
+ subject.root(node)
30
+ end
31
+ memoize :root
32
+
33
+ # Insert mutated node
34
+ #
35
+ # @return [self]
36
+ #
37
+ # @api private
38
+ #
39
+ def insert
40
+ Loader::Eval.run(root)
41
+ self
11
42
  end
12
43
 
13
- def_delegators :@node, :line, :from, :to
44
+ # Return identification
45
+ #
46
+ # @return [String]
47
+ #
48
+ # @api private
49
+ #
50
+ def identification
51
+ "#{subject.identification}:#{code}"
52
+ end
53
+ memoize :identification
54
+
55
+ # Return mutation code
56
+ #
57
+ # @return [String]
58
+ #
59
+ # @api private
60
+ #
61
+ def code
62
+ sha1[0..4]
63
+ end
64
+ memoize :code
14
65
 
15
- def mutated?
16
- @mutated
66
+ # Return sha1 sum of source and subject identification
67
+ #
68
+ # @return [String]
69
+ #
70
+ # @api private
71
+ #
72
+ def sha1
73
+ Digest::SHA1.hexdigest(subject.identification + source)
17
74
  end
75
+ memoize :sha1
76
+
77
+ # Return source
78
+ #
79
+ # @return [String]
80
+ #
81
+ # @api private
82
+ #
83
+ def source
84
+ ToSource.to_source(node)
85
+ end
86
+ memoize :source
87
+
88
+ # Return original source
89
+ #
90
+ # @return [String]
91
+ #
92
+ # @api private
93
+ #
94
+ def original_source
95
+ subject.source
96
+ end
97
+
98
+ private
18
99
 
19
- def mutate
20
- @array[@array.index(@node.item)] = @node.swap
21
- @mutated = true
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
22
111
  end
23
112
  end
24
113
  end