mutant 0.5.23 → 0.5.24

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 (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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 19cc50cff5125bbeef98eb0511a7c02c7154b4d5
4
- data.tar.gz: 153344653cd236a26f822ea809333a881b66491b
3
+ metadata.gz: 2af74623c08acfc217b54ebc8701ac11c122f243
4
+ data.tar.gz: c9899c8efaad75e829ebf634095a4e88ca72e693
5
5
  SHA512:
6
- metadata.gz: 1b3b1a8e57fcfc7c5423e16b1c7a375ef26494e1d6df55c12e458efcf7cc4f26be1681c379b7ce110d91f3c7179f43f294d099b1ce41203a162043ce893ba505
7
- data.tar.gz: 43b9c7b3c628cf529316433463083163ec8ae83911575df994cdc71d604b34a6e05872be557cef18150c78c20015973bd5db37fd81ec170b377f02b220264bc0
6
+ metadata.gz: 9f0f560faa4d8771649af1baef4ff2dd56c6d1a618ad7e4c640dbfcfc2f4e80b6c7963474e89f799a0f2ba1446a14a55dcab35c62653ce34462d042ca653d9dd
7
+ data.tar.gz: b2d1eb8f58ce5b1a9278e11456742853940c44c4cad7bb5ecaabb01e411576beab12fcdcc419899a2b8a33bd7afa36ea4b7eedc16995728861d38a580e6f13c5
@@ -1,3 +1,13 @@
1
+ # v0.5.24 2014-06-30
2
+
3
+ * Fix invalid AST on op_assign mutations
4
+ * Make subject matching result order deterministic
5
+ * Improve internals a bit for more consistency.
6
+ * Add instance methods expression 'Foo#'
7
+ * Add singleton methods expression 'Foo.'
8
+ * Split rspec2 and rspec3 integration with minimal duplication
9
+ * Move test matching outside of integrations.
10
+
1
11
  # v0.5.23 2014-06-15
2
12
 
3
13
  * Propagate exceptions from child-isolation-killforks to master
@@ -1,3 +1,3 @@
1
1
  ---
2
2
  threshold: 18
3
- total_score: 899
3
+ total_score: 973
@@ -25,12 +25,14 @@ DuplicateMethodCall:
25
25
  FeatureEnvy:
26
26
  enabled: true
27
27
  exclude:
28
+ - Mutant::Integration::Rspec2#full_description
29
+ - Mutant::Integration::Rspec3#full_description
28
30
  - Mutant::Matcher::Method::Instance#match?
29
31
  - Mutant::Matcher::Method::Singleton#receiver?
32
+ - Mutant::Matcher::Namespace#scope_name
30
33
  - Mutant::Mutation::Evil#success?
31
34
  - Mutant::Mutation::Neutral#success?
32
35
  - Mutant::Reporter::CLI#subject_results
33
- - Mutant::Rspec::Strategy#options
34
36
  # Nature of OptionParser :(
35
37
  - Mutant::CLI#add_environmental_options
36
38
  - Mutant::CLI#parse
@@ -61,7 +63,7 @@ NestedIterators:
61
63
  - Mutant::RequireHighjack#infect
62
64
  - Mutant::RequireHighjack#desinfect
63
65
  - Mutant::Reporter::CLI::Registry#included
64
- - Mutant::Strategy#tests
66
+ - Mutant::Config#tests
65
67
  - Parser::Lexer#self.new
66
68
  max_allowed_nesting: 1
67
69
  ignore_iterators: []
@@ -71,7 +73,6 @@ RepeatedConditional:
71
73
  enabled: true
72
74
  exclude:
73
75
  - Mutant::Mutator
74
- - Mutant::Rspec::Strategy
75
76
  - Mutant::Reporter::CLI
76
77
  - Mutant::Meta::Example::DSL
77
78
  max_ifs: 1
@@ -95,18 +96,15 @@ TooManyStatements:
95
96
  enabled: true
96
97
  exclude:
97
98
  - Mutant#self.singleton_subclass_instance
98
- - Mutant::Isolation#self.call
99
- - Mutant::Rspec::Killer#run
100
- - Mutant::Reporter::CLI#colorized_diff
101
99
  - Mutant::Reporter::CLI::Report::Config#run
100
+ - Mutant::Reporter::CLI::Registry#included
101
+ - Mutant::Reporter::CLI#colorized_diff
102
+ - Mutant::RequireHighjack#infect
103
+ - Mutant::Rspec::Killer#run
102
104
  - Mutant::Runner#visit_collection
103
105
  - Mutant::Runner#initialize
104
106
  - Mutant::Runner::Mutation#run
105
107
  - Mutant::Zombifier::File#self.find
106
- - Mutant::RequireHighjack#infect
107
- - Mutant::Reporter::CLI::Registry#included
108
- - Mutant::Rspec::Strategy#new_reporter
109
- - Mutant::Rspec::Strategy#run
110
108
  # How mutant does CLI parsing is shit
111
109
  - Mutant::CLI#parse
112
110
  - Mutant::CLI#initialize
@@ -116,7 +114,7 @@ UncommunicativeMethodName:
116
114
  enabled: true
117
115
  exclude:
118
116
  - Mutant::Mutation#sha1
119
- - Mutant::NodeHelpers#s
117
+ - Mutant::AST::Sexp#s
120
118
  reject:
121
119
  - !ruby/regexp /^[a-z]$/
122
120
  - !ruby/regexp /[0-9]$/
@@ -124,7 +122,9 @@ UncommunicativeMethodName:
124
122
  accept: []
125
123
  UncommunicativeModuleName:
126
124
  enabled: true
127
- exclude: []
125
+ exclude:
126
+ - Rspec2
127
+ - Rspec3
128
128
  reject:
129
129
  - !ruby/regexp /^.$/
130
130
  - !ruby/regexp /[0-9]$/
@@ -152,13 +152,13 @@ UtilityFunction:
152
152
  enabled: true
153
153
  exclude:
154
154
  - Mutant::CLI#reporter
155
+ - Mutant::Integration::Rspec#configuration
156
+ - Mutant::Integration::Rspec#options
157
+ - Mutant::Integration::Rspec2#full_description
158
+ - Mutant::Integration::Rspec2#new_reporter
159
+ - Mutant::Integration::Rspec3#full_description
160
+ - Mutant::Meta::Example::Verification#format_mutation
155
161
  - Mutant::Mutation::Evil#success?
156
162
  - Mutant::Mutation::Neutral#success?
157
- - Mutant::NodeHelpers#s
158
- - Mutant::Rspec::Strategy#configuration
159
- - Mutant::Rspec::Strategy#example_groups
160
- - Mutant::Rspec::Strategy#options
161
- - Mutant::Rspec::Strategy#world
162
- - Mutant::Rspec::Strategy#rspec2
163
- - Mutant::Meta::Example::Verification#format_mutation
163
+ - Mutant::AST::Sexp#s
164
164
  max_helper_calls: 0
@@ -25,45 +25,8 @@ module Mutant
25
25
  # The frozen empty array used within mutant
26
26
  EMPTY_ARRAY = [].freeze
27
27
 
28
- symbolset = ->(strings) { strings.map(&:to_sym).to_set.freeze }
29
-
30
28
  SCOPE_OPERATOR = '::'.freeze
31
29
 
32
- # Set of nodes that cannot be on the LHS of an assignment
33
- NOT_ASSIGNABLE = symbolset.(%w[int float str dstr class module self nil])
34
- # Set of op-assign types
35
- OP_ASSIGN = symbolset.call(%w[or_asgn and_asgn op_asgn])
36
- # Set of node types that are not valid when emitted standalone
37
- NOT_STANDALONE = symbolset.(%w[splat restarg block_pass])
38
- INDEX_OPERATORS = symbolset.(%w[[] []=])
39
- UNARY_METHOD_OPERATORS = symbolset.(%w[~@ +@ -@ !])
40
-
41
- # Operators ruby implementeds as methods
42
- METHOD_OPERATORS = symbolset.(%w[
43
- <=> === []= [] <= >= == !~ != =~ <<
44
- >> ** * % / | ^ & < > + - ~@ +@ -@ !
45
- ])
46
-
47
- BINARY_METHOD_OPERATORS = (
48
- METHOD_OPERATORS - (INDEX_OPERATORS + UNARY_METHOD_OPERATORS)
49
- ).to_set.freeze
50
-
51
- OPERATOR_METHODS = (
52
- METHOD_OPERATORS + INDEX_OPERATORS + UNARY_METHOD_OPERATORS
53
- ).to_set.freeze
54
-
55
- # Nodes that are NOT handled by mutant.
56
- #
57
- # not - 1.8 only, mutant does not support 1.8
58
- #
59
- NODE_BLACKLIST = symbolset.(%w[not])
60
-
61
- # Nodes that are NOT generated by parser but used by mutant / unparser.
62
- NODE_EXTRA = symbolset.(%w[empty])
63
-
64
- # All node types mutant handles
65
- NODE_TYPES = ((Parser::Meta::NODE_TYPES + NODE_EXTRA) - NODE_BLACKLIST).to_set.freeze
66
-
67
30
  # Lookup constant for location
68
31
  #
69
32
  # @param [String] location
@@ -116,9 +79,16 @@ module Mutant
116
79
  end # Mutant
117
80
 
118
81
  require 'mutant/version'
82
+ require 'mutant/env'
83
+ require 'mutant/ast'
84
+ require 'mutant/ast/sexp'
85
+ require 'mutant/ast/types'
86
+ require 'mutant/ast/nodes'
87
+ require 'mutant/ast/named_children'
88
+ require 'mutant/ast/node_predicates'
89
+ require 'mutant/ast/meta'
119
90
  require 'mutant/cache'
120
91
  require 'mutant/delegator'
121
- require 'mutant/node_helpers'
122
92
  require 'mutant/warning_filter'
123
93
  require 'mutant/warning_expectation'
124
94
  require 'mutant/walker'
@@ -195,6 +165,7 @@ require 'mutant/subject/method'
195
165
  require 'mutant/subject/method/instance'
196
166
  require 'mutant/subject/method/singleton'
197
167
  require 'mutant/matcher'
168
+ require 'mutant/matcher/builder'
198
169
  require 'mutant/matcher/chain'
199
170
  require 'mutant/matcher/method'
200
171
  require 'mutant/matcher/method/finder'
@@ -207,10 +178,12 @@ require 'mutant/matcher/filter'
207
178
  require 'mutant/matcher/null'
208
179
  require 'mutant/expression'
209
180
  require 'mutant/expression/method'
181
+ require 'mutant/expression/methods'
210
182
  require 'mutant/expression/namespace'
211
183
  require 'mutant/killer'
212
184
  require 'mutant/test'
213
- require 'mutant/strategy'
185
+ require 'mutant/test/report'
186
+ require 'mutant/integration'
214
187
  require 'mutant/runner'
215
188
  require 'mutant/runner/config'
216
189
  require 'mutant/runner/subject'
@@ -0,0 +1,5 @@
1
+ module Mutant
2
+ # AST helpers
3
+ module AST
4
+ end # AST
5
+ end # Mutant
@@ -0,0 +1,131 @@
1
+ module Mutant
2
+ module AST
3
+ # Node meta information mixin
4
+ module Meta
5
+
6
+ REGISTRY = {}
7
+
8
+ # Return meta for node
9
+ #
10
+ # @param [Parser::AST::Node] node
11
+ #
12
+ # @return [Meta]
13
+ #
14
+ # @api private
15
+ #
16
+ def self.for(node)
17
+ REGISTRY.fetch(node.type, Generic).new(node)
18
+ end
19
+
20
+ # Generic metadata for send nodes
21
+ class Send
22
+ include Concord.new(:node), NamedChildren
23
+
24
+ children :receiver, :selector
25
+
26
+ REGISTRY[:send] = self
27
+
28
+ INDEX_ASSIGNMENT_SELECTOR = :[]=
29
+ ATTRIBUTE_ASSIGNMENT_SELECTOR_SUFFIX = '='.freeze
30
+
31
+ # Return arguments
32
+ #
33
+ # @return [Enumerable<Parser::AST::Node>]
34
+ #
35
+ # @api private
36
+ #
37
+ alias_method :arguments, :remaining_children
38
+
39
+ # Test if AST node is a valid assignment target
40
+ #
41
+ # @return [Boolean]
42
+ #
43
+ # @api private
44
+ #
45
+ def assignment?
46
+ index_assignment? || attribute_assignment?
47
+ end
48
+
49
+ # Test if AST node is an attribute assignment?
50
+ #
51
+ # @return [Boolean]
52
+ #
53
+ # @api private
54
+ #
55
+ def attribute_assignment?
56
+ arguments.one? && attribute_assignment_selector?
57
+ end
58
+
59
+ # Test if AST node is an index assign
60
+ #
61
+ # @return [Boolean]
62
+ #
63
+ # @api private
64
+ #
65
+ def index_assignment?
66
+ arguments.length.equal?(2) && index_assignment_selector?
67
+ end
68
+
69
+ # Test for binary operator implemented as method
70
+ #
71
+ # @return [Boolean]
72
+ #
73
+ # @api private
74
+ #
75
+ def binary_method_operator?
76
+ arguments.one? && Types::BINARY_METHOD_OPERATORS.include?(selector)
77
+ end
78
+
79
+ # Test if node is part of an mlhs
80
+ #
81
+ # @return [Boolean]
82
+ #
83
+ # @api private
84
+ #
85
+ def mlhs?
86
+ (index_assignment_selector? && arguments.one?) || (arguments.empty? && attribute_assignment_selector?)
87
+ end
88
+
89
+ private
90
+
91
+ # Test for index assignment operator
92
+ #
93
+ # @return [Boolean]
94
+ #
95
+ # @api private
96
+ #
97
+ def index_assignment_selector?
98
+ selector.equal?(INDEX_ASSIGNMENT_SELECTOR)
99
+ end
100
+
101
+ # Test for attribute assignment selector
102
+ #
103
+ # @return [Boolean]
104
+ #
105
+ # @api private
106
+ #
107
+ def attribute_assignment_selector?
108
+ !Types::METHOD_OPERATORS.include?(selector) && selector.to_s.end_with?(ATTRIBUTE_ASSIGNMENT_SELECTOR_SUFFIX)
109
+ end
110
+
111
+ end # Send
112
+
113
+ # Generic node metatada
114
+ class Generic
115
+ include Adamantium, Concord.new(:node)
116
+
117
+ # Test if AST node is a valid assign target
118
+ #
119
+ # @return [Boolean]
120
+ #
121
+ # @api private
122
+ #
123
+ def assignment?
124
+ Types::ASSIGNABLE_VARIABLES.include?(node.type)
125
+ end
126
+
127
+ end # Generic
128
+
129
+ end #
130
+ end # AST
131
+ end # Mutant
@@ -0,0 +1,98 @@
1
+ module Mutant
2
+ module AST
3
+
4
+ # Helper methods to define named children
5
+ module NamedChildren
6
+
7
+ # Hook called when module gets included
8
+ #
9
+ # @param [Class, Module] host
10
+ #
11
+ # @return [undefined]
12
+ #
13
+ # @api private
14
+ #
15
+ def self.included(host)
16
+ super
17
+ host.class_eval do
18
+ include InstanceMethods
19
+ extend ClassMethods
20
+ end
21
+ end
22
+
23
+ # Methods mixed int ot instance level
24
+ module InstanceMethods
25
+
26
+ private
27
+
28
+ # Return children
29
+ #
30
+ # @return [Array<Parser::AST::Node]
31
+ #
32
+ # @api private
33
+ #
34
+ def children
35
+ node.children
36
+ end
37
+
38
+ end # InstanceMethods
39
+
40
+ # Methods mixed in at class level
41
+ module ClassMethods
42
+
43
+ private
44
+
45
+ # Define named child
46
+ #
47
+ # @param [Symbol] name
48
+ # @param [Fixnum] index
49
+ #
50
+ # @return [undefined]
51
+ #
52
+ # @api private
53
+ #
54
+ def define_named_child(name, index)
55
+ define_method(name) do
56
+ children.at(index)
57
+ end
58
+ end
59
+
60
+ # Define remaining children
61
+ #
62
+ # @param [Array<Symbol>] names
63
+ #
64
+ # @return [undefined]
65
+ #
66
+ # @api private
67
+ #
68
+ def define_remaining_children(names)
69
+ define_method(:remaining_children_with_index) do
70
+ children.each_with_index.drop(names.length)
71
+ end
72
+
73
+ define_method(:remaining_children_indices) do
74
+ children.each_index.drop(names.length)
75
+ end
76
+
77
+ define_method(:remaining_children) do
78
+ children.drop(names.length)
79
+ end
80
+ end
81
+
82
+ # Create name helpers
83
+ #
84
+ # @return [undefined]
85
+ #
86
+ # @api private
87
+ #
88
+ def children(*names)
89
+ names.each_with_index do |name, index|
90
+ define_named_child(name, index)
91
+ end
92
+ define_remaining_children(names)
93
+ end
94
+
95
+ end # ClassMethods
96
+ end # NamedChildren
97
+ end # AST
98
+ end # Mutant