Skip to content

Commit 552c72e

Browse files
zbynekniloc132
andauthored
Java 12-17API additions (#10106)
Fixes #9872 Fixes #10091 Fixes #9991 --------- Co-authored-by: Colin Alworth <[email protected]>
1 parent db6f61c commit 552c72e

File tree

34 files changed

+1172
-14
lines changed

34 files changed

+1172
-14
lines changed

dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ public class JavaResourceBase {
8282
"public interface CharSequence {",
8383
" char charAt(int index);",
8484
" int length();",
85+
" default boolean isEmpty() { return length() == 0; }",
8586
" String toString();",
8687
"}");
8788

@@ -345,7 +346,6 @@ public class JavaResourceBase {
345346
" }",
346347
" private native boolean equals(String obj) /*-{ return false; }-*/;",
347348
" public boolean equalsIgnoreCase(String str) { return false; }",
348-
" public native boolean isEmpty() /*-{ return true; }-*/;",
349349
" public int length() { return 0; }",
350350
" public static String valueOf(int i) { return \"\" + i; }",
351351
" public static String valueOf(char c) { return \"\" + c; }",

tools/api-checker/config/gwt212_213userapi.conf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ java.lang.Deprecated MISSING
156156
java.lang.FunctionalInterface MISSING
157157
java.lang.Override MISSING
158158
java.lang.SafeVarargs MISSING
159+
# Moved to CharSequence as a default method
160+
java.lang.String::isEmpty() MISSING
159161
java.lang.SuppressWarnings MISSING
160162
java.lang.annotation.AnnotationTypeMismatchException MISSING
161163
java.lang.annotation.Documented MISSING

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,38 @@ public boolean hasNext() {
5858
}, Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED, false);
5959
}
6060

61+
default IntStream codePoints() {
62+
return StreamSupport.intStream(() -> {
63+
PrimitiveIterator.OfInt it = new PrimitiveIterator.OfInt() {
64+
int cursor;
65+
66+
@Override
67+
public int nextInt() {
68+
checkElement(hasNext());
69+
int codePoint = CharSequence.this.toString().codePointAt(cursor++);
70+
if (codePoint >= 1 << 16) {
71+
cursor++;
72+
}
73+
return codePoint;
74+
}
75+
76+
@Override
77+
public boolean hasNext() {
78+
return cursor < length();
79+
}
80+
};
81+
return Spliterators.spliterator(it, length(), Spliterator.ORDERED);
82+
}, Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED, false);
83+
}
84+
85+
default boolean isEmpty() {
86+
return length() == 0;
87+
}
88+
89+
static int compare(CharSequence cs1, CharSequence cs2) {
90+
return cs1.toString().compareTo(cs2.toString());
91+
}
92+
6193
// CHECKSTYLE_OFF: Utility methods.
6294
@JsMethod
6395
static boolean $isInstance(HasCharSequenceTypeMarker instance) {

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

Lines changed: 132 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,14 @@
2727
import java.nio.charset.Charset;
2828
import java.nio.charset.UnsupportedCharsetException;
2929
import java.util.Comparator;
30+
import java.util.List;
3031
import java.util.Locale;
3132
import java.util.Spliterator;
3233
import java.util.Spliterators;
3334
import java.util.StringJoiner;
3435
import java.util.function.Consumer;
36+
import java.util.function.Function;
37+
import java.util.stream.Collectors;
3538
import java.util.stream.Stream;
3639
import java.util.stream.StreamSupport;
3740
import javaemul.internal.ArrayHelper;
@@ -488,10 +491,6 @@ public String intern() {
488491
return checkNotNull(this);
489492
}
490493

491-
public boolean isEmpty() {
492-
return length() == 0;
493-
}
494-
495494
public int lastIndexOf(int codePoint) {
496495
return lastIndexOf(fromCodePoint(codePoint));
497496
}
@@ -803,6 +802,10 @@ public String repeat(int count) {
803802
return asNativeString().repeat(count);
804803
}
805804

805+
public <R> R transform(Function<? super String,? extends R> f) {
806+
return f.apply(this);
807+
}
808+
806809
private int getLeadingWhitespaceLength() {
807810
int length = length();
808811
for (int i = 0; i < length; i++) {
@@ -823,6 +826,131 @@ private int getTrailingWhitespaceLength() {
823826
return length;
824827
}
825828

829+
public String indent(int spaces) {
830+
if (isEmpty()) {
831+
return "";
832+
}
833+
Stream<String> indentedLines;
834+
if (spaces >= 0) {
835+
String spaceString = " ".repeat(spaces);
836+
indentedLines = lines().map(line -> spaceString + line);
837+
} else {
838+
indentedLines = lines().map(
839+
line -> line.substring(Math.min(-spaces, line.getLeadingWhitespaceLength())));
840+
}
841+
return indentedLines.collect(Collectors.joining("\n", "", "\n"));
842+
}
843+
844+
public String stripIndent() {
845+
if (isEmpty()) {
846+
return "";
847+
}
848+
List<String> lines = lines().collect(Collectors.toList());
849+
int minIndent;
850+
char lastChar = charAt(length() - 1);
851+
String suffix = "";
852+
if (lastChar != '\r' && lastChar != '\n') {
853+
minIndent = Integer.MAX_VALUE;
854+
for (int i = 0; i < lines.size() - 1; i++) {
855+
String line = lines.get(i);
856+
int leadingWhitespace = line.getLeadingWhitespaceLength();
857+
// only update minIndent if not blank
858+
if (leadingWhitespace < line.length()) {
859+
minIndent = Math.min(minIndent, leadingWhitespace);
860+
}
861+
}
862+
// the last line affects minIndent even if blank
863+
minIndent = Math.min(minIndent, lines.get(lines.size() - 1).getLeadingWhitespaceLength());
864+
} else {
865+
suffix = "\n";
866+
minIndent = 0;
867+
}
868+
final int outdent = minIndent;
869+
return lines.stream().map(line -> {
870+
if (line.isBlank()) {
871+
return "";
872+
}
873+
return line.substring(outdent).stripTrailing();
874+
})
875+
.collect(Collectors.joining("\n", "", suffix));
876+
}
877+
878+
public String translateEscapes() {
879+
StringBuilder result = new StringBuilder();
880+
int translated = 0;
881+
while (translated < length()) {
882+
int nextBackslash = indexOf("\\", translated);
883+
if (nextBackslash == -1) {
884+
result.append(substring(translated));
885+
return result.toString();
886+
}
887+
if (nextBackslash == length() - 1) {
888+
throw new IllegalArgumentException();
889+
}
890+
result.append(substring(translated, nextBackslash));
891+
char currentChar = charAt(nextBackslash + 1);
892+
translated = nextBackslash + 2;
893+
switch (currentChar) {
894+
case 'b':
895+
result.append('\b');
896+
break;
897+
case 's':
898+
result.append(' ');
899+
break;
900+
case 't':
901+
result.append('\t');
902+
break;
903+
case 'n':
904+
result.append('\n');
905+
break;
906+
case 'f':
907+
result.append('\f');
908+
break;
909+
case 'r':
910+
result.append('\r');
911+
break;
912+
case '\n':
913+
// discard
914+
break;
915+
case '\r':
916+
// discard \r and possibly \n that comes right after
917+
if (translated < length() && charAt(translated) == '\n') {
918+
translated++;
919+
}
920+
break;
921+
case '"':
922+
result.append('"');
923+
break;
924+
case '\'':
925+
result.append('\'');
926+
break;
927+
case '\\':
928+
result.append('\\');
929+
break;
930+
case '0':
931+
case '1':
932+
case '2':
933+
case '3':
934+
case '4':
935+
case '5':
936+
case '6':
937+
case '7':
938+
int unicode = currentChar - '0';
939+
char nextChar = charAt(translated);
940+
while (nextChar >= '0' && nextChar < '8' && unicode < 32) {
941+
unicode = (unicode << 3) + (nextChar - '0');
942+
translated++;
943+
nextChar = translated < length() ? charAt(translated) : 0;
944+
}
945+
result.append((char) unicode);
946+
break;
947+
default:
948+
throw new IllegalArgumentException();
949+
}
950+
}
951+
return result.toString();
952+
}
953+
826954
private class LinesSpliterator extends Spliterators.AbstractSpliterator<String> {
827955
private int nextIndex = 0;
828956
private int rPosition = -1;

user/super/com/google/gwt/emul/java/util/BitSet.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818

1919
import static javaemul.internal.InternalPreconditions.checkArraySize;
2020

21+
import java.util.function.IntConsumer;
22+
import java.util.stream.IntStream;
23+
import java.util.stream.StreamSupport;
2124
import javaemul.internal.ArrayHelper;
2225
import javaemul.internal.LongUtils;
2326

@@ -37,6 +40,37 @@ public class BitSet {
3740

3841
private final int[] array;
3942

43+
private class BitSetSpliterator implements Spliterator.OfInt {
44+
int nextBitIndex = 0;
45+
46+
@Override
47+
public boolean tryAdvance(IntConsumer action) {
48+
int nextBit = nextSetBit(nextBitIndex);
49+
if (nextBit >= 0) {
50+
nextBitIndex = nextBit + 1;
51+
action.accept(nextBit);
52+
return true;
53+
}
54+
return false;
55+
}
56+
57+
@Override
58+
public Spliterator.OfInt trySplit() {
59+
return null;
60+
}
61+
62+
@Override
63+
public long estimateSize() {
64+
return size();
65+
}
66+
67+
@Override
68+
public int characteristics() {
69+
return Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED
70+
| Spliterator.DISTINCT | Spliterator.SORTED;
71+
}
72+
}
73+
4074
public BitSet() {
4175
array = new int[0];
4276
}
@@ -604,6 +638,11 @@ public int nextSetBit(int fromIndex) {
604638
return bitIndex(index) + Integer.numberOfTrailingZeros(word);
605639
}
606640

641+
public IntStream stream() {
642+
Spliterator.OfInt spliterator = new BitSetSpliterator();
643+
return StreamSupport.intStream(spliterator, false);
644+
}
645+
607646
public int previousClearBit(int fromIndex) {
608647
if (fromIndex == -1) {
609648
return -1;

user/super/com/google/gwt/emul/java/util/Map.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,13 @@ static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V>
276276
return (Comparator<Map.Entry<K, V>> & Serializable)
277277
(a, b) -> cmp.compare(a.getValue(), b.getValue());
278278
}
279+
280+
static <K,V> Map.Entry<K,V> copyOf(Map.Entry<? extends K,? extends V> e) {
281+
if (e instanceof AbstractMap.SimpleImmutableEntry) {
282+
return (Entry<K, V>) e;
283+
}
284+
return entry(e.getKey(), e.getValue());
285+
}
279286
}
280287

281288
void clear();

user/super/com/google/gwt/emul/java/util/stream/Collectors.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package java.util.stream;
1818

19+
import java.util.AbstractMap;
1920
import java.util.ArrayList;
2021
import java.util.Collection;
2122
import java.util.Collections;
@@ -33,6 +34,7 @@
3334
import java.util.Set;
3435
import java.util.StringJoiner;
3536
import java.util.function.BiConsumer;
37+
import java.util.function.BiFunction;
3638
import java.util.function.BinaryOperator;
3739
import java.util.function.Function;
3840
import java.util.function.Predicate;
@@ -71,6 +73,30 @@ public static <T, A, R, RR> Collector<T, A, RR> collectingAndThen(
7173
downstream.finisher().andThen(finisher));
7274
}
7375

76+
public static <T,R1,R2,R> Collector<T,?,R> teeing(Collector<? super T,?,R1> downstream1,
77+
Collector<? super T,?,R2> downstream2, BiFunction<? super R1,? super R2,R> merger) {
78+
return teeing2(downstream1, downstream2, merger);
79+
}
80+
81+
private static <T,R1,R2,R,X,Y> Collector<T,?,R> teeing2(Collector<? super T,X,R1> downstream1,
82+
Collector<? super T,Y,R2> downstream2, BiFunction<? super R1,? super R2,R> merger) {
83+
return Collector.of(
84+
() -> new AbstractMap.SimpleEntry<>(downstream1.supplier().get(),
85+
downstream2.supplier().get()),
86+
(a,b) -> {
87+
downstream1.accumulator().accept(a.getKey(), b);
88+
downstream2.accumulator().accept(a.getValue(), b);
89+
},
90+
(a,b) -> {
91+
X part = downstream1.combiner().apply(a.getKey(), b.getKey());
92+
Y part2 = downstream2.combiner().apply(a.getValue(), b.getValue());
93+
return new AbstractMap.SimpleEntry<>(part, part2);
94+
},
95+
(e) -> merger.apply(downstream1.finisher().apply(e.getKey()),
96+
downstream2.finisher().apply(e.getValue()))
97+
);
98+
}
99+
74100
public static <T> Collector<T,?,Long> counting() {
75101
// Using Long::sum here fails in JDT
76102
return reducing(0L, item -> 1L, (a, b) -> (Long) a.longValue() + b.longValue());

user/super/com/google/gwt/emul/java/util/stream/DoubleStream.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ default DoubleStream.Builder add(double t) {
5858
DoubleStream build();
5959
}
6060

61+
/**
62+
* See <a
63+
* href="https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/stream/DoubleStream.DoubleMapMultiConsumer.html">
64+
* the official Java API doc</a> for details.
65+
*/
66+
interface DoubleMapMultiConsumer {
67+
void accept(double value, DoubleConsumer consumer);
68+
}
69+
6170
static Builder builder() {
6271
return new Builder() {
6372
private double[] items = new double[0];
@@ -317,5 +326,13 @@ public boolean tryAdvance(DoubleConsumer action) {
317326
return StreamSupport.doubleStream(spliterator, false);
318327
}
319328

329+
default DoubleStream mapMulti(DoubleStream.DoubleMapMultiConsumer mapper) {
330+
return flatMap(element -> {
331+
Builder builder = builder();
332+
mapper.accept(element, (DoubleConsumer) builder::add);
333+
return builder.build();
334+
});
335+
}
336+
320337
double[] toArray();
321338
}

0 commit comments

Comments
 (0)