Skip to content

Commit 66fc6ff

Browse files
authored
Implement Java 8 String.split() semantics (#10054)
In Java 8, String.split() changed to not return an initial empty string on a zero-width match. This patch brings GWT's String emulation in compliance with that specification change. Added additional tests for non-zero-width matches and verifying behavior on all-empty matches. Compile time constant tests also updated to match. Fixes #8868
1 parent d687bf0 commit 66fc6ff

File tree

3 files changed

+47
-14
lines changed

3 files changed

+47
-14
lines changed

user/super/com/google/gwt/emul/java/lang/String.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,10 +647,22 @@ public String[] split(String regex, int maxMatch) {
647647
// subgroup handling
648648
NativeRegExp.Match matchObj = compiled.exec(trail);
649649
if (matchObj == null || trail == "" || (count == (maxMatch - 1) && maxMatch > 0)) {
650+
// At the end of the string, or we have performed the maximum number of matches,
651+
// record the remaining string and break
650652
out[count] = trail;
651653
break;
652654
} else {
653655
int matchIndex = matchObj.getIndex();
656+
657+
if (lastTrail == null && matchIndex == 0 && matchObj.asArray()[0].length() == 0) {
658+
// As of Java 8, we should discard the first zero-length match if it is the beginning of
659+
// the string. Do not increment the count, and do not add to the output array.
660+
trail = trail.substring(matchIndex + matchObj.asArray()[0].length(), trail.length());
661+
compiled.lastIndex = 0;
662+
lastTrail = trail;
663+
continue;
664+
}
665+
654666
out[count] = trail.substring(0, matchIndex);
655667
trail = trail.substring(matchIndex + matchObj.asArray()[0].length(), trail.length());
656668
// Force the compiled pattern to reset internal state

user/test/com/google/gwt/emultest/java/lang/CompilerConstantStringTest.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package com.google.gwt.emultest.java.lang;
1717

1818
import com.google.gwt.junit.client.GWTTestCase;
19-
import com.google.gwt.testing.TestUtils;
2019

2120
import java.util.Locale;
2221

@@ -245,15 +244,30 @@ public void testSplit() {
245244
"b", "", ":and:f"});
246245
compareList("0:", "boo:and:foo".split(":", 0), new String[] {
247246
"boo", "and", "foo"});
248-
}
247+
// issue 2742
248+
compareList("issue2742", new String[] {}, "/".split("/", 0));
249+
250+
// Splitting an empty string should result in an array containing a single
251+
// empty string.
252+
String[] s = "".split(",");
253+
assertTrue(s != null);
254+
assertTrue(s.length == 1);
255+
assertTrue(s[0] != null);
256+
assertTrue(s[0].length() == 0);
257+
258+
s = "abcada".split("a");
259+
assertTrue(s != null);
260+
assertEquals(3, s.length);
261+
assertEquals("", s[0]);
262+
assertEquals("bc", s[1]);
263+
assertEquals("d", s[2]); }
249264

250265
public void testSplit_emptyExpr() {
251-
// TODO(rluble): implement JDK8 string.split semantics and fix test.
252-
// See issue 8913.
253-
String[] expected = (TestUtils.getJdkVersion() > 7) ?
254-
new String[] {"a", "b", "c", "x", "x", "d", "e", "x", "f", "x"} :
255-
new String[] {"", "a", "b", "c", "x", "x", "d", "e", "x", "f", "x"};
266+
String[] expected = new String[] {"a", "b", "c", "x", "x", "d", "e", "x", "f", "x"};
256267
compareList("emptyRegexSplit", expected, "abcxxdexfx".split(""));
268+
269+
String[] arr = ",".split(",");
270+
assertEquals(0, arr.length);
257271
}
258272

259273
public void testStartsWith() {

user/test/com/google/gwt/emultest/java/lang/StringTest.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -781,23 +781,30 @@ public void testSplit() {
781781

782782
// Splitting an empty string should result in an array containing a single
783783
// empty string.
784-
String[] s = "".split(",");
784+
String[] s = hideFromCompiler("").split(",");
785785
assertTrue(s != null);
786786
assertTrue(s.length == 1);
787787
assertTrue(s[0] != null);
788788
assertTrue(s[0].length() == 0);
789+
790+
s = hideFromCompiler("abcada").split("a");
791+
assertTrue(s != null);
792+
assertEquals(3, s.length);
793+
assertEquals("", s[0]);
794+
assertEquals("bc", s[1]);
795+
assertEquals("d", s[2]);
789796
}
790797

791798
public void testSplit_emptyExpr() {
792-
// TODO(rluble): implement JDK8 string.split semantics and fix test.
793-
String[] expected = (TestUtils.getJdkVersion() > 7) ?
794-
new String[] {"a", "b", "c", "x", "x", "d", "e", "x", "f", "x"} :
795-
new String[] {"", "a", "b", "c", "x", "x", "d", "e", "x", "f", "x"};
796-
compareList("emptyRegexSplit", expected, "abcxxdexfx".split(""));
799+
String[] expected = new String[] {"a", "b", "c", "x", "x", "d", "e", "x", "f", "x"};
800+
compareList("emptyRegexSplit", expected, hideFromCompiler("abcxxdexfx").split(""));
801+
802+
String[] arr = hideFromCompiler(",").split(",");
803+
assertEquals(0, arr.length);
797804
}
798805

799806
public void testStartsWith() {
800-
String haystack = "abcdefghi";
807+
String haystack = hideFromCompiler("abcdefghi");
801808
assertTrue(haystack.startsWith("abc"));
802809
assertTrue(haystack.startsWith("bc", 1));
803810
assertTrue(haystack.startsWith(haystack));

0 commit comments

Comments
 (0)