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
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