mutant 0.10.23 → 0.10.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/lib/mutant.rb +20 -4
- data/lib/mutant/ast/regexp.rb +37 -0
- data/lib/mutant/ast/regexp/transformer.rb +150 -0
- data/lib/mutant/ast/regexp/transformer/direct.rb +121 -0
- data/lib/mutant/ast/regexp/transformer/named_group.rb +50 -0
- data/lib/mutant/ast/regexp/transformer/options_group.rb +68 -0
- data/lib/mutant/ast/regexp/transformer/quantifier.rb +90 -0
- data/lib/mutant/ast/regexp/transformer/recursive.rb +56 -0
- data/lib/mutant/ast/regexp/transformer/root.rb +28 -0
- data/lib/mutant/ast/regexp/transformer/text.rb +58 -0
- data/lib/mutant/ast/types.rb +115 -2
- data/lib/mutant/cli/command/environment.rb +9 -3
- data/lib/mutant/config.rb +8 -54
- data/lib/mutant/config/coverage_criteria.rb +61 -0
- data/lib/mutant/expression.rb +0 -12
- data/lib/mutant/matcher.rb +2 -2
- data/lib/mutant/matcher/config.rb +25 -6
- data/lib/mutant/matcher/method.rb +2 -3
- data/lib/mutant/meta/example/dsl.rb +6 -1
- data/lib/mutant/mutator/node/kwargs.rb +2 -2
- data/lib/mutant/mutator/node/literal/regex.rb +26 -0
- data/lib/mutant/mutator/node/regexp.rb +31 -0
- data/lib/mutant/mutator/node/regexp/alternation_meta.rb +20 -0
- data/lib/mutant/mutator/node/regexp/capture_group.rb +25 -0
- data/lib/mutant/mutator/node/regexp/character_type.rb +31 -0
- data/lib/mutant/mutator/node/regexp/end_of_line_anchor.rb +20 -0
- data/lib/mutant/mutator/node/regexp/end_of_string_or_before_end_of_line_anchor.rb +20 -0
- data/lib/mutant/mutator/node/regexp/greedy_zero_or_more.rb +24 -0
- data/lib/mutant/subject.rb +1 -3
- data/lib/mutant/subject/method/instance.rb +1 -3
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/world.rb +1 -2
- metadata +40 -4
- data/lib/mutant/warnings.rb +0 -106
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
module AST
|
5
|
+
module Regexp
|
6
|
+
class Transformer
|
7
|
+
# Transformer for option groups
|
8
|
+
class OptionsGroup < self
|
9
|
+
register :regexp_options_group
|
10
|
+
register :regexp_options_switch_group
|
11
|
+
|
12
|
+
# Mapper from `Regexp::Expression` to `Parser::AST::Node`
|
13
|
+
class ExpressionToAST < Transformer::ExpressionToAST
|
14
|
+
|
15
|
+
# Transform options group into node
|
16
|
+
#
|
17
|
+
# @return [Parser::AST::Node]
|
18
|
+
def call
|
19
|
+
quantify(ast(expression.option_changes, *children))
|
20
|
+
end
|
21
|
+
end # ExpressionToAST
|
22
|
+
|
23
|
+
# Mapper from `Parser::AST::Node` to `Regexp::Expression`
|
24
|
+
class ASTToExpression < Transformer::ASTToExpression
|
25
|
+
include NamedChildren
|
26
|
+
|
27
|
+
children :option_changes
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def transform
|
32
|
+
options_group.tap do |expression|
|
33
|
+
expression.expressions = subexpressions
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def subexpressions
|
38
|
+
remaining_children.map(&Regexp.public_method(:to_expression))
|
39
|
+
end
|
40
|
+
|
41
|
+
def options_group
|
42
|
+
::Regexp::Expression::Group::Options.new(
|
43
|
+
::Regexp::Token.new(:group, type, text)
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
def type
|
48
|
+
{
|
49
|
+
regexp_options_group: :options,
|
50
|
+
regexp_options_switch_group: :options_switch
|
51
|
+
}.fetch(node.type)
|
52
|
+
end
|
53
|
+
|
54
|
+
def text
|
55
|
+
pos, neg = option_changes.partition { |_opt, val| val }.map do |arr|
|
56
|
+
arr.map(&:first).join
|
57
|
+
end
|
58
|
+
neg_opt_sep = '-' unless neg.empty?
|
59
|
+
content_sep = ':' unless type.equal?(:options_switch)
|
60
|
+
|
61
|
+
"(?#{pos}#{neg_opt_sep}#{neg}#{content_sep}"
|
62
|
+
end
|
63
|
+
end # ASTToExpression
|
64
|
+
end # OptionsGroup
|
65
|
+
end # Transformer
|
66
|
+
end # Regexp
|
67
|
+
end # AST
|
68
|
+
end # Mutant
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
module AST
|
5
|
+
module Regexp
|
6
|
+
class Transformer
|
7
|
+
# Transformer for regexp quantifiers
|
8
|
+
class Quantifier < self
|
9
|
+
# Mapper from `Regexp::Expression` to `Parser::AST::Node`
|
10
|
+
class ExpressionToAST < Transformer::ExpressionToAST
|
11
|
+
# Transform quantifier into node
|
12
|
+
#
|
13
|
+
# @return [Parser::AST::Node]
|
14
|
+
def call
|
15
|
+
ast(expression.min, expression.max)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def type
|
21
|
+
:"regexp_#{expression.mode}_#{expression.token}"
|
22
|
+
end
|
23
|
+
end # ExpressionToAST
|
24
|
+
|
25
|
+
# Mapper from `Parser::AST::Node` to `Regexp::Expression`
|
26
|
+
class ASTToExpression < Transformer::ASTToExpression
|
27
|
+
include NamedChildren
|
28
|
+
|
29
|
+
children :min, :max, :subject
|
30
|
+
|
31
|
+
Quantifier = Class.new.include(Concord::Public.new(:type, :suffix, :mode))
|
32
|
+
|
33
|
+
QUANTIFIER_MAP = IceNine.deep_freeze({
|
34
|
+
regexp_greedy_zero_or_more: [:zero_or_more, '*', :greedy],
|
35
|
+
regexp_greedy_one_or_more: [:one_or_more, '+', :greedy],
|
36
|
+
regexp_greedy_zero_or_one: [:zero_or_one, '?', :greedy],
|
37
|
+
regexp_possessive_zero_or_one: [:zero_or_one, '?+', :possessive],
|
38
|
+
regexp_reluctant_zero_or_more: [:zero_or_more, '*?', :reluctant],
|
39
|
+
regexp_reluctant_one_or_more: [:one_or_more, '+?', :reluctant],
|
40
|
+
regexp_possessive_zero_or_more: [:zero_or_more, '*+', :possessive],
|
41
|
+
regexp_possessive_one_or_more: [:one_or_more, '++', :possessive],
|
42
|
+
regexp_greedy_interval: [:interval, '', :greedy],
|
43
|
+
regexp_reluctant_interval: [:interval, '?', :reluctant],
|
44
|
+
regexp_possessive_interval: [:interval, '+', :possessive]
|
45
|
+
}.transform_values { |arguments| Quantifier.new(*arguments) }.to_h)
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def transform
|
50
|
+
Regexp.to_expression(subject).dup.tap do |expression|
|
51
|
+
expression.quantify(type, text, min, max, mode)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def text
|
56
|
+
if type.equal?(:interval)
|
57
|
+
interval_text + suffix
|
58
|
+
else
|
59
|
+
suffix
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def type
|
64
|
+
quantifier.type
|
65
|
+
end
|
66
|
+
|
67
|
+
def suffix
|
68
|
+
quantifier.suffix
|
69
|
+
end
|
70
|
+
|
71
|
+
def mode
|
72
|
+
quantifier.mode
|
73
|
+
end
|
74
|
+
|
75
|
+
def quantifier
|
76
|
+
QUANTIFIER_MAP.fetch(node.type)
|
77
|
+
end
|
78
|
+
|
79
|
+
def interval_text
|
80
|
+
interval = [min, max].map { |num| num if num.positive? }.uniq
|
81
|
+
"{#{interval.join(',')}}"
|
82
|
+
end
|
83
|
+
end # ASTToExpression
|
84
|
+
|
85
|
+
ASTToExpression::QUANTIFIER_MAP.keys.each(&method(:register))
|
86
|
+
end # Quantifier
|
87
|
+
end # Transformer
|
88
|
+
end # Regexp
|
89
|
+
end # AST
|
90
|
+
end # Mutant
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
module AST
|
5
|
+
module Regexp
|
6
|
+
class Transformer
|
7
|
+
# Transformer for nodes with children
|
8
|
+
class Recursive < self
|
9
|
+
# Mapper from `Regexp::Expression` to `Parser::AST::Node`
|
10
|
+
class ExpressionToAST < Transformer::ExpressionToAST
|
11
|
+
# Transform expression and children into nodes
|
12
|
+
#
|
13
|
+
# @return [Parser::AST::Node]
|
14
|
+
def call
|
15
|
+
quantify(ast(*children))
|
16
|
+
end
|
17
|
+
end # ExpressionToAST
|
18
|
+
|
19
|
+
# Mapper from `Parser::AST::Node` to `Regexp::Expression`
|
20
|
+
class ASTToExpression < Transformer::ASTToExpression
|
21
|
+
include LookupTable
|
22
|
+
|
23
|
+
# Expression::Sequence represents conditional branches, alternation branches, and intersection branches
|
24
|
+
# rubocop:disable Layout/LineLength
|
25
|
+
TABLE = Table.create(
|
26
|
+
[:regexp_alternation_meta, [:meta, :alternation, '|'], ::Regexp::Expression::Alternation],
|
27
|
+
[:regexp_atomic_group, [:group, :atomic, '(?>'], ::Regexp::Expression::Group::Atomic],
|
28
|
+
[:regexp_capture_group, [:group, :capture, '('], ::Regexp::Expression::Group::Capture],
|
29
|
+
[:regexp_character_set, [:set, :character, '['], ::Regexp::Expression::CharacterSet],
|
30
|
+
[:regexp_intersection_set, [:set, :intersection, '&&'], ::Regexp::Expression::CharacterSet::Intersection],
|
31
|
+
[:regexp_lookahead_assertion, [:assertion, :lookahead, '(?='], ::Regexp::Expression::Assertion::Lookahead],
|
32
|
+
[:regexp_lookbehind_assertion, [:assertion, :lookbehind, '(?<='], ::Regexp::Expression::Assertion::Lookbehind],
|
33
|
+
[:regexp_nlookahead_assertion, [:assertion, :nlookahead, '(?!'], ::Regexp::Expression::Assertion::NegativeLookahead],
|
34
|
+
[:regexp_nlookbehind_assertion, [:assertion, :nlookbehind, '(?<!'], ::Regexp::Expression::Assertion::NegativeLookbehind],
|
35
|
+
[:regexp_open_conditional, [:conditional, :open, '(?'], ::Regexp::Expression::Conditional::Expression],
|
36
|
+
[:regexp_passive_group, [:group, :passive, '(?:'], ::Regexp::Expression::Group::Passive],
|
37
|
+
[:regexp_range_set, [:set, :range, '-'], ::Regexp::Expression::CharacterSet::Range],
|
38
|
+
[:regexp_sequence_expression, [:expression, :sequence, ''], ::Regexp::Expression::Sequence]
|
39
|
+
)
|
40
|
+
# rubocop:enable Layout/LineLength
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def transform
|
45
|
+
expression_class.new(expression_token).tap do |expression|
|
46
|
+
expression.expressions = subexpressions
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end # ASTToExpression
|
50
|
+
|
51
|
+
ASTToExpression::TABLE.types.each(&method(:register))
|
52
|
+
end # Recursive
|
53
|
+
end # Transformer
|
54
|
+
end # Regexp
|
55
|
+
end # AST
|
56
|
+
end # Mutant
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
module AST
|
5
|
+
module Regexp
|
6
|
+
class Transformer
|
7
|
+
# Transformer for root nodes
|
8
|
+
class Root < self
|
9
|
+
register :regexp_root_expression
|
10
|
+
|
11
|
+
ExpressionToAST = Class.new(Recursive::ExpressionToAST)
|
12
|
+
|
13
|
+
# Mapper from `Parser::AST::Node` to `Regexp::Expression`
|
14
|
+
class ASTToExpression < Transformer::ASTToExpression
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def transform
|
19
|
+
::Regexp::Expression::Root.build.tap do |root|
|
20
|
+
root.expressions = subexpressions
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end # ASTToExpression
|
24
|
+
end # Root
|
25
|
+
end # Transformer
|
26
|
+
end # Regexp
|
27
|
+
end # AST
|
28
|
+
end # Mutant
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
module AST
|
5
|
+
module Regexp
|
6
|
+
class Transformer
|
7
|
+
# Regexp AST transformer for nodes that encode a text value
|
8
|
+
class Text < self
|
9
|
+
# Mapper from `Regexp::Expression` to `Parser::AST::Node`
|
10
|
+
class ExpressionToAST < Transformer::ExpressionToAST
|
11
|
+
# Transform expression into node preserving text value
|
12
|
+
#
|
13
|
+
# @return [Parser::AST::Node]
|
14
|
+
def call
|
15
|
+
quantify(ast(expression.text))
|
16
|
+
end
|
17
|
+
end # ExpressionToAST
|
18
|
+
|
19
|
+
# Mapper from `Parser::AST::Node` to `Regexp::Expression`
|
20
|
+
class ASTToExpression < Transformer::ASTToExpression
|
21
|
+
include LookupTable
|
22
|
+
|
23
|
+
# rubocop:disable Layout/LineLength
|
24
|
+
TABLE = Table.create(
|
25
|
+
[:regexp_literal_literal, %i[literal literal], ::Regexp::Expression::Literal],
|
26
|
+
[:regexp_comment_group, %i[group comment], ::Regexp::Expression::Group::Comment],
|
27
|
+
[:regexp_number_backref, %i[backref number], ::Regexp::Expression::Backreference::Number],
|
28
|
+
[:regexp_name_call_backref, %i[backref name_call], ::Regexp::Expression::Backreference::NameCall],
|
29
|
+
[:regexp_whitespace_free_space, %i[free_space whitespace], ::Regexp::Expression::WhiteSpace],
|
30
|
+
[:regexp_comment_free_space, %i[free_space comment], ::Regexp::Expression::WhiteSpace],
|
31
|
+
[:regexp_hex_escape, %i[escape hex], ::Regexp::Expression::EscapeSequence::Hex],
|
32
|
+
[:regexp_octal_escape, %i[escape octal], ::Regexp::Expression::EscapeSequence::Octal],
|
33
|
+
[:regexp_literal_escape, %i[escape literal], ::Regexp::Expression::EscapeSequence::Literal],
|
34
|
+
[:regexp_backslash_escape, %i[escape backslash], ::Regexp::Expression::EscapeSequence::Literal],
|
35
|
+
[:regexp_tab_escape, %i[escape tab], ::Regexp::Expression::EscapeSequence::Literal],
|
36
|
+
[:regexp_codepoint_list_escape, %i[escape codepoint_list], ::Regexp::Expression::EscapeSequence::CodepointList],
|
37
|
+
[:regexp_codepoint_escape, %i[escape codepoint], ::Regexp::Expression::EscapeSequence::Codepoint],
|
38
|
+
[:regexp_control_escape, %i[escape control], ::Regexp::Expression::EscapeSequence::Control],
|
39
|
+
[:regexp_meta_sequence_escape, %i[escape meta_sequence], ::Regexp::Expression::EscapeSequence::Control],
|
40
|
+
[:regexp_condition_conditional, %i[conditional condition], ::Regexp::Expression::Conditional::Condition]
|
41
|
+
)
|
42
|
+
# rubocop:enable Layout/LineLength
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def transform
|
47
|
+
token = expression_token.dup
|
48
|
+
token.text = Util.one(node.children)
|
49
|
+
expression_class.new(token)
|
50
|
+
end
|
51
|
+
end # ASTToExpression
|
52
|
+
|
53
|
+
ASTToExpression::TABLE.types.each(&method(:register))
|
54
|
+
end # Text
|
55
|
+
end # Transformer
|
56
|
+
end # Regexp
|
57
|
+
end # AST
|
58
|
+
end # Mutant
|
data/lib/mutant/ast/types.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Mutant
|
4
4
|
module AST
|
5
5
|
# Groups of node types
|
6
|
-
module Types
|
6
|
+
module Types # rubocop:disable Metrics/ModuleLength
|
7
7
|
ASSIGNABLE_VARIABLES = Set.new(%i[ivasgn lvasgn cvasgn gvasgn]).freeze
|
8
8
|
|
9
9
|
# Set of op-assign types
|
@@ -54,11 +54,124 @@ module Mutant
|
|
54
54
|
#
|
55
55
|
BLACKLIST = Set.new(%i[not]).freeze
|
56
56
|
|
57
|
+
# Nodes generated by regular expression body parsing
|
58
|
+
REGEXP = Set.new(%i[
|
59
|
+
regexp_alnum_posixclass
|
60
|
+
regexp_alpha_posixclass
|
61
|
+
regexp_alpha_property
|
62
|
+
regexp_alternation_escape
|
63
|
+
regexp_alternation_meta
|
64
|
+
regexp_arabic_property
|
65
|
+
regexp_ascii_posixclass
|
66
|
+
regexp_atomic_group
|
67
|
+
regexp_backslash_escape
|
68
|
+
regexp_backspace_escape
|
69
|
+
regexp_bell_escape
|
70
|
+
regexp_blank_posixclass
|
71
|
+
regexp_bol_anchor
|
72
|
+
regexp_bol_escape
|
73
|
+
regexp_bos_anchor
|
74
|
+
regexp_capture_group
|
75
|
+
regexp_carriage_escape
|
76
|
+
regexp_character_set
|
77
|
+
regexp_cntrl_posixclass
|
78
|
+
regexp_codepoint_escape
|
79
|
+
regexp_codepoint_list_escape
|
80
|
+
regexp_comment_free_space
|
81
|
+
regexp_comment_group
|
82
|
+
regexp_condition_conditional
|
83
|
+
regexp_control_escape
|
84
|
+
regexp_digit_posixclass
|
85
|
+
regexp_digit_type
|
86
|
+
regexp_dot_escape
|
87
|
+
regexp_dot_meta
|
88
|
+
regexp_eol_anchor
|
89
|
+
regexp_eol_escape
|
90
|
+
regexp_eos_anchor
|
91
|
+
regexp_eos_ob_eol_anchor
|
92
|
+
regexp_escape_escape
|
93
|
+
regexp_form_feed_escape
|
94
|
+
regexp_graph_posixclass
|
95
|
+
regexp_greedy_interval
|
96
|
+
regexp_greedy_one_or_more
|
97
|
+
regexp_greedy_zero_or_more
|
98
|
+
regexp_greedy_zero_or_one
|
99
|
+
regexp_group_close_escape
|
100
|
+
regexp_group_open_escape
|
101
|
+
regexp_han_property
|
102
|
+
regexp_hangul_property
|
103
|
+
regexp_hex_escape
|
104
|
+
regexp_hex_type
|
105
|
+
regexp_hiragana_property
|
106
|
+
regexp_intersection_set
|
107
|
+
regexp_interval_close_escape
|
108
|
+
regexp_interval_open_escape
|
109
|
+
regexp_katakana_property
|
110
|
+
regexp_letter_property
|
111
|
+
regexp_linebreak_type
|
112
|
+
regexp_literal_escape
|
113
|
+
regexp_literal_literal
|
114
|
+
regexp_lookahead_assertion
|
115
|
+
regexp_lookbehind_assertion
|
116
|
+
regexp_lower_posixclass
|
117
|
+
regexp_mark_keep
|
118
|
+
regexp_match_start_anchor
|
119
|
+
regexp_meta_sequence_escape
|
120
|
+
regexp_name_call_backref
|
121
|
+
regexp_named_group
|
122
|
+
regexp_newline_escape
|
123
|
+
regexp_nlookahead_assertion
|
124
|
+
regexp_nlookbehind_assertion
|
125
|
+
regexp_nondigit_type
|
126
|
+
regexp_nonhex_type
|
127
|
+
regexp_nonspace_type
|
128
|
+
regexp_nonword_boundary_anchor
|
129
|
+
regexp_nonword_type
|
130
|
+
regexp_number_backref
|
131
|
+
regexp_octal_escape
|
132
|
+
regexp_one_or_more_escape
|
133
|
+
regexp_open_conditional
|
134
|
+
regexp_options_group
|
135
|
+
regexp_options_switch_group
|
136
|
+
regexp_passive_group
|
137
|
+
regexp_possessive_interval
|
138
|
+
regexp_possessive_one_or_more
|
139
|
+
regexp_possessive_zero_or_more
|
140
|
+
regexp_possessive_zero_or_one
|
141
|
+
regexp_print_nonposixclass
|
142
|
+
regexp_print_nonproperty
|
143
|
+
regexp_print_posixclass
|
144
|
+
regexp_print_posixclass
|
145
|
+
regexp_print_property
|
146
|
+
regexp_punct_posixclass
|
147
|
+
regexp_range_set
|
148
|
+
regexp_reluctant_interval
|
149
|
+
regexp_reluctant_one_or_more
|
150
|
+
regexp_reluctant_zero_or_more
|
151
|
+
regexp_root_expression
|
152
|
+
regexp_sequence_expression
|
153
|
+
regexp_set_close_escape
|
154
|
+
regexp_set_open_escape
|
155
|
+
regexp_space_posixclass
|
156
|
+
regexp_space_type
|
157
|
+
regexp_tab_escape
|
158
|
+
regexp_upper_posixclass
|
159
|
+
regexp_vertical_tab_escape
|
160
|
+
regexp_whitespace_free_space
|
161
|
+
regexp_word_boundary_anchor
|
162
|
+
regexp_word_posixclass
|
163
|
+
regexp_word_type
|
164
|
+
regexp_xdigit_posixclass
|
165
|
+
regexp_xgrapheme_type
|
166
|
+
regexp_zero_or_more_escape
|
167
|
+
regexp_zero_or_one_escape
|
168
|
+
]).freeze
|
169
|
+
|
57
170
|
# Nodes that are NOT generated by parser but used by mutant / unparser.
|
58
171
|
GENERATED = Set.new(%i[empty]).freeze
|
59
172
|
|
60
173
|
ALL = Set.new(
|
61
|
-
(Parser::Meta::NODE_TYPES + GENERATED) - BLACKLIST
|
174
|
+
(Parser::Meta::NODE_TYPES + GENERATED + REGEXP) - BLACKLIST
|
62
175
|
).freeze
|
63
176
|
end # Types
|
64
177
|
end # AST
|
@@ -29,13 +29,19 @@ module Mutant
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def expand(file_config)
|
32
|
+
if @config.matcher.subjects.any?
|
33
|
+
file_config = file_config.with(
|
34
|
+
matcher: file_config.matcher.with(subjects: [])
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
32
38
|
@config = Config.env.merge(file_config).merge(@config).expand_defaults
|
33
39
|
end
|
34
40
|
|
35
41
|
def parse_remaining_arguments(arguments)
|
36
42
|
Mutant.traverse(@config.expression_parser, arguments)
|
37
|
-
.fmap do |
|
38
|
-
matcher(
|
43
|
+
.fmap do |expressions|
|
44
|
+
matcher(subjects: expressions)
|
39
45
|
self
|
40
46
|
end
|
41
47
|
end
|
@@ -82,7 +88,7 @@ module Mutant
|
|
82
88
|
parser.separator('Matcher:')
|
83
89
|
|
84
90
|
parser.on('--ignore-subject EXPRESSION', 'Ignore subjects that match EXPRESSION as prefix') do |pattern|
|
85
|
-
add_matcher(:
|
91
|
+
add_matcher(:ignore, @config.expression_parser.call(pattern).from_right)
|
86
92
|
end
|
87
93
|
parser.on('--start-subject EXPRESSION', 'Start mutation testing at a specific subject') do |pattern|
|
88
94
|
add_matcher(:start_expressions, @config.expression_parser.call(pattern).from_right)
|