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,55 @@
1
+ module Mutant
2
+ # Abstract matcher to find ASTs to mutate
3
+ class Matcher
4
+ include Adamantium::Flat, Enumerable, AbstractType
5
+ extend DescendantsTracker
6
+
7
+ # Enumerate subjects
8
+ #
9
+ # @api private
10
+ #
11
+ # @return [undefined]
12
+ #
13
+ abstract_method :each
14
+
15
+ # Return identification
16
+ #
17
+ # @return [String
18
+ #
19
+ # @api private
20
+ #
21
+ abstract_method :identification
22
+
23
+ # Return matcher
24
+ #
25
+ # @param [String] input
26
+ #
27
+ # @return [nil]
28
+ # returns nil as default implementation
29
+ #
30
+ # @api private
31
+ #
32
+ def self.parse(input)
33
+ nil
34
+ end
35
+
36
+ # Return match from string
37
+ #
38
+ # @param [String] input
39
+ #
40
+ # @return [Matcher]
41
+ # returns matcher input if successful
42
+ #
43
+ # @return [nil]
44
+ # returns nil otherwise
45
+ #
46
+ def self.from_string(input)
47
+ descendants.each do |descendant|
48
+ matcher = descendant.parse(input)
49
+ return matcher if matcher
50
+ end
51
+
52
+ nil
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,66 @@
1
+ module Mutant
2
+ class Matcher
3
+ # A chain of matchers
4
+ class Chain < self
5
+ include Equalizer.new(:matchers)
6
+
7
+ # Enumerate subjects
8
+ #
9
+ # @return [Enumerator<Subject]
10
+ # returns subject enumerator if no block given
11
+ #
12
+ # @return [self]
13
+ # returnns self otherwise
14
+ #
15
+ # @api private
16
+ #
17
+ def each(&block)
18
+ return to_enum unless block_given?
19
+
20
+ matchers.each do |matcher|
21
+ matcher.each(&block)
22
+ end
23
+
24
+ self
25
+ end
26
+
27
+ # Return the chain of matchers
28
+ #
29
+ # @return [Enumerable<Chain>]
30
+ #
31
+ # @api private
32
+ #
33
+ attr_reader :matchers
34
+
35
+ # Build matcher chain
36
+ #
37
+ # @param [Enumerable<Matcher>] matchers
38
+ #
39
+ # @return [Matcher]
40
+ #
41
+ # @api private
42
+ #
43
+ def self.build(matchers)
44
+ if matchers.length == 1
45
+ return matchers.first
46
+ end
47
+
48
+ new(matchers)
49
+ end
50
+
51
+ private
52
+
53
+ # Initialize chain matcher
54
+ #
55
+ # @param [Enumerable<Matcher>] matchers
56
+ #
57
+ # @return [undefined]
58
+ #
59
+ # @api private
60
+ #
61
+ def initialize(matchers)
62
+ @matchers = matchers
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,173 @@
1
+ module Mutant
2
+ class Matcher
3
+ # Matcher for subjects that are a specific method
4
+ class Method < self
5
+ include Adamantium::Flat, Equalizer.new(:identification)
6
+
7
+ # Parse a method string into filter
8
+ #
9
+ # @param [String] input
10
+ #
11
+ # @return [Matcher::Method]
12
+ #
13
+ # @api private
14
+ #
15
+ def self.parse(input)
16
+ Classifier.run(input)
17
+ end
18
+
19
+ # Enumerate matches
20
+ #
21
+ # @return [Enumerable]
22
+ # returns enumerable when no block given
23
+ #
24
+ # @return [self]
25
+ # returns self when block given
26
+ #
27
+ # @api private
28
+ #
29
+ def each(&block)
30
+ return to_enum unless block_given?
31
+ subject.tap do |subject|
32
+ yield subject if subject
33
+ end
34
+
35
+ self
36
+ end
37
+
38
+ # Return scope
39
+ #
40
+ # @return [Class|Module]
41
+ #
42
+ # @api private
43
+ #
44
+ attr_reader :scope
45
+
46
+ # Return context
47
+ #
48
+ # @return [Context::Scope]
49
+ #
50
+ # @api private
51
+ #
52
+ attr_reader :context
53
+
54
+ # Return method name
55
+ #
56
+ # @return [String]
57
+ #
58
+ # @api private
59
+ #
60
+ attr_reader :method_name
61
+
62
+ # Test if method is public
63
+ #
64
+ # @return [true]
65
+ # if method is public
66
+ #
67
+ # @retur [false]
68
+ # otherwise
69
+ #
70
+ # @api private
71
+ #
72
+ abstract_method :public?
73
+
74
+ private
75
+
76
+ # Initialize method filter
77
+ #
78
+ # @param [Class|Module] scope
79
+ # @param [Symbol] method_name
80
+ #
81
+ # @return [undefined]
82
+ #
83
+ # @api private
84
+ #
85
+ def initialize(scope, method_name)
86
+ @scope, @method_name = scope, method_name.to_sym
87
+ @context = Context::Scope.build(scope, source_path)
88
+ # FIXME: cache public private should not be needed, loader should not override visibility! (But does currently) :(
89
+ public?
90
+ end
91
+
92
+ # Return method
93
+ #
94
+ # @return [UnboundMethod, Method]
95
+ #
96
+ # @api private
97
+ #
98
+ abstract_method :method
99
+
100
+ # Return full ast
101
+ #
102
+ # @return [Rubinius::AST::Node]
103
+ #
104
+ # @api private
105
+ #
106
+ def ast
107
+ File.read(source_path).to_ast
108
+ end
109
+
110
+ # Return path to source
111
+ #
112
+ # @return [String]
113
+ #
114
+ # @api private
115
+ #
116
+ def source_path
117
+ source_location.first
118
+ end
119
+
120
+ # Return source file line
121
+ #
122
+ # @return [Integer]
123
+ #
124
+ # @api private
125
+ #
126
+ def source_line
127
+ source_location.last
128
+ end
129
+
130
+ # Return source location
131
+ #
132
+ # @return [Array]
133
+ #
134
+ # @api private
135
+ #
136
+ def source_location
137
+ method.source_location
138
+ end
139
+
140
+ # Return subject
141
+ #
142
+ # @return [Subject]
143
+ # returns subject if there is a matched node
144
+ #
145
+ # @return [nil]
146
+ # otherwise
147
+ #
148
+ # @api private
149
+ #
150
+ def subject
151
+ node = matched_node
152
+ return unless node
153
+ Subject.new(self, context, node)
154
+ end
155
+ memoize :subject
156
+
157
+ # Return matched node
158
+ #
159
+ # @return [Rubinus::AST::Node]
160
+ #
161
+ # @api private
162
+ #
163
+ def matched_node
164
+ last_match = nil
165
+ ast.walk do |predicate, node|
166
+ last_match = node if match?(node)
167
+ predicate
168
+ end
169
+ last_match
170
+ end
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,126 @@
1
+ module Mutant
2
+ class Matcher
3
+ class Method < self
4
+ # A classifier for input strings
5
+ class Classifier
6
+ include Adamantium::Flat
7
+
8
+ TABLE = {
9
+ '.' => Matcher::Method::Singleton,
10
+ '#' => Matcher::Method::Instance
11
+ }.freeze
12
+
13
+ SCOPE_FORMAT = /\A([^#.]+)(\.|#)(.+)\z/.freeze
14
+
15
+ # Positions of captured regexp groups
16
+ # Freezing fixnums to avoid their singleton classes are patched.
17
+ SCOPE_NAME_POSITION = 1.freeze
18
+ SCOPE_SYMBOL_POSITION = 2.freeze
19
+ METHOD_NAME_POSITION = 3.freeze
20
+
21
+ private_class_method :new
22
+
23
+ # Run classifier
24
+ #
25
+ # @param [String] input
26
+ #
27
+ # @return [Matcher::Method]
28
+ # returns matcher when input is in
29
+ #
30
+ # @return [nil]
31
+ # returns nil otherwise
32
+ #
33
+ # @api private
34
+ #
35
+ def self.run(input)
36
+ match = SCOPE_FORMAT.match(input)
37
+ return unless match
38
+ new(match).matcher
39
+ end
40
+
41
+ # Return method matcher
42
+ #
43
+ # @return [Matcher::Method]
44
+ #
45
+ # @api private
46
+ #
47
+ def matcher
48
+ matcher_class.new(scope, method_name)
49
+ end
50
+
51
+ # Return match
52
+ #
53
+ # @return [Matche]
54
+ #
55
+ # @api private
56
+ #
57
+ attr_reader :match
58
+
59
+ private
60
+
61
+ # Initialize matcher
62
+ #
63
+ # @param [MatchData] match
64
+ #
65
+ # @api private
66
+ #
67
+ def initialize(match)
68
+ @match = match
69
+ end
70
+
71
+ # Return scope
72
+ #
73
+ # @return [Class|Module]
74
+ #
75
+ # @api private
76
+ #
77
+ def scope
78
+ scope_name.gsub(%r(\A::), '').split('::').inject(::Object) do |parent, name|
79
+ parent.const_get(name)
80
+ end
81
+ end
82
+ memoize :scope
83
+
84
+ # Return scope name
85
+ #
86
+ # @return [String]
87
+ #
88
+ # @api private
89
+ #
90
+ def scope_name
91
+ match[SCOPE_NAME_POSITION]
92
+ end
93
+
94
+ # Return method name
95
+ #
96
+ # @return [String]
97
+ #
98
+ # @api private
99
+ #
100
+ def method_name
101
+ match[METHOD_NAME_POSITION].to_sym
102
+ end
103
+
104
+ # Return scope symbol
105
+ #
106
+ # @return [Symbol]
107
+ #
108
+ # @api private
109
+ #
110
+ def scope_symbol
111
+ match[SCOPE_SYMBOL_POSITION]
112
+ end
113
+
114
+ # Return matcher class
115
+ #
116
+ # @return [Class:Mutant::Matcher]
117
+ #
118
+ # @api private
119
+ #
120
+ def matcher_class
121
+ TABLE.fetch(scope_symbol)
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,67 @@
1
+ module Mutant
2
+ class Matcher
3
+ class Method < self
4
+ # Matcher for instance methods
5
+ class Instance < self
6
+
7
+
8
+ # Return identification
9
+ #
10
+ # @return [String]
11
+ #
12
+ # @api private
13
+ #
14
+ def identification
15
+ "#{scope.name}##{method_name}"
16
+ end
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.public_method_defined?(method_name)
30
+ end
31
+ memoize :public?
32
+
33
+ private
34
+
35
+ # Check if node is matched
36
+ #
37
+ # @param [Rubinius::AST::Node] node
38
+ #
39
+ # @return [true]
40
+ # returns true if node matches method
41
+ #
42
+ # @return [false]
43
+ # returns false if node NOT matches method
44
+ #
45
+ # @api private
46
+ #
47
+ def match?(node)
48
+ node.line == source_line &&
49
+ node.class == Rubinius::AST::Define &&
50
+ node.name == method_name
51
+ end
52
+
53
+ # Return method instance
54
+ #
55
+ # @return [UnboundMethod]
56
+ #
57
+ # @api private
58
+ #
59
+ def method
60
+ scope.instance_method(method_name)
61
+ end
62
+ memoize :method, :freezer => :noop
63
+
64
+ end
65
+ end
66
+ end
67
+ end