mutant 0.3.3 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|