mutant 0.3.3 → 0.3.4
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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -0
- data/Changelog.md +6 -0
- data/config/flay.yml +1 -1
- data/lib/mutant.rb +1 -26
- data/lib/mutant/constants.rb +24 -22
- data/lib/mutant/mutator/node/send.rb +63 -5
- data/lib/mutant/version.rb +1 -1
- data/lib/parser-node-list.rb +26 -0
- data/mutant.gemspec +1 -1
- data/spec/unit/mutant/mutator/node/send_spec.rb +31 -11
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 673a7c4c1760422c883da5e4808459a53738661e
|
4
|
+
data.tar.gz: 08bd96b3e089053be868b81f93f6b71f85c9d99e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbd708905cb93671b7d3f714422873ca056a46c86c902a633f9b2ee948e323448434d25cc4cf547d10bad59bc90ccd101d005f2e415f67fbed885fc48c834d05
|
7
|
+
data.tar.gz: 308364fea4146848b5bccc79ec9b5249850a21cecc23eea59ae71887170cefc0ef781825069a2110e16fcd2b78fa8e7dade18f57b38ab19695e8cd8404da4bf4
|
data/.travis.yml
CHANGED
data/Changelog.md
CHANGED
data/config/flay.yml
CHANGED
data/lib/mutant.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
require 'stringio'
|
4
|
-
require 'benchmark'
|
5
4
|
require 'set'
|
6
5
|
require 'adamantium'
|
7
6
|
require 'ice_nine'
|
@@ -13,6 +12,7 @@ require 'digest/sha1'
|
|
13
12
|
require 'inflecto'
|
14
13
|
require 'parser'
|
15
14
|
require 'parser/current'
|
15
|
+
require 'parser-node-list'
|
16
16
|
require 'unparser'
|
17
17
|
require 'ice_nine'
|
18
18
|
require 'diff/lcs'
|
@@ -22,31 +22,6 @@ require 'anima'
|
|
22
22
|
require 'concord'
|
23
23
|
require 'rspec'
|
24
24
|
|
25
|
-
# Monkeypatch on parser with a list of allowed nodes.
|
26
|
-
# Will be pushed upstream once turning out to be correct.
|
27
|
-
module Parser
|
28
|
-
module Meta
|
29
|
-
NODE_TYPES =
|
30
|
-
%w(
|
31
|
-
true false nil int float str dstr str
|
32
|
-
sym dsym xstr regopt regexp array splat
|
33
|
-
array pair kwsplat hash irange erange self
|
34
|
-
lvar ivar cvar gvar const defined? lvasgn
|
35
|
-
ivasgn cvasgn gvasgn casgn mlhs masgn op_asgn
|
36
|
-
op_asgn and_asgn ensure rescue arg_expr
|
37
|
-
or_asgn and_asgn or_asgn back_ref nth_ref
|
38
|
-
match_with_lvasgn match_current_line
|
39
|
-
module class sclass def defs undef alias args
|
40
|
-
cbase arg optarg restarg blockarg block_pass args def kwarg kwoptarg
|
41
|
-
kwrestarg send super zsuper yield block send
|
42
|
-
and not or if when case while until while_post
|
43
|
-
until_post for break next redo return resbody
|
44
|
-
kwbegin begin retry preexe postexe iflipflop eflipflop
|
45
|
-
shadowarg
|
46
|
-
).map(&:to_sym).to_set.freeze
|
47
|
-
end # Meta
|
48
|
-
end # Parser
|
49
|
-
|
50
25
|
# Library namespace
|
51
26
|
module Mutant
|
52
27
|
# The empty string used within this namespace
|
data/lib/mutant/constants.rb
CHANGED
@@ -2,30 +2,36 @@
|
|
2
2
|
|
3
3
|
module Mutant
|
4
4
|
|
5
|
+
# Return a frozen set of symbols from string enumerable
|
6
|
+
#
|
7
|
+
# @param [Enumerable<String>]
|
8
|
+
#
|
9
|
+
# @return [Set<Symbol>]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
#
|
13
|
+
def self.symbolset(strings)
|
14
|
+
strings.map(&:to_sym).to_set.freeze
|
15
|
+
end
|
16
|
+
private_class_method :symbolset
|
17
|
+
|
5
18
|
# Set of nodes that cannot be on the LHS of an assignment
|
6
|
-
NOT_ASSIGNABLE =
|
7
|
-
|
8
|
-
|
19
|
+
NOT_ASSIGNABLE = symbolset %w(
|
20
|
+
int float str dstr class module self
|
21
|
+
)
|
9
22
|
|
10
23
|
# Set of op-assign types
|
11
|
-
OP_ASSIGN
|
12
|
-
:or_asgn, :and_asgn, :op_asgn
|
13
|
-
].to_set.freeze
|
14
|
-
|
24
|
+
OP_ASSIGN = symbolset %w(or_asgn and_asgn op_asgn)
|
15
25
|
# Set of node types that are not valid when emitted standalone
|
16
|
-
NOT_STANDALONE
|
26
|
+
NOT_STANDALONE = symbolset %w( splat restarg block_pass)
|
27
|
+
INDEX_OPERATORS = symbolset %w([] []=)
|
28
|
+
UNARY_METHOD_OPERATORS = symbolset %w(~@ +@ -@ !)
|
17
29
|
|
18
30
|
# Operators ruby implementeds as methods
|
19
|
-
METHOD_OPERATORS = %w(
|
31
|
+
METHOD_OPERATORS = symbolset %w(
|
20
32
|
<=> === []= [] <= >= == !~ != =~ <<
|
21
33
|
>> ** * % / | ^ & < > + - ~@ +@ -@ !
|
22
|
-
)
|
23
|
-
|
24
|
-
INDEX_OPERATORS = [:[], :[]=].to_set.freeze
|
25
|
-
|
26
|
-
UNARY_METHOD_OPERATORS = %w(
|
27
|
-
~@ +@ -@ !
|
28
|
-
).map(&:to_sym).to_set.freeze
|
34
|
+
)
|
29
35
|
|
30
36
|
BINARY_METHOD_OPERATORS = (
|
31
37
|
METHOD_OPERATORS - (INDEX_OPERATORS + UNARY_METHOD_OPERATORS)
|
@@ -39,14 +45,10 @@ module Mutant
|
|
39
45
|
#
|
40
46
|
# not - 1.8 only, mutant does not support 1.8
|
41
47
|
#
|
42
|
-
NODE_BLACKLIST = %w(
|
43
|
-
not
|
44
|
-
).map(&:to_sym).freeze
|
48
|
+
NODE_BLACKLIST = symbolset %w(not)
|
45
49
|
|
46
50
|
# Nodes that are NOT generated by parser but used by mutant / unparser.
|
47
|
-
NODE_EXTRA = %w(
|
48
|
-
empty
|
49
|
-
).map(&:to_sym).freeze
|
51
|
+
NODE_EXTRA = symbolset %w(empty)
|
50
52
|
|
51
53
|
NODE_TYPES = ((Parser::Meta::NODE_TYPES + NODE_EXTRA) - NODE_BLACKLIST).to_set.freeze
|
52
54
|
|
@@ -18,7 +18,7 @@ module Mutant
|
|
18
18
|
|
19
19
|
INDEX_REFERENCE = :[]
|
20
20
|
INDEX_ASSIGN = :[]=
|
21
|
-
ASSIGN_SUFFIX =
|
21
|
+
ASSIGN_SUFFIX = '='.freeze
|
22
22
|
|
23
23
|
# Base mutator for index operations
|
24
24
|
class Index < self
|
@@ -81,11 +81,12 @@ module Mutant
|
|
81
81
|
# @api private
|
82
82
|
#
|
83
83
|
def non_index_dispatch
|
84
|
-
|
84
|
+
case
|
85
|
+
when binary_operator?
|
85
86
|
run(Binary)
|
86
|
-
|
87
|
+
else
|
88
|
+
normal_dispatch
|
87
89
|
end
|
88
|
-
normal_dispatch
|
89
90
|
end
|
90
91
|
|
91
92
|
# Return arguments
|
@@ -149,6 +150,19 @@ module Mutant
|
|
149
150
|
arguments.one? && BINARY_METHOD_OPERATORS.include?(selector)
|
150
151
|
end
|
151
152
|
|
153
|
+
# Test for attribute assignment
|
154
|
+
#
|
155
|
+
# @return [true]
|
156
|
+
# if node represetns and attribute assignment
|
157
|
+
#
|
158
|
+
# @return [false]
|
159
|
+
#
|
160
|
+
# @api private
|
161
|
+
#
|
162
|
+
def attribute_assignment?
|
163
|
+
!BINARY_OPERATORS.include?(selector) && !UNARY_OPERATORS.include?(selector) && assignment? && !mlhs?
|
164
|
+
end
|
165
|
+
|
152
166
|
# Mutate arguments
|
153
167
|
#
|
154
168
|
# @return [undefined]
|
@@ -196,11 +210,55 @@ module Mutant
|
|
196
210
|
# @api private
|
197
211
|
#
|
198
212
|
def emit_implicit_self
|
199
|
-
if receiver.type == :self
|
213
|
+
if receiver.type == :self && !KEYWORDS.include?(selector) && !attribute_assignment?
|
200
214
|
emit_receiver(nil)
|
201
215
|
end
|
202
216
|
end
|
203
217
|
|
218
|
+
# Test for assignment
|
219
|
+
#
|
220
|
+
# FIXME: This also returns true for <= operator!
|
221
|
+
#
|
222
|
+
# @return [true]
|
223
|
+
# if node represents attribute / element assignment
|
224
|
+
#
|
225
|
+
# @return [false]
|
226
|
+
# otherwise
|
227
|
+
#
|
228
|
+
# @api private
|
229
|
+
#
|
230
|
+
def assignment?
|
231
|
+
selector.to_s[-1] == ASSIGN_SUFFIX
|
232
|
+
end
|
233
|
+
|
234
|
+
# Test for mlhs
|
235
|
+
#
|
236
|
+
# @return [true]
|
237
|
+
# if node is within an mlhs
|
238
|
+
#
|
239
|
+
# @return [false]
|
240
|
+
# otherwise
|
241
|
+
#
|
242
|
+
# @api private
|
243
|
+
#
|
244
|
+
def mlhs?
|
245
|
+
assignment? && !arguments?
|
246
|
+
end
|
247
|
+
|
248
|
+
# Test for empty arguments
|
249
|
+
#
|
250
|
+
# @return [true]
|
251
|
+
# if arguments are empty
|
252
|
+
#
|
253
|
+
# @return [false]
|
254
|
+
# otherwise
|
255
|
+
#
|
256
|
+
# @api private
|
257
|
+
#
|
258
|
+
def arguments?
|
259
|
+
arguments.any?
|
260
|
+
end
|
261
|
+
|
204
262
|
end # Send
|
205
263
|
end # Node
|
206
264
|
end # Mutator
|
data/lib/mutant/version.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Monkeypatch on parser with a list of allowed nodes.
|
4
|
+
# Will be pushed upstream once turning out to be correct.
|
5
|
+
module Parser
|
6
|
+
module Meta
|
7
|
+
NODE_TYPES =
|
8
|
+
%w(
|
9
|
+
true false nil int float str dstr str
|
10
|
+
sym dsym xstr regopt regexp array splat
|
11
|
+
array pair kwsplat hash irange erange self
|
12
|
+
lvar ivar cvar gvar const defined? lvasgn
|
13
|
+
ivasgn cvasgn gvasgn casgn mlhs masgn op_asgn
|
14
|
+
op_asgn and_asgn ensure rescue arg_expr
|
15
|
+
or_asgn and_asgn or_asgn back_ref nth_ref
|
16
|
+
match_with_lvasgn match_current_line
|
17
|
+
module class sclass def defs undef alias args
|
18
|
+
cbase arg optarg restarg blockarg block_pass args def kwarg kwoptarg
|
19
|
+
kwrestarg send super zsuper yield block send
|
20
|
+
and not or if when case while until while_post
|
21
|
+
until_post for break next redo return resbody
|
22
|
+
kwbegin begin retry preexe postexe iflipflop eflipflop
|
23
|
+
shadowarg
|
24
|
+
).map(&:to_sym).to_set.freeze
|
25
|
+
end # Meta
|
26
|
+
end # Parser
|
data/mutant.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |gem|
|
|
20
20
|
|
21
21
|
gem.required_ruby_version = '>= 1.9.3'
|
22
22
|
|
23
|
-
gem.add_runtime_dependency('parser', '~> 2.1.
|
23
|
+
gem.add_runtime_dependency('parser', '~> 2.1.4')
|
24
24
|
gem.add_runtime_dependency('procto', '~> 0.0.2')
|
25
25
|
gem.add_runtime_dependency('abstract_type', '~> 0.0.7')
|
26
26
|
gem.add_runtime_dependency('unparser', '~> 0.1.8')
|
@@ -56,20 +56,40 @@ describe Mutant::Mutator, 'send' do
|
|
56
56
|
end
|
57
57
|
|
58
58
|
context 'attribute assign' do
|
59
|
-
let(:source) { 'foo.bar=baz' }
|
60
59
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
mutations
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
60
|
+
context 'to self' do
|
61
|
+
let(:source) { 'self.bar=baz' }
|
62
|
+
|
63
|
+
let(:mutations) do
|
64
|
+
mutations = []
|
65
|
+
mutations << 'nil'
|
66
|
+
mutations << 'self.bar=nil'
|
67
|
+
mutations << 'self'
|
68
|
+
mutations << 'self.bar'
|
69
|
+
mutations << 'baz'
|
70
|
+
# This one could probably be removed
|
71
|
+
mutations << 'nil.bar=baz'
|
72
|
+
end
|
73
|
+
|
74
|
+
it_should_behave_like 'a mutator'
|
70
75
|
end
|
71
76
|
|
72
|
-
|
77
|
+
context 'to other object' do
|
78
|
+
let(:source) { 'foo.bar=baz' }
|
79
|
+
|
80
|
+
let(:mutations) do
|
81
|
+
mutations = []
|
82
|
+
mutations << 'foo'
|
83
|
+
mutations << 'nil'
|
84
|
+
mutations << 'foo.bar=nil'
|
85
|
+
mutations << 'foo.bar'
|
86
|
+
mutations << 'baz'
|
87
|
+
# This one could probably be removed
|
88
|
+
mutations << 'nil.bar=baz'
|
89
|
+
end
|
90
|
+
|
91
|
+
it_should_behave_like 'a mutator'
|
92
|
+
end
|
73
93
|
end
|
74
94
|
|
75
95
|
context 'index assign' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mutant
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Markus Schirp
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 2.1.
|
19
|
+
version: 2.1.4
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 2.1.
|
26
|
+
version: 2.1.4
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: procto
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -344,6 +344,7 @@ files:
|
|
344
344
|
- lib/mutant/subject/method/singleton.rb
|
345
345
|
- lib/mutant/version.rb
|
346
346
|
- lib/mutant/zombifier.rb
|
347
|
+
- lib/parser-node-list.rb
|
347
348
|
- mutant.gemspec
|
348
349
|
- spec/integration/mutant/rspec_spec.rb
|
349
350
|
- spec/integration/mutant/test_mutator_handles_types_spec.rb
|