mutant 0.5.23 → 0.5.24

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +10 -0
  3. data/config/flay.yml +1 -1
  4. data/config/reek.yml +19 -19
  5. data/lib/mutant.rb +12 -39
  6. data/lib/mutant/ast.rb +5 -0
  7. data/lib/mutant/ast/meta.rb +131 -0
  8. data/lib/mutant/ast/named_children.rb +98 -0
  9. data/lib/mutant/ast/node_predicates.rb +19 -0
  10. data/lib/mutant/ast/nodes.rb +21 -0
  11. data/lib/mutant/ast/sexp.rb +34 -0
  12. data/lib/mutant/ast/types.rb +48 -0
  13. data/lib/mutant/cache.rb +3 -2
  14. data/lib/mutant/cli.rb +11 -151
  15. data/lib/mutant/config.rb +22 -2
  16. data/lib/mutant/context/scope.rb +11 -21
  17. data/lib/mutant/delegator.rb +2 -0
  18. data/lib/mutant/diff.rb +7 -3
  19. data/lib/mutant/env.rb +49 -0
  20. data/lib/mutant/expression.rb +36 -8
  21. data/lib/mutant/expression/methods.rb +62 -0
  22. data/lib/mutant/expression/namespace.rb +41 -28
  23. data/lib/mutant/{strategy.rb → integration.rb} +12 -31
  24. data/lib/mutant/isolation.rb +1 -1
  25. data/lib/mutant/matcher.rb +1 -21
  26. data/lib/mutant/matcher/builder.rb +142 -0
  27. data/lib/mutant/matcher/method.rb +3 -7
  28. data/lib/mutant/matcher/method/instance.rb +6 -5
  29. data/lib/mutant/matcher/method/singleton.rb +2 -7
  30. data/lib/mutant/matcher/methods.rb +11 -14
  31. data/lib/mutant/matcher/namespace.rb +31 -39
  32. data/lib/mutant/matcher/scope.rb +13 -2
  33. data/lib/mutant/meta.rb +0 -1
  34. data/lib/mutant/meta/example/dsl.rb +5 -1
  35. data/lib/mutant/mutator/node.rb +16 -44
  36. data/lib/mutant/mutator/node/or_asgn.rb +1 -1
  37. data/lib/mutant/mutator/node/send.rb +5 -60
  38. data/lib/mutant/mutator/node/super.rb +2 -5
  39. data/lib/mutant/mutator/registry.rb +1 -1
  40. data/lib/mutant/reporter.rb +10 -0
  41. data/lib/mutant/reporter/cli.rb +13 -0
  42. data/lib/mutant/reporter/cli/printer.rb +2 -0
  43. data/lib/mutant/reporter/cli/progress/config.rb +1 -1
  44. data/lib/mutant/reporter/cli/progress/noop.rb +2 -0
  45. data/lib/mutant/reporter/cli/registry.rb +2 -0
  46. data/lib/mutant/reporter/null.rb +12 -0
  47. data/lib/mutant/reporter/trace.rb +4 -0
  48. data/lib/mutant/require_highjack.rb +2 -2
  49. data/lib/mutant/rspec.rb +0 -0
  50. data/lib/mutant/runner.rb +2 -0
  51. data/lib/mutant/runner/config.rb +8 -8
  52. data/lib/mutant/runner/killer.rb +5 -0
  53. data/lib/mutant/runner/subject.rb +1 -1
  54. data/lib/mutant/subject.rb +8 -8
  55. data/lib/mutant/subject/method.rb +3 -2
  56. data/lib/mutant/subject/method/instance.rb +1 -1
  57. data/lib/mutant/test.rb +7 -65
  58. data/lib/mutant/test/report.rb +59 -0
  59. data/lib/mutant/version.rb +1 -1
  60. data/lib/mutant/warning_filter.rb +2 -0
  61. data/lib/mutant/zombifier.rb +3 -0
  62. data/lib/mutant/zombifier/file.rb +1 -1
  63. data/meta/or_asgn.rb +11 -0
  64. data/meta/send.rb +1 -1
  65. data/mutant-rspec.gemspec +1 -1
  66. data/mutant.gemspec +1 -1
  67. data/spec/integration/mutant/corpus_spec.rb +2 -0
  68. data/spec/integration/mutant/test_mutator_handles_types_spec.rb +2 -2
  69. data/spec/spec_helper.rb +4 -3
  70. data/spec/unit/mutant/cli_new_spec.rb +11 -11
  71. data/spec/unit/mutant/expression/methods_spec.rb +43 -0
  72. data/spec/unit/mutant/expression/namespace/flat_spec.rb +1 -1
  73. data/spec/unit/mutant/expression/namespace/recursive_spec.rb +19 -5
  74. data/spec/unit/mutant/{strategy_spec.rb → integration_spec.rb} +1 -1
  75. data/spec/unit/mutant/isolation_spec.rb +3 -1
  76. data/spec/unit/mutant/matcher/method/instance_spec.rb +5 -5
  77. data/spec/unit/mutant/matcher/method/singleton_spec.rb +8 -8
  78. data/spec/unit/mutant/matcher/methods/instance_spec.rb +5 -8
  79. data/spec/unit/mutant/matcher/methods/singleton_spec.rb +5 -5
  80. data/spec/unit/mutant/matcher/namespace_spec.rb +18 -23
  81. data/spec/unit/mutant/mutation_spec.rb +1 -1
  82. data/spec/unit/mutant/runner/config_spec.rb +4 -5
  83. data/spec/unit/mutant/runner/mutation_spec.rb +21 -21
  84. data/spec/unit/mutant/runner/subject_spec.rb +6 -6
  85. data/spec/unit/mutant/subject/method/instance_spec.rb +0 -4
  86. data/spec/unit/mutant/subject/method/singleton_spec.rb +0 -1
  87. data/spec/unit/mutant/subject_spec.rb +3 -3
  88. metadata +20 -6
  89. data/lib/mutant/node_helpers.rb +0 -52
@@ -4,7 +4,7 @@ module Mutant
4
4
 
5
5
  # Example DSL
6
6
  class DSL
7
- include NodeHelpers
7
+ include AST::Sexp
8
8
 
9
9
  # Run DSL on block
10
10
  #
@@ -51,6 +51,8 @@ module Mutant
51
51
  #
52
52
  # @return [self]
53
53
  #
54
+ # @api private
55
+ #
54
56
  def source(input)
55
57
  raise 'source already defined' if @source
56
58
  @source = node(input)
@@ -64,6 +66,8 @@ module Mutant
64
66
  #
65
67
  # @return [self]
66
68
  #
69
+ # @api private
70
+ #
67
71
  def mutation(input)
68
72
  node = node(input)
69
73
  if @expected.include?(node)
@@ -5,11 +5,13 @@ module Mutant
5
5
 
6
6
  # Abstract base class for node mutators
7
7
  class Node < self
8
- include AbstractType, NodeHelpers, Unparser::Constants
8
+ include AbstractType, Unparser::Constants
9
+ include AST::NamedChildren, AST::NodePredicates, AST::Sexp, AST::Nodes
9
10
 
10
- # Define named child
11
+ # Helper to define a named child
12
+ #
13
+ # @param [Parser::AST::Node] node
11
14
  #
12
- # @param [Symbol] name
13
15
  # @param [Fixnum] index
14
16
  #
15
17
  # @return [undefined]
@@ -17,9 +19,7 @@ module Mutant
17
19
  # @api private
18
20
  #
19
21
  def self.define_named_child(name, index)
20
- define_method(name) do
21
- children.at(index)
22
- end
22
+ super
23
23
 
24
24
  define_method("emit_#{name}_mutations") do |&block|
25
25
  mutate_child(index, &block)
@@ -29,43 +29,6 @@ module Mutant
29
29
  emit_child_update(index, node)
30
30
  end
31
31
  end
32
- private_class_method :define_named_child
33
-
34
- # Define remaining children
35
- #
36
- # @param [Array<Symbol>] names
37
- #
38
- # @return [undefined]
39
- #
40
- # @api private
41
- #
42
- def self.define_remaining_children(names)
43
- define_method(:remaining_children_with_index) do
44
- children.each_with_index.drop(names.length)
45
- end
46
-
47
- define_method(:remaining_children_indices) do
48
- children.each_index.drop(names.length)
49
- end
50
-
51
- define_method(:remaining_children) do
52
- children.drop(names.length)
53
- end
54
- end
55
- private_class_method :define_remaining_children
56
-
57
- # Create name helpers
58
- #
59
- # @return [undefined]
60
- #
61
- # @api private
62
- #
63
- def self.children(*names)
64
- names.each_with_index do |name, index|
65
- define_named_child(name, index)
66
- end
67
- define_remaining_children(names)
68
- end
69
32
  private_class_method :children
70
33
 
71
34
  private
@@ -98,6 +61,15 @@ module Mutant
98
61
  end
99
62
  end
100
63
 
64
+ # Return ast meta description
65
+ #
66
+ # @return [AST::Meta]
67
+ #
68
+ def meta
69
+ AST::Meta.for(node)
70
+ end
71
+ memoize :meta
72
+
101
73
  # Return children
102
74
  #
103
75
  # @return [Array<Parser::AST::Node>]
@@ -246,7 +218,7 @@ module Mutant
246
218
  # @api private
247
219
  #
248
220
  def asgn_left?
249
- OP_ASSIGN.include?(parent_type) && parent.node.children.first.equal?(node)
221
+ AST::Types::OP_ASSIGN.include?(parent_type) && parent.node.children.first.equal?(node)
250
222
  end
251
223
 
252
224
  end # Node
@@ -22,7 +22,7 @@ module Mutant
22
22
  emit_right_mutations
23
23
  return if n_ivasgn?(left)
24
24
  emit_left_mutations do |node|
25
- !n_self?(node)
25
+ AST::Meta.for(node).assignment?
26
26
  end
27
27
  end
28
28
 
@@ -4,6 +4,7 @@ module Mutant
4
4
 
5
5
  # Namespace for send mutators
6
6
  class Send < self
7
+ include AST::Types
7
8
 
8
9
  handle(:send)
9
10
 
@@ -19,12 +20,6 @@ module Mutant
19
20
  :== => [:eql?, :equal?]
20
21
  )
21
22
 
22
- INDEX_REFERENCE = :[]
23
- INDEX_ASSIGN = :[]=
24
- VARIABLE_ASSIGN = :'='
25
- ASSIGNMENT_OPERATORS = [INDEX_ASSIGN, VARIABLE_ASSIGN].to_set.freeze
26
- ATTRIBUTE_ASSIGNMENT = /\A[a-z\d_]+=\z/.freeze
27
-
28
23
  private
29
24
 
30
25
  # Perform dispatch
@@ -35,7 +30,7 @@ module Mutant
35
30
  #
36
31
  def dispatch
37
32
  emit_singletons
38
- if selector.equal?(INDEX_ASSIGN)
33
+ if meta.index_assignment?
39
34
  run(Index::Assign)
40
35
  else
41
36
  non_index_dispatch
@@ -50,9 +45,9 @@ module Mutant
50
45
  #
51
46
  def non_index_dispatch
52
47
  case
53
- when binary_operator?
48
+ when meta.binary_method_operator?
54
49
  run(Binary)
55
- when attribute_assignment?
50
+ when meta.attribute_assignment?
56
51
  run(AttributeAssignment)
57
52
  else
58
53
  normal_dispatch
@@ -103,26 +98,6 @@ module Mutant
103
98
  emit(receiver) if receiver && !NOT_ASSIGNABLE.include?(receiver.type)
104
99
  end
105
100
 
106
- # Test for binary operator
107
- #
108
- # @return [Boolean]
109
- #
110
- # @api private
111
- #
112
- def binary_operator?
113
- arguments.one? && BINARY_METHOD_OPERATORS.include?(selector)
114
- end
115
-
116
- # Test for attribute assignment
117
- #
118
- # @return [Boolean]
119
- #
120
- # @api private
121
- #
122
- def attribute_assignment?
123
- arguments.one? && ATTRIBUTE_ASSIGNMENT =~ selector
124
- end
125
-
126
101
  # Mutate arguments
127
102
  #
128
103
  # @return [undefined]
@@ -173,40 +148,10 @@ module Mutant
173
148
  KEYWORDS.include?(selector) ||
174
149
  METHOD_OPERATORS.include?(selector) ||
175
150
  OP_ASSIGN.include?(parent_type) ||
176
- attribute_assignment?
151
+ meta.attribute_assignment?
177
152
  )
178
153
  end
179
154
 
180
- # Test for assignment
181
- #
182
- # @return [Boolean]
183
- #
184
- # @api private
185
- #
186
- def assignment?
187
- arguments.one? && (ASSIGNMENT_OPERATORS.include?(selector) || attribute_assignment?)
188
- end
189
-
190
- # Test if node is part of an mlhs
191
- #
192
- # @return [Boolean]
193
- #
194
- # @api private
195
- #
196
- def mlhs?
197
- assignment? && !arguments?
198
- end
199
-
200
- # Test for empty arguments
201
- #
202
- # @return [Boolean]
203
- #
204
- # @api private
205
- #
206
- def arguments?
207
- arguments.any?
208
- end
209
-
210
155
  end # Send
211
156
  end # Node
212
157
  end # Mutator
@@ -7,9 +7,6 @@ module Mutant
7
7
 
8
8
  handle(:super)
9
9
 
10
- Z_SUPER = NodeHelpers.s(:zsuper)
11
- EMPTY_SUPER = NodeHelpers.s(:super)
12
-
13
10
  private
14
11
 
15
12
  # Emit mutations
@@ -20,8 +17,8 @@ module Mutant
20
17
  #
21
18
  def dispatch
22
19
  emit_singletons
23
- emit(Z_SUPER)
24
- emit(EMPTY_SUPER)
20
+ emit(N_ZSUPER)
21
+ emit(N_EMPTY_SUPER)
25
22
  children.each_index do |index|
26
23
  mutate_child(index)
27
24
  delete_child(index)
@@ -64,7 +64,7 @@ module Mutant
64
64
  # @api private
65
65
  #
66
66
  def self.assert_valid_type(type)
67
- unless NODE_TYPES.include?(type) || type.kind_of?(Class)
67
+ unless AST::Types::ALL.include?(type) || type.kind_of?(Class)
68
68
  raise InvalidTypeError, "invalid type registration: #{type}"
69
69
  end
70
70
  end
@@ -3,6 +3,16 @@ module Mutant
3
3
  class Reporter
4
4
  include Adamantium::Flat, AbstractType
5
5
 
6
+ # Write warning message
7
+ #
8
+ # @param [String] message
9
+ #
10
+ # @return [self]
11
+ #
12
+ # @api private
13
+ #
14
+ abstract_method :warn
15
+
6
16
  # Report object
7
17
  #
8
18
  # @param [Object] object
@@ -19,6 +19,19 @@ module Mutant
19
19
  self
20
20
  end
21
21
 
22
+ # Report warning
23
+ #
24
+ # @param [String] message
25
+ #
26
+ # @return [self]
27
+ #
28
+ # @api private
29
+ #
30
+ def warn(message)
31
+ output.puts(message)
32
+ self
33
+ end
34
+
22
35
  # Report object
23
36
  #
24
37
  # @param [Object] object
@@ -13,6 +13,8 @@ module Mutant
13
13
  #
14
14
  # @return [self]
15
15
  #
16
+ # @api private
17
+ #
16
18
  def self.run(output, object)
17
19
  handler = lookup(object.class)
18
20
  handler.new(output, object).run
@@ -21,7 +21,7 @@ module Mutant
21
21
  if running?
22
22
  info 'Mutant configuration:'
23
23
  info 'Matcher: %s', config.matcher.inspect
24
- info 'Strategy: %s', config.strategy.inspect
24
+ info 'Integration: %s', config.integration.name
25
25
  info 'Expect Coverage: %0.2f%%', config.expected_coverage.inspect
26
26
  end
27
27
  self
@@ -11,6 +11,8 @@ module Mutant
11
11
  #
12
12
  # @return [self]
13
13
  #
14
+ # @api private
15
+ #
14
16
  def run
15
17
  self
16
18
  end
@@ -58,6 +58,8 @@ module Mutant
58
58
  #
59
59
  # @return [undefined]
60
60
  #
61
+ # @api private
62
+ #
61
63
  def included(host)
62
64
  object = self
63
65
  host.class_eval do
@@ -5,6 +5,18 @@ module Mutant
5
5
  class Null < self
6
6
  include Equalizer.new
7
7
 
8
+ # Write warning message
9
+ #
10
+ # @param [String] _message
11
+ #
12
+ # @return [self]
13
+ #
14
+ # @api private
15
+ #
16
+ def report(_message)
17
+ self
18
+ end
19
+
8
20
  # Report object
9
21
  #
10
22
  # @param [Object] _object
@@ -20,6 +20,8 @@ module Mutant
20
20
  #
21
21
  # @return [self]
22
22
  #
23
+ # @api private
24
+ #
23
25
  def report(object)
24
26
  report_calls << object
25
27
  self
@@ -31,6 +33,8 @@ module Mutant
31
33
  #
32
34
  # @return [self]
33
35
  #
36
+ # @api private
37
+ #
34
38
  def progress(object)
35
39
  progress_calls << object
36
40
  self
@@ -15,7 +15,7 @@ module Mutant
15
15
  #
16
16
  # @return [self]
17
17
  #
18
- # @api pivate
18
+ # @api private
19
19
  #
20
20
  def run
21
21
  infect
@@ -29,7 +29,7 @@ module Mutant
29
29
  #
30
30
  # @return [self]
31
31
  #
32
- # @api pivate
32
+ # @api private
33
33
  #
34
34
  def infect
35
35
  callback = @callback
File without changes
@@ -57,6 +57,8 @@ module Mutant
57
57
  #
58
58
  # @return [Boolean]
59
59
  #
60
+ # @api private
61
+ #
60
62
  def running?
61
63
  @running
62
64
  end
@@ -52,14 +52,14 @@ module Mutant
52
52
  end
53
53
  memoize :success?
54
54
 
55
- # Return strategy
55
+ # Return integration
56
56
  #
57
- # @return [Strategy]
57
+ # @return [Integration]
58
58
  #
59
59
  # @api private
60
60
  #
61
- def strategy
62
- config.strategy
61
+ def integration
62
+ config.integration
63
63
  end
64
64
 
65
65
  # Return coverage
@@ -115,13 +115,13 @@ module Mutant
115
115
  # @api private
116
116
  #
117
117
  def run_subjects
118
- strategy = self.strategy
119
- strategy.setup
118
+ integration = self.integration
119
+ integration.setup
120
120
  @subjects = visit_collection(config.subjects)
121
- strategy.teardown
121
+ integration.teardown
122
122
  end
123
123
 
124
- # Run with strategy management
124
+ # Run configuration
125
125
  #
126
126
  # @return [undefined]
127
127
  #