diff --git a/libraries/stdlib/jdk8/test/text/RegexTest.kt b/libraries/stdlib/jdk8/test/text/RegexTest.kt index f3d13fc556a..f8dc62defd3 100644 --- a/libraries/stdlib/jdk8/test/text/RegexTest.kt +++ b/libraries/stdlib/jdk8/test/text/RegexTest.kt @@ -21,22 +21,28 @@ import kotlin.test.* class RegexTest { @Test fun namedGroups() { - val input = "1a 2b 3c" - val regex = "(?\\d)(?\\w)".toRegex() + val input = "1a 2b 3" + val regex = "(?\\d)(?\\w)?".toRegex() val matches = regex.findAll(input).toList() assertTrue(matches.all { it.groups.size == 3 }) - val m1 = matches[0] + val (m1, m2, m3) = matches assertEquals("1", m1.groups["num"]?.value) assertEquals(0..0, m1.groups["num"]?.range) assertEquals("a", m1.groups["liter"]?.value) assertEquals(1..1, m1.groups["liter"]?.range) - val m2 = matches[1] assertEquals("2", m2.groups["num"]?.value) assertEquals(3..3, m2.groups["num"]?.range) assertEquals("b", m2.groups["liter"]?.value) assertEquals(4..4, m2.groups["liter"]?.range) + + assertEquals("3", m3.groups["num"]?.value) + assertNull(m3.groups["liter"]) + + assertFailsWith { m2.groups["unknown_group"] }.let { e -> + assertTrue("unknown_group" in e.message!!) + } } } diff --git a/libraries/stdlib/jvm/src/kotlin/text/regex/Regex.kt b/libraries/stdlib/jvm/src/kotlin/text/regex/Regex.kt index 7e17864a886..0ed232674ac 100644 --- a/libraries/stdlib/jvm/src/kotlin/text/regex/Regex.kt +++ b/libraries/stdlib/jvm/src/kotlin/text/regex/Regex.kt @@ -263,7 +263,7 @@ private fun Matcher.matchEntire(input: CharSequence): MatchResult? { } private class MatcherMatchResult(private val matcher: Matcher, private val input: CharSequence) : MatchResult { - private val matchResult = matcher.toMatchResult() + private val matchResult: java.util.regex.MatchResult get() = matcher override val range: IntRange get() = matchResult.range() override val value: String @@ -302,7 +302,7 @@ private class MatcherMatchResult(private val matcher: Matcher, private val input override fun next(): MatchResult? { val nextIndex = matchResult.end() + if (matchResult.end() == matchResult.start()) 1 else 0 - return if (nextIndex <= input.length) matcher.findNext(nextIndex, input) else null + return if (nextIndex <= input.length) matcher.pattern().matcher(input).findNext(nextIndex, input) else null } } diff --git a/libraries/stdlib/jvm/test/text/RegexJVMTest.kt b/libraries/stdlib/jvm/test/text/RegexJVMTest.kt index eb4a81b0565..24485c6b733 100644 --- a/libraries/stdlib/jvm/test/text/RegexJVMTest.kt +++ b/libraries/stdlib/jvm/test/text/RegexJVMTest.kt @@ -14,12 +14,14 @@ import java.util.regex.Pattern class RegexJVMTest { @Test fun matchGroups() { - val input = "1a 2b 3c" - val regex = "(\\d)(\\w)".toRegex() + val input = "1a 2b 3" + val regex = "(\\d)(\\w)?".toRegex() val matches = regex.findAll(input).toList() assertTrue(matches.all { it.groups.size == 3 }) - val m1 = matches[0] + + val (m1, m2, m3) = matches + assertEquals("1a", m1.groups[0]?.value) assertEquals(0..1, m1.groups[0]?.range) assertEquals("1", m1.groups[1]?.value) @@ -27,13 +29,28 @@ class RegexJVMTest { assertEquals("a", m1.groups[2]?.value) assertEquals(1..1, m1.groups[2]?.range) - val m2 = matches[1] assertEquals("2", m2.groups[1]?.value) assertEquals(3..3, m2.groups[1]?.range) assertEquals("b", m2.groups[2]?.value) assertEquals(4..4, m2.groups[2]?.range) + + assertEquals("3", m3.groups[1]?.value) + assertNull(m3.groups[2]) } + @Test fun matchSequenceWithLookbehind() { + val input = "123_000 456 789" + val pattern = "(?<=^|\\s)\\d+_?".toRegex() + + val matches = pattern.findAll(input) + val values = matches.map { it.value } + val expected = listOf("123_", "456", "789") + assertEquals(expected, values.toList()) + assertEquals(expected, values.toList(), "running match sequence second time") + assertEquals(expected.drop(1), pattern.findAll(input, startIndex = 3).map { it.value }.toList()) + + assertEquals(listOf(0..3, 8..10, 12..14), matches.map { it.range }.toList()) + } private fun compareRegex(expected: Regex, actual: Regex) = compare(expected, actual) { propertyEquals(Regex::pattern)