mutant 0.10.20 → 0.10.25

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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/lib/mutant.rb +23 -4
  3. data/lib/mutant/ast/meta/send.rb +0 -1
  4. data/lib/mutant/ast/regexp.rb +37 -0
  5. data/lib/mutant/ast/regexp/transformer.rb +150 -0
  6. data/lib/mutant/ast/regexp/transformer/direct.rb +121 -0
  7. data/lib/mutant/ast/regexp/transformer/named_group.rb +50 -0
  8. data/lib/mutant/ast/regexp/transformer/options_group.rb +68 -0
  9. data/lib/mutant/ast/regexp/transformer/quantifier.rb +90 -0
  10. data/lib/mutant/ast/regexp/transformer/recursive.rb +56 -0
  11. data/lib/mutant/ast/regexp/transformer/root.rb +28 -0
  12. data/lib/mutant/ast/regexp/transformer/text.rb +58 -0
  13. data/lib/mutant/ast/types.rb +115 -11
  14. data/lib/mutant/cli/command/environment.rb +9 -3
  15. data/lib/mutant/config.rb +8 -54
  16. data/lib/mutant/config/coverage_criteria.rb +61 -0
  17. data/lib/mutant/env.rb +8 -6
  18. data/lib/mutant/expression.rb +0 -12
  19. data/lib/mutant/expression/namespace.rb +1 -1
  20. data/lib/mutant/isolation/fork.rb +1 -1
  21. data/lib/mutant/loader.rb +1 -1
  22. data/lib/mutant/matcher.rb +2 -2
  23. data/lib/mutant/matcher/config.rb +27 -6
  24. data/lib/mutant/matcher/method.rb +2 -3
  25. data/lib/mutant/matcher/method/metaclass.rb +1 -1
  26. data/lib/mutant/meta/example/dsl.rb +6 -1
  27. data/lib/mutant/mutator/node/arguments.rb +0 -2
  28. data/lib/mutant/mutator/node/block.rb +5 -1
  29. data/lib/mutant/mutator/node/dynamic_literal.rb +1 -1
  30. data/lib/mutant/mutator/node/kwargs.rb +44 -0
  31. data/lib/mutant/mutator/node/literal/regex.rb +26 -0
  32. data/lib/mutant/mutator/node/literal/symbol.rb +0 -2
  33. data/lib/mutant/mutator/node/regexp.rb +20 -0
  34. data/lib/mutant/mutator/node/regexp/alternation_meta.rb +20 -0
  35. data/lib/mutant/mutator/node/regexp/beginning_of_line_anchor.rb +20 -0
  36. data/lib/mutant/mutator/node/regexp/capture_group.rb +25 -0
  37. data/lib/mutant/mutator/node/regexp/character_type.rb +31 -0
  38. data/lib/mutant/mutator/node/regexp/end_of_line_anchor.rb +20 -0
  39. data/lib/mutant/mutator/node/regexp/end_of_string_or_before_end_of_line_anchor.rb +20 -0
  40. data/lib/mutant/mutator/node/regexp/zero_or_more.rb +34 -0
  41. data/lib/mutant/mutator/node/sclass.rb +1 -1
  42. data/lib/mutant/mutator/node/send.rb +36 -19
  43. data/lib/mutant/parallel.rb +43 -28
  44. data/lib/mutant/parallel/driver.rb +9 -3
  45. data/lib/mutant/parallel/worker.rb +60 -2
  46. data/lib/mutant/pipe.rb +94 -0
  47. data/lib/mutant/reporter/cli/printer/env.rb +1 -1
  48. data/lib/mutant/reporter/cli/printer/isolation_result.rb +1 -6
  49. data/lib/mutant/result.rb +8 -0
  50. data/lib/mutant/runner.rb +7 -10
  51. data/lib/mutant/runner/sink.rb +12 -2
  52. data/lib/mutant/subject.rb +1 -3
  53. data/lib/mutant/subject/method/instance.rb +2 -4
  54. data/lib/mutant/timer.rb +2 -4
  55. data/lib/mutant/transform.rb +25 -2
  56. data/lib/mutant/version.rb +1 -1
  57. data/lib/mutant/world.rb +1 -2
  58. metadata +48 -9
  59. data/lib/mutant/warnings.rb +0 -106
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a3308efe39e70e35d8c0fc11294280713c3c69f402e3dc59a30e3a3789a5744
4
- data.tar.gz: ce590187601f50a475271571b7da3bd744d1b2196fc15f249de3fbec62913de5
3
+ metadata.gz: f02dec057593b8e61c2b207918ed6f1b9c4aa1d41bc0b2f2390c2a1da9172b5d
4
+ data.tar.gz: 99a318ed1f02d9976037694b2dbc1de463863f747cc4b8b5e95809b307680f03
5
5
  SHA512:
6
- metadata.gz: adc7dd97643cd658857712d4ae220fa167777145e9cae93db73a1c43be9db63a98b03fe549c0b7eac5c595b4b8f80892e8ca1c12fcfcf8385ffdc360d4b95f65
7
- data.tar.gz: 51e49cfc6d35f60b7b9e5f3bd2c4991ceba3e383a60192a57920aab16860fbebda0f560ec39cf552994c3a1f6319793a0483f9fc3d2b4669ec556b7526df8b8d
6
+ metadata.gz: 5312bd87fc41b3442b886b40b200357c254c2d7d65081cdfaca2e2e213311539eb23b00eb5b792c9f7978c8eeed5a6cbd72b3a513598b9abc9f72a3beaa9989d
7
+ data.tar.gz: 922e0ea1878e05f014a3c832d7bfa23e0d8410cc8c8d5b9bd1bc8b81124a18ecd11403be643cd144772863950076b17ab06ce3cd809cda01a9563ec815c95e79
@@ -17,6 +17,7 @@ require 'optparse'
17
17
  require 'parser'
18
18
  require 'parser/current'
19
19
  require 'pathname'
20
+ require 'regexp_parser'
20
21
  require 'set'
21
22
  require 'singleton'
22
23
  require 'stringio'
@@ -40,9 +41,11 @@ module Mutant
40
41
  SCOPE_OPERATOR = '::'
41
42
  end # Mutant
42
43
 
44
+ require 'mutant/transform'
43
45
  require 'mutant/bootstrap'
44
46
  require 'mutant/version'
45
47
  require 'mutant/env'
48
+ require 'mutant/pipe'
46
49
  require 'mutant/util'
47
50
  require 'mutant/registry'
48
51
  require 'mutant/ast'
@@ -52,6 +55,15 @@ require 'mutant/ast/nodes'
52
55
  require 'mutant/ast/named_children'
53
56
  require 'mutant/ast/node_predicates'
54
57
  require 'mutant/ast/find_metaclass_containing'
58
+ require 'mutant/ast/regexp'
59
+ require 'mutant/ast/regexp/transformer'
60
+ require 'mutant/ast/regexp/transformer/direct'
61
+ require 'mutant/ast/regexp/transformer/named_group'
62
+ require 'mutant/ast/regexp/transformer/options_group'
63
+ require 'mutant/ast/regexp/transformer/quantifier'
64
+ require 'mutant/ast/regexp/transformer/recursive'
65
+ require 'mutant/ast/regexp/transformer/root'
66
+ require 'mutant/ast/regexp/transformer/text'
55
67
  require 'mutant/ast/meta'
56
68
  require 'mutant/ast/meta/send'
57
69
  require 'mutant/ast/meta/const'
@@ -74,6 +86,14 @@ require 'mutant/mutator/util/array'
74
86
  require 'mutant/mutator/util/symbol'
75
87
  require 'mutant/mutator/node'
76
88
  require 'mutant/mutator/node/generic'
89
+ require 'mutant/mutator/node/regexp'
90
+ require 'mutant/mutator/node/regexp/alternation_meta'
91
+ require 'mutant/mutator/node/regexp/beginning_of_line_anchor'
92
+ require 'mutant/mutator/node/regexp/capture_group'
93
+ require 'mutant/mutator/node/regexp/character_type'
94
+ require 'mutant/mutator/node/regexp/end_of_line_anchor'
95
+ require 'mutant/mutator/node/regexp/end_of_string_or_before_end_of_line_anchor'
96
+ require 'mutant/mutator/node/regexp/zero_or_more'
77
97
  require 'mutant/mutator/node/literal'
78
98
  require 'mutant/mutator/node/literal/boolean'
79
99
  require 'mutant/mutator/node/literal/range'
@@ -129,6 +149,7 @@ require 'mutant/mutator/node/rescue'
129
149
  require 'mutant/mutator/node/match_current_line'
130
150
  require 'mutant/mutator/node/index'
131
151
  require 'mutant/mutator/node/procarg_zero'
152
+ require 'mutant/mutator/node/kwargs'
132
153
  require 'mutant/loader'
133
154
  require 'mutant/context'
134
155
  require 'mutant/scope'
@@ -157,7 +178,6 @@ require 'mutant/expression/methods'
157
178
  require 'mutant/expression/namespace'
158
179
  require 'mutant/test'
159
180
  require 'mutant/timer'
160
- require 'mutant/transform'
161
181
  require 'mutant/integration'
162
182
  require 'mutant/integration/null'
163
183
  require 'mutant/selector'
@@ -165,6 +185,7 @@ require 'mutant/selector/expression'
165
185
  require 'mutant/selector/null'
166
186
  require 'mutant/world'
167
187
  require 'mutant/config'
188
+ require 'mutant/config/coverage_criteria'
168
189
  require 'mutant/cli'
169
190
  require 'mutant/cli/command'
170
191
  require 'mutant/cli/command/subscription'
@@ -194,7 +215,6 @@ require 'mutant/reporter/cli/format'
194
215
  require 'mutant/repository'
195
216
  require 'mutant/repository/diff'
196
217
  require 'mutant/repository/diff/ranges'
197
- require 'mutant/warnings'
198
218
  require 'mutant/zombifier'
199
219
  require 'mutant/range'
200
220
  require 'mutant/license'
@@ -220,8 +240,7 @@ module Mutant
220
240
  stderr: $stderr,
221
241
  stdout: $stdout,
222
242
  thread: Thread,
223
- timer: Timer.new(Process),
224
- warnings: Warnings.new(Warning)
243
+ timer: Timer.new(Process)
225
244
  )
226
245
 
227
246
  # Reopen class to initialize constant to avoid dep circle
@@ -13,7 +13,6 @@ module Mutant
13
13
 
14
14
  public :receiver, :selector
15
15
 
16
- INDEX_ASSIGNMENT_SELECTOR = :[]=
17
16
  ATTRIBUTE_ASSIGNMENT_SELECTOR_SUFFIX = '='
18
17
 
19
18
  # Arguments of mutated node
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutant
4
+ module AST
5
+ # Regexp source mapper
6
+ module Regexp
7
+ # Parse regex string into expression
8
+ #
9
+ # @param regexp [String]
10
+ #
11
+ # @return [Regexp::Expression, nil]
12
+ def self.parse(regexp)
13
+ ::Regexp::Parser.parse(regexp)
14
+ end
15
+
16
+ # Convert expression into ast node
17
+ #
18
+ # @param expression [Regexp::Expression]
19
+ #
20
+ # @return [Parser::AST::Node]
21
+ def self.to_ast(expression)
22
+ ast_type = :"regexp_#{expression.token}_#{expression.type}"
23
+
24
+ Transformer.lookup(ast_type).to_ast(expression)
25
+ end
26
+
27
+ # Convert node into expression
28
+ #
29
+ # @param node [Parser::AST::Node]
30
+ #
31
+ # @return [Regexp::Expression]
32
+ def self.to_expression(node)
33
+ Transformer.lookup(node.type).to_expression(node)
34
+ end
35
+ end # Regexp
36
+ end # AST
37
+ end # Mutant
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutant
4
+ module AST
5
+ module Regexp
6
+ # Regexp bijective mapper
7
+ #
8
+ # Transforms parsed regular expression representation from
9
+ # `Regexp::Expression` instances (provided by `regexp_parser`) into
10
+ # equivalent representations using `Parser::AST::Node`
11
+ class Transformer
12
+ include AbstractType
13
+
14
+ REGISTRY = Registry.new
15
+
16
+ # Lookup transformer class for regular expression node type
17
+ #
18
+ # @param type [Symbol]
19
+ #
20
+ # @return [Class<Transformer>]
21
+ def self.lookup(type)
22
+ REGISTRY.lookup(type)
23
+ end
24
+
25
+ def self.register(type)
26
+ REGISTRY.register(type, self)
27
+ end
28
+ private_class_method :register
29
+
30
+ # Transform expression
31
+ #
32
+ # @param expression [Regexp::Expression]
33
+ #
34
+ # @return [Parser::AST::Node]
35
+ def self.to_ast(expression)
36
+ self::ExpressionToAST.call(expression)
37
+ end
38
+
39
+ # Transform node
40
+ #
41
+ # @param node [Parser::AST::Node]
42
+ #
43
+ # @return [Regexp::Expression]
44
+ def self.to_expression(node)
45
+ self::ASTToExpression.call(node)
46
+ end
47
+
48
+ # Abstract expression transformer
49
+ class ExpressionToAST
50
+ PREFIX = :regexp
51
+
52
+ include Concord.new(:expression), Procto.call, AST::Sexp, AbstractType, Adamantium
53
+
54
+ private
55
+
56
+ def ast(*children)
57
+ s(type, *children)
58
+ end
59
+
60
+ def quantify(node)
61
+ return node unless expression.quantified?
62
+
63
+ Quantifier.to_ast(expression.quantifier).append(node)
64
+ end
65
+
66
+ def children
67
+ expression.map(&Regexp.public_method(:to_ast))
68
+ end
69
+
70
+ def type
71
+ :"#{PREFIX}_#{expression.token}_#{expression.type}"
72
+ end
73
+ end # ExpressionToAST
74
+
75
+ # Abstract node transformer
76
+ class ASTToExpression
77
+ include Concord.new(:node), Procto.call, AbstractType, Adamantium
78
+
79
+ # Call generic transform method and freeze result
80
+ #
81
+ # @return [Regexp::Expression]
82
+ def call
83
+ transform.freeze
84
+ end
85
+
86
+ private
87
+
88
+ abstract_method :transform
89
+
90
+ def subexpressions
91
+ node.children.map(&Regexp.public_method(:to_expression))
92
+ end
93
+ end # ASTToExpression
94
+
95
+ # Mixin for node transformers
96
+ #
97
+ # Helps construct a mapping from Parser::AST::Node domain to
98
+ # Regexp::Expression domain
99
+ module LookupTable
100
+ Mapping = Class.new.include(Concord::Public.new(:token, :regexp_class))
101
+
102
+ # Table mapping ast types to object information for regexp domain
103
+ class Table
104
+
105
+ # Coerce array of mapping information into structured table
106
+ #
107
+ # @param [Array(Symbol, Array, Class<Regexp::Expression>)]
108
+ #
109
+ # @return [Table]
110
+ def self.create(*rows)
111
+ table = rows.map do |ast_type, token, klass|
112
+ [ast_type, Mapping.new(::Regexp::Token.new(*token), klass)]
113
+ end.to_h
114
+
115
+ new(table)
116
+ end
117
+
118
+ include Concord.new(:table), Adamantium
119
+
120
+ # Types defined by the table
121
+ #
122
+ # @return [Array<Symbol>]
123
+ def types
124
+ table.keys
125
+ end
126
+
127
+ # Lookup mapping information given an ast node type
128
+ #
129
+ # @param type [Symbol]
130
+ #
131
+ # @return [Mapping]
132
+ def lookup(type)
133
+ table.fetch(type)
134
+ end
135
+ end # Table
136
+
137
+ private
138
+
139
+ def expression_token
140
+ self.class::TABLE.lookup(node.type).token
141
+ end
142
+
143
+ def expression_class
144
+ self.class::TABLE.lookup(node.type).regexp_class
145
+ end
146
+ end # LookupTable
147
+ end # Transformer
148
+ end # Regexp
149
+ end # AST
150
+ end # Mutant
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutant
4
+ module AST
5
+ module Regexp
6
+ class Transformer
7
+ # Transformer for nodes which map directly to other domain
8
+ #
9
+ # A node maps "directly" to another domain if the node never
10
+ # has children or text which needs to be preserved for a mapping
11
+ #
12
+ # @example direct mapping
13
+ #
14
+ # input = /\d/
15
+ # expression = Regexp::Parser.parse(input).first
16
+ # node = Transformer::Direct.to_ast(expression)
17
+ #
18
+ # # the digit type always has the same text and no children
19
+ # expression.text # => "\\d"
20
+ # expression.terminal? # => true
21
+ #
22
+ # # therefore the `Parser::AST::Node` is always the same
23
+ # node # => s(:regexp_digit_type)
24
+ class Direct < self
25
+ # Mapper from `Regexp::Expression` to `Parser::AST::Node`
26
+ class ExpressionToAST < Transformer::ExpressionToAST
27
+ # Transform expression into node
28
+ #
29
+ # @return [Parser::AST::Node]
30
+ def call
31
+ quantify(ast)
32
+ end
33
+ end # ExpressionToAST
34
+
35
+ # Mapper from `Parser::AST::Node` to `Regexp::Expression`
36
+ class ASTToExpression < Transformer::ASTToExpression
37
+ include LookupTable
38
+
39
+ # rubocop:disable Layout/LineLength
40
+ TABLE = Table.create(
41
+ [:regexp_alnum_posixclass, [:posixclass, :alnum, '[:alnum:]'], ::Regexp::Expression::PosixClass],
42
+ [:regexp_alpha_posixclass, [:posixclass, :alpha, '[:alpha:]'], ::Regexp::Expression::PosixClass],
43
+ [:regexp_alpha_property, [:property, :alpha, '\p{Alpha}'], ::Regexp::Expression::UnicodeProperty::Alpha],
44
+ [:regexp_alternation_escape, [:escape, :alternation, '\|'], ::Regexp::Expression::EscapeSequence::Literal],
45
+ [:regexp_arabic_property, [:property, :arabic, '\p{Arabic}'], ::Regexp::Expression::UnicodeProperty::Script],
46
+ [:regexp_ascii_posixclass, [:posixclass, :ascii, '[:ascii:]'], ::Regexp::Expression::PosixClass],
47
+ [:regexp_backspace_escape, [:escape, :backspace, '\b'], ::Regexp::Expression::EscapeSequence::Backspace],
48
+ [:regexp_bell_escape, [:escape, :bell, '\a'], ::Regexp::Expression::EscapeSequence::Literal],
49
+ [:regexp_blank_posixclass, [:posixclass, :blank, '[:blank:]'], ::Regexp::Expression::PosixClass],
50
+ [:regexp_bol_anchor, [:anchor, :bol, '^'], ::Regexp::Expression::Anchor::BeginningOfLine],
51
+ [:regexp_bol_escape, [:escape, :bol, '\^'], ::Regexp::Expression::EscapeSequence::Literal],
52
+ [:regexp_bos_anchor, [:anchor, :bos, '\\A'], ::Regexp::Expression::Anchor::BeginningOfString],
53
+ [:regexp_carriage_escape, [:escape, :carriage, '\r'], ::Regexp::Expression::EscapeSequence::Literal],
54
+ [:regexp_cntrl_posixclass, [:posixclass, :cntrl, '[:cntrl:]'], ::Regexp::Expression::PosixClass],
55
+ [:regexp_digit_posixclass, [:posixclass, :digit, '[:digit:]'], ::Regexp::Expression::PosixClass],
56
+ [:regexp_digit_type, [:type, :digit, '\d'], ::Regexp::Expression::CharacterType::Digit],
57
+ [:regexp_dot_escape, [:escape, :dot, '\.'], ::Regexp::Expression::EscapeSequence::Literal],
58
+ [:regexp_dot_meta, [:meta, :dot, '.'], ::Regexp::Expression::CharacterType::Any],
59
+ [:regexp_eol_anchor, [:anchor, :eol, '$'], ::Regexp::Expression::Anchor::EndOfLine],
60
+ [:regexp_eol_escape, [:escape, :eol, '\$'], ::Regexp::Expression::EscapeSequence::Literal],
61
+ [:regexp_eos_anchor, [:anchor, :eos, '\\z'], ::Regexp::Expression::Anchor::EndOfString],
62
+ [:regexp_eos_ob_eol_anchor, [:anchor, :eos_ob_eol, '\\Z'], ::Regexp::Expression::Anchor::EndOfStringOrBeforeEndOfLine],
63
+ [:regexp_escape_escape, [:escape, :escape, '\e'], ::Regexp::Expression::EscapeSequence::AsciiEscape],
64
+ [:regexp_form_feed_escape, [:escape, :form_feed, '\f'], ::Regexp::Expression::EscapeSequence::FormFeed],
65
+ [:regexp_graph_posixclass, [:posixclass, :graph, '[:graph:]'], ::Regexp::Expression::PosixClass],
66
+ [:regexp_group_close_escape, [:escape, :group_close, '\)'], ::Regexp::Expression::EscapeSequence::Literal],
67
+ [:regexp_group_open_escape, [:escape, :group_open, '\('], ::Regexp::Expression::EscapeSequence::Literal],
68
+ [:regexp_han_property, [:property, :han, '\p{Han}'], ::Regexp::Expression::UnicodeProperty::Script],
69
+ [:regexp_hangul_property, [:property, :hangul, '\p{Hangul}'], ::Regexp::Expression::UnicodeProperty::Script],
70
+ [:regexp_hex_type, [:type, :hex, '\h'], ::Regexp::Expression::CharacterType::Hex],
71
+ [:regexp_hiragana_property, [:property, :hiragana, '\p{Hiragana}'], ::Regexp::Expression::UnicodeProperty::Script],
72
+ [:regexp_interval_close_escape, [:escape, :interval_close, '\}'], ::Regexp::Expression::EscapeSequence::Literal],
73
+ [:regexp_interval_open_escape, [:escape, :interval_open, '\{'], ::Regexp::Expression::EscapeSequence::Literal],
74
+ [:regexp_katakana_property, [:property, :katakana, '\p{Katakana}'], ::Regexp::Expression::UnicodeProperty::Script],
75
+ [:regexp_letter_property, [:property, :letter, '\p{L}'], ::Regexp::Expression::UnicodeProperty::Letter::Any],
76
+ [:regexp_linebreak_type, [:type, :linebreak, '\R'], ::Regexp::Expression::CharacterType::Linebreak],
77
+ [:regexp_lower_posixclass, [:posixclass, :lower, '[:lower:]'], ::Regexp::Expression::PosixClass],
78
+ [:regexp_mark_keep, [:keep, :mark, '\K'], ::Regexp::Expression::Keep::Mark],
79
+ [:regexp_match_start_anchor, [:anchor, :match_start, '\\G'], ::Regexp::Expression::Anchor::MatchStart],
80
+ [:regexp_newline_escape, [:escape, :newline, '\n'], ::Regexp::Expression::EscapeSequence::Literal],
81
+ [:regexp_nondigit_type, [:type, :nondigit, '\D'], ::Regexp::Expression::CharacterType::NonDigit],
82
+ [:regexp_nonhex_type, [:type, :nonhex, '\H'], ::Regexp::Expression::CharacterType::NonHex],
83
+ [:regexp_nonspace_type, [:type, :nonspace, '\S'], ::Regexp::Expression::CharacterType::NonSpace],
84
+ [:regexp_nonword_boundary_anchor, [:anchor, :nonword_boundary, '\\B'], ::Regexp::Expression::Anchor::NonWordBoundary],
85
+ [:regexp_nonword_type, [:type, :nonword, '\W'], ::Regexp::Expression::CharacterType::NonWord],
86
+ [:regexp_one_or_more_escape, [:escape, :one_or_more, '\+'], ::Regexp::Expression::EscapeSequence::Literal],
87
+ [:regexp_print_nonposixclass, [:nonposixclass, :print, '[:^print:]'], ::Regexp::Expression::PosixClass],
88
+ [:regexp_print_nonproperty, [:nonproperty, :print, '\P{Print}'], ::Regexp::Expression::UnicodeProperty::Print],
89
+ [:regexp_print_posixclass, [:posixclass, :print, '[:print:]'], ::Regexp::Expression::PosixClass],
90
+ [:regexp_print_posixclass, [:posixclass, :print, '[:print:]'], ::Regexp::Expression::PosixClass],
91
+ [:regexp_print_property, [:property, :print, '\p{Print}'], ::Regexp::Expression::UnicodeProperty::Print],
92
+ [:regexp_punct_posixclass, [:posixclass, :punct, '[:punct:]'], ::Regexp::Expression::PosixClass],
93
+ [:regexp_set_close_escape, [:escape, :set_close, '\]'], ::Regexp::Expression::EscapeSequence::Literal],
94
+ [:regexp_set_open_escape, [:escape, :set_open, '\['], ::Regexp::Expression::EscapeSequence::Literal],
95
+ [:regexp_space_posixclass, [:posixclass, :space, '[:space:]'], ::Regexp::Expression::PosixClass],
96
+ [:regexp_space_type, [:type, :space, '\s'], ::Regexp::Expression::CharacterType::Space],
97
+ [:regexp_upper_posixclass, [:posixclass, :upper, '[:upper:]'], ::Regexp::Expression::PosixClass],
98
+ [:regexp_vertical_tab_escape, [:escape, :vertical_tab, '\v'], ::Regexp::Expression::EscapeSequence::VerticalTab],
99
+ [:regexp_word_boundary_anchor, [:anchor, :word_boundary, '\b'], ::Regexp::Expression::Anchor::WordBoundary],
100
+ [:regexp_word_posixclass, [:posixclass, :word, '[:word:]'], ::Regexp::Expression::PosixClass],
101
+ [:regexp_word_type, [:type, :word, '\w'], ::Regexp::Expression::CharacterType::Word],
102
+ [:regexp_xdigit_posixclass, [:posixclass, :xdigit, '[:xdigit:]'], ::Regexp::Expression::PosixClass],
103
+ [:regexp_xgrapheme_type, [:type, :xgrapheme, '\X'], ::Regexp::Expression::CharacterType::ExtendedGrapheme],
104
+ [:regexp_zero_or_more_escape, [:escape, :zero_or_more, '\*'], ::Regexp::Expression::EscapeSequence::Literal],
105
+ [:regexp_zero_or_one_escape, [:escape, :zero_or_one, '\?'], ::Regexp::Expression::EscapeSequence::Literal]
106
+ )
107
+ # rubocop:enable Layout/LineLength
108
+
109
+ private
110
+
111
+ def transform
112
+ expression_class.new(expression_token)
113
+ end
114
+ end # ASTToExpression
115
+
116
+ ASTToExpression::TABLE.types.each(&method(:register))
117
+ end # Direct
118
+ end # Transformer
119
+ end # Regexp
120
+ end # AST
121
+ end # Mutant
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutant
4
+ module AST
5
+ module Regexp
6
+ class Transformer
7
+ # Transformer for named groups
8
+ class NamedGroup < self
9
+ register :regexp_named_group
10
+
11
+ # Mapper from `Regexp::Expression` to `Parser::AST::Node`
12
+ class ExpressionToAST < Transformer::ExpressionToAST
13
+
14
+ # Transform named group into node
15
+ #
16
+ # @return [Parser::AST::Node]
17
+ def call
18
+ quantify(ast(expression.name, *children))
19
+ end
20
+ end # ExpressionToAST
21
+
22
+ # Mapper from `Parser::AST::Node` to `Regexp::Expression`
23
+ class ASTToExpression < Transformer::ASTToExpression
24
+ include NamedChildren
25
+
26
+ children :name
27
+
28
+ private
29
+
30
+ def transform
31
+ named_group.tap do |expression|
32
+ expression.expressions = subexpressions
33
+ end
34
+ end
35
+
36
+ def subexpressions
37
+ remaining_children.map(&Regexp.public_method(:to_expression))
38
+ end
39
+
40
+ def named_group
41
+ ::Regexp::Expression::Group::Named.new(
42
+ ::Regexp::Token.new(:group, :named, "(?<#{name}>")
43
+ )
44
+ end
45
+ end # ASTToExpression
46
+ end # NamedGroup
47
+ end # Transformer
48
+ end # Regexp
49
+ end # AST
50
+ end # Mutant