From 195c8dd01b168689a2f0b2719811e90741c08e59 Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Wed, 12 Mar 2025 04:12:49 +0100 Subject: [PATCH 01/12] Java 12 emulation --- .../com/google/gwt/emul/java/lang/String.java | 4 ++ .../gwt/emul/java/util/stream/Collectors.java | 28 +++++++++++ .../gwt/emul/java/util/stream/Stream.java | 4 ++ .../gwt/emultest/java12/lang/StringTest.java | 50 +++++++++++++++++++ .../java12/util/stream/CollectorsTest.java | 33 ++++++++++++ .../google/gwt/emultest/EmulJava12Suite.java | 29 +++++++++++ .../gwt/emultest/java12/lang/StringTest.java | 46 +++++++++++++++++ .../java12/util/stream/CollectorsTest.java | 46 +++++++++++++++++ 8 files changed, 240 insertions(+) create mode 100644 user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/lang/StringTest.java create mode 100644 user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java create mode 100644 user/test/com/google/gwt/emultest/EmulJava12Suite.java create mode 100644 user/test/com/google/gwt/emultest/java12/lang/StringTest.java create mode 100644 user/test/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java diff --git a/user/super/com/google/gwt/emul/java/lang/String.java b/user/super/com/google/gwt/emul/java/lang/String.java index 693f53bdc7..9f4ed4c74f 100644 --- a/user/super/com/google/gwt/emul/java/lang/String.java +++ b/user/super/com/google/gwt/emul/java/lang/String.java @@ -791,6 +791,10 @@ public String repeat(int count) { return asNativeString().repeat(count); } + public R transform(Function f) { + return f.apply(this); + } + private int getLeadingWhitespaceLength() { int length = length(); for (int i = 0; i < length; i++) { diff --git a/user/super/com/google/gwt/emul/java/util/stream/Collectors.java b/user/super/com/google/gwt/emul/java/util/stream/Collectors.java index 519b375422..4cb57577cd 100644 --- a/user/super/com/google/gwt/emul/java/util/stream/Collectors.java +++ b/user/super/com/google/gwt/emul/java/util/stream/Collectors.java @@ -27,6 +27,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.LongSummaryStatistics; +import java.util.AbstractMap; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -34,6 +35,7 @@ import java.util.StringJoiner; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; +import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; @@ -71,6 +73,32 @@ public static Collector collectingAndThen( downstream.finisher().andThen(finisher)); } + public static Collector teeing(Collector downstream1, + Collector downstream2, + BiFunction merger) { + return teeing2(downstream1, downstream2, merger); + } + + private static Collector teeing2(Collector downstream1, + Collector downstream2, + BiFunction merger) { + return Collector.of( + () -> new AbstractMap.SimpleEntry<>(downstream1.supplier().get(), downstream2.supplier().get()), + (a,b) -> { + downstream1.accumulator().accept(a.getKey(), b); + downstream2.accumulator().accept(a.getValue(), b); + }, + (a,b)-> { + X part = downstream1.combiner().apply(a.getKey(), b.getKey()); + Y part2 = downstream2.combiner().apply(a.getValue(), b.getValue()); + return new AbstractMap.SimpleEntry<>(part, part2); + }, + (e) -> merger.apply(downstream1.finisher().apply(e.getKey()), + downstream2.finisher().apply(e.getValue())) + ); + } + + public static Collector counting() { // Using Long::sum here fails in JDT return reducing(0L, item -> 1L, (a, b) -> (Long) a.longValue() + b.longValue()); diff --git a/user/super/com/google/gwt/emul/java/util/stream/Stream.java b/user/super/com/google/gwt/emul/java/util/stream/Stream.java index 386d329391..25e0c214c8 100644 --- a/user/super/com/google/gwt/emul/java/util/stream/Stream.java +++ b/user/super/com/google/gwt/emul/java/util/stream/Stream.java @@ -246,6 +246,10 @@ public boolean tryAdvance(Consumer action) { return StreamSupport.stream(spliterator, false); } + default List toList() { + return Collections.unmodifiableList(this.collect(Collectors.toList())); + } + Stream filter(Predicate predicate); Optional findAny(); diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/lang/StringTest.java b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/lang/StringTest.java new file mode 100644 index 0000000000..b3907a361a --- /dev/null +++ b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/lang/StringTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2024 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java11.lang; + +import com.google.gwt.emultest.java.util.EmulTestBase; + +import java.util.Arrays; +import java.util.stream.Collectors; + +/** + * Tests for java.lang.String Java 12 API emulation. + */ +public class StringTest extends EmulTestBase { + + public void testTransform() { + assertEquals(3, hideFromCompiler("foo").transform(String::length)); + } + + public void testIndent() { + assertEquals(" x", hideFromCompiler("x").indent(2)); + assertEquals("x", hideFromCompiler(" x").indent(-2)); + assertEquals(" x\n y", hideFromCompiler("x\ny").indent(2)); + assertEquals(" x\r\n y", hideFromCompiler("x\r\ny").indent(2)); + assertEquals(" x\r y", hideFromCompiler("x\ry").indent(2)); + assertEquals("x\ny", hideFromCompiler(" x\n y").indent(-2)); + assertEquals("x\r\ny", hideFromCompiler(" x\r\n y").indent(-2)); + assertEquals("x\ry", hideFromCompiler(" x\r y").indent(-2)); + } + + private T hideFromCompiler(T value) { + if (Math.random() < -1) { + // Can never happen, but fools the compiler enough not to optimize this call. + fail(); + } + return value; + } +} \ No newline at end of file diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java new file mode 100644 index 0000000000..a1bcd1e95f --- /dev/null +++ b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java @@ -0,0 +1,33 @@ +/* + * Copyright 2024 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java12.util.stream; + +import com.google.gwt.emultest.java.util.EmulTestBase; + +import java.util.Arrays; +import java.util.stream.Collectors; + +/** + * Tests for java.lang.String Java 12 API emulation. + */ +public class CollectorsTest extends EmulTestBase { + + public void testTeeing() { + assertEquals(4, Stram.of(2, 4, 6).teeing(Collectors.summingToDouble(n -> n), + Collectors.counting(), (sum, count) -> sum / count)); + } + +} \ No newline at end of file diff --git a/user/test/com/google/gwt/emultest/EmulJava12Suite.java b/user/test/com/google/gwt/emultest/EmulJava12Suite.java new file mode 100644 index 0000000000..11d7e322bb --- /dev/null +++ b/user/test/com/google/gwt/emultest/EmulJava12Suite.java @@ -0,0 +1,29 @@ +/* + * Copyright 2023 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest; + +import com.google.gwt.emultest.java12.lang.StringTest; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** Test JRE emulations. */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + StringTest.class, +}) +public class EmulJava12Suite { +} diff --git a/user/test/com/google/gwt/emultest/java12/lang/StringTest.java b/user/test/com/google/gwt/emultest/java12/lang/StringTest.java new file mode 100644 index 0000000000..8f3bab29a7 --- /dev/null +++ b/user/test/com/google/gwt/emultest/java12/lang/StringTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2024 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java12.lang; + +import com.google.gwt.dev.util.arg.SourceLevel; +import com.google.gwt.emultest.java.util.EmulTestBase; +import com.google.gwt.junit.JUnitShell; + +/** + * Tests for java.lang.String Java 12 API emulation. + */ +public class StringTest extends EmulTestBase { + + @Override + public void runTest() throws Throwable { + // Only run these tests if -sourceLevel 17 (or greater) is enabled. + if (isGwtSourceLevel17()) { + super.runTest(); + } + } + + public void testTransform() { + assertFalse(isGwtSourceLevel17()); + } + + public void testIndent() { + assertFalse(isGwtSourceLevel17()); + } + + private boolean isGwtSourceLevel17() { + return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA17) >= 0; + } +} \ No newline at end of file diff --git a/user/test/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java b/user/test/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java new file mode 100644 index 0000000000..aa73ad7ba1 --- /dev/null +++ b/user/test/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2024 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java12.util.stream; + +import com.google.gwt.dev.util.arg.SourceLevel; +import com.google.gwt.emultest.java.util.EmulTestBase; +import com.google.gwt.junit.JUnitShell; + +import java.util.Arrays; +import java.util.stream.Collectors; + +/** + * Tests for java.lang.String Java 12 API emulation. + */ +public class CollectorsTest extends EmulTestBase { + + @Override + public void runTest() throws Throwable { + // Only run these tests if -sourceLevel 17 (or greater) is enabled. + if (isGwtSourceLevel17()) { + super.runTest(); + } + } + + public void testTeeing() { + assertFalse(isGwtSourceLevel17()); + } + + private boolean isGwtSourceLevel17() { + return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA17) >= 0; + } + +} \ No newline at end of file From b04e627f9b07f34a47ec4b1dd244ab5548627935 Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Wed, 12 Mar 2025 20:25:58 +0100 Subject: [PATCH 02/12] Apply suggestions from code review Co-authored-by: Colin Alworth --- .../com/google/gwt/emul/java/util/stream/Collectors.java | 2 +- .../super/com/google/gwt/emultest/java12/lang/StringTest.java | 2 +- .../gwt/emultest/java12/util/stream/CollectorsTest.java | 4 ++-- user/test/com/google/gwt/emultest/EmulJava12Suite.java | 2 +- user/test/com/google/gwt/emultest/java12/lang/StringTest.java | 2 +- .../gwt/emultest/java12/util/stream/CollectorsTest.java | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/user/super/com/google/gwt/emul/java/util/stream/Collectors.java b/user/super/com/google/gwt/emul/java/util/stream/Collectors.java index 4cb57577cd..1a198ac5fc 100644 --- a/user/super/com/google/gwt/emul/java/util/stream/Collectors.java +++ b/user/super/com/google/gwt/emul/java/util/stream/Collectors.java @@ -88,7 +88,7 @@ private static Collector teeing2(Collector { + (a,b) -> { X part = downstream1.combiner().apply(a.getKey(), b.getKey()); Y part2 = downstream2.combiner().apply(a.getValue(), b.getValue()); return new AbstractMap.SimpleEntry<>(part, part2); diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/lang/StringTest.java b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/lang/StringTest.java index b3907a361a..25911cdaf1 100644 --- a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/lang/StringTest.java +++ b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/lang/StringTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 GWT Project Authors + * Copyright 2025 GWT Project Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java index a1bcd1e95f..606758238a 100644 --- a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java +++ b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 GWT Project Authors + * Copyright 2025 GWT Project Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of @@ -26,7 +26,7 @@ public class CollectorsTest extends EmulTestBase { public void testTeeing() { - assertEquals(4, Stram.of(2, 4, 6).teeing(Collectors.summingToDouble(n -> n), + assertEquals(4, Stream.of(2, 4, 6).teeing(Collectors.summingToDouble(n -> n), Collectors.counting(), (sum, count) -> sum / count)); } diff --git a/user/test/com/google/gwt/emultest/EmulJava12Suite.java b/user/test/com/google/gwt/emultest/EmulJava12Suite.java index 11d7e322bb..1f30ee58f0 100644 --- a/user/test/com/google/gwt/emultest/EmulJava12Suite.java +++ b/user/test/com/google/gwt/emultest/EmulJava12Suite.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google Inc. + * Copyright 2025 GWT Project Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of diff --git a/user/test/com/google/gwt/emultest/java12/lang/StringTest.java b/user/test/com/google/gwt/emultest/java12/lang/StringTest.java index 8f3bab29a7..4fdc06f1e7 100644 --- a/user/test/com/google/gwt/emultest/java12/lang/StringTest.java +++ b/user/test/com/google/gwt/emultest/java12/lang/StringTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 GWT Project Authors + * Copyright 2025 GWT Project Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of diff --git a/user/test/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java b/user/test/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java index aa73ad7ba1..e95b143e02 100644 --- a/user/test/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java +++ b/user/test/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 GWT Project Authors + * Copyright 2025 GWT Project Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of From dcf9006745015fdac23b96322895715d2b75aab4 Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Thu, 13 Mar 2025 00:38:03 +0100 Subject: [PATCH 03/12] More emulation --- .../javac/testing/impl/JavaResourceBase.java | 1 + .../gwt/emul/java/lang/CharSequence.java | 32 +++++ .../com/google/gwt/emul/java/lang/String.java | 136 +++++++++++++++++- .../com/google/gwt/emul/java/util/BitSet.java | 39 +++++ .../com/google/gwt/emul/java/util/Map.java | 7 + .../emul/java/util/stream/DoubleStream.java | 19 +++ .../gwt/emul/java/util/stream/IntStream.java | 19 +++ .../gwt/emul/java/util/stream/LongStream.java | 19 +++ .../gwt/emul/java/util/stream/Stream.java | 37 +++++ .../gwt/emultest/java12/lang/StringTest.java | 50 ------- .../java17/lang/CharSequenceTest.java} | 19 ++- .../gwt/emultest/java17/lang/StringTest.java | 64 +++++++++ .../emultest/java17/util/MapEntryTest.java | 34 +++++ .../java17}/util/stream/CollectorsTest.java | 12 +- .../java17/util/stream/DoubleStreamTest.java | 37 +++++ .../java17/util/stream/IntStreamTest.java | 38 +++++ .../java17/util/stream/LongStreamTest.java | 37 +++++ .../java17/util/stream/StreamTest.java | 92 ++++++++++++ .../google/gwt/emultest/EmulJava17Suite.java | 41 ++++++ .../com/google/gwt/emultest/EmulSuite.gwt.xml | 3 +- .../com/google/gwt/emultest/EmulSuite.java | 2 + .../emultest/java/lang/CharSequenceTest.java | 45 ++++++ .../gwt/emultest/java/util/BitSetTest.java | 11 ++ .../gwt/emultest/java/util/EmulTestBase.java | 8 ++ .../gwt/emultest/java11/lang/StringTest.java | 8 -- .../java17/lang/CharSequenceTest.java | 34 +++++ .../{java12 => java17}/lang/StringTest.java | 19 ++- .../emultest/java17/util/MapEntryTest.java | 34 +++++ .../util/stream/CollectorsTest.java | 18 +-- .../java17/util/stream/DoubleStreamTest.java | 34 +++++ .../java17/util/stream/IntStreamTest.java | 34 +++++ .../java17/util/stream/LongStreamTest.java | 34 +++++ .../java17/util/stream/StreamTest.java | 53 +++++++ 33 files changed, 968 insertions(+), 102 deletions(-) delete mode 100644 user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/lang/StringTest.java rename user/{test/com/google/gwt/emultest/EmulJava12Suite.java => test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/CharSequenceTest.java} (58%) create mode 100644 user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/StringTest.java create mode 100644 user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/MapEntryTest.java rename user/test-super/com/google/gwt/{dev/jjs/super/com/google/gwt/emultest/java12 => emultest/super/com/google/gwt/emultest/java17}/util/stream/CollectorsTest.java (69%) create mode 100644 user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/DoubleStreamTest.java create mode 100644 user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/IntStreamTest.java create mode 100644 user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/LongStreamTest.java create mode 100644 user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/StreamTest.java create mode 100644 user/test/com/google/gwt/emultest/EmulJava17Suite.java create mode 100644 user/test/com/google/gwt/emultest/java/lang/CharSequenceTest.java create mode 100644 user/test/com/google/gwt/emultest/java17/lang/CharSequenceTest.java rename user/test/com/google/gwt/emultest/{java12 => java17}/lang/StringTest.java (79%) create mode 100644 user/test/com/google/gwt/emultest/java17/util/MapEntryTest.java rename user/test/com/google/gwt/emultest/{java12 => java17}/util/stream/CollectorsTest.java (73%) create mode 100644 user/test/com/google/gwt/emultest/java17/util/stream/DoubleStreamTest.java create mode 100644 user/test/com/google/gwt/emultest/java17/util/stream/IntStreamTest.java create mode 100644 user/test/com/google/gwt/emultest/java17/util/stream/LongStreamTest.java create mode 100644 user/test/com/google/gwt/emultest/java17/util/stream/StreamTest.java diff --git a/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java b/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java index fdec1b1e4d..2845067eb7 100644 --- a/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java +++ b/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java @@ -82,6 +82,7 @@ public class JavaResourceBase { "public interface CharSequence {", " char charAt(int index);", " int length();", + " default boolean isEmpty() { return length() == 0; }", " String toString();", "}"); diff --git a/user/super/com/google/gwt/emul/java/lang/CharSequence.java b/user/super/com/google/gwt/emul/java/lang/CharSequence.java index 560bd9f875..e4a01f1f4b 100644 --- a/user/super/com/google/gwt/emul/java/lang/CharSequence.java +++ b/user/super/com/google/gwt/emul/java/lang/CharSequence.java @@ -58,6 +58,38 @@ public boolean hasNext() { }, Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED, false); } + default IntStream codePoints() { + return StreamSupport.intStream(() -> { + PrimitiveIterator.OfInt it = new PrimitiveIterator.OfInt() { + int cursor; + + @Override + public int nextInt() { + checkElement(hasNext()); + int codePoint = CharSequence.this.toString().codePointAt(cursor++); + if (codePoint >= 1 << 16) { + cursor++; + } + return codePoint; + } + + @Override + public boolean hasNext() { + return cursor < length(); + } + }; + return Spliterators.spliterator(it, length(), Spliterator.ORDERED); + }, Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED, false); + } + + default boolean isEmpty() { + return length() == 0; + } + + static int compare(CharSequence cs1, CharSequence cs2) { + return cs1.toString().compareTo(cs2.toString()); + } + // CHECKSTYLE_OFF: Utility methods. @JsMethod static boolean $isInstance(HasCharSequenceTypeMarker instance) { diff --git a/user/super/com/google/gwt/emul/java/lang/String.java b/user/super/com/google/gwt/emul/java/lang/String.java index 9f4ed4c74f..73d868af72 100644 --- a/user/super/com/google/gwt/emul/java/lang/String.java +++ b/user/super/com/google/gwt/emul/java/lang/String.java @@ -27,11 +27,14 @@ import java.nio.charset.Charset; import java.nio.charset.UnsupportedCharsetException; import java.util.Comparator; +import java.util.List; import java.util.Locale; import java.util.Spliterator; import java.util.Spliterators; import java.util.StringJoiner; import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; import javaemul.internal.ArrayHelper; @@ -488,6 +491,7 @@ public String intern() { return checkNotNull(this); } + @Override public boolean isEmpty() { return length() == 0; } @@ -815,6 +819,126 @@ private int getTrailingWhitespaceLength() { return length; } + public String indent(int spaces) { + if (spaces == 0) { + return this; + } + Stream indentedLines; + if (spaces > 0) { + String spaceString = " ".repeat(spaces); + indentedLines = lines().map(line -> spaceString + line); + } else { + indentedLines = lines().map( + line -> line.substring(Math.min(-spaces, line.getLeadingWhitespaceLength()))); + } + return indentedLines.collect(Collectors.joining("\n", "", "\n")); + } + + public String stripIndent() { + if (isEmpty()) { + return ""; + } + List lines = lines().collect(Collectors.toList()); + int minIndent; + char lastChar = charAt(length() - 1); + String suffix = ""; + if (lastChar != '\r' && lastChar != '\n') { + minIndent = Integer.MAX_VALUE; + for (int i = 0; i < lines.size() - 1; i++) { + String line = lines.get(i); + int leadingWhitespace = line.getLeadingWhitespaceLength(); + // only update minIndent if not blank + if (leadingWhitespace < line.length()) { + minIndent = Math.min(minIndent, leadingWhitespace); + } + } + // the last line affects minIndent even if blank + minIndent = Math.min(minIndent, lines.get(lines.size() - 1).getLeadingWhitespaceLength()); + suffix = "\n"; + } else { + minIndent = 0; + } + final int outdent = minIndent; + return lines.stream().map(line -> { + if (line.isBlank()) { + return ""; + } + return line.substring(outdent).stripTrailing(); + }) + .collect(Collectors.joining("\n", "", suffix)); + } + + public String translateEscapes() { + StringBuilder result = new StringBuilder(); + int translated = 0; + while (translated < length()) { + int nextBackslash = indexOf("\\", translated); + if (nextBackslash == -1) { + result.append(substring(translated)); + return result.toString(); + } + if (nextBackslash == length() - 1) { + throw new IllegalArgumentException(); + } + result.append(substring(translated, nextBackslash)); + char currentChar = charAt(nextBackslash + 1); + translated = nextBackslash + 2; + switch (currentChar) { + case 'b': + result.append('\b'); + break; + case 's': + result.append(' '); + break; + case 't': + result.append('\t'); + break; + case 'n': + result.append('\n'); + break; + case 'f': + result.append('\f'); + break; + case 'r': + result.append('\r'); + break; + case '\n': + case '\r': + // discard + break; + case '"': + result.append('"'); + break; + case '\'': + result.append('\''); + break; + case '\\': + result.append('\\'); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + int unicode = currentChar - '0'; + char nextChar = charAt(translated); + while (nextChar >= '0' && nextChar < '8' && unicode < 32) { + unicode = (unicode << 3) + (nextChar - '0'); + translated++; + nextChar = translated < length() ? charAt(translated) : 0; + } + result.append((char) unicode); + break; + default: + throw new IllegalArgumentException(); + } + } + return result.toString(); + } + private class LinesSpliterator extends Spliterators.AbstractSpliterator { private int nextIndex = 0; private int rPosition = -1; @@ -830,10 +954,10 @@ public boolean tryAdvance(Consumer action) { return false; } if (rPosition < nextIndex) { - rPosition = cappedIndexOf('\r'); + rPosition = cappedIndexOf('\r', nextIndex); } if (nPosition < nextIndex) { - nPosition = cappedIndexOf('\n'); + nPosition = cappedIndexOf('\n', nextIndex); } int lineEnd = Math.min(nPosition, rPosition); action.accept(substring(nextIndex, lineEnd)); @@ -843,11 +967,11 @@ public boolean tryAdvance(Consumer action) { } return nextIndex < length(); } + } - private int cappedIndexOf(char c) { - int index = indexOf(c, nextIndex); - return index == -1 ? length() : index; - } + private int cappedIndexOf(char c, int nextIndex) { + int index = indexOf(c, nextIndex); + return index == -1 ? length() : index; } @JsType(isNative = true, name = "String", namespace = "") diff --git a/user/super/com/google/gwt/emul/java/util/BitSet.java b/user/super/com/google/gwt/emul/java/util/BitSet.java index ea8a087c5b..975161aeca 100644 --- a/user/super/com/google/gwt/emul/java/util/BitSet.java +++ b/user/super/com/google/gwt/emul/java/util/BitSet.java @@ -21,6 +21,10 @@ import javaemul.internal.ArrayHelper; import javaemul.internal.LongUtils; +import java.util.function.IntConsumer; +import java.util.stream.IntStream; +import java.util.stream.StreamSupport; + /** * This implementation uses a dense array holding bit groups of size 31 to keep track of when bits * are set to true or false. Using 31 bits keeps our implementation within the range of V8's @@ -37,6 +41,36 @@ public class BitSet { private final int[] array; + private class BitSetSpliterator implements Spliterator.OfInt { + int nextBitIndex = 0; + + @Override + public boolean tryAdvance(IntConsumer action) { + int nextBit = nextSetBit(nextBitIndex); + if (nextBit >= 0) { + nextBitIndex = nextBit + 1; + action.accept(nextBit); + return true; + } + return false; + } + + @Override + public Spliterator.OfInt trySplit() { + return null; + } + + @Override + public long estimateSize() { + return size(); + } + + @Override + public int characteristics() { + return Spliterator.SIZED | Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED; + } + } + public BitSet() { array = new int[0]; } @@ -604,6 +638,11 @@ public int nextSetBit(int fromIndex) { return bitIndex(index) + Integer.numberOfTrailingZeros(word); } + public IntStream stream() { + Spliterator.OfInt spliterator = new BitSetSpliterator(); + return StreamSupport.intStream(spliterator, false); + } + public int previousClearBit(int fromIndex) { if (fromIndex == -1) { return -1; diff --git a/user/super/com/google/gwt/emul/java/util/Map.java b/user/super/com/google/gwt/emul/java/util/Map.java index 06d057017b..470b0c56ed 100644 --- a/user/super/com/google/gwt/emul/java/util/Map.java +++ b/user/super/com/google/gwt/emul/java/util/Map.java @@ -276,6 +276,13 @@ static Comparator> comparingByValue(Comparator return (Comparator> & Serializable) (a, b) -> cmp.compare(a.getValue(), b.getValue()); } + + static Map.Entry copyOf(Map.Entry e) { + if (e instanceof AbstractMap.SimpleImmutableEntry) { + return (Entry) e; + } + return entry(e.getKey(), e.getValue()); + } } void clear(); diff --git a/user/super/com/google/gwt/emul/java/util/stream/DoubleStream.java b/user/super/com/google/gwt/emul/java/util/stream/DoubleStream.java index c0d81589a4..197eac552c 100644 --- a/user/super/com/google/gwt/emul/java/util/stream/DoubleStream.java +++ b/user/super/com/google/gwt/emul/java/util/stream/DoubleStream.java @@ -17,8 +17,10 @@ import static javaemul.internal.InternalPreconditions.checkState; +import java.util.ArrayList; import java.util.Arrays; import java.util.DoubleSummaryStatistics; +import java.util.List; import java.util.OptionalDouble; import java.util.PrimitiveIterator; import java.util.Spliterator; @@ -58,6 +60,15 @@ default DoubleStream.Builder add(double t) { DoubleStream build(); } + /** + * See + * the official Java API doc for details. + */ + interface DoubleMapMultiConsumer { + void accept(double value, DoubleConsumer consumer); + } + static Builder builder() { return new Builder() { private double[] items = new double[0]; @@ -317,5 +328,13 @@ public boolean tryAdvance(DoubleConsumer action) { return StreamSupport.doubleStream(spliterator, false); } + default DoubleStream mapMulti(DoubleStream.DoubleMapMultiConsumer mapper) { + return flatMap(element -> { + List buffer = new ArrayList<>(); + mapper.accept(element, (DoubleConsumer) buffer::add); + return buffer.stream().mapToDouble(n -> n); + }); + } + double[] toArray(); } diff --git a/user/super/com/google/gwt/emul/java/util/stream/IntStream.java b/user/super/com/google/gwt/emul/java/util/stream/IntStream.java index bac1b49844..bd9caf674b 100644 --- a/user/super/com/google/gwt/emul/java/util/stream/IntStream.java +++ b/user/super/com/google/gwt/emul/java/util/stream/IntStream.java @@ -17,9 +17,11 @@ import static javaemul.internal.InternalPreconditions.checkState; +import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.IntSummaryStatistics; +import java.util.List; import java.util.OptionalDouble; import java.util.OptionalInt; import java.util.PrimitiveIterator; @@ -61,6 +63,15 @@ default IntStream.Builder add(int t) { IntStream build(); } + /** + * See + * the official Java API doc for details. + */ + interface IntMapMultiConsumer { + void accept(int value, IntConsumer consumer); + } + static Builder builder() { return new Builder() { private int[] items = new int[0]; @@ -366,5 +377,13 @@ public boolean tryAdvance(IntConsumer action) { return StreamSupport.intStream(spliterator, false); } + default IntStream mapMulti(IntMapMultiConsumer mapper) { + return flatMap(element -> { + List buffer = new ArrayList<>(); + mapper.accept(element, (IntConsumer) buffer::add); + return buffer.stream().mapToInt(n -> n); + }); + } + int[] toArray(); } diff --git a/user/super/com/google/gwt/emul/java/util/stream/LongStream.java b/user/super/com/google/gwt/emul/java/util/stream/LongStream.java index 821c2f7f40..4943d0d1cb 100644 --- a/user/super/com/google/gwt/emul/java/util/stream/LongStream.java +++ b/user/super/com/google/gwt/emul/java/util/stream/LongStream.java @@ -17,8 +17,10 @@ import static javaemul.internal.InternalPreconditions.checkState; +import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; +import java.util.List; import java.util.LongSummaryStatistics; import java.util.OptionalDouble; import java.util.OptionalLong; @@ -61,6 +63,15 @@ default LongStream.Builder add(long t) { LongStream build(); } + /** + * See + * the official Java API doc for details. + */ + interface LongMapMultiConsumer { + void accept(long value, LongConsumer consumer); + } + static Builder builder() { return new Builder() { private long[] items = new long[0]; @@ -364,5 +375,13 @@ public boolean tryAdvance(LongConsumer action) { return StreamSupport.longStream(spliterator, false); } + default LongStream mapMulti(LongStream.LongMapMultiConsumer mapper) { + return flatMap(element -> { + List buffer = new ArrayList<>(); + mapper.accept(element, (LongConsumer) buffer::add); + return buffer.stream().mapToLong(n -> n); + }); + } + long[] toArray(); } diff --git a/user/super/com/google/gwt/emul/java/util/stream/Stream.java b/user/super/com/google/gwt/emul/java/util/stream/Stream.java index 25e0c214c8..a0a468f110 100644 --- a/user/super/com/google/gwt/emul/java/util/stream/Stream.java +++ b/user/super/com/google/gwt/emul/java/util/stream/Stream.java @@ -17,9 +17,11 @@ import static javaemul.internal.InternalPreconditions.checkState; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; +import java.util.List; import java.util.Optional; import java.util.Spliterator; import java.util.Spliterators; @@ -28,8 +30,11 @@ import java.util.function.BiFunction; import java.util.function.BinaryOperator; import java.util.function.Consumer; +import java.util.function.DoubleConsumer; import java.util.function.Function; +import java.util.function.IntConsumer; import java.util.function.IntFunction; +import java.util.function.LongConsumer; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.function.ToDoubleFunction; @@ -327,6 +332,38 @@ public boolean tryAdvance(Consumer action) { return StreamSupport.stream(spliterator, false); } + default Stream mapMulti(BiConsumer> mapper) { + return flatMap(element -> { + List buffer = new ArrayList<>(); + mapper.accept(element, (Consumer) buffer::add); + return buffer.stream(); + }); + } + + default DoubleStream mapMultiToDouble(BiConsumer mapper) { + return flatMapToDouble(element -> { + List buffer = new ArrayList<>(); + mapper.accept(element, (DoubleConsumer) buffer::add); + return buffer.stream().mapToDouble(n -> n); + }); + } + + default IntStream mapMultiToInt(BiConsumer mapper) { + return flatMapToInt(element -> { + List buffer = new ArrayList<>(); + mapper.accept(element, (IntConsumer) buffer::add); + return buffer.stream().mapToInt(n -> n); + }); + } + + default LongStream mapMultiToLong(BiConsumer mapper) { + return flatMapToLong(element -> { + List buffer = new ArrayList<>(); + mapper.accept(element, (LongConsumer) buffer::add); + return buffer.stream().mapToLong(n -> n); + }); + } + Object[] toArray(); A[] toArray(IntFunction generator); diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/lang/StringTest.java b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/lang/StringTest.java deleted file mode 100644 index 25911cdaf1..0000000000 --- a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/lang/StringTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2025 GWT Project Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.gwt.emultest.java11.lang; - -import com.google.gwt.emultest.java.util.EmulTestBase; - -import java.util.Arrays; -import java.util.stream.Collectors; - -/** - * Tests for java.lang.String Java 12 API emulation. - */ -public class StringTest extends EmulTestBase { - - public void testTransform() { - assertEquals(3, hideFromCompiler("foo").transform(String::length)); - } - - public void testIndent() { - assertEquals(" x", hideFromCompiler("x").indent(2)); - assertEquals("x", hideFromCompiler(" x").indent(-2)); - assertEquals(" x\n y", hideFromCompiler("x\ny").indent(2)); - assertEquals(" x\r\n y", hideFromCompiler("x\r\ny").indent(2)); - assertEquals(" x\r y", hideFromCompiler("x\ry").indent(2)); - assertEquals("x\ny", hideFromCompiler(" x\n y").indent(-2)); - assertEquals("x\r\ny", hideFromCompiler(" x\r\n y").indent(-2)); - assertEquals("x\ry", hideFromCompiler(" x\r y").indent(-2)); - } - - private T hideFromCompiler(T value) { - if (Math.random() < -1) { - // Can never happen, but fools the compiler enough not to optimize this call. - fail(); - } - return value; - } -} \ No newline at end of file diff --git a/user/test/com/google/gwt/emultest/EmulJava12Suite.java b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/CharSequenceTest.java similarity index 58% rename from user/test/com/google/gwt/emultest/EmulJava12Suite.java rename to user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/CharSequenceTest.java index 1f30ee58f0..226655d2b5 100644 --- a/user/test/com/google/gwt/emultest/EmulJava12Suite.java +++ b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/CharSequenceTest.java @@ -13,17 +13,16 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.google.gwt.emultest; +package com.google.gwt.emultest.java17.lang; -import com.google.gwt.emultest.java12.lang.StringTest; +import com.google.gwt.emultest.java.util.EmulTestBase; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; +public class CharSequenceTest extends EmulTestBase { -/** Test JRE emulations. */ -@RunWith(Suite.class) -@Suite.SuiteClasses({ - StringTest.class, -}) -public class EmulJava12Suite { + public void testIsEmpty() { + assertTrue(hideFromCompiler(new StringBuilder()).isEmpty()); + assertFalse(hideFromCompiler(new StringBuilder("foo")).isEmpty()); + assertTrue(hideFromCompiler("").isEmpty()); + assertFalse(hideFromCompiler("foo").isEmpty()); + } } diff --git a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/StringTest.java b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/StringTest.java new file mode 100644 index 0000000000..4ec007b741 --- /dev/null +++ b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/StringTest.java @@ -0,0 +1,64 @@ +/* + * Copyright 2025 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java17.lang; + +import com.google.gwt.emultest.java.util.EmulTestBase; + +/** + * Tests for java.lang.String Java 12 API emulation. + */ +public class StringTest extends EmulTestBase { + + public void testTransform() { + int stringLength = hideFromCompiler("foo").transform(String::length); + assertEquals(3, stringLength); + } + + public void testIndent() { + assertEquals(" x\n", hideFromCompiler("x").indent(2)); + assertEquals("x\n", hideFromCompiler(" x").indent(-2)); + assertEquals(" x\n y\n", hideFromCompiler("x\ny").indent(2)); + assertEquals(" x\n y\n", hideFromCompiler("x\r\ny").indent(2)); + assertEquals(" x\n y\n", hideFromCompiler("x\ry").indent(2)); + assertEquals("x\ny\n", hideFromCompiler(" x\n y").indent(-2)); + assertEquals("x\ny\n", hideFromCompiler(" x\r\n y").indent(-2)); + assertEquals("x\ny\n", hideFromCompiler(" x\r y").indent(-2)); + } + + public void testStripIndent() { + assertEquals("", hideFromCompiler("").stripIndent()); + assertEquals("x", hideFromCompiler("x").stripIndent()); + assertEquals("x", hideFromCompiler(" x").stripIndent()); + assertEquals("x\n", hideFromCompiler("x\r\n").stripIndent()); + assertEquals("x\ny", hideFromCompiler(" x\n y").stripIndent()); + assertEquals("x\ny", hideFromCompiler(" x\r\n y").stripIndent()); + assertEquals(" x\ny", hideFromCompiler(" x\n y").stripIndent()); + assertEquals("x\n y", hideFromCompiler(" x\n y").stripIndent()); + assertEquals("x\n\ny", hideFromCompiler(" x\n \n y").stripIndent()); + assertEquals(" x\ny", hideFromCompiler("\t x\r\n y").stripIndent()); + } + + public void testTranslateEscapes() { + assertEquals("\b \r\n\t\f", + hideFromCompiler("\\b\\s\\r\\n\\t\\f").translateEscapes()); + assertEquals("\u0001\u0011\u00d1", + hideFromCompiler("\\1\\21\\321").translateEscapes()); + assertEquals("\u00ff\u001f8\u00200", + hideFromCompiler("\\377\\378\\400").translateEscapes()); + assertEquals("ab", + hideFromCompiler("a\\\nb").translateEscapes()); + } +} \ No newline at end of file diff --git a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/MapEntryTest.java b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/MapEntryTest.java new file mode 100644 index 0000000000..11aa1ff959 --- /dev/null +++ b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/MapEntryTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2025 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java17.util; + +import com.google.gwt.emultest.java.util.EmulTestBase; + +import java.util.AbstractMap; +import java.util.Map; + +public class MapEntryTest extends EmulTestBase { + + public void testCopyOf() { + AbstractMap.SimpleEntry mutableEntry = new AbstractMap.SimpleEntry<>("a", 4); + Map.Entry copy = Map.Entry.copyOf(mutableEntry); + assertEquals(mutableEntry.getKey(), copy.getKey()); + assertEquals(mutableEntry.getValue(), copy.getValue()); + assertNotSame(mutableEntry, copy); + Map.Entry otherCopy = Map.Entry.copyOf(copy); + assertSame(copy, otherCopy); + } +} diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/CollectorsTest.java similarity index 69% rename from user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java rename to user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/CollectorsTest.java index 606758238a..ae6bdf1b89 100644 --- a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java +++ b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/CollectorsTest.java @@ -13,12 +13,13 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.google.gwt.emultest.java12.util.stream; +package com.google.gwt.emultest.java17.util.stream; import com.google.gwt.emultest.java.util.EmulTestBase; -import java.util.Arrays; +import java.util.stream.Collector; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * Tests for java.lang.String Java 12 API emulation. @@ -26,8 +27,11 @@ public class CollectorsTest extends EmulTestBase { public void testTeeing() { - assertEquals(4, Stream.of(2, 4, 6).teeing(Collectors.summingToDouble(n -> n), - Collectors.counting(), (sum, count) -> sum / count)); + Collector teeing = Collectors.teeing( + Collectors.reducing(Double::sum), + Collectors.counting(), + (sum, count) -> sum.orElse(0.0) / count); + assertEquals(4.0, Stream.of(2.0, 4.0, 6.0).collect(teeing), 0.01); } } \ No newline at end of file diff --git a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/DoubleStreamTest.java b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/DoubleStreamTest.java new file mode 100644 index 0000000000..cef7a9434f --- /dev/null +++ b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/DoubleStreamTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2025 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java17.util.stream; + +import com.google.gwt.emultest.java.util.EmulTestBase; + +import java.util.stream.DoubleStream; + +public class DoubleStreamTest extends EmulTestBase { + + public void testMapMulti() { + DoubleStream.DoubleMapMultiConsumer doubling = (num, callback) -> { + callback.accept(num); + callback.accept(num + num); + }; + assertEquals(new double[0], + hideFromCompiler(DoubleStream.of()).mapMulti(doubling).toArray()); + assertEquals(new double[]{1.0, 2.0, 3.0, 6.0}, + hideFromCompiler(DoubleStream.of(1.0, 3.0)).mapMulti(doubling).toArray()); + assertEquals(new double[0], + hideFromCompiler(DoubleStream.of(1.0, 2.0)).mapMulti((a, b) -> { + }).toArray()); + } +} diff --git a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/IntStreamTest.java b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/IntStreamTest.java new file mode 100644 index 0000000000..c98f949a99 --- /dev/null +++ b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/IntStreamTest.java @@ -0,0 +1,38 @@ +/* + * Copyright 2025 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java17.util.stream; + +import com.google.gwt.emultest.java.util.EmulTestBase; + +import java.util.stream.IntStream; +import java.util.stream.Stream; + +public class IntStreamTest extends EmulTestBase { + + public void testMapMulti() { + IntStream.IntMapMultiConsumer doubling = (num, callback) -> { + callback.accept(num); + callback.accept(num + num); + }; + assertEquals(new int[0], + hideFromCompiler(IntStream.of()).mapMulti(doubling).toArray()); + assertEquals(new int[]{1, 2, 3, 6}, + hideFromCompiler(IntStream.of(1, 3)).mapMulti(doubling).toArray()); + assertEquals(new int[0], + hideFromCompiler(IntStream.of(1, 3)).mapMulti((a, b) -> { + }).toArray()); + } +} diff --git a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/LongStreamTest.java b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/LongStreamTest.java new file mode 100644 index 0000000000..dc5cd85831 --- /dev/null +++ b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/LongStreamTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2025 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java17.util.stream; + +import com.google.gwt.emultest.java.util.EmulTestBase; + +import java.util.stream.LongStream; + +public class LongStreamTest extends EmulTestBase { + + public void testMapMulti() { + LongStream.LongMapMultiConsumer doubling = (num, callback) -> { + callback.accept(num); + callback.accept(num + num); + }; + assertEquals(new long[0], + hideFromCompiler(LongStream.of()).mapMulti(doubling).toArray()); + assertEquals(new long[]{1L, 2L, 3L, 6L}, + hideFromCompiler(LongStream.of(1L, 3L)).mapMulti(doubling).toArray()); + assertEquals(new long[0], + hideFromCompiler(LongStream.of(1L, 2L)).mapMulti((a, b) -> { + }).toArray()); + } +} diff --git a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/StreamTest.java b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/StreamTest.java new file mode 100644 index 0000000000..678e40dbbf --- /dev/null +++ b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/StreamTest.java @@ -0,0 +1,92 @@ +/* + * Copyright 2025 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java17.util.stream; + +import com.google.gwt.emultest.java.util.EmulTestBase; + +import java.util.Arrays; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.DoubleConsumer; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; +import java.util.stream.Stream; + +public class StreamTest extends EmulTestBase { + + public void testToList() { + assertEquals(Arrays.asList(), + hideFromCompiler(Stream.of()).toList()); + assertEquals(Arrays.asList("a", "b"), + hideFromCompiler(Stream.of("a", "b")).toList()); + } + + public void testMapMulti() { + BiConsumer> doubling = (str, callback) -> { + callback.accept(str); + callback.accept(str + str); + }; + assertEquals(Arrays.asList(), + this.>hideFromCompiler(Stream.of()).mapMulti(doubling).toList()); + assertEquals(Arrays.asList("a", "aa", "b", "bb"), + hideFromCompiler(Stream.of("a", "b")).mapMulti(doubling).toList()); + assertEquals(Arrays.asList(), + hideFromCompiler(Stream.of("a", "b")).mapMulti((a, b) -> { + }).toList()); + } + + public void testMapMultiToInt() { + BiConsumer doubling = (str, callback) -> { + callback.accept(str.length()); + callback.accept(str.length() * 2); + }; + assertEquals(new int[]{1, 2, 3, 6}, + hideFromCompiler(Stream.of("a", "bbb")).mapMultiToInt(doubling).toArray()); + assertEquals(new int[0], + hideFromCompiler(Stream.of()).mapMultiToInt(doubling).toArray()); + assertEquals(new int[0], + hideFromCompiler(Stream.of("a", "b")).mapMultiToInt((a, b) -> { + }).toArray()); + } + + public void testMapMultiToLong() { + BiConsumer doubling = (str, callback) -> { + callback.accept(str.length()); + callback.accept(str.length() * 2L); + }; + assertEquals(new long[]{1L, 2L, 3L, 6L}, + hideFromCompiler(Stream.of("a", "bbb")).mapMultiToLong(doubling).toArray()); + assertEquals(new long[0], + hideFromCompiler(Stream.of()).mapMultiToLong(doubling).toArray()); + assertEquals(new long[0], + hideFromCompiler(Stream.of("a", "b")).mapMultiToLong((a, b) -> { + }).toArray()); + } + + public void testMapMultiToDouble() { + BiConsumer doubling = (str, callback) -> { + callback.accept(str.length()); + callback.accept(str.length() * 2); + }; + assertEquals(new double[]{1.0, 2.0, 3.0, 6.0}, + hideFromCompiler(Stream.of("a", "bbb")).mapMultiToDouble(doubling).toArray()); + assertEquals(new double[0], + hideFromCompiler(Stream.of()).mapMultiToDouble(doubling).toArray()); + assertEquals(new double[0], + hideFromCompiler(Stream.of("a", "b")).mapMultiToDouble((a, b) -> { + }).toArray()); + } +} diff --git a/user/test/com/google/gwt/emultest/EmulJava17Suite.java b/user/test/com/google/gwt/emultest/EmulJava17Suite.java new file mode 100644 index 0000000000..f92754451e --- /dev/null +++ b/user/test/com/google/gwt/emultest/EmulJava17Suite.java @@ -0,0 +1,41 @@ +/* + * Copyright 2025 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest; + +import com.google.gwt.emultest.java17.lang.CharSequenceTest; +import com.google.gwt.emultest.java17.lang.StringTest; +import com.google.gwt.emultest.java17.util.stream.CollectorsTest; +import com.google.gwt.emultest.java17.util.stream.DoubleStreamTest; +import com.google.gwt.emultest.java17.util.stream.IntStreamTest; +import com.google.gwt.emultest.java17.util.stream.LongStreamTest; +import com.google.gwt.emultest.java17.util.stream.StreamTest; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** Test JRE emulations. */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + CharSequenceTest.class, + StringTest.class, + CollectorsTest.class, + StreamTest.class, + DoubleStreamTest.class, + IntStreamTest.class, + LongStreamTest.class +}) +public class EmulJava17Suite { +} diff --git a/user/test/com/google/gwt/emultest/EmulSuite.gwt.xml b/user/test/com/google/gwt/emultest/EmulSuite.gwt.xml index 85c3a4cf6b..b545eb5314 100644 --- a/user/test/com/google/gwt/emultest/EmulSuite.gwt.xml +++ b/user/test/com/google/gwt/emultest/EmulSuite.gwt.xml @@ -20,7 +20,8 @@ - + + diff --git a/user/test/com/google/gwt/emultest/EmulSuite.java b/user/test/com/google/gwt/emultest/EmulSuite.java index 6cbe3ef105..5ac7cde95d 100644 --- a/user/test/com/google/gwt/emultest/EmulSuite.java +++ b/user/test/com/google/gwt/emultest/EmulSuite.java @@ -28,6 +28,7 @@ import com.google.gwt.emultest.java.io.WriterTest; import com.google.gwt.emultest.java.lang.BooleanTest; import com.google.gwt.emultest.java.lang.ByteTest; +import com.google.gwt.emultest.java.lang.CharSequenceTest; import com.google.gwt.emultest.java.lang.CharacterTest; import com.google.gwt.emultest.java.lang.CompilerConstantStringTest; import com.google.gwt.emultest.java.lang.DoubleEqualsSemanticsTest; @@ -88,6 +89,7 @@ // -- java.lang BooleanTest.class, ByteTest.class, + CharSequenceTest.class, CharacterTest.class, CompilerConstantStringTest.class, DoubleTest.class, diff --git a/user/test/com/google/gwt/emultest/java/lang/CharSequenceTest.java b/user/test/com/google/gwt/emultest/java/lang/CharSequenceTest.java new file mode 100644 index 0000000000..45e34ee86d --- /dev/null +++ b/user/test/com/google/gwt/emultest/java/lang/CharSequenceTest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2025 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java.lang; + +import com.google.gwt.emultest.java.util.EmulTestBase; + +import java.util.List; +import java.util.stream.Collectors; + +public class CharSequenceTest extends EmulTestBase { + + public void testCompare() { + assertEquals(-1, CharSequence.compare(hideFromCompiler("a"), "b")); + assertEquals(1, CharSequence.compare(hideFromCompiler("b"), "a")); + assertEquals(0, CharSequence.compare(hideFromCompiler("a"), "a")); + assertEquals(-1, CharSequence.compare(hideFromCompiler("a"), + new StringBuilder("b"))); + } + + public void testCodePoints() { + assertEquals(List.of(), collectCodePoints("")); + assertEquals(List.of("a", "b", "c"), collectCodePoints("abc")); + assertEquals(List.of("\uD83D\uDE0D"), collectCodePoints("\uD83D\uDE0D")); + assertEquals(List.of("x", "\uD83D\uDE0D", "y"), collectCodePoints("x\uD83D\uDE0Dy")); + } + + private List collectCodePoints(String str) { + return str.codePoints().mapToObj(cp -> new String(Character.toChars(cp))) + .collect(Collectors.toList()); + } + +} diff --git a/user/test/com/google/gwt/emultest/java/util/BitSetTest.java b/user/test/com/google/gwt/emultest/java/util/BitSetTest.java index 071288e548..7a299e4138 100644 --- a/user/test/com/google/gwt/emultest/java/util/BitSetTest.java +++ b/user/test/com/google/gwt/emultest/java/util/BitSetTest.java @@ -1421,4 +1421,15 @@ public void testValueOfLongs() { "565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 584, 640, 641, 642, 643, 644, 645, " + "646, 711}", set.toString()); } + + public void testStream() { + BitSet bitSet = new BitSet(); + assertEquals(new int[]{}, bitSet.stream().toArray()); + bitSet.set(2); + assertEquals(new int[]{2}, bitSet.stream().toArray()); + bitSet.set(5); + assertEquals(new int[]{2, 5}, bitSet.stream().toArray()); + bitSet.set(100); + assertEquals(new int[]{2, 5, 100}, bitSet.stream().toArray()); + } } diff --git a/user/test/com/google/gwt/emultest/java/util/EmulTestBase.java b/user/test/com/google/gwt/emultest/java/util/EmulTestBase.java index 93fd94b9e7..ead15f52e3 100644 --- a/user/test/com/google/gwt/emultest/java/util/EmulTestBase.java +++ b/user/test/com/google/gwt/emultest/java/util/EmulTestBase.java @@ -79,4 +79,12 @@ public static void assertIAE(String methodName, Runnable runnable) { public String getModuleName() { return "com.google.gwt.emultest.EmulSuite"; } + + protected T hideFromCompiler(T value) { + if (Math.random() < -1) { + // Can never happen, but fools the compiler enough not to optimize this call. + fail(); + } + return value; + } } diff --git a/user/test/com/google/gwt/emultest/java11/lang/StringTest.java b/user/test/com/google/gwt/emultest/java11/lang/StringTest.java index 92650aca51..fd22210702 100644 --- a/user/test/com/google/gwt/emultest/java11/lang/StringTest.java +++ b/user/test/com/google/gwt/emultest/java11/lang/StringTest.java @@ -99,12 +99,4 @@ public void testLines() { assertEquals(Arrays.asList("", "", "c"), "\n\r\nc".lines().collect(Collectors.toList())); } - - private T hideFromCompiler(T value) { - if (Math.random() < -1) { - // Can never happen, but fools the compiler enough not to optimize this call. - fail(); - } - return value; - } } diff --git a/user/test/com/google/gwt/emultest/java17/lang/CharSequenceTest.java b/user/test/com/google/gwt/emultest/java17/lang/CharSequenceTest.java new file mode 100644 index 0000000000..e5e14ecc8b --- /dev/null +++ b/user/test/com/google/gwt/emultest/java17/lang/CharSequenceTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2025 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java17.lang; + +import com.google.gwt.dev.util.arg.SourceLevel; +import com.google.gwt.emultest.java.util.EmulTestBase; +import com.google.gwt.junit.DoNotRunWith; +import com.google.gwt.junit.JUnitShell; +import com.google.gwt.junit.Platform; + +@DoNotRunWith(Platform.Devel) +public class CharSequenceTest extends EmulTestBase { + + public void testIsEmpty() { + assertFalse(isGwtSourceLevel17()); + } + + private boolean isGwtSourceLevel17() { + return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA17) >= 0; + } +} diff --git a/user/test/com/google/gwt/emultest/java12/lang/StringTest.java b/user/test/com/google/gwt/emultest/java17/lang/StringTest.java similarity index 79% rename from user/test/com/google/gwt/emultest/java12/lang/StringTest.java rename to user/test/com/google/gwt/emultest/java17/lang/StringTest.java index 4fdc06f1e7..b8be318ee5 100644 --- a/user/test/com/google/gwt/emultest/java12/lang/StringTest.java +++ b/user/test/com/google/gwt/emultest/java17/lang/StringTest.java @@ -13,25 +13,20 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.google.gwt.emultest.java12.lang; +package com.google.gwt.emultest.java17.lang; import com.google.gwt.dev.util.arg.SourceLevel; import com.google.gwt.emultest.java.util.EmulTestBase; +import com.google.gwt.junit.DoNotRunWith; import com.google.gwt.junit.JUnitShell; +import com.google.gwt.junit.Platform; /** - * Tests for java.lang.String Java 12 API emulation. + * Tests for java.lang.String Java 12 - 17 API emulation. */ +@DoNotRunWith(Platform.Devel) public class StringTest extends EmulTestBase { - @Override - public void runTest() throws Throwable { - // Only run these tests if -sourceLevel 17 (or greater) is enabled. - if (isGwtSourceLevel17()) { - super.runTest(); - } - } - public void testTransform() { assertFalse(isGwtSourceLevel17()); } @@ -40,6 +35,10 @@ public void testIndent() { assertFalse(isGwtSourceLevel17()); } + public void testTranslateEscapes() { + assertFalse(isGwtSourceLevel17()); + } + private boolean isGwtSourceLevel17() { return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA17) >= 0; } diff --git a/user/test/com/google/gwt/emultest/java17/util/MapEntryTest.java b/user/test/com/google/gwt/emultest/java17/util/MapEntryTest.java new file mode 100644 index 0000000000..c09e437e8c --- /dev/null +++ b/user/test/com/google/gwt/emultest/java17/util/MapEntryTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2025 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java17.util; + +import com.google.gwt.dev.util.arg.SourceLevel; +import com.google.gwt.emultest.java.util.EmulTestBase; +import com.google.gwt.junit.DoNotRunWith; +import com.google.gwt.junit.JUnitShell; +import com.google.gwt.junit.Platform; + +@DoNotRunWith(Platform.Devel) +public class MapEntryTest extends EmulTestBase { + + public void testCopyOf() { + assertFalse(isGwtSourceLevel17()); + } + + private boolean isGwtSourceLevel17() { + return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA17) >= 0; + } +} diff --git a/user/test/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java b/user/test/com/google/gwt/emultest/java17/util/stream/CollectorsTest.java similarity index 73% rename from user/test/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java rename to user/test/com/google/gwt/emultest/java17/util/stream/CollectorsTest.java index e95b143e02..c2820cfc06 100644 --- a/user/test/com/google/gwt/emultest/java12/util/stream/CollectorsTest.java +++ b/user/test/com/google/gwt/emultest/java17/util/stream/CollectorsTest.java @@ -13,28 +13,20 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.google.gwt.emultest.java12.util.stream; +package com.google.gwt.emultest.java17.util.stream; import com.google.gwt.dev.util.arg.SourceLevel; import com.google.gwt.emultest.java.util.EmulTestBase; +import com.google.gwt.junit.DoNotRunWith; import com.google.gwt.junit.JUnitShell; - -import java.util.Arrays; -import java.util.stream.Collectors; +import com.google.gwt.junit.Platform; /** - * Tests for java.lang.String Java 12 API emulation. + * Tests for java.util.stream.Collectors Java 12 - 17 API emulation. */ +@DoNotRunWith(Platform.Devel) public class CollectorsTest extends EmulTestBase { - @Override - public void runTest() throws Throwable { - // Only run these tests if -sourceLevel 17 (or greater) is enabled. - if (isGwtSourceLevel17()) { - super.runTest(); - } - } - public void testTeeing() { assertFalse(isGwtSourceLevel17()); } diff --git a/user/test/com/google/gwt/emultest/java17/util/stream/DoubleStreamTest.java b/user/test/com/google/gwt/emultest/java17/util/stream/DoubleStreamTest.java new file mode 100644 index 0000000000..fa772d53fd --- /dev/null +++ b/user/test/com/google/gwt/emultest/java17/util/stream/DoubleStreamTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2025 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java17.util.stream; + +import com.google.gwt.dev.util.arg.SourceLevel; +import com.google.gwt.emultest.java.util.EmulTestBase; +import com.google.gwt.junit.DoNotRunWith; +import com.google.gwt.junit.JUnitShell; +import com.google.gwt.junit.Platform; + +@DoNotRunWith(Platform.Devel) +public class DoubleStreamTest extends EmulTestBase { + + public void testMapMulti() { + assertFalse(isGwtSourceLevel17()); + } + + private boolean isGwtSourceLevel17() { + return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA17) >= 0; + } +} diff --git a/user/test/com/google/gwt/emultest/java17/util/stream/IntStreamTest.java b/user/test/com/google/gwt/emultest/java17/util/stream/IntStreamTest.java new file mode 100644 index 0000000000..4432504bfa --- /dev/null +++ b/user/test/com/google/gwt/emultest/java17/util/stream/IntStreamTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2025 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java17.util.stream; + +import com.google.gwt.dev.util.arg.SourceLevel; +import com.google.gwt.emultest.java.util.EmulTestBase; +import com.google.gwt.junit.DoNotRunWith; +import com.google.gwt.junit.JUnitShell; +import com.google.gwt.junit.Platform; + +@DoNotRunWith(Platform.Devel) +public class IntStreamTest extends EmulTestBase { + + public void testMapMulti() { + assertFalse(isGwtSourceLevel17()); + } + + private boolean isGwtSourceLevel17() { + return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA17) >= 0; + } +} diff --git a/user/test/com/google/gwt/emultest/java17/util/stream/LongStreamTest.java b/user/test/com/google/gwt/emultest/java17/util/stream/LongStreamTest.java new file mode 100644 index 0000000000..b986afc012 --- /dev/null +++ b/user/test/com/google/gwt/emultest/java17/util/stream/LongStreamTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2025 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java17.util.stream; + +import com.google.gwt.dev.util.arg.SourceLevel; +import com.google.gwt.emultest.java.util.EmulTestBase; +import com.google.gwt.junit.DoNotRunWith; +import com.google.gwt.junit.JUnitShell; +import com.google.gwt.junit.Platform; + +@DoNotRunWith(Platform.Devel) +public class LongStreamTest extends EmulTestBase { + + public void testMapMulti() { + assertFalse(isGwtSourceLevel17()); + } + + private boolean isGwtSourceLevel17() { + return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA17) >= 0; + } +} diff --git a/user/test/com/google/gwt/emultest/java17/util/stream/StreamTest.java b/user/test/com/google/gwt/emultest/java17/util/stream/StreamTest.java new file mode 100644 index 0000000000..92fc217135 --- /dev/null +++ b/user/test/com/google/gwt/emultest/java17/util/stream/StreamTest.java @@ -0,0 +1,53 @@ +/* + * Copyright 2025 GWT Project Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java17.util.stream; + +import com.google.gwt.dev.util.arg.SourceLevel; +import com.google.gwt.emultest.java.util.EmulTestBase; +import com.google.gwt.junit.DoNotRunWith; +import com.google.gwt.junit.JUnitShell; +import com.google.gwt.junit.Platform; + +/** + * Tests for java.util.stream.Stream Java 12 - 17 API emulation. + */ +@DoNotRunWith(Platform.Devel) +public class StreamTest extends EmulTestBase { + + public void testToList() { + assertFalse(isGwtSourceLevel17()); + } + + public void testMapMulti() { + assertFalse(isGwtSourceLevel17()); + } + + public void testMapMultiToInt() { + assertFalse(isGwtSourceLevel17()); + } + + public void testMapMultiToLong() { + assertFalse(isGwtSourceLevel17()); + } + + public void testMapMultiToDouble() { + assertFalse(isGwtSourceLevel17()); + } + + private boolean isGwtSourceLevel17() { + return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA17) >= 0; + } +} From 1ef880da403c92dc2bc649bbe3936a257087890a Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Tue, 22 Jul 2025 20:21:37 +0200 Subject: [PATCH 04/12] Review feedback --- gwt.iml | 97 +++++++++++++++++++ .../com/google/gwt/emul/java/lang/String.java | 2 +- .../gwt/emul/java/util/stream/Collectors.java | 10 +- .../emul/java/util/stream/DoubleStream.java | 8 +- .../gwt/emul/java/util/stream/IntStream.java | 8 +- .../gwt/emul/java/util/stream/LongStream.java | 8 +- .../java17/util/stream/DoubleStreamTest.java | 7 +- .../java17/util/stream/IntStreamTest.java | 7 +- .../java17/util/stream/LongStreamTest.java | 7 +- .../java17/util/stream/StreamTest.java | 27 +++--- .../google/gwt/emultest/EmulJava17Suite.java | 4 +- .../gwt/emultest/java17/lang/StringTest.java | 4 + 12 files changed, 139 insertions(+), 50 deletions(-) create mode 100644 gwt.iml diff --git a/gwt.iml b/gwt.iml new file mode 100644 index 0000000000..9dc0c4011d --- /dev/null +++ b/gwt.iml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/user/super/com/google/gwt/emul/java/lang/String.java b/user/super/com/google/gwt/emul/java/lang/String.java index 73d868af72..48fca41615 100644 --- a/user/super/com/google/gwt/emul/java/lang/String.java +++ b/user/super/com/google/gwt/emul/java/lang/String.java @@ -854,8 +854,8 @@ public String stripIndent() { } // the last line affects minIndent even if blank minIndent = Math.min(minIndent, lines.get(lines.size() - 1).getLeadingWhitespaceLength()); - suffix = "\n"; } else { + suffix = "\n"; minIndent = 0; } final int outdent = minIndent; diff --git a/user/super/com/google/gwt/emul/java/util/stream/Collectors.java b/user/super/com/google/gwt/emul/java/util/stream/Collectors.java index 1a198ac5fc..dfbf1cf379 100644 --- a/user/super/com/google/gwt/emul/java/util/stream/Collectors.java +++ b/user/super/com/google/gwt/emul/java/util/stream/Collectors.java @@ -74,16 +74,15 @@ public static Collector collectingAndThen( } public static Collector teeing(Collector downstream1, - Collector downstream2, - BiFunction merger) { + Collector downstream2, BiFunction merger) { return teeing2(downstream1, downstream2, merger); } private static Collector teeing2(Collector downstream1, - Collector downstream2, - BiFunction merger) { + Collector downstream2, BiFunction merger) { return Collector.of( - () -> new AbstractMap.SimpleEntry<>(downstream1.supplier().get(), downstream2.supplier().get()), + () -> new AbstractMap.SimpleEntry<>(downstream1.supplier().get(), + downstream2.supplier().get()), (a,b) -> { downstream1.accumulator().accept(a.getKey(), b); downstream2.accumulator().accept(a.getValue(), b); @@ -98,7 +97,6 @@ private static Collector teeing2(Collector Collector counting() { // Using Long::sum here fails in JDT return reducing(0L, item -> 1L, (a, b) -> (Long) a.longValue() + b.longValue()); diff --git a/user/super/com/google/gwt/emul/java/util/stream/DoubleStream.java b/user/super/com/google/gwt/emul/java/util/stream/DoubleStream.java index 197eac552c..a26d15e04b 100644 --- a/user/super/com/google/gwt/emul/java/util/stream/DoubleStream.java +++ b/user/super/com/google/gwt/emul/java/util/stream/DoubleStream.java @@ -17,10 +17,8 @@ import static javaemul.internal.InternalPreconditions.checkState; -import java.util.ArrayList; import java.util.Arrays; import java.util.DoubleSummaryStatistics; -import java.util.List; import java.util.OptionalDouble; import java.util.PrimitiveIterator; import java.util.Spliterator; @@ -330,9 +328,9 @@ public boolean tryAdvance(DoubleConsumer action) { default DoubleStream mapMulti(DoubleStream.DoubleMapMultiConsumer mapper) { return flatMap(element -> { - List buffer = new ArrayList<>(); - mapper.accept(element, (DoubleConsumer) buffer::add); - return buffer.stream().mapToDouble(n -> n); + Builder builder = builder(); + mapper.accept(element, (DoubleConsumer) builder::add); + return builder.build(); }); } diff --git a/user/super/com/google/gwt/emul/java/util/stream/IntStream.java b/user/super/com/google/gwt/emul/java/util/stream/IntStream.java index bd9caf674b..81d687fa6b 100644 --- a/user/super/com/google/gwt/emul/java/util/stream/IntStream.java +++ b/user/super/com/google/gwt/emul/java/util/stream/IntStream.java @@ -17,11 +17,9 @@ import static javaemul.internal.InternalPreconditions.checkState; -import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.IntSummaryStatistics; -import java.util.List; import java.util.OptionalDouble; import java.util.OptionalInt; import java.util.PrimitiveIterator; @@ -379,9 +377,9 @@ public boolean tryAdvance(IntConsumer action) { default IntStream mapMulti(IntMapMultiConsumer mapper) { return flatMap(element -> { - List buffer = new ArrayList<>(); - mapper.accept(element, (IntConsumer) buffer::add); - return buffer.stream().mapToInt(n -> n); + Builder builder = builder(); + mapper.accept(element, (IntConsumer) builder::add); + return builder.build(); }); } diff --git a/user/super/com/google/gwt/emul/java/util/stream/LongStream.java b/user/super/com/google/gwt/emul/java/util/stream/LongStream.java index 4943d0d1cb..dfe97dd74b 100644 --- a/user/super/com/google/gwt/emul/java/util/stream/LongStream.java +++ b/user/super/com/google/gwt/emul/java/util/stream/LongStream.java @@ -17,10 +17,8 @@ import static javaemul.internal.InternalPreconditions.checkState; -import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; -import java.util.List; import java.util.LongSummaryStatistics; import java.util.OptionalDouble; import java.util.OptionalLong; @@ -377,9 +375,9 @@ public boolean tryAdvance(LongConsumer action) { default LongStream mapMulti(LongStream.LongMapMultiConsumer mapper) { return flatMap(element -> { - List buffer = new ArrayList<>(); - mapper.accept(element, (LongConsumer) buffer::add); - return buffer.stream().mapToLong(n -> n); + Builder builder = builder(); + mapper.accept(element, (LongConsumer) builder::add); + return builder.build(); }); } diff --git a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/DoubleStreamTest.java b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/DoubleStreamTest.java index cef7a9434f..99aa744edc 100644 --- a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/DoubleStreamTest.java +++ b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/DoubleStreamTest.java @@ -27,11 +27,10 @@ public void testMapMulti() { callback.accept(num + num); }; assertEquals(new double[0], - hideFromCompiler(DoubleStream.of()).mapMulti(doubling).toArray()); + DoubleStream.of().mapMulti(doubling).toArray()); assertEquals(new double[]{1.0, 2.0, 3.0, 6.0}, - hideFromCompiler(DoubleStream.of(1.0, 3.0)).mapMulti(doubling).toArray()); + DoubleStream.of(1.0, 3.0).mapMulti(doubling).toArray()); assertEquals(new double[0], - hideFromCompiler(DoubleStream.of(1.0, 2.0)).mapMulti((a, b) -> { - }).toArray()); + DoubleStream.of(1.0, 2.0).mapMulti((a, b) -> {}).toArray()); } } diff --git a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/IntStreamTest.java b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/IntStreamTest.java index c98f949a99..ac82090a84 100644 --- a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/IntStreamTest.java +++ b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/IntStreamTest.java @@ -28,11 +28,10 @@ public void testMapMulti() { callback.accept(num + num); }; assertEquals(new int[0], - hideFromCompiler(IntStream.of()).mapMulti(doubling).toArray()); + IntStream.of().mapMulti(doubling).toArray()); assertEquals(new int[]{1, 2, 3, 6}, - hideFromCompiler(IntStream.of(1, 3)).mapMulti(doubling).toArray()); + IntStream.of(1, 3).mapMulti(doubling).toArray()); assertEquals(new int[0], - hideFromCompiler(IntStream.of(1, 3)).mapMulti((a, b) -> { - }).toArray()); + IntStream.of(1, 3).mapMulti((a, b) -> {}).toArray()); } } diff --git a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/LongStreamTest.java b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/LongStreamTest.java index dc5cd85831..a3496f8c92 100644 --- a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/LongStreamTest.java +++ b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/LongStreamTest.java @@ -27,11 +27,10 @@ public void testMapMulti() { callback.accept(num + num); }; assertEquals(new long[0], - hideFromCompiler(LongStream.of()).mapMulti(doubling).toArray()); + LongStream.of().mapMulti(doubling).toArray()); assertEquals(new long[]{1L, 2L, 3L, 6L}, - hideFromCompiler(LongStream.of(1L, 3L)).mapMulti(doubling).toArray()); + LongStream.of(1L, 3L).mapMulti(doubling).toArray()); assertEquals(new long[0], - hideFromCompiler(LongStream.of(1L, 2L)).mapMulti((a, b) -> { - }).toArray()); + LongStream.of(1L, 2L).mapMulti((a, b) -> {}).toArray()); } } diff --git a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/StreamTest.java b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/StreamTest.java index 678e40dbbf..72a46e6c73 100644 --- a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/StreamTest.java +++ b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/util/stream/StreamTest.java @@ -40,12 +40,11 @@ public void testMapMulti() { callback.accept(str + str); }; assertEquals(Arrays.asList(), - this.>hideFromCompiler(Stream.of()).mapMulti(doubling).toList()); + Stream.of().mapMulti(doubling).toList()); assertEquals(Arrays.asList("a", "aa", "b", "bb"), - hideFromCompiler(Stream.of("a", "b")).mapMulti(doubling).toList()); + Stream.of("a", "b").mapMulti(doubling).toList()); assertEquals(Arrays.asList(), - hideFromCompiler(Stream.of("a", "b")).mapMulti((a, b) -> { - }).toList()); + Stream.of("a", "b").mapMulti((a, b) -> {}).toList()); } public void testMapMultiToInt() { @@ -54,12 +53,11 @@ public void testMapMultiToInt() { callback.accept(str.length() * 2); }; assertEquals(new int[]{1, 2, 3, 6}, - hideFromCompiler(Stream.of("a", "bbb")).mapMultiToInt(doubling).toArray()); + Stream.of("a", "bbb").mapMultiToInt(doubling).toArray()); assertEquals(new int[0], - hideFromCompiler(Stream.of()).mapMultiToInt(doubling).toArray()); + Stream.of().mapMultiToInt(doubling).toArray()); assertEquals(new int[0], - hideFromCompiler(Stream.of("a", "b")).mapMultiToInt((a, b) -> { - }).toArray()); + Stream.of("a", "b").mapMultiToInt((a, b) -> {}).toArray()); } public void testMapMultiToLong() { @@ -68,11 +66,11 @@ public void testMapMultiToLong() { callback.accept(str.length() * 2L); }; assertEquals(new long[]{1L, 2L, 3L, 6L}, - hideFromCompiler(Stream.of("a", "bbb")).mapMultiToLong(doubling).toArray()); + Stream.of("a", "bbb").mapMultiToLong(doubling).toArray()); assertEquals(new long[0], - hideFromCompiler(Stream.of()).mapMultiToLong(doubling).toArray()); + Stream.of().mapMultiToLong(doubling).toArray()); assertEquals(new long[0], - hideFromCompiler(Stream.of("a", "b")).mapMultiToLong((a, b) -> { + Stream.of("a", "b").mapMultiToLong((a, b) -> { }).toArray()); } @@ -82,11 +80,10 @@ public void testMapMultiToDouble() { callback.accept(str.length() * 2); }; assertEquals(new double[]{1.0, 2.0, 3.0, 6.0}, - hideFromCompiler(Stream.of("a", "bbb")).mapMultiToDouble(doubling).toArray()); + Stream.of("a", "bbb").mapMultiToDouble(doubling).toArray()); assertEquals(new double[0], - hideFromCompiler(Stream.of()).mapMultiToDouble(doubling).toArray()); + Stream.of().mapMultiToDouble(doubling).toArray()); assertEquals(new double[0], - hideFromCompiler(Stream.of("a", "b")).mapMultiToDouble((a, b) -> { - }).toArray()); + Stream.of("a", "b").mapMultiToDouble((a, b) -> {}).toArray()); } } diff --git a/user/test/com/google/gwt/emultest/EmulJava17Suite.java b/user/test/com/google/gwt/emultest/EmulJava17Suite.java index f92754451e..b71f8d0f5f 100644 --- a/user/test/com/google/gwt/emultest/EmulJava17Suite.java +++ b/user/test/com/google/gwt/emultest/EmulJava17Suite.java @@ -17,6 +17,7 @@ import com.google.gwt.emultest.java17.lang.CharSequenceTest; import com.google.gwt.emultest.java17.lang.StringTest; +import com.google.gwt.emultest.java17.util.MapEntryTest; import com.google.gwt.emultest.java17.util.stream.CollectorsTest; import com.google.gwt.emultest.java17.util.stream.DoubleStreamTest; import com.google.gwt.emultest.java17.util.stream.IntStreamTest; @@ -35,7 +36,8 @@ StreamTest.class, DoubleStreamTest.class, IntStreamTest.class, - LongStreamTest.class + LongStreamTest.class, + MapEntryTest.class }) public class EmulJava17Suite { } diff --git a/user/test/com/google/gwt/emultest/java17/lang/StringTest.java b/user/test/com/google/gwt/emultest/java17/lang/StringTest.java index b8be318ee5..39d61a4f69 100644 --- a/user/test/com/google/gwt/emultest/java17/lang/StringTest.java +++ b/user/test/com/google/gwt/emultest/java17/lang/StringTest.java @@ -35,6 +35,10 @@ public void testIndent() { assertFalse(isGwtSourceLevel17()); } + public void testStripIndent() { + assertFalse(isGwtSourceLevel17()); + } + public void testTranslateEscapes() { assertFalse(isGwtSourceLevel17()); } From 4549a2cad7f42626d692ddcc3266909ab3a0fb77 Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Tue, 29 Jul 2025 21:16:50 +0200 Subject: [PATCH 05/12] Remove iml file --- gwt.iml | 97 --------------------------------------------------------- 1 file changed, 97 deletions(-) delete mode 100644 gwt.iml diff --git a/gwt.iml b/gwt.iml deleted file mode 100644 index 9dc0c4011d..0000000000 --- a/gwt.iml +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From a5611f0780e81c9b07e456bfccdee638c282c861 Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Tue, 29 Jul 2025 22:36:29 +0200 Subject: [PATCH 06/12] Review feedback --- user/super/com/google/gwt/emul/java/lang/String.java | 12 ++++++------ user/super/com/google/gwt/emul/java/util/BitSet.java | 8 ++++---- .../google/gwt/emul/java/util/stream/Collectors.java | 4 ++-- .../google/gwt/emultest/java17/lang/StringTest.java | 4 ++++ 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/user/super/com/google/gwt/emul/java/lang/String.java b/user/super/com/google/gwt/emul/java/lang/String.java index 48fca41615..d4d959b179 100644 --- a/user/super/com/google/gwt/emul/java/lang/String.java +++ b/user/super/com/google/gwt/emul/java/lang/String.java @@ -491,11 +491,6 @@ public String intern() { return checkNotNull(this); } - @Override - public boolean isEmpty() { - return length() == 0; - } - public int lastIndexOf(int codePoint) { return lastIndexOf(fromCodePoint(codePoint)); } @@ -903,9 +898,14 @@ public String translateEscapes() { result.append('\r'); break; case '\n': - case '\r': // discard break; + case '\r': + // discard \r and possibly \n that comes right after + if (translated < length() && charAt(translated) == '\n') { + translated++; + } + break; case '"': result.append('"'); break; diff --git a/user/super/com/google/gwt/emul/java/util/BitSet.java b/user/super/com/google/gwt/emul/java/util/BitSet.java index 975161aeca..1fa15d5567 100644 --- a/user/super/com/google/gwt/emul/java/util/BitSet.java +++ b/user/super/com/google/gwt/emul/java/util/BitSet.java @@ -18,12 +18,11 @@ import static javaemul.internal.InternalPreconditions.checkArraySize; -import javaemul.internal.ArrayHelper; -import javaemul.internal.LongUtils; - import java.util.function.IntConsumer; import java.util.stream.IntStream; import java.util.stream.StreamSupport; +import javaemul.internal.ArrayHelper; +import javaemul.internal.LongUtils; /** * This implementation uses a dense array holding bit groups of size 31 to keep track of when bits @@ -67,7 +66,8 @@ public long estimateSize() { @Override public int characteristics() { - return Spliterator.SIZED | Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED; + return Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED + | Spliterator.DISTINCT | Spliterator.SORTED; } } diff --git a/user/super/com/google/gwt/emul/java/util/stream/Collectors.java b/user/super/com/google/gwt/emul/java/util/stream/Collectors.java index dfbf1cf379..3966af525d 100644 --- a/user/super/com/google/gwt/emul/java/util/stream/Collectors.java +++ b/user/super/com/google/gwt/emul/java/util/stream/Collectors.java @@ -16,6 +16,7 @@ package java.util.stream; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -27,15 +28,14 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.LongSummaryStatistics; -import java.util.AbstractMap; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.StringJoiner; import java.util.function.BiConsumer; -import java.util.function.BinaryOperator; import java.util.function.BiFunction; +import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; diff --git a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/StringTest.java b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/StringTest.java index 4ec007b741..db637d46eb 100644 --- a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/StringTest.java +++ b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/StringTest.java @@ -60,5 +60,9 @@ public void testTranslateEscapes() { hideFromCompiler("\\377\\378\\400").translateEscapes()); assertEquals("ab", hideFromCompiler("a\\\nb").translateEscapes()); + assertEquals("", + hideFromCompiler("\\\r\n").translateEscapes()); + assertEquals("", + hideFromCompiler("\\\r\\\n").translateEscapes()); } } \ No newline at end of file From ceb2069357296fad38c2873245adf51555bc8770 Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Tue, 29 Jul 2025 23:32:15 +0200 Subject: [PATCH 07/12] Mention override as missing --- tools/api-checker/config/gwt212_213userapi.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/api-checker/config/gwt212_213userapi.conf b/tools/api-checker/config/gwt212_213userapi.conf index 1c09dc5145..951395dcc5 100644 --- a/tools/api-checker/config/gwt212_213userapi.conf +++ b/tools/api-checker/config/gwt212_213userapi.conf @@ -156,6 +156,7 @@ java.lang.Deprecated MISSING java.lang.FunctionalInterface MISSING java.lang.Override MISSING java.lang.SafeVarargs MISSING +java.lang.String::isEmpty() MISSING java.lang.SuppressWarnings MISSING java.lang.annotation.AnnotationTypeMismatchException MISSING java.lang.annotation.Documented MISSING From f71b697bb317a86f626a573e799be5fce0cd93cc Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Wed, 30 Jul 2025 19:53:36 +0200 Subject: [PATCH 08/12] Undo unused refactoring --- user/super/com/google/gwt/emul/java/lang/String.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/user/super/com/google/gwt/emul/java/lang/String.java b/user/super/com/google/gwt/emul/java/lang/String.java index d4d959b179..6809b91650 100644 --- a/user/super/com/google/gwt/emul/java/lang/String.java +++ b/user/super/com/google/gwt/emul/java/lang/String.java @@ -954,10 +954,10 @@ public boolean tryAdvance(Consumer action) { return false; } if (rPosition < nextIndex) { - rPosition = cappedIndexOf('\r', nextIndex); + rPosition = cappedIndexOf('\r'); } if (nPosition < nextIndex) { - nPosition = cappedIndexOf('\n', nextIndex); + nPosition = cappedIndexOf('\n'); } int lineEnd = Math.min(nPosition, rPosition); action.accept(substring(nextIndex, lineEnd)); @@ -967,11 +967,11 @@ public boolean tryAdvance(Consumer action) { } return nextIndex < length(); } - } - private int cappedIndexOf(char c, int nextIndex) { - int index = indexOf(c, nextIndex); - return index == -1 ? length() : index; + private int cappedIndexOf(char c) { + int index = indexOf(c, nextIndex); + return index == -1 ? length() : index; + } } @JsType(isNative = true, name = "String", namespace = "") From 8dc18567cbe9aba66c91d877ddd3e8e466611151 Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Wed, 3 Sep 2025 20:11:56 +0200 Subject: [PATCH 09/12] Explain moved method Co-authored-by: Colin Alworth --- tools/api-checker/config/gwt212_213userapi.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/api-checker/config/gwt212_213userapi.conf b/tools/api-checker/config/gwt212_213userapi.conf index 951395dcc5..b43799d894 100644 --- a/tools/api-checker/config/gwt212_213userapi.conf +++ b/tools/api-checker/config/gwt212_213userapi.conf @@ -156,6 +156,7 @@ java.lang.Deprecated MISSING java.lang.FunctionalInterface MISSING java.lang.Override MISSING java.lang.SafeVarargs MISSING +# Moved to CharSequence as a default method java.lang.String::isEmpty() MISSING java.lang.SuppressWarnings MISSING java.lang.annotation.AnnotationTypeMismatchException MISSING From 0023483fce570d2b98682a57f6e4be1580170f13 Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Thu, 4 Sep 2025 01:31:57 +0200 Subject: [PATCH 10/12] Remove useless override in test code --- .../com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java b/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java index 2845067eb7..e33559b54d 100644 --- a/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java +++ b/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java @@ -347,7 +347,6 @@ public class JavaResourceBase { " private native boolean equals(String obj) /*-{ return false; }-*/;", " public boolean equalsIgnoreCase(String str) { return false; }", " public native boolean isEmpty() /*-{ return true; }-*/;", - " public int length() { return 0; }", " public static String valueOf(int i) { return \"\" + i; }", " public static String valueOf(char c) { return \"\" + c; }", " public int hashCode() { return 0; }", From aafd3e9e6e66c6bf70142ff8ad5b82da9a2a81c0 Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Tue, 16 Sep 2025 01:28:10 +0200 Subject: [PATCH 11/12] Fix indent for empty string, add tests --- .../com/google/gwt/emul/java/lang/String.java | 6 +++--- .../gwt/emultest/java17/lang/StringTest.java | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/user/super/com/google/gwt/emul/java/lang/String.java b/user/super/com/google/gwt/emul/java/lang/String.java index 6809b91650..5d7f6c25c9 100644 --- a/user/super/com/google/gwt/emul/java/lang/String.java +++ b/user/super/com/google/gwt/emul/java/lang/String.java @@ -815,11 +815,11 @@ private int getTrailingWhitespaceLength() { } public String indent(int spaces) { - if (spaces == 0) { - return this; + if (isEmpty()) { + return ""; } Stream indentedLines; - if (spaces > 0) { + if (spaces >= 0) { String spaceString = " ".repeat(spaces); indentedLines = lines().map(line -> spaceString + line); } else { diff --git a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/StringTest.java b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/StringTest.java index db637d46eb..9132629447 100644 --- a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/StringTest.java +++ b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/StringTest.java @@ -28,8 +28,23 @@ public void testTransform() { } public void testIndent() { + assertEquals("", hideFromCompiler("").indent(0)); + assertEquals("", hideFromCompiler("").indent(2)); + assertEquals("", hideFromCompiler("").indent(-2)); + assertEquals(" \n", hideFromCompiler(" ").indent(0)); + assertEquals(" \n", hideFromCompiler(" ").indent(2)); + assertEquals("\n", hideFromCompiler(" ").indent(-2)); + assertEquals("x\n", hideFromCompiler("x").indent(0)); assertEquals(" x\n", hideFromCompiler("x").indent(2)); + assertEquals("x\n", hideFromCompiler("x").indent(-2)); + assertEquals(" x \n", hideFromCompiler(" x ").indent(0)); + assertEquals(" x \n", hideFromCompiler(" x ").indent(2)); + assertEquals("x \n", hideFromCompiler(" x ").indent(-2)); assertEquals("x\n", hideFromCompiler(" x").indent(-2)); + assertEquals(" x \n", hideFromCompiler(" \t x ").indent(-2)); + assertEquals("x\ny\n", hideFromCompiler("x\ny").indent(0)); + assertEquals("x\ny\n", hideFromCompiler("x\r\ny").indent(0)); + assertEquals("x\ny\n", hideFromCompiler("x\ry").indent(0)); assertEquals(" x\n y\n", hideFromCompiler("x\ny").indent(2)); assertEquals(" x\n y\n", hideFromCompiler("x\r\ny").indent(2)); assertEquals(" x\n y\n", hideFromCompiler("x\ry").indent(2)); From 8241c51109b7c5fc55fe817d73e3d15f515576a0 Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Tue, 16 Sep 2025 20:05:24 +0200 Subject: [PATCH 12/12] Add tests for stripIndent --- .../google/gwt/dev/javac/testing/impl/JavaResourceBase.java | 2 +- .../super/com/google/gwt/emultest/java17/lang/StringTest.java | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java b/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java index e33559b54d..e4fe4fea2c 100644 --- a/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java +++ b/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java @@ -346,7 +346,7 @@ public class JavaResourceBase { " }", " private native boolean equals(String obj) /*-{ return false; }-*/;", " public boolean equalsIgnoreCase(String str) { return false; }", - " public native boolean isEmpty() /*-{ return true; }-*/;", + " public int length() { return 0; }", " public static String valueOf(int i) { return \"\" + i; }", " public static String valueOf(char c) { return \"\" + c; }", " public int hashCode() { return 0; }", diff --git a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/StringTest.java b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/StringTest.java index 9132629447..872f9e183d 100644 --- a/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/StringTest.java +++ b/user/test-super/com/google/gwt/emultest/super/com/google/gwt/emultest/java17/lang/StringTest.java @@ -58,12 +58,16 @@ public void testStripIndent() { assertEquals("x", hideFromCompiler("x").stripIndent()); assertEquals("x", hideFromCompiler(" x").stripIndent()); assertEquals("x\n", hideFromCompiler("x\r\n").stripIndent()); + assertEquals("x\n", hideFromCompiler(" x\n ").stripIndent()); + assertEquals(" x\n", hideFromCompiler(" x\n ").stripIndent()); + assertEquals(" x\n", hideFromCompiler(" x\n").stripIndent()); assertEquals("x\ny", hideFromCompiler(" x\n y").stripIndent()); assertEquals("x\ny", hideFromCompiler(" x\r\n y").stripIndent()); assertEquals(" x\ny", hideFromCompiler(" x\n y").stripIndent()); assertEquals("x\n y", hideFromCompiler(" x\n y").stripIndent()); assertEquals("x\n\ny", hideFromCompiler(" x\n \n y").stripIndent()); assertEquals(" x\ny", hideFromCompiler("\t x\r\n y").stripIndent()); + assertEquals("x\n\ny", hideFromCompiler(" x\n\n y").stripIndent()); } public void testTranslateEscapes() {