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.
- checksums.yaml +4 -4
- data/Changelog.md +10 -0
- data/config/flay.yml +1 -1
- data/config/reek.yml +19 -19
- data/lib/mutant.rb +12 -39
- data/lib/mutant/ast.rb +5 -0
- data/lib/mutant/ast/meta.rb +131 -0
- data/lib/mutant/ast/named_children.rb +98 -0
- data/lib/mutant/ast/node_predicates.rb +19 -0
- data/lib/mutant/ast/nodes.rb +21 -0
- data/lib/mutant/ast/sexp.rb +34 -0
- data/lib/mutant/ast/types.rb +48 -0
- data/lib/mutant/cache.rb +3 -2
- data/lib/mutant/cli.rb +11 -151
- data/lib/mutant/config.rb +22 -2
- data/lib/mutant/context/scope.rb +11 -21
- data/lib/mutant/delegator.rb +2 -0
- data/lib/mutant/diff.rb +7 -3
- data/lib/mutant/env.rb +49 -0
- data/lib/mutant/expression.rb +36 -8
- data/lib/mutant/expression/methods.rb +62 -0
- data/lib/mutant/expression/namespace.rb +41 -28
- data/lib/mutant/{strategy.rb → integration.rb} +12 -31
- data/lib/mutant/isolation.rb +1 -1
- data/lib/mutant/matcher.rb +1 -21
- data/lib/mutant/matcher/builder.rb +142 -0
- data/lib/mutant/matcher/method.rb +3 -7
- data/lib/mutant/matcher/method/instance.rb +6 -5
- data/lib/mutant/matcher/method/singleton.rb +2 -7
- data/lib/mutant/matcher/methods.rb +11 -14
- data/lib/mutant/matcher/namespace.rb +31 -39
- data/lib/mutant/matcher/scope.rb +13 -2
- data/lib/mutant/meta.rb +0 -1
- data/lib/mutant/meta/example/dsl.rb +5 -1
- data/lib/mutant/mutator/node.rb +16 -44
- data/lib/mutant/mutator/node/or_asgn.rb +1 -1
- data/lib/mutant/mutator/node/send.rb +5 -60
- data/lib/mutant/mutator/node/super.rb +2 -5
- data/lib/mutant/mutator/registry.rb +1 -1
- data/lib/mutant/reporter.rb +10 -0
- data/lib/mutant/reporter/cli.rb +13 -0
- data/lib/mutant/reporter/cli/printer.rb +2 -0
- data/lib/mutant/reporter/cli/progress/config.rb +1 -1
- data/lib/mutant/reporter/cli/progress/noop.rb +2 -0
- data/lib/mutant/reporter/cli/registry.rb +2 -0
- data/lib/mutant/reporter/null.rb +12 -0
- data/lib/mutant/reporter/trace.rb +4 -0
- data/lib/mutant/require_highjack.rb +2 -2
- data/lib/mutant/rspec.rb +0 -0
- data/lib/mutant/runner.rb +2 -0
- data/lib/mutant/runner/config.rb +8 -8
- data/lib/mutant/runner/killer.rb +5 -0
- data/lib/mutant/runner/subject.rb +1 -1
- data/lib/mutant/subject.rb +8 -8
- data/lib/mutant/subject/method.rb +3 -2
- data/lib/mutant/subject/method/instance.rb +1 -1
- data/lib/mutant/test.rb +7 -65
- data/lib/mutant/test/report.rb +59 -0
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/warning_filter.rb +2 -0
- data/lib/mutant/zombifier.rb +3 -0
- data/lib/mutant/zombifier/file.rb +1 -1
- data/meta/or_asgn.rb +11 -0
- data/meta/send.rb +1 -1
- data/mutant-rspec.gemspec +1 -1
- data/mutant.gemspec +1 -1
- data/spec/integration/mutant/corpus_spec.rb +2 -0
- data/spec/integration/mutant/test_mutator_handles_types_spec.rb +2 -2
- data/spec/spec_helper.rb +4 -3
- data/spec/unit/mutant/cli_new_spec.rb +11 -11
- data/spec/unit/mutant/expression/methods_spec.rb +43 -0
- data/spec/unit/mutant/expression/namespace/flat_spec.rb +1 -1
- data/spec/unit/mutant/expression/namespace/recursive_spec.rb +19 -5
- data/spec/unit/mutant/{strategy_spec.rb → integration_spec.rb} +1 -1
- data/spec/unit/mutant/isolation_spec.rb +3 -1
- data/spec/unit/mutant/matcher/method/instance_spec.rb +5 -5
- data/spec/unit/mutant/matcher/method/singleton_spec.rb +8 -8
- data/spec/unit/mutant/matcher/methods/instance_spec.rb +5 -8
- data/spec/unit/mutant/matcher/methods/singleton_spec.rb +5 -5
- data/spec/unit/mutant/matcher/namespace_spec.rb +18 -23
- data/spec/unit/mutant/mutation_spec.rb +1 -1
- data/spec/unit/mutant/runner/config_spec.rb +4 -5
- data/spec/unit/mutant/runner/mutation_spec.rb +21 -21
- data/spec/unit/mutant/runner/subject_spec.rb +6 -6
- data/spec/unit/mutant/subject/method/instance_spec.rb +0 -4
- data/spec/unit/mutant/subject/method/singleton_spec.rb +0 -1
- data/spec/unit/mutant/subject_spec.rb +3 -3
- metadata +20 -6
- data/lib/mutant/node_helpers.rb +0 -52
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2af74623c08acfc217b54ebc8701ac11c122f243
|
4
|
+
data.tar.gz: c9899c8efaad75e829ebf634095a4e88ca72e693
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f0f560faa4d8771649af1baef4ff2dd56c6d1a618ad7e4c640dbfcfc2f4e80b6c7963474e89f799a0f2ba1446a14a55dcab35c62653ce34462d042ca653d9dd
|
7
|
+
data.tar.gz: b2d1eb8f58ce5b1a9278e11456742853940c44c4cad7bb5ecaabb01e411576beab12fcdcc419899a2b8a33bd7afa36ea4b7eedc16995728861d38a580e6f13c5
|
data/Changelog.md
CHANGED
@@ -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
|
data/config/flay.yml
CHANGED
data/config/reek.yml
CHANGED
@@ -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::
|
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::
|
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::
|
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
|
data/lib/mutant.rb
CHANGED
@@ -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/
|
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'
|
data/lib/mutant/ast.rb
ADDED
@@ -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
|