summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--prism/extension.c28
-rw-r--r--test/prism/regexp_test.rb120
2 files changed, 59 insertions, 89 deletions
diff --git a/prism/extension.c b/prism/extension.c
index f4d7674de6..3d118b1edd 100644
--- a/prism/extension.c
+++ b/prism/extension.c
@@ -1093,33 +1093,6 @@ parse_file_failure_p(int argc, VALUE *argv, VALUE self) {
/* Utility functions exposed to make testing easier */
/******************************************************************************/
-/**
- * call-seq:
- * Debug::named_captures(source) -> Array
- *
- * Returns an array of strings corresponding to the named capture groups in the
- * given source string. If prism was unable to parse the regular expression,
- * this function returns nil.
- */
-static VALUE
-named_captures(VALUE self, VALUE source) {
- pm_string_list_t string_list = { 0 };
-
- if (!pm_regexp_named_capture_group_names((const uint8_t *) RSTRING_PTR(source), RSTRING_LEN(source), &string_list, false, PM_ENCODING_UTF_8_ENTRY)) {
- pm_string_list_free(&string_list);
- return Qnil;
- }
-
- VALUE names = rb_ary_new();
- for (size_t index = 0; index < string_list.length; index++) {
- const pm_string_t *string = &string_list.strings[index];
- rb_ary_push(names, rb_str_new((const char *) pm_string_source(string), pm_string_length(string)));
- }
-
- pm_string_list_free(&string_list);
- return names;
-}
-
#ifndef PRISM_EXCLUDE_PRETTYPRINT
/**
@@ -1336,7 +1309,6 @@ Init_prism(void) {
// Next, the functions that will be called by the parser to perform various
// internal tasks. We expose these to make them easier to test.
VALUE rb_cPrismDebug = rb_define_module_under(rb_cPrism, "Debug");
- rb_define_singleton_method(rb_cPrismDebug, "named_captures", named_captures, 1);
rb_define_singleton_method(rb_cPrismDebug, "format_errors", format_errors, 2);
#ifndef PRISM_EXCLUDE_PRETTYPRINT
diff --git a/test/prism/regexp_test.rb b/test/prism/regexp_test.rb
index 0a5fc2b4fc..35be217f79 100644
--- a/test/prism/regexp_test.rb
+++ b/test/prism/regexp_test.rb
@@ -2,78 +2,84 @@
require_relative "test_helper"
-return if Prism::BACKEND == :FFI
-
module Prism
class RegexpTest < TestCase
- ##############################################################################
+ ############################################################################
# These tests test the actual use case of extracting named capture groups
- ##############################################################################
+ ############################################################################
def test_named_captures_with_arrows
- assert_equal(["foo"], named_captures("(?<foo>bar)"))
+ assert_equal([:foo], named_captures("(?<foo>bar)"))
end
def test_named_captures_with_single_quotes
- assert_equal(["foo"], named_captures("(?'foo'bar)"))
+ assert_equal([:foo], named_captures("(?'foo'bar)"))
end
def test_nested_named_captures_with_arrows
- assert_equal(["foo", "bar"], named_captures("(?<foo>(?<bar>baz))"))
+ assert_equal([:foo, :bar], named_captures("(?<foo>(?<bar>baz))"))
end
def test_nested_named_captures_with_single_quotes
- assert_equal(["foo", "bar"], named_captures("(?'foo'(?'bar'baz))"))
+ assert_equal([:foo, :bar], named_captures("(?'foo'(?'bar'baz))"))
end
def test_allows_duplicate_named_captures
- assert_equal(["foo", "foo"], named_captures("(?<foo>bar)(?<foo>baz)"))
+ assert_equal([:foo], named_captures("(?<foo>bar)(?<foo>baz)"))
end
def test_named_capture_inside_fake_range_quantifier
- assert_equal(["foo"], named_captures("foo{1, (?<foo>2)}"))
+ assert_equal([:foo], named_captures("foo{1, (?<foo>2)}"))
+ end
+
+ def test_fake_named_captures_inside_character_sets
+ assert_equal([], named_captures("[a-z(?<foo>)]"))
end
- ##############################################################################
+ def test_fake_named_capture_inside_character_set_with_escaped_ending
+ assert_equal([], named_captures("[a-z\\](?<foo>)]"))
+ end
+
+ ############################################################################
# These tests test the rest of the AST. They are not exhaustive, but they
# should cover the most common cases. We test these to make sure we don't
# accidentally regress and stop being able to extract named captures.
- ##############################################################################
+ ############################################################################
def test_alternation
- refute_nil(named_captures("foo|bar"))
+ assert_valid_regexp("foo|bar")
end
def test_anchors
- refute_nil(named_captures("^foo$"))
+ assert_valid_regexp("^foo$")
end
def test_any
- refute_nil(named_captures("."))
+ assert_valid_regexp(".")
end
def test_posix_character_classes
- refute_nil(named_captures("[[:digit:]]"))
+ assert_valid_regexp("[[:digit:]]")
end
def test_negated_posix_character_classes
- refute_nil(named_captures("[[:^digit:]]"))
+ assert_valid_regexp("[[:^digit:]]")
end
def test_invalid_posix_character_classes_should_fall_back_to_regular_classes
- refute_nil(named_captures("[[:foo]]"))
+ assert_valid_regexp("[[:foo]]")
end
def test_character_sets
- refute_nil(named_captures("[abc]"))
+ assert_valid_regexp("[abc]")
end
def test_nested_character_sets
- refute_nil(named_captures("[[abc]]"))
+ assert_valid_regexp("[[abc]]")
end
def test_nested_character_sets_with_operators
- refute_nil(named_captures("[[abc] && [def]]"))
+ assert_valid_regexp("[[abc] && [def]]")
end
def test_named_capture_inside_nested_character_set
@@ -81,120 +87,108 @@ module Prism
end
def test_negated_character_sets
- refute_nil(named_captures("[^abc]"))
+ assert_valid_regexp("[^abc]")
end
def test_character_ranges
- refute_nil(named_captures("[a-z]"))
+ assert_valid_regexp("[a-z]")
end
def test_negated_character_ranges
- refute_nil(named_captures("[^a-z]"))
- end
-
- def test_fake_named_captures_inside_character_sets
- assert_equal([], named_captures("[a-z(?<foo>)]"))
- end
-
- def test_fake_named_capture_inside_character_set_with_escaped_ending
- assert_equal([], named_captures("[a-z\\](?<foo>)]"))
+ assert_valid_regexp("[^a-z]")
end
def test_comments
- refute_nil(named_captures("(?#foo)"))
+ assert_valid_regexp("(?#foo)")
end
def test_comments_with_escaped_parentheses
- refute_nil(named_captures("(?#foo\\)\\))"))
+ assert_valid_regexp("(?#foo\\)\\))")
end
def test_non_capturing_groups
- refute_nil(named_captures("(?:foo)"))
+ assert_valid_regexp("(?:foo)")
end
def test_positive_lookaheads
- refute_nil(named_captures("(?=foo)"))
+ assert_valid_regexp("(?=foo)")
end
def test_negative_lookaheads
- refute_nil(named_captures("(?!foo)"))
+ assert_valid_regexp("(?!foo)")
end
def test_positive_lookbehinds
- refute_nil(named_captures("(?<=foo)"))
+ assert_valid_regexp("(?<=foo)")
end
def test_negative_lookbehinds
- refute_nil(named_captures("(?<!foo)"))
+ assert_valid_regexp("(?<!foo)")
end
def test_atomic_groups
- refute_nil(named_captures("(?>foo)"))
+ assert_valid_regexp("(?>foo)")
end
def test_absence_operator
- refute_nil(named_captures("(?~foo)"))
+ assert_valid_regexp("(?~foo)")
end
def test_conditional_expression_with_index
- refute_nil(named_captures("(?(1)foo)"))
+ assert_valid_regexp("(?(1)foo)")
end
def test_conditional_expression_with_name
- refute_nil(named_captures("(?(foo)bar)"))
+ assert_valid_regexp("(?(foo)bar)")
end
def test_conditional_expression_with_group
- refute_nil(named_captures("(?(<foo>)bar)"))
+ assert_valid_regexp("(?(<foo>)bar)")
end
def test_options_on_groups
- refute_nil(named_captures("(?imxdau:foo)"))
- end
-
- def test_options_on_groups_with_invalid_options
- assert_nil(named_captures("(?z:bar)"))
+ assert_valid_regexp("(?imxdau:foo)")
end
def test_options_on_groups_getting_turned_off
- refute_nil(named_captures("(?-imx:foo)"))
+ assert_valid_regexp("(?-imx:foo)")
end
def test_options_on_groups_some_getting_turned_on_some_getting_turned_off
- refute_nil(named_captures("(?im-x:foo)"))
+ assert_valid_regexp("(?im-x:foo)")
end
def test_star_quantifier
- refute_nil(named_captures("foo*"))
+ assert_valid_regexp("foo*")
end
def test_plus_quantifier
- refute_nil(named_captures("foo+"))
+ assert_valid_regexp("foo+")
end
def test_question_mark_quantifier
- refute_nil(named_captures("foo?"))
+ assert_valid_regexp("foo?")
end
def test_endless_range_quantifier
- refute_nil(named_captures("foo{1,}"))
+ assert_valid_regexp("foo{1,}")
end
def test_beginless_range_quantifier
- refute_nil(named_captures("foo{,1}"))
+ assert_valid_regexp("foo{,1}")
end
def test_range_quantifier
- refute_nil(named_captures("foo{1,2}"))
+ assert_valid_regexp("foo{1,2}")
end
def test_fake_range_quantifier_because_of_spaces
- refute_nil(named_captures("foo{1, 2}"))
+ assert_valid_regexp("foo{1, 2}")
end
- ##############################################################################
+ ############################################################################
# These test that flag values are correct.
- ##############################################################################
+ ############################################################################
def test_flag_ignorecase
assert_equal(Regexp::IGNORECASE, options("i"))
@@ -241,8 +235,12 @@ module Prism
private
+ def assert_valid_regexp(source)
+ assert Prism.parse_success?("/#{source}/ =~ \"\"")
+ end
+
def named_captures(source)
- Debug.named_captures(source)
+ Prism.parse("/#{source}/ =~ \"\"").value.locals
end
def options(flags)