Align JS and JVM behavior of Regex replace function #KT-28378

This commit is contained in:
Abduqodiri Qurbonzoda
2021-09-28 02:20:22 +03:00
committed by Space
parent 5326c875c0
commit dc2f5eab25
9 changed files with 258 additions and 19 deletions
+69
View File
@@ -7,6 +7,7 @@
package test.text
import test.supportsNamedCapturingGroup
import kotlin.test.*
class RegexTest {
@@ -238,10 +239,78 @@ class RegexTest {
@Test fun replace() {
val input = "123-456"
val pattern = "(\\d+)".toRegex()
// js String.prototype.replace() inserts a "$"
assertFailsWith<IllegalArgumentException>("$$") { pattern.replace(input, "$$") }
// js String.prototype.replace() inserts the matched substring
assertFailsWith<IllegalArgumentException>("$&") { pattern.replace(input, "$&") }
// js String.prototype.replace() inserts the portion of the string that precedes the matched substring
assertFailsWith<IllegalArgumentException>("\$`") { pattern.replace(input, "\$`") }
// js String.prototype.replace() inserts the portion of the string that follows the matched substring
assertFailsWith<IllegalArgumentException>("$'") { pattern.replace(input, "$'") }
// js String.prototype.replace() inserts the replacement string as a literal if it refers to a non-existing capturing group
assertFailsWith<RuntimeException>("$") { pattern.replace(input, "$") } // should be IAE, however jdk7 throws String IOOBE
assertFailsWith<IndexOutOfBoundsException>("$2") { pattern.replace(input, "$2") }
assertFailsWith<IllegalArgumentException>("\$name") { pattern.replace(input, "\$name") }
assertFailsWith<IllegalArgumentException>("\${name}") { pattern.replace(input, "\${name}") }
assertFailsWith<IllegalArgumentException>("$-") { pattern.replace(input, "$-") }
// inserts "$" literally
assertEquals("$-$", pattern.replace(input, "\\$"))
// inserts the matched substring
assertEquals("(123)-(456)", pattern.replace(input, "($0)"))
// inserts the first captured group
assertEquals("(123)-(456)", pattern.replace(input, "($1)"))
assertEquals("$&-$&", pattern.replace(input, Regex.escapeReplacement("$&")))
assertEquals("X-456", pattern.replaceFirst(input, "X"))
val longInput = "0123456789ABC"
val longPattern = "0(1(2(3(4(5(6(7(8(9(A(B(C))))))))))))".toRegex()
for (groupIndex in 0..12) {
assertEquals(longInput.substring(groupIndex), longPattern.replace(longInput, "$$groupIndex"))
}
assertEquals(longInput.substring(1) + "3", longPattern.replace(longInput, "$13"))
// KT-38000
assertEquals("""\,""", ",".replace("([,])".toRegex(), """\\$1"""))
// KT-28378
assertEquals("$ 2", "2".replace(Regex("(.+)"), "\\$ $1"))
assertEquals("$2", "2".replace(Regex("(.+)"), "\\$$1"))
assertFailsWith<IllegalArgumentException> { "2".replace(Regex("(.+)"), "$ $1") }
}
@Test fun replaceWithNamedGroups() {
if (!supportsNamedCapturingGroup) {
assertFails {
val pattern = Regex("(?<first>\\d+)-(?<second>\\d+)")
pattern.replace("123-456", "\${first}+\${second}")
}
return
}
val pattern = Regex("(?<first>\\d+)-(?<second>\\d+)")
"123-456".let { input ->
assertEquals("(123-456)", pattern.replace(input, "($0)"))
assertEquals("123+456", pattern.replace(input, "$1+$2"))
// take largest legal group number reference
assertEquals("1230+456", pattern.replace(input, "$10+$2"))
assertEquals("123+456", pattern.replace(input, "$01+$2"))
// js refers to named capturing groups with "$<name>" syntax
assertFailsWith<IllegalArgumentException>("\$<first>+\$<second>") { pattern.replace(input, "\$<first>+\$<second>") }
assertEquals("123+456", pattern.replace(input, "\${first}+\${second}"))
// missing trailing '}'
assertFailsWith<IllegalArgumentException>("\${first+\${second}") { pattern.replace(input, "\${first+\${second}") }
assertFailsWith<IllegalArgumentException>("\${first}+\${second") { pattern.replace(input, "\${first}+\${second") }
}
"123-456-789-012".let { input ->
assertEquals("123/456-789/012", pattern.replace(input, "$1/$2"))
assertEquals("123/456-789/012", pattern.replace(input, "\${first}/\${second}"))
assertEquals("123/456-789-012", pattern.replaceFirst(input, "\${first}/\${second}"))
}
}
@Test fun replaceEvaluator() {