mutant 0.8.18 → 0.8.19

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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/{circle.yml → .circleci/config.yml} +3 -9
  3. data/.rubocop.yml +1 -1
  4. data/Changelog.md +5 -0
  5. data/Gemfile.lock +6 -6
  6. data/README.md +1 -1
  7. data/config/flay.yml +1 -1
  8. data/lib/mutant.rb +4 -5
  9. data/lib/mutant/ast/regexp.rb +0 -15
  10. data/lib/mutant/ast/regexp/transformer/direct.rb +65 -47
  11. data/lib/mutant/ast/regexp/transformer/named_group.rb +59 -0
  12. data/lib/mutant/ast/regexp/transformer/options_group.rb +22 -7
  13. data/lib/mutant/ast/regexp/transformer/recursive.rb +14 -8
  14. data/lib/mutant/ast/regexp/transformer/root.rb +1 -1
  15. data/lib/mutant/ast/regexp/transformer/text.rb +7 -5
  16. data/lib/mutant/ast/types.rb +29 -6
  17. data/lib/mutant/expression/namespace.rb +1 -1
  18. data/lib/mutant/matcher/method/instance.rb +3 -1
  19. data/lib/mutant/mutator/node/generic.rb +1 -0
  20. data/lib/mutant/mutator/node/literal/regex.rb +0 -1
  21. data/lib/mutant/mutator/node/regexp/character_type.rb +1 -1
  22. data/lib/mutant/version.rb +1 -1
  23. data/lib/mutant/warning_filter.rb +1 -1
  24. data/meta/regexp.rb +3 -0
  25. data/meta/regexp/character_types.rb +1 -1
  26. data/mutant.gemspec +2 -2
  27. data/spec/integrations.yml +2 -4
  28. data/spec/support/warnings.yml +1 -3
  29. data/spec/unit/mutant/ast/regexp_spec.rb +108 -23
  30. data/spec/unit/mutant/matcher/method/instance_spec.rb +4 -4
  31. data/test_app/lib/test_app.rb +1 -1
  32. metadata +7 -10
  33. data/lib/mutant/ast/regexp/transformer/alternative.rb +0 -41
  34. data/lib/mutant/ast/regexp/transformer/character_set.rb +0 -48
  35. data/spec/unit/mutant/ast/regexp/supported_predicate_spec.rb +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e671cfb966debd1654091d93bd356505efdd8c30ed8c440c98b141f40f0e375b
4
- data.tar.gz: 403a97ad6d13f1fd9809b0acc48fcb8e19289b3a01b0aaccb25bb83ea49bc4a3
3
+ metadata.gz: dbaeba3292082f39979c87a1918f1a75a681f4cca1299fee251373779c1f381b
4
+ data.tar.gz: b1e57ca598f25e27d1c74e2b17d2033edb1d3b602742eb0fa62a6a7ac1f1058a
5
5
  SHA512:
6
- metadata.gz: 892d50fd61d110717f60877f1c1249c92d33179b70f44fdbb725dea7b3b34a82a8f8aa8c9b79329dbc74b12b15006a15d0cc2a118727d4732c65095b19421a64
7
- data.tar.gz: 2b2f81d37ba20d4884e168dfe43ad8744e57b9bc0311aeb97f666f0652def83b98df9b71b1855b24070c1cbe16491eecd12f295d65d58bbe6c328041791225e6
6
+ metadata.gz: 53d8e07cbcfc3ce3c8f1848ae34438f5e31ee3cbb8af8784e02e1f5a4cccc61554ac9f404d07083c0ce1210b4329de873e0ecb3e274260798484a1cabc53f758
7
+ data.tar.gz: 5ca7d7e28311f4c359d07f823d069b1ace3ed8b408bcb5c9f912d6f106ff469be4d38a4e7ea37afd46083d30eab818039c72f306d323ee4a364e5a6fb3b0beb8
@@ -4,20 +4,14 @@ defaults: &defaults
4
4
  - checkout
5
5
  - run: bundle install
6
6
  - run: bundle exec rake ci
7
-
8
7
  version: 2
9
8
  jobs:
10
- ruby_2_3:
9
+ ruby_2_5:
11
10
  <<: *defaults
12
11
  docker:
13
- - image: circleci/ruby:2.3.4
14
- ruby_2_4:
15
- <<: *defaults
16
- docker:
17
- - image: circleci/ruby:2.4.1
12
+ - image: circleci/ruby:2.5.3
18
13
  workflows:
19
14
  version: 2
20
15
  test:
21
16
  jobs:
22
- - ruby_2_3
23
- - ruby_2_4
17
+ - ruby_2_5
data/.rubocop.yml CHANGED
@@ -4,4 +4,4 @@ AllCops:
4
4
  - 'test_app/**/*'
5
5
  - 'tmp/**/*'
6
6
  - 'vendor/**/*'
7
- TargetRubyVersion: 2.3
7
+ TargetRubyVersion: 2.5
data/Changelog.md CHANGED
@@ -1,3 +1,8 @@
1
+ # v0.8.19 2018-11-06
2
+
3
+ * Drop support for Ruby < 2.5
4
+ * Fix bug when mutating a module that includes Memoizable
5
+
1
6
  # v0.8.18 2018-10-24
2
7
 
3
8
  * Add support for regexp unicode print nodes https://github.com/mbj/mutant/pull/749
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mutant (0.8.16)
4
+ mutant (0.8.18)
5
5
  abstract_type (~> 0.0.7)
6
6
  adamantium (~> 0.2.0)
7
7
  anima (~> 0.3.0)
@@ -15,10 +15,10 @@ PATH
15
15
  parallel (~> 1.3)
16
16
  parser (~> 2.5.1)
17
17
  procto (~> 0.0.2)
18
- regexp_parser (~> 0.4.9)
18
+ regexp_parser (~> 1.2)
19
19
  unparser (~> 0.2.5)
20
- mutant-rspec (0.8.16)
21
- mutant (~> 0.8.16)
20
+ mutant-rspec (0.8.18)
21
+ mutant (~> 0.8.18)
22
22
  rspec-core (>= 3.4.0, < 4.0.0)
23
23
 
24
24
  GEM
@@ -107,7 +107,7 @@ GEM
107
107
  kwalify (~> 0.7.0)
108
108
  parser (>= 2.5.0.0, < 2.6, != 2.5.1.1)
109
109
  rainbow (>= 2.0, < 4.0)
110
- regexp_parser (0.4.13)
110
+ regexp_parser (1.2.0)
111
111
  rspec (3.8.0)
112
112
  rspec-core (~> 3.8.0)
113
113
  rspec-expectations (~> 3.8.0)
@@ -170,4 +170,4 @@ DEPENDENCIES
170
170
  mutant!
171
171
 
172
172
  BUNDLED WITH
173
- 1.16.4
173
+ 1.17.1
data/README.md CHANGED
@@ -353,7 +353,7 @@ Sorted by recency:
353
353
  [sitepoint]: http://www.sitepoint.com/mutation-testing-mutant/
354
354
  [arkency1]: http://blog.arkency.com/2015/06/how-good-are-your-ruby-tests-testing-your-tests-with-mutant/
355
355
  [arkency2]: http://blog.arkency.com/2015/05/mutation-testing-and-continuous-integration/
356
- [arkency3]: http://blog.arkency.com/2015/04/why-i-want-to-introduce-mutation-testing-to-the-rails-event-store-gem/
356
+ [arkency3]: http://blog.arkency.com/2015/04/why-i-want-to-introduce-mutation-testing-to-the-rails-event-store-gem/
357
357
  [solnic]: http://solnic.eu/2013/01/23/mutation-testing-with-mutant.html
358
358
 
359
359
  Support
data/config/flay.yml CHANGED
@@ -1,3 +1,3 @@
1
1
  ---
2
2
  threshold: 16
3
- total_score: 1318
3
+ total_score: 1364
data/lib/mutant.rb CHANGED
@@ -56,13 +56,12 @@ require 'mutant/ast/node_predicates'
56
56
  require 'mutant/ast/regexp'
57
57
  require 'mutant/ast/regexp/transformer'
58
58
  require 'mutant/ast/regexp/transformer/direct'
59
- require 'mutant/ast/regexp/transformer/text'
60
- require 'mutant/ast/regexp/transformer/recursive'
61
- require 'mutant/ast/regexp/transformer/quantifier'
59
+ require 'mutant/ast/regexp/transformer/named_group'
62
60
  require 'mutant/ast/regexp/transformer/options_group'
63
- require 'mutant/ast/regexp/transformer/character_set'
61
+ require 'mutant/ast/regexp/transformer/quantifier'
62
+ require 'mutant/ast/regexp/transformer/recursive'
64
63
  require 'mutant/ast/regexp/transformer/root'
65
- require 'mutant/ast/regexp/transformer/alternative'
64
+ require 'mutant/ast/regexp/transformer/text'
66
65
  require 'mutant/ast/meta'
67
66
  require 'mutant/ast/meta/send'
68
67
  require 'mutant/ast/meta/const'
@@ -4,10 +4,6 @@ module Mutant
4
4
  module AST
5
5
  # Regexp source mapper
6
6
  module Regexp
7
- UNSUPPORTED_EXPRESSION_TYPE = :conditional
8
-
9
- private_constant(*constants(false))
10
-
11
7
  # Parse regex string into expression
12
8
  #
13
9
  # @param regexp [String]
@@ -17,17 +13,6 @@ module Mutant
17
13
  ::Regexp::Parser.parse(regexp)
18
14
  end
19
15
 
20
- # Check if expression is supported by mapper
21
- #
22
- # @param expression [Regexp::Expression]
23
- #
24
- # @return [Boolean]
25
- def self.supported?(expression)
26
- expression.terminal? || expression.all? do |subexp|
27
- !subexp.type.equal?(UNSUPPORTED_EXPRESSION_TYPE) && supported?(subexp)
28
- end
29
- end
30
-
31
16
  # Convert expression into ast node
32
17
  #
33
18
  # @param expression [Regexp::Expression]
@@ -38,53 +38,71 @@ module Mutant
38
38
 
39
39
  # rubocop:disable LineLength
40
40
  TABLE = Table.create(
41
- [:regexp_alpha_property, [:property, :alpha, '\p{Alpha}'], ::Regexp::Expression::UnicodeProperty::Alpha],
42
- [:regexp_alternation_escape, [:escape, :alternation, '\|'], ::Regexp::Expression::EscapeSequence::Literal],
43
- [:regexp_bell_escape, [:escape, :bell, '\a'], ::Regexp::Expression::EscapeSequence::Literal],
44
- [:regexp_bol_anchor, [:anchor, :bol, '^'], ::Regexp::Expression::Anchor::BeginningOfLine],
45
- [:regexp_bol_escape, [:escape, :bol, '\^'], ::Regexp::Expression::EscapeSequence::Literal],
46
- [:regexp_bos_anchor, [:anchor, :bos, '\\A'], ::Regexp::Expression::Anchor::BeginningOfString],
47
- [:regexp_carriage_escape, [:escape, :carriage, '\r'], ::Regexp::Expression::EscapeSequence::Literal],
48
- [:regexp_digit_type, [:type, :digit, '\d'], ::Regexp::Expression::CharacterType::Digit],
49
- [:regexp_dot_escape, [:escape, :dot, '\.'], ::Regexp::Expression::EscapeSequence::Literal],
50
- [:regexp_dot_meta, [:meta, :dot, '.'], ::Regexp::Expression::CharacterType::Any],
51
- [:regexp_eol_anchor, [:anchor, :eol, '$'], ::Regexp::Expression::Anchor::EndOfLine],
52
- [:regexp_eol_escape, [:escape, :eol, '\$'], ::Regexp::Expression::EscapeSequence::Literal],
53
- [:regexp_eos_anchor, [:anchor, :eos, '\\z'], ::Regexp::Expression::Anchor::EndOfString],
54
- [:regexp_eos_ob_eol_anchor, [:anchor, :eos_ob_eol, '\\Z'], ::Regexp::Expression::Anchor::EndOfStringOrBeforeEndOfLine],
55
- [:regexp_escape_escape, [:escape, :escape, '\e'], ::Regexp::Expression::EscapeSequence::AsciiEscape],
56
- [:regexp_form_feed_escape, [:escape, :form_feed, '\f'], ::Regexp::Expression::EscapeSequence::FormFeed],
57
- [:regexp_group_close_escape, [:escape, :group_close, '\)'], ::Regexp::Expression::EscapeSequence::Literal],
58
- [:regexp_group_open_escape, [:escape, :group_open, '\('], ::Regexp::Expression::EscapeSequence::Literal],
59
- [:regexp_hex_type, [:type, :hex, '\h'], ::Regexp::Expression::CharacterType::Hex],
60
- [:regexp_interval_close_escape, [:escape, :interval_close, '\}'], ::Regexp::Expression::EscapeSequence::Literal],
61
- [:regexp_interval_open_escape, [:escape, :interval_open, '\{'], ::Regexp::Expression::EscapeSequence::Literal],
62
- [:regexp_letter_any_property, [:property, :letter_any, '\p{L}'], ::Regexp::Expression::UnicodeProperty::Letter::Any],
63
- [:regexp_mark_keep, [:keep, :mark, '\K'], ::Regexp::Expression::Keep::Mark],
64
- [:regexp_match_start_anchor, [:anchor, :match_start, '\\G'], ::Regexp::Expression::Anchor::MatchStart],
65
- [:regexp_newline_escape, [:escape, :newline, '\n'], ::Regexp::Expression::EscapeSequence::Literal],
66
- [:regexp_nondigit_type, [:type, :nondigit, '\D'], ::Regexp::Expression::CharacterType::NonDigit],
67
- [:regexp_nonhex_type, [:type, :nonhex, '\H'], ::Regexp::Expression::CharacterType::NonHex],
68
- [:regexp_nonspace_type, [:type, :nonspace, '\S'], ::Regexp::Expression::CharacterType::NonSpace],
69
- [:regexp_nonword_boundary_anchor, [:anchor, :nonword_boundary, '\\B'], ::Regexp::Expression::Anchor::NonWordBoundary],
70
- [:regexp_nonword_type, [:type, :nonword, '\W'], ::Regexp::Expression::CharacterType::NonWord],
71
- [:regexp_one_or_more_escape, [:escape, :one_or_more, '\+'], ::Regexp::Expression::EscapeSequence::Literal],
72
- [:regexp_print_nonproperty, [:property, :nonprint, '\P{Print}'], ::Regexp::Expression::UnicodeProperty::Print],
73
- [:regexp_print_property, [:property, :print, '\p{Print}'], ::Regexp::Expression::UnicodeProperty::Print],
74
- [:regexp_script_arabic_property, [:property, :script_arabic, '\p{Arabic}'], ::Regexp::Expression::UnicodeProperty::Script],
75
- [:regexp_script_han_property, [:property, :script_han, '\p{Han}'], ::Regexp::Expression::UnicodeProperty::Script],
76
- [:regexp_script_hangul_property, [:property, :script_hangul, '\p{Hangul}'], ::Regexp::Expression::UnicodeProperty::Script],
77
- [:regexp_script_hiragana_property, [:property, :script_hiragana, '\p{Hiragana}'], ::Regexp::Expression::UnicodeProperty::Script],
78
- [:regexp_script_katakana_property, [:property, :script_katakana, '\p{Katakana}'], ::Regexp::Expression::UnicodeProperty::Script],
79
- [:regexp_set_close_escape, [:escape, :set_close, '\]'], ::Regexp::Expression::EscapeSequence::Literal],
80
- [:regexp_set_open_escape, [:escape, :set_open, '\['], ::Regexp::Expression::EscapeSequence::Literal],
81
- [:regexp_space_type, [:type, :space, '\s'], ::Regexp::Expression::CharacterType::Space],
82
- [:regexp_vertical_tab_escape, [:escape, :vertical_tab, '\v'], ::Regexp::Expression::EscapeSequence::VerticalTab],
83
- [:regexp_word_boundary_anchor, [:anchor, :word_boundary, '\b'], ::Regexp::Expression::Anchor::WordBoundary],
84
- [:regexp_word_type, [:type, :word, '\w'], ::Regexp::Expression::CharacterType::Word],
85
- [:regexp_xgrapheme_type, [:type, :xgrapheme, '\X'], ::Regexp::Expression::CharacterType::ExtendedGrapheme],
86
- [:regexp_zero_or_more_escape, [:escape, :zero_or_more, '\*'], ::Regexp::Expression::EscapeSequence::Literal],
87
- [:regexp_zero_or_one_escape, [:escape, :zero_or_one, '\?'], ::Regexp::Expression::EscapeSequence::Literal]
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]
88
106
  )
89
107
 
90
108
  private
@@ -0,0 +1,59 @@
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
+ # Convert node into expression
31
+ #
32
+ # @return [Regexp::Expression::Group::Named]
33
+ def transform
34
+ named_group.tap do |expression|
35
+ expression.expressions = subexpressions
36
+ end
37
+ end
38
+
39
+ # Recursive mapping of children
40
+ #
41
+ # @return [Array<Regexp::Expression>]
42
+ def subexpressions
43
+ remaining_children.map(&Regexp.public_method(:to_expression))
44
+ end
45
+
46
+ # Named group instance constructed using name
47
+ #
48
+ # @return [Regexp::Expression::Group::Named]
49
+ def named_group
50
+ ::Regexp::Expression::Group::Named.new(
51
+ ::Regexp::Token.new(:group, :named, "(?<#{name}>")
52
+ )
53
+ end
54
+ end # ASTToExpression
55
+ end # NamedGroup
56
+ end # Transformer
57
+ end # Regexp
58
+ end # AST
59
+ end # Mutant
@@ -7,6 +7,7 @@ module Mutant
7
7
  # Transformer for option groups
8
8
  class OptionsGroup < self
9
9
  register :regexp_options_group
10
+ register :regexp_options_switch_group
10
11
 
11
12
  # Mapper from `Regexp::Expression` to `Parser::AST::Node`
12
13
  class ExpressionToAST < Transformer::ExpressionToAST
@@ -15,7 +16,7 @@ module Mutant
15
16
  #
16
17
  # @return [Parser::AST::Node]
17
18
  def call
18
- quantify(ast(expression.options, *children))
19
+ quantify(ast(expression.option_changes, *children))
19
20
  end
20
21
  end # ExpressionToAST
21
22
 
@@ -23,11 +24,11 @@ module Mutant
23
24
  class ASTToExpression < Transformer::ASTToExpression
24
25
  include NamedChildren
25
26
 
26
- children :options
27
+ children :option_changes
27
28
 
28
29
  private
29
30
 
30
- # Covnert node into expression
31
+ # Convert node into expression
31
32
  #
32
33
  # @return [Regexp::Expression::Group::Options]
33
34
  def transform
@@ -48,17 +49,31 @@ module Mutant
48
49
  # @return [Regexp::Expression::Group::Options]
49
50
  def options_group
50
51
  ::Regexp::Expression::Group::Options.new(
51
- ::Regexp::Token.new(:group, :options, text)
52
+ ::Regexp::Token.new(:group, type, text)
52
53
  )
53
54
  end
54
55
 
55
- # Flag text constructed from enabled options
56
+ # Options group type derived from node type
57
+ #
58
+ # @return [Symbol]
59
+ def type
60
+ {
61
+ regexp_options_group: :options,
62
+ regexp_options_switch_group: :options_switch
63
+ }.fetch(node.type)
64
+ end
65
+
66
+ # Flag text constructed from enabled and disabled options
56
67
  #
57
68
  # @return [String]
58
69
  def text
59
- flags = options.map { |key, value| key if value }.join
70
+ pos, neg = option_changes.partition { |_opt, val| val }.map do |arr|
71
+ arr.map(&:first).join
72
+ end
73
+ neg_opt_sep = '-' unless neg.empty?
74
+ content_sep = ':' unless type.equal?(:options_switch)
60
75
 
61
- "(?#{flags}-:"
76
+ "(?#{pos}#{neg_opt_sep}#{neg}#{content_sep}"
62
77
  end
63
78
  end # ASTToExpression
64
79
  end # OptionsGroup
@@ -21,15 +21,21 @@ module Mutant
21
21
  include LookupTable
22
22
 
23
23
  # rubocop:disable LineLength
24
+ # Expression::Sequence represents conditional branches, alternation branches, and intersection branches
24
25
  TABLE = Table.create(
25
- [:regexp_alternation_meta, [:meta, :alternation, '|'], ::Regexp::Expression::Alternation],
26
- [:regexp_nlookahead_assertion, [:assertion, :nlookahead, '(?!'], ::Regexp::Expression::Assertion::NegativeLookahead],
27
- [:regexp_passive_group, [:group, :passive, '(?:'], ::Regexp::Expression::Group::Passive],
28
- [:regexp_nlookbehind_assertion, [:assertion, :nlookbehind, '(?<!'], ::Regexp::Expression::Assertion::NegativeLookbehind],
29
- [:regexp_lookbehind_assertion, [:assertion, :lookbehind, '(?<='], ::Regexp::Expression::Assertion::Lookbehind],
30
- [:regexp_lookahead_assertion, [:assertion, :lookahead, '(?='], ::Regexp::Expression::Assertion::Lookahead],
31
- [:regexp_atomic_group, [:group, :atomic, '(?>'], ::Regexp::Expression::Group::Atomic],
32
- [:regexp_capture_group, [:group, :capture, '('], ::Regexp::Expression::Group::Capture]
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]
33
39
  )
34
40
 
35
41
  private
@@ -19,7 +19,7 @@ module Mutant
19
19
  #
20
20
  # @return [Regexp::Expression::Root]
21
21
  def transform
22
- ::Regexp::Expression::Root.new.tap do |root|
22
+ ::Regexp::Expression::Root.build.tap do |root|
23
23
  root.expressions = subexpressions
24
24
  end
25
25
  end
@@ -20,22 +20,24 @@ module Mutant
20
20
  class ASTToExpression < Transformer::ASTToExpression
21
21
  include LookupTable
22
22
 
23
+ # rubocop:disable LineLength
23
24
  TABLE = Table.create(
24
25
  [:regexp_literal_literal, %i[literal literal], ::Regexp::Expression::Literal],
25
26
  [:regexp_comment_group, %i[group comment], ::Regexp::Expression::Group::Comment],
26
- [:regexp_named_group, %i[group named], ::Regexp::Expression::Group::Named],
27
27
  [:regexp_number_backref, %i[backref number], ::Regexp::Expression::Backreference::Number],
28
28
  [:regexp_name_call_backref, %i[backref name_call], ::Regexp::Expression::Backreference::NameCall],
29
29
  [:regexp_whitespace_free_space, %i[free_space whitespace], ::Regexp::Expression::WhiteSpace],
30
30
  [:regexp_comment_free_space, %i[free_space comment], ::Regexp::Expression::WhiteSpace],
31
- [:regexp_hex_escape, %i[escape hex], ::Regexp::Expression::EscapeSequence::Literal],
31
+ [:regexp_hex_escape, %i[escape hex], ::Regexp::Expression::EscapeSequence::Hex],
32
+ [:regexp_octal_escape, %i[escape octal], ::Regexp::Expression::EscapeSequence::Octal],
32
33
  [:regexp_literal_escape, %i[escape literal], ::Regexp::Expression::EscapeSequence::Literal],
33
34
  [:regexp_backslash_escape, %i[escape backslash], ::Regexp::Expression::EscapeSequence::Literal],
34
35
  [:regexp_tab_escape, %i[escape tab], ::Regexp::Expression::EscapeSequence::Literal],
35
- [:regexp_codepoint_list_escape, %i[escape codepoint_list], ::Regexp::Expression::EscapeSequence::Literal],
36
- [:regexp_codepoint_escape, %i[escape codepoint], ::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],
37
38
  [:regexp_control_escape, %i[escape control], ::Regexp::Expression::EscapeSequence::Control],
38
- [:regexp_meta_sequence_escape, %i[escape meta_sequence], ::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]
39
41
  )
40
42
 
41
43
  private
@@ -45,23 +45,32 @@ module Mutant
45
45
 
46
46
  # Nodes generated by regular expression body parsing
47
47
  REGEXP = symbolset.(%w[
48
+ regexp_alnum_posixclass
49
+ regexp_alpha_posixclass
48
50
  regexp_alpha_property
49
51
  regexp_alternation_escape
50
52
  regexp_alternation_meta
53
+ regexp_arabic_property
54
+ regexp_ascii_posixclass
51
55
  regexp_atomic_group
52
56
  regexp_backslash_escape
57
+ regexp_backspace_escape
53
58
  regexp_bell_escape
59
+ regexp_blank_posixclass
54
60
  regexp_bol_anchor
55
61
  regexp_bol_escape
56
62
  regexp_bos_anchor
57
63
  regexp_capture_group
58
64
  regexp_carriage_escape
59
65
  regexp_character_set
66
+ regexp_cntrl_posixclass
60
67
  regexp_codepoint_escape
61
68
  regexp_codepoint_list_escape
62
69
  regexp_comment_free_space
63
70
  regexp_comment_group
71
+ regexp_condition_conditional
64
72
  regexp_control_escape
73
+ regexp_digit_posixclass
65
74
  regexp_digit_type
66
75
  regexp_dot_escape
67
76
  regexp_dot_meta
@@ -71,21 +80,29 @@ module Mutant
71
80
  regexp_eos_ob_eol_anchor
72
81
  regexp_escape_escape
73
82
  regexp_form_feed_escape
83
+ regexp_graph_posixclass
74
84
  regexp_greedy_interval
75
85
  regexp_greedy_one_or_more
76
86
  regexp_greedy_zero_or_more
77
87
  regexp_greedy_zero_or_one
78
88
  regexp_group_close_escape
79
89
  regexp_group_open_escape
90
+ regexp_han_property
91
+ regexp_hangul_property
80
92
  regexp_hex_escape
81
93
  regexp_hex_type
94
+ regexp_hiragana_property
95
+ regexp_intersection_set
82
96
  regexp_interval_close_escape
83
97
  regexp_interval_open_escape
84
- regexp_letter_any_property
98
+ regexp_katakana_property
99
+ regexp_letter_property
100
+ regexp_linebreak_type
85
101
  regexp_literal_escape
86
102
  regexp_literal_literal
87
103
  regexp_lookahead_assertion
88
104
  regexp_lookbehind_assertion
105
+ regexp_lower_posixclass
89
106
  regexp_mark_keep
90
107
  regexp_match_start_anchor
91
108
  regexp_meta_sequence_escape
@@ -100,34 +117,40 @@ module Mutant
100
117
  regexp_nonword_boundary_anchor
101
118
  regexp_nonword_type
102
119
  regexp_number_backref
120
+ regexp_octal_escape
103
121
  regexp_one_or_more_escape
104
122
  regexp_open_conditional
105
123
  regexp_options_group
124
+ regexp_options_switch_group
106
125
  regexp_passive_group
107
126
  regexp_possessive_interval
108
127
  regexp_possessive_one_or_more
109
128
  regexp_possessive_zero_or_more
110
129
  regexp_possessive_zero_or_one
130
+ regexp_print_nonposixclass
111
131
  regexp_print_nonproperty
132
+ regexp_print_posixclass
133
+ regexp_print_posixclass
112
134
  regexp_print_property
135
+ regexp_punct_posixclass
136
+ regexp_range_set
113
137
  regexp_reluctant_interval
114
138
  regexp_reluctant_one_or_more
115
139
  regexp_reluctant_zero_or_more
116
140
  regexp_root_expression
117
- regexp_script_arabic_property
118
- regexp_script_han_property
119
- regexp_script_hangul_property
120
- regexp_script_hiragana_property
121
- regexp_script_katakana_property
122
141
  regexp_sequence_expression
123
142
  regexp_set_close_escape
124
143
  regexp_set_open_escape
144
+ regexp_space_posixclass
125
145
  regexp_space_type
126
146
  regexp_tab_escape
147
+ regexp_upper_posixclass
127
148
  regexp_vertical_tab_escape
128
149
  regexp_whitespace_free_space
129
150
  regexp_word_boundary_anchor
151
+ regexp_word_posixclass
130
152
  regexp_word_type
153
+ regexp_xdigit_posixclass
131
154
  regexp_xgrapheme_type
132
155
  regexp_zero_or_more_escape
133
156
  regexp_zero_or_one_escape
@@ -44,7 +44,7 @@ module Mutant
44
44
  #
45
45
  # @return [Integer]
46
46
  def match_length(expression)
47
- if @recursion_pattern =~ expression.syntax
47
+ if @recursion_pattern.match?(expression.syntax)
48
48
  scope_name.length
49
49
  else
50
50
  0
@@ -12,10 +12,12 @@ module Mutant
12
12
  # @param [UnboundMethod] method
13
13
  #
14
14
  # @return [Matcher::Method::Instance]
15
+ #
16
+ # :reek:ManualDispatch
15
17
  def self.new(scope, target_method)
16
18
  name = target_method.name
17
19
  evaluator =
18
- if scope.include?(Memoizable) && scope.memoized?(name)
20
+ if scope.respond_to?(:memoized?) && scope.memoized?(name)
19
21
  Evaluator::Memoized
20
22
  else
21
23
  Evaluator
@@ -47,6 +47,7 @@ module Mutant
47
47
  regexp_eos_ob_eol_anchor
48
48
  regexp_greedy_zero_or_more
49
49
  regexp_hex_type
50
+ regexp_linebreak_type
50
51
  regexp_nondigit_type
51
52
  regexp_nonhex_type
52
53
  regexp_nonspace_type
@@ -43,7 +43,6 @@ module Mutant
43
43
  # @return [undefined]
44
44
  def mutate_body
45
45
  return unless body.all?(&method(:n_str?))
46
- return unless AST::Regexp.supported?(body_expression)
47
46
 
48
47
  Mutator.mutate(body_ast).each do |mutation|
49
48
  source = AST::Regexp.to_expression(mutation).to_s
@@ -12,7 +12,7 @@ module Mutant
12
12
  regexp_space_type: :regexp_nonspace_type,
13
13
  regexp_word_boundary_anchor: :regexp_nonword_boundary_anchor,
14
14
  regexp_word_type: :regexp_nonword_type,
15
- regexp_xgrapheme_type: :regexp_space_type
15
+ regexp_xgrapheme_type: :regexp_linebreak_type
16
16
  }
17
17
 
18
18
  MAP = IceNine.deep_freeze(map.merge(map.invert))
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Mutant
4
4
  # Current mutant version
5
- VERSION = '0.8.18'.freeze
5
+ VERSION = '0.8.19'.freeze
6
6
  end # Mutant
@@ -36,7 +36,7 @@ module Mutant
36
36
  #
37
37
  # @return [self]
38
38
  def write(message)
39
- if WARNING_PATTERN =~ message
39
+ if WARNING_PATTERN.match?(message)
40
40
  warnings << message
41
41
  else
42
42
  target.write(message)
data/meta/regexp.rb CHANGED
@@ -71,6 +71,9 @@ Mutant::Meta::Example.add :regexp do
71
71
 
72
72
  singleton_mutations
73
73
  regexp_mutations
74
+
75
+ mutation '/(?(1)(?:foo)(bar))/'
76
+ mutation '/(?(1)(foo)(?:bar))/'
74
77
  end
75
78
 
76
79
  Pathname
@@ -6,7 +6,7 @@ mutations = {
6
6
  [:regexp_space_type, '/\s/'] => [:regexp_nonspace_type, '/\S/'],
7
7
  [:regexp_word_boundary_anchor, '/\b/'] => [:regexp_nonword_boundary_anchor, '/\B/'],
8
8
  [:regexp_word_type, '/\w/'] => [:regexp_nonword_type, '/\W/'],
9
- [:regexp_xgrapheme_type, '/\X/'] => [:regexp_space_type, '/\s/']
9
+ [:regexp_xgrapheme_type, '/\X/'] => [:regexp_linebreak_type, '/\R/']
10
10
  }
11
11
 
12
12
  mutations = mutations.merge(mutations.invert)
data/mutant.gemspec CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |gem|
21
21
  gem.extra_rdoc_files = %w[LICENSE]
22
22
  gem.executables = %w[mutant]
23
23
 
24
- gem.required_ruby_version = '>= 2.3'
24
+ gem.required_ruby_version = '>= 2.5'
25
25
 
26
26
  gem.add_runtime_dependency('abstract_type', '~> 0.0.7')
27
27
  gem.add_runtime_dependency('adamantium', '~> 0.2.0')
@@ -36,7 +36,7 @@ Gem::Specification.new do |gem|
36
36
  gem.add_runtime_dependency('parallel', '~> 1.3')
37
37
  gem.add_runtime_dependency('parser', '~> 2.5.1')
38
38
  gem.add_runtime_dependency('procto', '~> 0.0.2')
39
- gem.add_runtime_dependency('regexp_parser', '~> 0.4.9')
39
+ gem.add_runtime_dependency('regexp_parser', '~> 1.2')
40
40
  gem.add_runtime_dependency('unparser', '~> 0.2.5')
41
41
 
42
42
  gem.add_development_dependency('bundler', '~> 1.10')
@@ -23,13 +23,11 @@
23
23
  - name: regexp_parser
24
24
  namespace: Regexp
25
25
  repo_uri: 'https://github.com/ammar/regexp_parser.git'
26
- repo_ref: 'v0.4.4'
26
+ repo_ref: 'v1.2.0'
27
27
  ruby_glob_pattern: '**/*.rb'
28
28
  mutation_coverage: false
29
29
  mutation_generation: true
30
- expected_errors:
31
- "Regexp::Syntax::Ruby::V233 does not implement: [escape:codepoint]":
32
- - regexp_parser/test/parser/test_escapes.rb
30
+ expected_errors: {}
33
31
  exclude: []
34
32
  - name: auom
35
33
  namespace: AUOM
@@ -3,6 +3,4 @@
3
3
  - 'lib/parallel.rb:222: warning: shadowing outer local variable - args'
4
4
  - 'lib/parallel.rb:227: warning: shadowing outer local variable - args'
5
5
  - 'lib/parser/lexer.rb:10836: warning: assigned but unused variable - testEof'
6
- - 'lib/regexp_parser/scanner.rb:1675: warning: assigned but unused variable - testEof'
7
- - 'lib/regexp_parser/scanner.rb:1689: warning: assigned but unused variable - testEof'
8
- - 'lib/regexp_parser/scanner.rb:1692: warning: assigned but unused variable - testEof'
6
+ - 'lib/regexp_parser/scanner.rb:1146: warning: assigned but unused variable - testEof'
@@ -202,17 +202,53 @@ end
202
202
  RegexpSpec.expect_mapping(/[ab]+/, :regexp_character_set) do
203
203
  s(:regexp_root_expression,
204
204
  s(:regexp_greedy_one_or_more, 1, -1,
205
- s(:regexp_character_set, 'a', 'b')))
205
+ s(:regexp_character_set,
206
+ s(:regexp_literal_literal, 'a'),
207
+ s(:regexp_literal_literal, 'b'))))
206
208
  end
207
209
 
208
210
  RegexpSpec.expect_mapping(/[ab]/, :regexp_character_set) do
209
211
  s(:regexp_root_expression,
210
- s(:regexp_character_set, 'a', 'b'))
212
+ s(:regexp_character_set,
213
+ s(:regexp_literal_literal, 'a'),
214
+ s(:regexp_literal_literal, 'b')))
211
215
  end
212
216
 
213
217
  RegexpSpec.expect_mapping(/[a-j]/, :regexp_character_set) do
214
218
  s(:regexp_root_expression,
215
- s(:regexp_character_set, 'a-j'))
219
+ s(:regexp_character_set,
220
+ s(:regexp_range_set,
221
+ s(:regexp_literal_literal, 'a'),
222
+ s(:regexp_literal_literal, 'j'))))
223
+ end
224
+
225
+ RegexpSpec.expect_mapping(/[\b]/, :regexp_backspace_escape) do
226
+ s(:regexp_root_expression,
227
+ s(:regexp_character_set,
228
+ s(:regexp_backspace_escape)))
229
+ end
230
+
231
+ RegexpSpec.expect_mapping(/()(?(1)a|b)/, :regexp_open_conditional) do
232
+ s(:regexp_root_expression,
233
+ s(:regexp_capture_group),
234
+ s(:regexp_open_conditional,
235
+ s(:regexp_condition_conditional, '(1)'),
236
+ s(:regexp_sequence_expression,
237
+ s(:regexp_literal_literal, 'a')),
238
+ s(:regexp_sequence_expression,
239
+ s(:regexp_literal_literal, 'b'))))
240
+ end
241
+
242
+ RegexpSpec.expect_mapping(/[ab&&bc]/, :regexp_intersection_set) do
243
+ s(:regexp_root_expression,
244
+ s(:regexp_character_set,
245
+ s(:regexp_intersection_set,
246
+ s(:regexp_sequence_expression,
247
+ s(:regexp_literal_literal, 'a'),
248
+ s(:regexp_literal_literal, 'b')),
249
+ s(:regexp_sequence_expression,
250
+ s(:regexp_literal_literal, 'b'),
251
+ s(:regexp_literal_literal, 'c')))))
216
252
  end
217
253
 
218
254
  RegexpSpec.expect_mapping(/\u{9879}/, :regexp_codepoint_list_escape) do
@@ -225,7 +261,7 @@ RegexpSpec.expect_mapping(/(?#foo)/, :regexp_comment_group) do
225
261
  s(:regexp_comment_group, '(?#foo)'))
226
262
  end
227
263
 
228
- RegexpSpec.expect_mapping(/(?x-: # comment
264
+ RegexpSpec.expect_mapping(/(?x: # comment
229
265
  )/, :regexp_comment_free_space) do
230
266
  s(:regexp_root_expression,
231
267
  s(:regexp_options_group, {
@@ -304,7 +340,9 @@ end
304
340
  RegexpSpec.expect_mapping(/[ab]+/, :regexp_greedy_one_or_more) do
305
341
  s(:regexp_root_expression,
306
342
  s(:regexp_greedy_one_or_more, 1, -1,
307
- s(:regexp_character_set, 'a', 'b')))
343
+ s(:regexp_character_set,
344
+ s(:regexp_literal_literal, 'a'),
345
+ s(:regexp_literal_literal, 'b'))))
308
346
  end
309
347
 
310
348
  RegexpSpec.expect_mapping(/(a)*/, :regexp_greedy_zero_or_more) do
@@ -336,6 +374,11 @@ RegexpSpec.expect_mapping(/\(/, :regexp_group_open_escape) do
336
374
  s(:regexp_group_open_escape))
337
375
  end
338
376
 
377
+ RegexpSpec.expect_mapping(/\101/, :regexp_octal_escape) do
378
+ s(:regexp_root_expression,
379
+ s(:regexp_octal_escape, '\\101'))
380
+ end
381
+
339
382
  RegexpSpec.expect_mapping(/\xFF/n, :regexp_hex_escape) do
340
383
  s(:regexp_root_expression,
341
384
  s(:regexp_hex_escape, '\\xFF'))
@@ -346,11 +389,16 @@ RegexpSpec.expect_mapping(/\h/, :regexp_hex_type) do
346
389
  s(:regexp_hex_type))
347
390
  end
348
391
 
349
- RegexpSpec.expect_mapping(/\H/, :regexp_hex_type) do
392
+ RegexpSpec.expect_mapping(/\H/, :regexp_nonhex_type) do
350
393
  s(:regexp_root_expression,
351
394
  s(:regexp_nonhex_type))
352
395
  end
353
396
 
397
+ RegexpSpec.expect_mapping(/\R/, :regexp_linebreak_type) do
398
+ s(:regexp_root_expression,
399
+ s(:regexp_linebreak_type))
400
+ end
401
+
354
402
  RegexpSpec.expect_mapping(/\X/, :regexp_xgrapheme_type) do
355
403
  s(:regexp_root_expression,
356
404
  s(:regexp_xgrapheme_type))
@@ -366,9 +414,9 @@ RegexpSpec.expect_mapping(/\{/, :regexp_interval_open_escape) do
366
414
  s(:regexp_interval_open_escape))
367
415
  end
368
416
 
369
- RegexpSpec.expect_mapping(/\p{L}/, :regexp_letter_any_property) do
417
+ RegexpSpec.expect_mapping(/\p{L}/, :regexp_letter_property) do
370
418
  s(:regexp_root_expression,
371
- s(:regexp_letter_any_property))
419
+ s(:regexp_letter_property))
372
420
  end
373
421
 
374
422
  RegexpSpec.expect_mapping(/\-/, :regexp_literal_escape) do
@@ -424,14 +472,16 @@ RegexpSpec.expect_mapping(/\G/, :regexp_match_start_anchor) do
424
472
  s(:regexp_match_start_anchor))
425
473
  end
426
474
 
427
- RegexpSpec.expect_mapping(/(?<foo>)/, :regexp_named_group) do
475
+ RegexpSpec.expect_mapping(/(?<foo>a)+/, :regexp_named_group) do
428
476
  s(:regexp_root_expression,
429
- s(:regexp_named_group, '(?<foo>'))
477
+ s(:regexp_greedy_one_or_more, 1, -1,
478
+ s(:regexp_named_group, 'foo',
479
+ s(:regexp_literal_literal, 'a'))))
430
480
  end
431
481
 
432
482
  RegexpSpec.expect_mapping(/(?<a>)\g<a>/, :regexp_name_call_backref) do
433
483
  s(:regexp_root_expression,
434
- s(:regexp_named_group, '(?<a>'),
484
+ s(:regexp_named_group, 'a'),
435
485
  s(:regexp_name_call_backref, '\\g<a>'))
436
486
  end
437
487
 
@@ -477,7 +527,7 @@ RegexpSpec.expect_mapping(/\+/, :regexp_one_or_more_escape) do
477
527
  s(:regexp_one_or_more_escape))
478
528
  end
479
529
 
480
- RegexpSpec.expect_mapping(/(?i-:a)+/, :regexp_options_group) do
530
+ RegexpSpec.expect_mapping(/(?i:a)+/, :regexp_options_group) do
481
531
  s(:regexp_root_expression,
482
532
  s(:regexp_greedy_one_or_more, 1, -1,
483
533
  s(:regexp_options_group,
@@ -487,7 +537,25 @@ RegexpSpec.expect_mapping(/(?i-:a)+/, :regexp_options_group) do
487
537
  s(:regexp_literal_literal, 'a'))))
488
538
  end
489
539
 
490
- RegexpSpec.expect_mapping(/(?x-: #{"\n"} )/, :regexp_whitespace_free_space) do
540
+ RegexpSpec.expect_mapping(/(?i-x:a)+/, :regexp_options_group) do
541
+ s(:regexp_root_expression,
542
+ s(:regexp_greedy_one_or_more, 1, -1,
543
+ s(:regexp_options_group,
544
+ {
545
+ i: true,
546
+ x: false
547
+ },
548
+ s(:regexp_literal_literal, 'a'))))
549
+ end
550
+
551
+ RegexpSpec.expect_mapping(/a(?i)b/, :regexp_options_switch_group) do
552
+ s(:regexp_root_expression,
553
+ s(:regexp_literal_literal, 'a'),
554
+ s(:regexp_options_switch_group, i: true),
555
+ s(:regexp_literal_literal, 'b'))
556
+ end
557
+
558
+ RegexpSpec.expect_mapping(/(?x: #{"\n"} )/, :regexp_whitespace_free_space) do
491
559
  s(:regexp_root_expression,
492
560
  s(:regexp_options_group,
493
561
  {
@@ -526,6 +594,23 @@ RegexpSpec.expect_mapping(/.?+/, :regexp_possessive_zero_or_one) do
526
594
  s(:regexp_dot_meta)))
527
595
  end
528
596
 
597
+ RegexpSpec.expect_mapping(/\P{Print}/, :regexp_print_nonproperty) do
598
+ s(:regexp_root_expression,
599
+ s(:regexp_print_nonproperty))
600
+ end
601
+
602
+ RegexpSpec.expect_mapping(/[[:print:]]/, :regexp_print_posixclass) do
603
+ s(:regexp_root_expression,
604
+ s(:regexp_character_set,
605
+ s(:regexp_print_posixclass)))
606
+ end
607
+
608
+ RegexpSpec.expect_mapping(/[[:^print:]]/, :regexp_print_nonposixclass) do
609
+ s(:regexp_root_expression,
610
+ s(:regexp_character_set,
611
+ s(:regexp_print_nonposixclass)))
612
+ end
613
+
529
614
  RegexpSpec.expect_mapping(/.{1,3}?/, :regexp_reluctant_interval) do
530
615
  s(:regexp_root_expression,
531
616
  s(:regexp_reluctant_interval, 1, 3,
@@ -544,29 +629,29 @@ RegexpSpec.expect_mapping(/.*?/, :regexp_reluctant_zero_or_more) do
544
629
  s(:regexp_dot_meta)))
545
630
  end
546
631
 
547
- RegexpSpec.expect_mapping(/\p{Arabic}/, :regexp_script_arabic_property) do
632
+ RegexpSpec.expect_mapping(/\p{Arabic}/, :regexp_arabic_property) do
548
633
  s(:regexp_root_expression,
549
- s(:regexp_script_arabic_property))
634
+ s(:regexp_arabic_property))
550
635
  end
551
636
 
552
- RegexpSpec.expect_mapping(/\p{Han}/, :regexp_script_han_property) do
637
+ RegexpSpec.expect_mapping(/\p{Han}/, :regexp_han_property) do
553
638
  s(:regexp_root_expression,
554
- s(:regexp_script_han_property))
639
+ s(:regexp_han_property))
555
640
  end
556
641
 
557
- RegexpSpec.expect_mapping(/\p{Hangul}/, :regexp_script_hangul_property) do
642
+ RegexpSpec.expect_mapping(/\p{Hangul}/, :regexp_hangul_property) do
558
643
  s(:regexp_root_expression,
559
- s(:regexp_script_hangul_property))
644
+ s(:regexp_hangul_property))
560
645
  end
561
646
 
562
- RegexpSpec.expect_mapping(/\p{Hiragana}/, :regexp_script_hiragana_property) do
647
+ RegexpSpec.expect_mapping(/\p{Hiragana}/, :regexp_hiragana_property) do
563
648
  s(:regexp_root_expression,
564
- s(:regexp_script_hiragana_property))
649
+ s(:regexp_hiragana_property))
565
650
  end
566
651
 
567
- RegexpSpec.expect_mapping(/\p{Katakana}/, :regexp_script_katakana_property) do
652
+ RegexpSpec.expect_mapping(/\p{Katakana}/, :regexp_katakana_property) do
568
653
  s(:regexp_root_expression,
569
- s(:regexp_script_katakana_property))
654
+ s(:regexp_katakana_property))
570
655
  end
571
656
 
572
657
  RegexpSpec.expect_mapping(/foo|bar/, :regexp_sequence_expression) do
@@ -28,8 +28,8 @@ RSpec.describe Mutant::Matcher::Method::Instance, '#call' do
28
28
  end
29
29
 
30
30
  context 'when method is defined inside eval' do
31
- let(:scope) { base::WithMemoizer }
32
- let(:method) { scope.instance_method(:boz) }
31
+ let(:scope) { base::WithMemoizer }
32
+ let(:method) { scope.instance_method(:boz) }
33
33
 
34
34
  let(:expected_warnings) do
35
35
  [
@@ -41,8 +41,8 @@ RSpec.describe Mutant::Matcher::Method::Instance, '#call' do
41
41
  end
42
42
 
43
43
  context 'when method is defined without source location' do
44
- let(:scope) { Module }
45
- let(:method) { scope.instance_method(:object_id) }
44
+ let(:scope) { Module }
45
+ let(:method) { scope.instance_method(:object_id) }
46
46
 
47
47
  let(:expected_warnings) do
48
48
  [
@@ -7,7 +7,7 @@ $VERBOSE = false
7
7
  # Namespace for test application
8
8
  module TestApp
9
9
  module InstanceMethodTests
10
- class WithMemoizer
10
+ module WithMemoizer
11
11
  include Adamantium
12
12
 
13
13
  def bar; end; def baz; end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mutant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.18
4
+ version: 0.8.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Markus Schirp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-24 00:00:00.000000000 Z
11
+ date: 2018-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: abstract_type
@@ -198,14 +198,14 @@ dependencies:
198
198
  requirements:
199
199
  - - "~>"
200
200
  - !ruby/object:Gem::Version
201
- version: 0.4.9
201
+ version: '1.2'
202
202
  type: :runtime
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
206
  - - "~>"
207
207
  - !ruby/object:Gem::Version
208
- version: 0.4.9
208
+ version: '1.2'
209
209
  - !ruby/object:Gem::Dependency
210
210
  name: unparser
211
211
  requirement: !ruby/object:Gem::Requirement
@@ -271,6 +271,7 @@ extensions: []
271
271
  extra_rdoc_files:
272
272
  - LICENSE
273
273
  files:
274
+ - ".circleci/config.yml"
274
275
  - ".gitattributes"
275
276
  - ".gitignore"
276
277
  - ".rspec"
@@ -284,7 +285,6 @@ files:
284
285
  - README.md
285
286
  - Rakefile
286
287
  - bin/mutant
287
- - circle.yml
288
288
  - config/devtools.yml
289
289
  - config/flay.yml
290
290
  - config/flog.yml
@@ -311,9 +311,8 @@ files:
311
311
  - lib/mutant/ast/nodes.rb
312
312
  - lib/mutant/ast/regexp.rb
313
313
  - lib/mutant/ast/regexp/transformer.rb
314
- - lib/mutant/ast/regexp/transformer/alternative.rb
315
- - lib/mutant/ast/regexp/transformer/character_set.rb
316
314
  - lib/mutant/ast/regexp/transformer/direct.rb
315
+ - lib/mutant/ast/regexp/transformer/named_group.rb
317
316
  - lib/mutant/ast/regexp/transformer/options_group.rb
318
317
  - lib/mutant/ast/regexp/transformer/quantifier.rb
319
318
  - lib/mutant/ast/regexp/transformer/recursive.rb
@@ -567,7 +566,6 @@ files:
567
566
  - spec/unit/mutant/ast/meta/send_spec.rb
568
567
  - spec/unit/mutant/ast/named_children_spec.rb
569
568
  - spec/unit/mutant/ast/regexp/parse_spec.rb
570
- - spec/unit/mutant/ast/regexp/supported_predicate_spec.rb
571
569
  - spec/unit/mutant/ast/regexp/transformer/lookup_table/table_spec.rb
572
570
  - spec/unit/mutant/ast/regexp/transformer/lookup_table_spec.rb
573
571
  - spec/unit/mutant/ast/regexp/transformer_spec.rb
@@ -670,7 +668,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
670
668
  requirements:
671
669
  - - ">="
672
670
  - !ruby/object:Gem::Version
673
- version: '2.3'
671
+ version: '2.5'
674
672
  required_rubygems_version: !ruby/object:Gem::Requirement
675
673
  requirements:
676
674
  - - ">="
@@ -700,7 +698,6 @@ test_files:
700
698
  - spec/unit/mutant/ast/meta/send_spec.rb
701
699
  - spec/unit/mutant/ast/named_children_spec.rb
702
700
  - spec/unit/mutant/ast/regexp/parse_spec.rb
703
- - spec/unit/mutant/ast/regexp/supported_predicate_spec.rb
704
701
  - spec/unit/mutant/ast/regexp/transformer/lookup_table/table_spec.rb
705
702
  - spec/unit/mutant/ast/regexp/transformer/lookup_table_spec.rb
706
703
  - spec/unit/mutant/ast/regexp/transformer_spec.rb
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Mutant
4
- module AST
5
- module Regexp
6
- class Transformer
7
- # Transformer for Regexp `alternative` nodes
8
- #
9
- # This transformer is very similar to the generic recursive mapper
10
- # except for the fact that the `Regexp::Expression` class for
11
- # `alternative` nodes has a unique constructor
12
- class Alternative < self
13
- register :regexp_sequence_expression
14
-
15
- # Mapper from `Regexp::Expression` to `Parser::AST::Node`
16
- ExpressionToAST = Class.new(Recursive::ExpressionToAST)
17
-
18
- # Mapper from `Parser::AST::Node` to `Regexp::Expression`
19
- class ASTToExpression < Transformer::ASTToExpression
20
- # Alternative instance with dummy values for `level`, `set_level`,
21
- # and `conditional_level`. These values do not affect unparsing
22
- ALTERNATIVE = IceNine.deep_freeze(
23
- ::Regexp::Expression::Alternative.new(0, 0, 0)
24
- )
25
-
26
- private
27
-
28
- # Transform ast into expression
29
- #
30
- # @return [Regexp::Expression::Alternative]
31
- def transform
32
- ALTERNATIVE.dup.tap do |alt|
33
- alt.expressions = subexpressions
34
- end
35
- end
36
- end # ASTToExpression
37
- end # Alternative
38
- end # Transformer
39
- end # Regexp
40
- end # AST
41
- end # Mutant
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Mutant
4
- module AST
5
- module Regexp
6
- class Transformer
7
- # Transformer for character sets
8
- #
9
- # The `Regexp::Expression` representation of a character set
10
- # is unique due to its usage of the `#members` attribute which
11
- # is why it gets its own transformer
12
- class CharacterSet < self
13
- register :regexp_character_set
14
-
15
- # Mapper from `Regexp::Expression` to `Parser::AST::Node`
16
- class ExpressionToAST < Transformer::ExpressionToAST
17
- # Transform character set expression into node
18
- #
19
- # @return [Parser::AST::Node]
20
- def call
21
- quantify(ast(*expression.members))
22
- end
23
- end # ExpressionToAST
24
-
25
- # Mapper from `Parser::AST::Node` to `Regexp::Expression`
26
- class ASTToExpression < Transformer::ASTToExpression
27
- CHARACTER_SET = IceNine.deep_freeze(
28
- ::Regexp::Expression::CharacterSet.new(
29
- ::Regexp::Token.new(:set, :character, '[')
30
- )
31
- )
32
-
33
- private
34
-
35
- # Transform node into expression
36
- #
37
- # @return [Regexp::Expression]
38
- def transform
39
- CHARACTER_SET.dup.tap do |expression|
40
- expression.members = node.children
41
- end
42
- end
43
- end # ASTToExpression
44
- end # CharacterSet
45
- end # Transformer
46
- end # Regexp
47
- end # AST
48
- end # Mutant
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Mutant::AST::Regexp, '.supported?' do
4
- subject { described_class.supported?(expression) }
5
-
6
- let(:expression) { described_class.parse(regexp) }
7
- let(:regexp) { /foo/ }
8
-
9
- it { should be(true) }
10
-
11
- context 'conditional regular expressions' do
12
- let(:regexp) { /((?(1)(foo)(bar)))/ }
13
-
14
- it { should be(false) }
15
- end
16
- end