From c5d74f1734bd58a7e3e797a6cc8ca89e2cd7134c Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Sat, 23 Dec 2023 13:27:22 -0600 Subject: [PATCH 01/27] Add Java 10 Collectors APIs (#9860) Fixes #9547 --- .../gwt/emul/java/util/stream/Collectors.java | 35 ++++ .../google/gwt/emultest/EmulJava10Suite.java | 2 + .../java10/util/stream/CollectorsTest.java | 162 ++++++++++++++++++ 3 files changed, 199 insertions(+) create mode 100644 user/test/com/google/gwt/emultest/java10/util/stream/CollectorsTest.java 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 60d908edb9..0509fb2fe8 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 @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.DoubleSummaryStatistics; import java.util.HashMap; @@ -27,6 +28,7 @@ import java.util.List; import java.util.LongSummaryStatistics; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.StringJoiner; @@ -339,6 +341,11 @@ public static Collector> toList() { return toCollection(ArrayList::new); } + public static Collector> toUnmodifiableList() { + Collector> mapping = mapping(Objects::requireNonNull, toList()); + return collectingAndThen(mapping, Collections::unmodifiableList); + } + public static Collector> toMap( final Function keyMapper, final Function valueMapper) { @@ -357,6 +364,29 @@ public static Collector> toList() { return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new); } + public static Collector> toUnmodifiableMap( + Function keyMapper, + Function valueMapper) { + return collectingAndThen( + toMap(disallowNulls(keyMapper), disallowNulls(valueMapper)), + Collections::unmodifiableMap + ); + } + + public static Collector> toUnmodifiableMap( + Function keyMapper, + Function valueMapper, + BinaryOperator mergeFunction) { + return collectingAndThen( + toMap(disallowNulls(keyMapper), disallowNulls(valueMapper), mergeFunction), + Collections::unmodifiableMap + ); + } + + private static Function disallowNulls(Function func) { + return func.andThen(Objects::requireNonNull); + } + public static > Collector toMap( final Function keyMapper, final Function valueMapper, @@ -389,6 +419,11 @@ public static Collector> toSet() { ); } + public static Collector> toUnmodifiableSet() { + Collector> mapping = mapping(Objects::requireNonNull, toSet()); + return collectingAndThen(mapping, Collections::unmodifiableSet); + } + private static D streamAndCollect(Collector downstream, List list) { A a = downstream.supplier().get(); for (T t : list) { diff --git a/user/test/com/google/gwt/emultest/EmulJava10Suite.java b/user/test/com/google/gwt/emultest/EmulJava10Suite.java index e691477626..2cd6369bb8 100644 --- a/user/test/com/google/gwt/emultest/EmulJava10Suite.java +++ b/user/test/com/google/gwt/emultest/EmulJava10Suite.java @@ -19,6 +19,7 @@ import com.google.gwt.emultest.java10.util.OptionalIntTest; import com.google.gwt.emultest.java10.util.OptionalLongTest; import com.google.gwt.emultest.java10.util.OptionalTest; +import com.google.gwt.emultest.java10.util.stream.CollectorsTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @@ -26,6 +27,7 @@ /** Test JRE emulations. */ @RunWith(Suite.class) @SuiteClasses({ + CollectorsTest.class, OptionalDoubleTest.class, OptionalIntTest.class, OptionalLongTest.class, diff --git a/user/test/com/google/gwt/emultest/java10/util/stream/CollectorsTest.java b/user/test/com/google/gwt/emultest/java10/util/stream/CollectorsTest.java new file mode 100644 index 0000000000..ecf6654f19 --- /dev/null +++ b/user/test/com/google/gwt/emultest/java10/util/stream/CollectorsTest.java @@ -0,0 +1,162 @@ +/* + * 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.java10.util.stream; + +import static com.google.gwt.emultest.java8.util.stream.CollectorsTest.applyItems; +import static java.util.stream.Collectors.toUnmodifiableList; +import static java.util.stream.Collectors.toUnmodifiableMap; +import static java.util.stream.Collectors.toUnmodifiableSet; + +import com.google.gwt.emultest.java.util.EmulTestBase; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Stream; + +/** + * Tests for java.util.stream.Collectors Java 10 API emulation. + */ +public class CollectorsTest extends EmulTestBase { + private static boolean unmodifiableCollection(Collection c, T existingSample, T newSample) { + try { + c.remove(existingSample); + return false; + } catch (UnsupportedOperationException ignore) { + // expected + } + try { + c.add(newSample); + return false; + } catch (UnsupportedOperationException ignore) { + // expected + } + Iterator itr = c.iterator(); + itr.next(); + try { + itr.remove(); + return false; + } catch (UnsupportedOperationException e) { + // expected + } + return true; + } + + public void testToUnmodifiableList() { + applyItems(List.of("a", "b"), toUnmodifiableList(), "a", "b", (expected, actual) -> { + if (!expected.equals(actual)) { + return false; + } + + if (!unmodifiableCollection(actual, "a", "z")) { + return false; + } + + return true; + }); + + // verify nulls fail + try { + Stream.of("a").map(ignore -> null).collect(toUnmodifiableList()); + fail("Expected NPE"); + } catch (NullPointerException ignore) { + // expected + } + } + + public void testToUnmodifiableMap() { + // verify simple cases copy all values and results are unmodifiable + applyItems(Map.of("a", 0, "b", 1), toUnmodifiableMap(Function.identity(), + k -> k.charAt(0) - 'a'), "a", "b", (expected, actual) -> { + if (!expected.equals(actual)) { + return false; + } + + if (!unmodifiableMap(actual, "a", 0, "z", 100)) { + return false; + } + + return true; + }); + + // verify merge works with only one key (but this is just passing through to the toMap func + // anyway...) + applyItems(Map.of("a", 2), toUnmodifiableMap(Function.identity(), ignore -> 1, Integer::sum), + "a", "a"); + + // verify nulls blow up for both keys and values + try { + Stream.of("a").collect(toUnmodifiableMap(obj -> null, Function.identity())); + fail("Expected NPE"); + } catch (NullPointerException ignore) { + // expected + } + try { + Stream.of("a").collect(toUnmodifiableMap(Function.identity(), obj -> null)); + fail("Expected NPE"); + } catch (Exception ignore) { + // expected + } + } + + private boolean unmodifiableMap(Map a, K existingKey, V existingValue, K newKey, + V newValue) { + if (!unmodifiableCollection(a.keySet(), existingKey, newKey)) { + return false; + } + if (!unmodifiableCollection(a.values(), existingValue, newValue)) { + return false; + } + + try { + a.put(newKey, newValue); + return false; + } catch (Exception ignore) { + // expected + } + try { + a.remove(existingKey); + return false; + } catch (Exception ignore) { + // expected + } + + return true; + } + + public void testToUnmodifiableSet() { + applyItems(Set.of("a", "b"), toUnmodifiableSet(), "a", "b", (expected, actual) -> { + if (!expected.equals(actual)) { + return false; + } + if (!unmodifiableCollection(actual, "a", "z")) { + return false; + } + return true; + }); + + // verify nulls fail + try { + Stream.of("a").map(ignore -> null).collect(toUnmodifiableSet()); + fail("Expected NPE"); + } catch (NullPointerException ignore) { + // expected + } + } +} From 2efa9c60d095dc4410cbca7563a34f9758cf80b5 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Sat, 23 Dec 2023 13:51:12 -0600 Subject: [PATCH 02/27] Disable rpc.enhancedClasses by default at runtime (#9879) Logs warnings at compile time, indicating which classes need to be cleaned up to remove this feature. Mitigation for #9709 --- .../rpc/SerializableTypeOracleBuilder.java | 7 ++++++- .../user/server/rpc/RemoteServiceServlet.java | 16 ++++++++++++++++ .../gwt/user/server/rpc/SerializationPolicy.java | 10 ++++++++++ .../server/rpc/SerializationPolicyLoader.java | 13 +++++++++++++ .../rpc/impl/LegacySerializationPolicy.java | 5 +++++ .../rpc/impl/StandardSerializationPolicy.java | 5 +++++ 6 files changed, 55 insertions(+), 1 deletion(-) diff --git a/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java b/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java index 04a07a75c4..34f28fea57 100644 --- a/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java +++ b/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java @@ -320,7 +320,7 @@ public boolean isAllowed(JClassType type) { JPA_ENTITY_ANNOTATION = Class.forName("javax.persistence.Entity").asSubclass(Annotation.class); } catch (ClassNotFoundException e) { - // Ignore, JPA_ENTITY_CAPABLE_ANNOTATION will be null + // Ignore, JPA_ENTITY_CAPABLE_ANNOTATION will be null } } @@ -869,6 +869,11 @@ public SerializableTypeOracle build(TreeLogger logger) throws UnableToCompleteEx if (tic.maybeEnhanced() || (enhancedClasses != null && enhancedClasses.contains(type.getQualifiedSourceName()))) { + logger.log(TreeLogger.WARN, "The class " + type.getQualifiedSourceName() + " has " + + "JPA/JDO annotations or is explicitly configured as an enhanced class using the " + + "configuration property rpc.enhancedClasses. This makes the server vulnerable " + + "to an issue with deserialization of unsafe data. See " + + "https://github.com/gwtproject/gwt/issues/9709 for more information."); type.setEnhanced(); } } diff --git a/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java b/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java index 141d342ed1..1bd73e142e 100644 --- a/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java +++ b/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java @@ -16,6 +16,8 @@ package com.google.gwt.user.server.rpc; import static com.google.gwt.user.client.rpc.RpcRequestBuilder.MODULE_BASE_HEADER; +import static com.google.gwt.user.server.rpc.SerializationPolicyLoader.ENABLE_ENHANCED_CLASSES; +import static com.google.gwt.user.server.rpc.SerializationPolicyLoader.ENABLE_GWT_ENHANCED_CLASSES_PROPERTY; import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException; import com.google.gwt.user.client.rpc.RpcTokenException; @@ -94,6 +96,20 @@ static SerializationPolicy loadSerializationPolicy(HttpServlet servlet, try { serializationPolicy = SerializationPolicyLoader.loadFromStream(is, null); + if (serializationPolicy.hasClientFields()) { + if (ENABLE_ENHANCED_CLASSES) { + servlet.log("WARNING: Service deserializes enhanced JPA/JDO classes, which is " + + "unsafe. See https://github.com/gwtproject/gwt/issues/9709 for more " + + "detail on the vulnerability that this presents."); + } else { + servlet.log("ERROR: Service deserializes enhanced JPA/JDO classes, which is " + + "unsafe. Review build logs to see which classes are affected, or set " + + ENABLE_GWT_ENHANCED_CLASSES_PROPERTY + " to true to allow using this " + + "service. See https://github.com/gwtproject/gwt/issues/9709 for more " + + "detail."); + serializationPolicy = null; + } + } } catch (ParseException e) { servlet.log("ERROR: Failed to parse the policy file '" + serializationPolicyFilePath + "'", e); diff --git a/user/src/com/google/gwt/user/server/rpc/SerializationPolicy.java b/user/src/com/google/gwt/user/server/rpc/SerializationPolicy.java index f0390240ce..246c6c3c8e 100644 --- a/user/src/com/google/gwt/user/server/rpc/SerializationPolicy.java +++ b/user/src/com/google/gwt/user/server/rpc/SerializationPolicy.java @@ -82,4 +82,14 @@ public abstract void validateDeserialize(Class clazz) */ public abstract void validateSerialize(Class clazz) throws SerializationException; + + /** + * Returns true if there may be any unsafe client fields in the serialization policy. The default + * implementation returns true to ensure that custom implementations validate accordingly. + * + * @return true if the client may send unsafely serialized data, false otherwise + */ + public boolean hasClientFields() { + return true; + } } diff --git a/user/src/com/google/gwt/user/server/rpc/SerializationPolicyLoader.java b/user/src/com/google/gwt/user/server/rpc/SerializationPolicyLoader.java index d860e1d7d3..ba206670d0 100644 --- a/user/src/com/google/gwt/user/server/rpc/SerializationPolicyLoader.java +++ b/user/src/com/google/gwt/user/server/rpc/SerializationPolicyLoader.java @@ -51,6 +51,19 @@ public final class SerializationPolicyLoader { */ public static final String SERIALIZATION_POLICY_FILE_ENCODING = "UTF-8"; + /** + * System property to enable gwt-rpc enhanced classes. To use this, set the JVM system property + * with name {@value ENABLE_GWT_ENHANCED_CLASSES_PROPERTY} to {@code true}, any other value will + * leave this feature disabled in the server at runtime. + */ + public static final String ENABLE_GWT_ENHANCED_CLASSES_PROPERTY = "gwt.enhancedClasses.enabled"; + + /** + * Flag to enable using enhanced classes, for applications that need them and are taking + * appropriate steps to secure them. Defaults to false. + */ + public static final boolean ENABLE_ENHANCED_CLASSES = "true".equals(System.getProperty(ENABLE_GWT_ENHANCED_CLASSES_PROPERTY)); + private static final String FORMAT_ERROR_MESSAGE = "Expected: className, " + "[true | false], [true | false], [true | false], [true | false], typeId, signature"; diff --git a/user/src/com/google/gwt/user/server/rpc/impl/LegacySerializationPolicy.java b/user/src/com/google/gwt/user/server/rpc/impl/LegacySerializationPolicy.java index 62413b6ece..c11c4a7b9d 100644 --- a/user/src/com/google/gwt/user/server/rpc/impl/LegacySerializationPolicy.java +++ b/user/src/com/google/gwt/user/server/rpc/impl/LegacySerializationPolicy.java @@ -174,4 +174,9 @@ private boolean isInstantiable(Class clazz) { } return SerializabilityUtil.hasCustomFieldSerializer(clazz) != null; } + + @Override + public boolean hasClientFields() { + return false; + } } diff --git a/user/src/com/google/gwt/user/server/rpc/impl/StandardSerializationPolicy.java b/user/src/com/google/gwt/user/server/rpc/impl/StandardSerializationPolicy.java index 05c333df9a..aadd64517b 100644 --- a/user/src/com/google/gwt/user/server/rpc/impl/StandardSerializationPolicy.java +++ b/user/src/com/google/gwt/user/server/rpc/impl/StandardSerializationPolicy.java @@ -131,6 +131,11 @@ public Set getClientFieldNamesForEnhancedClass(Class clazz) { return fieldNames == null ? null : Collections.unmodifiableSet(fieldNames); } + @Override + public boolean hasClientFields() { + return clientFields != null && !clientFields.isEmpty(); + } + public final String getTypeIdForClass(Class clazz) throws SerializationException { return typeIds.get(clazz); From 642410ecfe5d061e6b3391a4fd7c23ea5955f017 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Fri, 29 Dec 2023 14:38:48 -0600 Subject: [PATCH 03/27] Log deprecation warning when using built-in JettyLauncher (#9866) This patch has two approaches to check if the JettyLauncher is being used, it checks for any configured filters/servlets (other than the defaults provided by Jetty) in order to log a warning on startup, and it checks for non-404 responses to catch other resources loaded after startup. No warning is logged for tests which use servlets. A new ServletContainerLauncher implementation is added, to be passed as `-server com.google.gwt.dev.shell.StaticResourceServer` to DevMode. This will serve only static contents instead of hosting the servlet- based web application. In the future, this may be the default in place of JettyLauncher. Fixes #9863 --- .../gwt/dev/shell/StaticResourceServer.java | 190 +++++++++++ .../gwt/dev/shell/jetty/ClientAuthType.java | 25 ++ .../gwt/dev/shell/jetty/JettyLauncher.java | 305 ++++-------------- .../dev/shell/jetty/JettyLauncherUtils.java | 102 ++++++ .../gwt/dev/shell/jetty/JettyTreeLogger.java | 134 ++++++++ .../gwt/dev/shell/jetty/SslConfiguration.java | 129 ++++++++ user/src/com/google/gwt/junit/JUnitShell.java | 1 + 7 files changed, 643 insertions(+), 243 deletions(-) create mode 100644 dev/core/src/com/google/gwt/dev/shell/StaticResourceServer.java create mode 100644 dev/core/src/com/google/gwt/dev/shell/jetty/ClientAuthType.java create mode 100644 dev/core/src/com/google/gwt/dev/shell/jetty/JettyLauncherUtils.java create mode 100644 dev/core/src/com/google/gwt/dev/shell/jetty/JettyTreeLogger.java create mode 100644 dev/core/src/com/google/gwt/dev/shell/jetty/SslConfiguration.java diff --git a/dev/core/src/com/google/gwt/dev/shell/StaticResourceServer.java b/dev/core/src/com/google/gwt/dev/shell/StaticResourceServer.java new file mode 100644 index 0000000000..df95aeb993 --- /dev/null +++ b/dev/core/src/com/google/gwt/dev/shell/StaticResourceServer.java @@ -0,0 +1,190 @@ +/* + * 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.dev.shell; + +import com.google.gwt.core.ext.ServletContainer; +import com.google.gwt.core.ext.ServletContainerLauncher; +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.dev.shell.jetty.ClientAuthType; +import com.google.gwt.dev.shell.jetty.JettyLauncherUtils; +import com.google.gwt.dev.shell.jetty.JettyTreeLogger; +import com.google.gwt.dev.shell.jetty.SslConfiguration; +import org.eclipse.jetty.security.ConstraintSecurityHandler; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ErrorPageErrorHandler; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.webapp.WebAppContext; + +import java.io.File; +import java.util.Optional; + +/** + * Simple webserver that only hosts static resources. Intended to be the replacement + * for JettyLauncher. + */ +public class StaticResourceServer extends ServletContainerLauncher { + + private String bindAddress = null; + + private SslConfiguration sslConfig = new SslConfiguration(ClientAuthType.NONE, null, null, false); + + @Override + public String getName() { + return "StaticResourceServer"; + } + + @Override + public void setBindAddress(String bindAddress) { + this.bindAddress = bindAddress; + } + + @Override + public boolean isSecure() { + return sslConfig.isUseSsl(); + } + + private void checkStartParams(TreeLogger logger, int port, File appRootDir) { + if (logger == null) { + throw new NullPointerException("logger cannot be null"); + } + + if (port < 0 || port > 65535) { + throw new IllegalArgumentException( + "port must be either 0 (for auto) or less than 65536"); + } + + if (appRootDir == null) { + throw new NullPointerException("app root directory cannot be null"); + } + } + + @Override + public boolean processArguments(TreeLogger logger, String arguments) { + if (arguments != null && arguments.length() > 0) { + Optional parsed = SslConfiguration.parseArgs(arguments.split(","), logger); + if (parsed.isPresent()) { + sslConfig = parsed.get(); + } else { + return false; + } + } + return true; + } + + + @Override + public ServletContainer start(TreeLogger logger, int port, File appRootDir) throws Exception { + TreeLogger branch = logger.branch(TreeLogger.TRACE, + "Starting StaticResourceServer on port " + port, null); + + checkStartParams(branch, port, appRootDir); + + // During startup, use the branch logger, we'll reset this later to the root logger + Log.setLog(new JettyTreeLogger(branch)); + + Server server = new Server(); + + ServerConnector connector = JettyLauncherUtils.getConnector(server, sslConfig, branch); + JettyLauncherUtils.setupConnector(connector, bindAddress, port); + server.addConnector(connector); + + WebAppContext webAppContext = new WebAppContext(null, "/", null, null, null, + new ErrorPageErrorHandler(), ServletContextHandler.NO_SECURITY); + webAppContext.setWar(appRootDir.getAbsolutePath()); + webAppContext.setSecurityHandler(new ConstraintSecurityHandler()); + + server.setHandler(webAppContext); + + server.start(); + server.setStopAtShutdown(true); + + // Now that we're started, log to the top level logger. + Log.setLog(new JettyTreeLogger(logger)); + + // DevMode#doStartUpServer() fails from time to time (rarely) due + // to an unknown error. Adding some logging to pinpoint the problem. + int connectorPort = connector.getLocalPort(); + if (connector.getLocalPort() < 0) { + branch.log(TreeLogger.ERROR, String.format( + "Failed to connect to open channel with port %d (return value %d)", + port, connectorPort)); + } + + return new StaticServerImpl(connectorPort, appRootDir, branch, server); + } + + private static final class StaticServerImpl extends ServletContainer { + private final int port; + private final File appRootDir; + private final TreeLogger logger; + private final Server server; + + private StaticServerImpl(int port, File appRootDir, TreeLogger logger, Server server) { + this.port = port; + this.appRootDir = appRootDir; + this.logger = logger; + this.server = server; + } + + @Override + public int getPort() { + return port; + } + + @Override + public void refresh() throws UnableToCompleteException { + String msg = "Reloading web app to reflect changes in " + + appRootDir.getAbsolutePath(); + TreeLogger branch = logger.branch(TreeLogger.INFO, msg); + // Temporarily log Jetty on the branch. + Log.setLog(new JettyTreeLogger(branch)); + try { + server.stop(); + server.start(); + branch.log(TreeLogger.INFO, "Reload completed successfully"); + } catch (Exception e) { + branch.log(TreeLogger.ERROR, "Unable to restart StaticResourceServer server", + e); + throw new UnableToCompleteException(); + } finally { + // Reset the top-level logger. + Log.setLog(new JettyTreeLogger(logger)); + } + } + + @Override + public void stop() throws UnableToCompleteException { + TreeLogger branch = logger.branch(TreeLogger.INFO, + "Stopping StaticResourceServer server"); + // Temporarily log Jetty on the branch. + Log.setLog(new JettyTreeLogger(branch)); + try { + server.stop(); + server.setStopAtShutdown(false); + branch.log(TreeLogger.TRACE, "Stopped successfully"); + } catch (Exception e) { + branch.log(TreeLogger.ERROR, "Unable to stop embedded StaticResourceServer server", e); + throw new UnableToCompleteException(); + } finally { + // Reset the top-level logger. + Log.setLog(new JettyTreeLogger(logger)); + } + } + } +} diff --git a/dev/core/src/com/google/gwt/dev/shell/jetty/ClientAuthType.java b/dev/core/src/com/google/gwt/dev/shell/jetty/ClientAuthType.java new file mode 100644 index 0000000000..c772e478fc --- /dev/null +++ b/dev/core/src/com/google/gwt/dev/shell/jetty/ClientAuthType.java @@ -0,0 +1,25 @@ +/* + * 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.dev.shell.jetty; + +/** + * Represents the type of SSL client certificate authentication desired. + */ +public enum ClientAuthType { + NONE, + WANT, + REQUIRE, +} diff --git a/dev/core/src/com/google/gwt/dev/shell/jetty/JettyLauncher.java b/dev/core/src/com/google/gwt/dev/shell/jetty/JettyLauncher.java index 69b1dc9dd7..c5d3cbcccd 100644 --- a/dev/core/src/com/google/gwt/dev/shell/jetty/JettyLauncher.java +++ b/dev/core/src/com/google/gwt/dev/shell/jetty/JettyLauncher.java @@ -27,26 +27,20 @@ import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.security.ConstraintSecurityHandler; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.RequestLog; import org.eclipse.jetty.server.Response; -import org.eclipse.jetty.server.SecureRequestCustomizer; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.SslConnectionFactory; import org.eclipse.jetty.server.handler.RequestLogHandler; import org.eclipse.jetty.servlet.ErrorPageErrorHandler; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.preventers.AppContextLeakPreventer; import org.eclipse.jetty.util.preventers.DOMLeakPreventer; import org.eclipse.jetty.util.preventers.GCThreadLeakPreventer; import org.eclipse.jetty.util.preventers.SecurityProviderLeakPreventer; -import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.webapp.ClasspathPattern; import org.eclipse.jetty.webapp.Configuration; import org.eclipse.jetty.webapp.WebAppClassLoader; @@ -63,11 +57,46 @@ import java.util.Enumeration; import java.util.Iterator; import java.util.List; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Stream; /** * A {@link ServletContainerLauncher} for an embedded Jetty server. + *

+ * @deprecated please migrate to {@link com.google.gwt.dev.shell.StaticResourceServer}, + * or provide your own implementation. */ +@Deprecated public class JettyLauncher extends ServletContainerLauncher { + private static final AtomicBoolean hasLoggedDeprecationWarning = new AtomicBoolean(false); + + /** + * Disable warning about JettyLauncher being deprecated when running tests, as this only is + * intended to apply to DevMode - The test runner can be updated at the same time as any other + * changes are made to JettyLauncher. + */ + public static void suppressDeprecationWarningForTests() { + hasLoggedDeprecationWarning.set(true); + } + + /** + * Warns, only once, that JettyLauncher is deprecated for removal. Call when it is clear that + * the developer is actively deploying code to, or loading resources from, the embedded Jetty + * instance. + * + * @param log existing TreeLogger to append warning to + */ + private static void maybeLogDeprecationWarning(TreeLogger log) { + if (hasLoggedDeprecationWarning.compareAndSet(false, true)) { + log.log(TreeLogger.Type.WARN, "DevMode will default to -noserver in a future release, and " + + "JettyLauncher may be removed or changed. Please consider running your own " + + "application server and either passing -noserver to DevMode or migrating to " + + "CodeServer. Alternatively, consider implementing your own " + + "ServletContainerLauncher to continue running your application server from " + + "DevMode."); + } + } /** * Log jetty requests/responses to TreeLogger. @@ -93,6 +122,10 @@ public void log(Request request, Response response) { // Copied from NCSARequestLog status = 404; } + if (status != 404) { + // Ignore 404 errors, log the first other call to the server if we haven't logged yet + maybeLogDeprecationWarning(logger); + } TreeLogger.Type logStatus, logHeaders; if (status >= 500) { logStatus = TreeLogger.ERROR; @@ -150,120 +183,15 @@ private void logHeaders(TreeLogger logger, TreeLogger.Type logLevel, HttpFields } /** - * An adapter for the Jetty logging system to GWT's TreeLogger. This - * implementation class is only public to allow {@link Log} to instantiate it. - * - * The weird static data / default construction setup is a game we play with - * {@link Log}'s static initializer to prevent the initial log message from - * going to stderr. + * An adapter for the Jetty logging system to GWT's TreeLogger. + * @deprecated use {@link com.google.gwt.dev.shell.jetty.JettyTreeLogger} instead. */ - public static class JettyTreeLogger implements Logger { - private final TreeLogger logger; - + @Deprecated + public static class JettyTreeLogger extends com.google.gwt.dev.shell.jetty.JettyTreeLogger { public JettyTreeLogger(TreeLogger logger) { - if (logger == null) { - throw new NullPointerException(); - } - this.logger = logger; - } - - public void debug(String msg, long arg) { - logger.log(TreeLogger.SPAM, format(msg, arg)); - } - - public void debug(String msg, Object... args) { - if (logger.isLoggable(TreeLogger.SPAM)) { - logger.log(TreeLogger.SPAM, format(msg, args)); - } - } - - public void debug(String msg, Throwable th) { - logger.log(TreeLogger.SPAM, msg, th); - } - - public void debug(Throwable th) { - logger.log(TreeLogger.SPAM, "", th); - } - - public Logger getLogger(String name) { - return this; - } - - public String getName() { - return ""; - } - - public void info(String msg, Object... args) { - if (logger.isLoggable(TreeLogger.TRACE)) { - logger.log(TreeLogger.TRACE, format(msg, args)); - } - } - - public void info(String msg, Throwable th) { - logger.log(TreeLogger.TRACE, msg, th); - } - - public void info(Throwable th) { - logger.log(TreeLogger.TRACE, "", th); - } - - public boolean isDebugEnabled() { - return logger.isLoggable(TreeLogger.SPAM); - } - - public void setDebugEnabled(boolean enabled) { - // ignored - } - - public void warn(String msg, Object... args) { - if (logger.isLoggable(TreeLogger.WARN)) { - logger.log(TreeLogger.WARN, format(msg, args)); - } - } - - public void warn(String msg, Throwable th) { - logger.log(TreeLogger.WARN, msg, th); - } - - public void warn(Throwable th) { - logger.log(TreeLogger.WARN, "", th); - } - - public void ignore(Throwable th) { - logger.log(TreeLogger.SPAM, "IGNORE", th); - } - - /** - * Copied from org.eclipse.log.StdErrLog. - */ - private String format(String msg, Object... args) { - if (msg == null) { - msg = ""; - for (int i = 0; i < args.length; i++) { - msg += "{} "; - } - } - String braces = "{}"; - int start = 0; - StringBuilder builder = new StringBuilder(); - for (Object arg : args) { - int bracesIndex = msg.indexOf(braces, start); - if (bracesIndex < 0) { - builder.append(msg.substring(start)); - builder.append(" "); - builder.append(arg); - start = msg.length(); - } else { - builder.append(msg.substring(start, bracesIndex)); - builder.append(String.valueOf(arg)); - start = bracesIndex + braces.length(); - } - } - builder.append(msg.substring(start)); - return builder.toString(); + super(logger); } } - /** * The resulting {@link ServletContainer} this is launched. */ @@ -566,6 +494,15 @@ private WebAppContextWithReload(TreeLogger logger, String webApp, protected void doStart() throws Exception { setClassLoader(new WebAppClassLoaderExtension()); super.doStart(); + + // After start, warn if a servlet/filter was configured other than those provided by Jetty + boolean hasNonJettyFiltersOrServlets = Stream.concat( + getServletContext().getServletRegistrations().values().stream(), + getServletContext().getFilterRegistrations().values().stream() + ).anyMatch(r -> !r.getClassName().startsWith("org.eclipse.jetty")); + if (hasNonJettyFiltersOrServlets) { + maybeLogDeprecationWarning(logger); + } } @Override @@ -581,15 +518,6 @@ protected void doStop() throws Exception { } } - /** - * Represents the type of SSL client certificate authentication desired. - */ - private enum ClientAuth { - NONE, - WANT, - REQUIRE, - } - /** * System property to suppress warnings about loading web app classes from the * system classpath. @@ -605,13 +533,7 @@ private enum ClientAuth { */ private static void setupConnector(ServerConnector connector, String bindAddress, int port) { - if (bindAddress != null) { - connector.setHost(bindAddress.toString()); - } - connector.setPort(port); - - // Allow binding to a port even if it's still in state TIME_WAIT. - connector.setReuseAddress(true); + JettyLauncherUtils.setupConnector(connector, bindAddress, port); } // default value used if setBaseLogLevel isn't called @@ -619,15 +541,10 @@ private static void setupConnector(ServerConnector connector, private String bindAddress = null; - private ClientAuth clientAuth; - - private String keyStore; - - private String keyStorePassword; + private SslConfiguration sslConfig = new SslConfiguration(ClientAuthType.NONE, null, null, false); private final Object privateInstanceLock = new Object(); - private boolean useSsl; @Override public String getName() { @@ -636,71 +553,17 @@ public String getName() { @Override public boolean isSecure() { - return useSsl; + return sslConfig.isUseSsl(); } @Override public boolean processArguments(TreeLogger logger, String arguments) { if (arguments != null && arguments.length() > 0) { - // TODO(jat): better parsing of the args - for (String arg : arguments.split(",")) { - int equals = arg.indexOf('='); - String tag; - String value = null; - if (equals < 0) { - tag = arg; - } else { - tag = arg.substring(0, equals); - value = arg.substring(equals + 1); - } - if ("ssl".equals(tag)) { - useSsl = true; - URL keyStoreUrl = getClass().getResource("localhost.keystore"); - if (keyStoreUrl == null) { - logger.log(TreeLogger.ERROR, "Default GWT keystore not found"); - return false; - } - keyStore = keyStoreUrl.toExternalForm(); - keyStorePassword = "localhost"; - } else if ("keystore".equals(tag)) { - useSsl = true; - keyStore = value; - } else if ("password".equals(tag)) { - useSsl = true; - keyStorePassword = value; - } else if ("pwfile".equals(tag)) { - useSsl = true; - keyStorePassword = Util.readFileAsString(new File(value)); - if (keyStorePassword == null) { - logger.log(TreeLogger.ERROR, - "Unable to read keystore password from '" + value + "'"); - return false; - } - keyStorePassword = keyStorePassword.trim(); - } else if ("clientAuth".equals(tag)) { - useSsl = true; - try { - clientAuth = ClientAuth.valueOf(value); - } catch (IllegalArgumentException e) { - logger.log(TreeLogger.WARN, "Ignoring invalid clientAuth of '" - + value + "'"); - } - } else { - logger.log(TreeLogger.ERROR, "Unexpected argument to " - + JettyLauncher.class.getSimpleName() + ": " + arg); - return false; - } - } - if (useSsl) { - if (keyStore == null) { - logger.log(TreeLogger.ERROR, "A keystore is required to use SSL"); - return false; - } - if (keyStorePassword == null) { - logger.log(TreeLogger.ERROR, - "A keystore password is required to use SSL"); - return false; - } + Optional parsed = SslConfiguration.parseArgs(arguments.split(","), logger); + if (parsed.isPresent()) { + sslConfig = parsed.get(); + } else { + return false; } } return true; @@ -813,51 +676,7 @@ protected WebAppContext createWebAppContext(TreeLogger logger, File appRootDir) } protected ServerConnector getConnector(Server server, TreeLogger logger) { - HttpConfiguration config = defaultConfig(); - if (useSsl) { - TreeLogger sslLogger = logger.branch(TreeLogger.INFO, - "Listening for SSL connections"); - if (sslLogger.isLoggable(TreeLogger.TRACE)) { - sslLogger.log(TreeLogger.TRACE, "Using keystore " + keyStore); - } - SslContextFactory ssl = new SslContextFactory(); - if (clientAuth != null) { - switch (clientAuth) { - case NONE: - ssl.setWantClientAuth(false); - ssl.setNeedClientAuth(false); - break; - case WANT: - sslLogger.log(TreeLogger.TRACE, "Requesting client certificates"); - ssl.setWantClientAuth(true); - ssl.setNeedClientAuth(false); - break; - case REQUIRE: - sslLogger.log(TreeLogger.TRACE, "Requiring client certificates"); - ssl.setWantClientAuth(true); - ssl.setNeedClientAuth(true); - break; - } - } - ssl.setKeyStorePath(keyStore); - ssl.setTrustStorePath(keyStore); - ssl.setKeyStorePassword(keyStorePassword); - ssl.setTrustStorePassword(keyStorePassword); - config.addCustomizer(new SecureRequestCustomizer()); - return new ServerConnector(server, - null, null, null, 0, 2, - new SslConnectionFactory(ssl, "http/1.1"), - new HttpConnectionFactory(config)); - } - return new ServerConnector(server, new HttpConnectionFactory(config)); - } - - protected HttpConfiguration defaultConfig() { - HttpConfiguration config = new HttpConfiguration(); - config.setRequestHeaderSize(16386); - config.setSendServerVersion(false); - config.setSendDateHeader(true); - return config; + return JettyLauncherUtils.getConnector(server, sslConfig, logger); } private void addPreventers(Server server) { diff --git a/dev/core/src/com/google/gwt/dev/shell/jetty/JettyLauncherUtils.java b/dev/core/src/com/google/gwt/dev/shell/jetty/JettyLauncherUtils.java new file mode 100644 index 0000000000..212c71ffd0 --- /dev/null +++ b/dev/core/src/com/google/gwt/dev/shell/jetty/JettyLauncherUtils.java @@ -0,0 +1,102 @@ +/* + * 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.dev.shell.jetty; + +import com.google.gwt.core.ext.TreeLogger; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.SecureRequestCustomizer; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.SslConnectionFactory; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +/** + * Shared static methods for both JettyLauncher and StaticResourceServer, useful for + * any Jetty-based implementation of a ServletContainerLauncher. + */ +public class JettyLauncherUtils { + + private JettyLauncherUtils() { + // non-instantiable + } + + /** + * Setup a connector for the bind address/port. + * + * @param connector + * @param bindAddress + * @param port + */ + public static void setupConnector(ServerConnector connector, + String bindAddress, int port) { + if (bindAddress != null) { + connector.setHost(bindAddress); + } + connector.setPort(port); + + // Allow binding to a port even if it's still in state TIME_WAIT. + connector.setReuseAddress(true); + } + + public static ServerConnector getConnector(Server server, SslConfiguration sslConfig, TreeLogger logger) { + HttpConfiguration config = defaultConfig(); + if (sslConfig.isUseSsl()) { + TreeLogger sslLogger = logger.branch(TreeLogger.INFO, + "Listening for SSL connections"); + if (sslLogger.isLoggable(TreeLogger.TRACE)) { + sslLogger.log(TreeLogger.TRACE, "Using keystore " + sslConfig.getKeyStore()); + } + SslContextFactory ssl = new SslContextFactory(); + if (sslConfig.getClientAuth() != null) { + switch (sslConfig.getClientAuth()) { + case NONE: + ssl.setWantClientAuth(false); + ssl.setNeedClientAuth(false); + break; + case WANT: + sslLogger.log(TreeLogger.TRACE, "Requesting client certificates"); + ssl.setWantClientAuth(true); + ssl.setNeedClientAuth(false); + break; + case REQUIRE: + sslLogger.log(TreeLogger.TRACE, "Requiring client certificates"); + ssl.setWantClientAuth(true); + ssl.setNeedClientAuth(true); + break; + } + } + ssl.setKeyStorePath(sslConfig.getKeyStore()); + ssl.setTrustStorePath(sslConfig.getKeyStore()); + ssl.setKeyStorePassword(sslConfig.getKeyStorePassword()); + ssl.setTrustStorePassword(sslConfig.getKeyStorePassword()); + config.addCustomizer(new SecureRequestCustomizer()); + return new ServerConnector(server, + null, null, null, 0, 2, + new SslConnectionFactory(ssl, "http/1.1"), + new HttpConnectionFactory(config)); + } + return new ServerConnector(server, new HttpConnectionFactory(config)); + } + + private static HttpConfiguration defaultConfig() { + HttpConfiguration config = new HttpConfiguration(); + config.setRequestHeaderSize(16386); + config.setSendServerVersion(false); + config.setSendDateHeader(true); + return config; + } +} diff --git a/dev/core/src/com/google/gwt/dev/shell/jetty/JettyTreeLogger.java b/dev/core/src/com/google/gwt/dev/shell/jetty/JettyTreeLogger.java new file mode 100644 index 0000000000..bd7952fb1f --- /dev/null +++ b/dev/core/src/com/google/gwt/dev/shell/jetty/JettyTreeLogger.java @@ -0,0 +1,134 @@ +/* + * 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.dev.shell.jetty; + +import com.google.gwt.core.ext.TreeLogger; +import org.eclipse.jetty.util.log.Logger; + +/** + * An adapter for the Jetty logging system to GWT's TreeLogger. This implementation class is only + * public to allow {@link org.eclipse.jetty.util.log.Log} to instantiate it. + *

+ * The weird static data / default construction setup is a game we play with + * {@link org.eclipse.jetty.util.log.Log}'s static initializer to prevent the initial log message + * from going to stderr. + */ +public class JettyTreeLogger implements Logger { + private final TreeLogger logger; + + public JettyTreeLogger(TreeLogger logger) { + if (logger == null) { + throw new NullPointerException(); + } + this.logger = logger; + } + + public void debug(String msg, long arg) { + logger.log(TreeLogger.SPAM, format(msg, arg)); + } + + public void debug(String msg, Object... args) { + if (logger.isLoggable(TreeLogger.SPAM)) { + logger.log(TreeLogger.SPAM, format(msg, args)); + } + } + + public void debug(String msg, Throwable th) { + logger.log(TreeLogger.SPAM, msg, th); + } + + public void debug(Throwable th) { + logger.log(TreeLogger.SPAM, "", th); + } + + public Logger getLogger(String name) { + return this; + } + + public String getName() { + return ""; + } + + public void info(String msg, Object... args) { + if (logger.isLoggable(TreeLogger.TRACE)) { + logger.log(TreeLogger.TRACE, format(msg, args)); + } + } + + public void info(String msg, Throwable th) { + logger.log(TreeLogger.TRACE, msg, th); + } + + public void info(Throwable th) { + logger.log(TreeLogger.TRACE, "", th); + } + + public boolean isDebugEnabled() { + return logger.isLoggable(TreeLogger.SPAM); + } + + public void setDebugEnabled(boolean enabled) { + // ignored + } + + public void warn(String msg, Object... args) { + if (logger.isLoggable(TreeLogger.WARN)) { + logger.log(TreeLogger.WARN, format(msg, args)); + } + } + + public void warn(String msg, Throwable th) { + logger.log(TreeLogger.WARN, msg, th); + } + + public void warn(Throwable th) { + logger.log(TreeLogger.WARN, "", th); + } + + public void ignore(Throwable th) { + logger.log(TreeLogger.SPAM, "IGNORE", th); + } + + /** + * Copied from org.eclipse.log.StdErrLog. + */ + private String format(String msg, Object... args) { + if (msg == null) { + msg = ""; + for (int i = 0; i < args.length; i++) { + msg += "{} "; + } + } + String braces = "{}"; + int start = 0; + StringBuilder builder = new StringBuilder(); + for (Object arg : args) { + int bracesIndex = msg.indexOf(braces, start); + if (bracesIndex < 0) { + builder.append(msg.substring(start)); + builder.append(" "); + builder.append(arg); + start = msg.length(); + } else { + builder.append(msg.substring(start, bracesIndex)); + builder.append(String.valueOf(arg)); + start = bracesIndex + braces.length(); + } + } + builder.append(msg.substring(start)); + return builder.toString(); + } +} diff --git a/dev/core/src/com/google/gwt/dev/shell/jetty/SslConfiguration.java b/dev/core/src/com/google/gwt/dev/shell/jetty/SslConfiguration.java new file mode 100644 index 0000000000..3d6da8ef1a --- /dev/null +++ b/dev/core/src/com/google/gwt/dev/shell/jetty/SslConfiguration.java @@ -0,0 +1,129 @@ +/* + * 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.dev.shell.jetty; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.dev.util.Util; + +import java.io.File; +import java.net.URL; +import java.util.Optional; + +/** + * Configuration object to parse selected command line args, store SSL options for use by in the + * server. + */ +public class SslConfiguration { + private final ClientAuthType clientAuth; + + private final String keyStore; + + private final String keyStorePassword; + + private final boolean useSsl; + + public static Optional parseArgs(String[] args, TreeLogger logger) { + boolean useSsl = false; + String keyStore = null; + String keyStorePassword = null; + ClientAuthType clientAuth = ClientAuthType.NONE; + + // TODO(jat): better parsing of the args + for (String arg : args) { + int equals = arg.indexOf('='); + String tag; + String value = null; + if (equals < 0) { + tag = arg; + } else { + tag = arg.substring(0, equals); + value = arg.substring(equals + 1); + } + if ("ssl".equals(tag)) { + useSsl = true; + URL keyStoreUrl = JettyLauncher.class.getResource("localhost.keystore"); + if (keyStoreUrl == null) { + logger.log(TreeLogger.ERROR, "Default GWT keystore not found"); + return Optional.empty(); + } + keyStore = keyStoreUrl.toExternalForm(); + keyStorePassword = "localhost"; + } else if ("keystore".equals(tag)) { + useSsl = true; + keyStore = value; + } else if ("password".equals(tag)) { + useSsl = true; + keyStorePassword = value; + } else if ("pwfile".equals(tag)) { + useSsl = true; + keyStorePassword = Util.readFileAsString(new File(value)); + if (keyStorePassword == null) { + logger.log(TreeLogger.ERROR, + "Unable to read keystore password from '" + value + "'"); + return Optional.empty(); + } + keyStorePassword = keyStorePassword.trim(); + } else if ("clientAuth".equals(tag)) { + useSsl = true; + try { + clientAuth = ClientAuthType.valueOf(value); + } catch (IllegalArgumentException e) { + logger.log(TreeLogger.WARN, "Ignoring invalid clientAuth of '" + + value + "'"); + } + } else { + logger.log(TreeLogger.ERROR, "Unexpected argument to " + + JettyLauncher.class.getSimpleName() + ": " + arg); + return Optional.empty(); + } + } + if (useSsl) { + if (keyStore == null) { + logger.log(TreeLogger.ERROR, "A keystore is required to use SSL"); + return Optional.empty(); + } + if (keyStorePassword == null) { + logger.log(TreeLogger.ERROR, + "A keystore password is required to use SSL"); + return Optional.empty(); + } + } + return Optional.of(new SslConfiguration(clientAuth, keyStore, keyStorePassword, useSsl)); + } + + public SslConfiguration(ClientAuthType clientAuth, String keyStore, String keyStorePassword, boolean useSsl) { + this.clientAuth = clientAuth; + this.keyStore = keyStore; + this.keyStorePassword = keyStorePassword; + this.useSsl = useSsl; + } + + public ClientAuthType getClientAuth() { + return clientAuth; + } + + public String getKeyStore() { + return keyStore; + } + + public String getKeyStorePassword() { + return keyStorePassword; + } + + public boolean isUseSsl() { + return useSsl; + } +} diff --git a/user/src/com/google/gwt/junit/JUnitShell.java b/user/src/com/google/gwt/junit/JUnitShell.java index a11b145283..277613cad0 100644 --- a/user/src/com/google/gwt/junit/JUnitShell.java +++ b/user/src/com/google/gwt/junit/JUnitShell.java @@ -248,6 +248,7 @@ public String[] getDefaultArgs() { * ----- Options from DevMode ------- */ // Hard code the server. + JettyLauncher.suppressDeprecationWarningForTests(); options.setServletContainerLauncher(shell.new MyJettyLauncher()); // DISABLE: ArgHandlerStartupURLs registerHandler(new ArgHandlerWarDir(options) { From 42c1e8a2057380d9cb67d86c2ca281b1e9f6b194 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Fri, 29 Dec 2023 14:39:24 -0600 Subject: [PATCH 04/27] Deprecate webAppCreator, encourage using the getting started guide (#9883) This encourages a few bad practices that we'd like to avoid, most notably mixing server and client classpaths, and encouraging using DevMode's built-in server as an application server. Partial #9863 --- user/src/com/google/gwt/user/tools/WebAppCreator.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/user/src/com/google/gwt/user/tools/WebAppCreator.java b/user/src/com/google/gwt/user/tools/WebAppCreator.java index eba228a8db..b787baaf97 100644 --- a/user/src/com/google/gwt/user/tools/WebAppCreator.java +++ b/user/src/com/google/gwt/user/tools/WebAppCreator.java @@ -456,6 +456,10 @@ private abstract static class Procrastinator { } public static void main(String[] args) { + System.err.println("WebAppCreator is deprecated - please refer to " + + "https://www.gwtproject.org/gettingstarted.html for other ways to create a new " + + "application with GWT, including with Maven archetypes. These encourage better " + + "separation of classpaths, and do not need IDE-specific setup."); System.exit(doMain(args) ? 0 : 1); } From cb2456e11d99e017d4fe8c051e6db55e4eb435b3 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Tue, 2 Jan 2024 09:33:48 -0600 Subject: [PATCH 05/27] RequestFactory parent pom should list rf-server-jakarta entries (#9887) --- maven/poms/requestfactory/pom-template.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/maven/poms/requestfactory/pom-template.xml b/maven/poms/requestfactory/pom-template.xml index be33a705e5..fff7f4756f 100644 --- a/maven/poms/requestfactory/pom-template.xml +++ b/maven/poms/requestfactory/pom-template.xml @@ -52,6 +52,16 @@ requestfactory-server ${project.version} + + com.google.web.bindery + requestfactory-server-jakarta + 2.10.0 + + + org.gwtproject.web.bindery + requestfactory-server-jakarta + ${project.version} + javax.validation validation-api From 257bc54fdd9770eedf5337c663d65f20584aa82b Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Wed, 3 Jan 2024 20:11:06 -0600 Subject: [PATCH 06/27] Google will never ship 2.10.0 rf-server-jakarta, remove it (#9890) Follow-up to #9887 --- maven/poms/requestfactory/pom-template.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/maven/poms/requestfactory/pom-template.xml b/maven/poms/requestfactory/pom-template.xml index fff7f4756f..24964e8975 100644 --- a/maven/poms/requestfactory/pom-template.xml +++ b/maven/poms/requestfactory/pom-template.xml @@ -52,11 +52,6 @@ requestfactory-server ${project.version} - - com.google.web.bindery - requestfactory-server-jakarta - 2.10.0 - org.gwtproject.web.bindery requestfactory-server-jakarta From 7f76f0f2b5b1b028d2d870782048e44402637fb0 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Wed, 3 Jan 2024 20:11:51 -0600 Subject: [PATCH 07/27] Remove unexpected sources from gwt-user by making valid servlet sources (#9888) Removes an old hack which uses gwt-user's sources as if they were the correct sources for gwt-servlet by creating a real build artifact that contains the sources which correspond to the classes found in gwt-servlet and gwt-servlet-jakarta. This lets us avoid using gwt-user's own sources as if they were the sources for other jars, which in turn allows us to only package gwt-user sources in gwt-user.jar. Fixes #9886 --- distro-source/build.xml | 4 +--- maven/lib-gwt.sh | 10 +++----- servlet/build.xml | 53 +++++++++++++++++++++++++++++++---------- user/build.xml | 2 -- 4 files changed, 45 insertions(+), 24 deletions(-) diff --git a/distro-source/build.xml b/distro-source/build.xml index 90e0448383..55c712802f 100755 --- a/distro-source/build.xml +++ b/distro-source/build.xml @@ -31,10 +31,8 @@ - - + - diff --git a/maven/lib-gwt.sh b/maven/lib-gwt.sh index bb8ac49f7e..4d3028523e 100644 --- a/maven/lib-gwt.sh +++ b/maven/lib-gwt.sh @@ -115,14 +115,10 @@ function maven-gwt() { gwtPomFile=$pomDir/gwt/gwt-$i/pom.xml SOURCES_FILE=gwt-${i}-sources.jar SOURCES_PATH_FILE=$GWT_EXTRACT_DIR/$SOURCES_FILE - # If there are no sources, use gwt-user sources. - # This is a bit hacky but Sonatype requires a - # source jar for Central, and lack of sources - # should only happen for gwt-servlet and - # gwt-servlet-jakarta, which are basically a - # subset of gwt-user. + # If there are no sources, fail, this is a requirement of maven central if [ ! -f $SOURCES_PATH_FILE ]; then - SOURCES_PATH_FILE=$GWT_EXTRACT_DIR/gwt-user-sources.jar + echo "ERROR: sources jar not found for $i" + exit 1 fi maven-deploy-file $mavenRepoUrl $mavenRepoId "$CUR_FILE" $gwtPomFile "$JAVADOC_FILE_PATH" "$SOURCES_PATH_FILE" || die diff --git a/servlet/build.xml b/servlet/build.xml index 60901a6876..47d554892f 100644 --- a/servlet/build.xml +++ b/servlet/build.xml @@ -13,7 +13,7 @@ location="${gwt.build.lib}/gwt-${ant.project.name}-deps.jar" /> + depends="-servlet, -servlet-jakarta, -servlet-sources, -servlet-jakarta-sources, -deps" /> @@ -30,7 +30,6 @@ - @@ -43,13 +42,28 @@ - - - - - + + + + + + + + + + + + + + + + + + + + @@ -62,7 +76,6 @@ - @@ -75,12 +88,28 @@ - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/user/build.xml b/user/build.xml index 1f43783a4c..d627a8078c 100755 --- a/user/build.xml +++ b/user/build.xml @@ -373,8 +373,6 @@ - - From 948bc557591e76ea82f0a06b91b2a0fcb409e546 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Tue, 9 Jan 2024 16:58:00 -0600 Subject: [PATCH 08/27] Enable dependabot and update CI actions (#9892) --- .github/dependabot.yml | 6 ++++++ .github/workflows/full-check.yml | 16 ++++++++-------- .github/workflows/quick-check.yml | 8 ++++---- 3 files changed, 18 insertions(+), 12 deletions(-) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..ca79ca5b4d --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly diff --git a/.github/workflows/full-check.yml b/.github/workflows/full-check.yml index 9d98ad5f80..5e5110f795 100644 --- a/.github/workflows/full-check.yml +++ b/.github/workflows/full-check.yml @@ -23,17 +23,17 @@ jobs: java-version: [ '8', '11', '17' ] steps: - name: Checkout GWT itself into one directory - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: path: 'gwt' - name: Checkout GWT tools into a sibling directory - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: repository: 'gwtproject/tools' path: 'tools' - name: Set up JDK ${{ matrix.java-version }} # GWT presently requires Java8 to build just the SDK and some tests, or 11 to build everything, but can run on newer Java versions - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: ${{ matrix.java-version }} distribution: 'temurin' @@ -57,32 +57,32 @@ jobs: -Dtest.emma.htmlunit.disable=true - name: Report test results - uses: mikepenz/action-junit-report@v3.1.0 + uses: mikepenz/action-junit-report@v4.0.3 if: always() with: report_paths: 'gwt/build/out/**/test/**/reports/TEST-*.xml' - name: Upload checkstyle xml for manual review in its own artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: always() with: name: checkstyle-reports-java${{ matrix.java-version }} path: 'gwt/build/out/**/checkstyle*.xml' - name: Upload test xml files for manual review in its own artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: always() with: name: junit-reports-java${{ matrix.java-version }} path: 'gwt/build/out/**/test/**/reports/TEST-*.xml' - name: On success, upload the release zip - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: gwt-java${{ matrix.java-version }} path: 'gwt/build/dist/gwt-*.zip' - name: Set up sonatype credentials # Using the same java version as above, set up a settings.xml file - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 if: ${{ github.event_name == 'schedule' && github.repository_owner == 'gwtproject' && matrix.java-version == '17' }} with: java-version: ${{ matrix.java-version }} diff --git a/.github/workflows/quick-check.yml b/.github/workflows/quick-check.yml index 75c861c469..6d6eea178d 100644 --- a/.github/workflows/quick-check.yml +++ b/.github/workflows/quick-check.yml @@ -11,19 +11,19 @@ jobs: java-version: ['8', '11', '17'] steps: - name: Checkout GWT itself into one directory - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: path: 'gwt' # we need depth=2 to see which style violations overlap with the current changes fetch-depth: 2 - name: Checkout GWT tools into a sibling directory - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: repository: 'gwtproject/tools' path: 'tools' - name: Set up JDK ${{ matrix.java-version }} # GWT presently requires Java8 to build just the SDK and some tests, or 11+ to build everything, and can run on newer Java versions - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: ${{ matrix.java-version }} distribution: 'temurin' @@ -57,7 +57,7 @@ jobs: reviewdog -f=checkstyle -filter-mode=diff_context -reporter=github-pr-review -level=info < $f done - name: Upload checkstyle xml for manual review - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: ${{ matrix.java-version == '17' }} with: name: checkstyle-reports-java${{ matrix.java-version }} From 709d7fd6071e2c4137137ac5b2921df38a49a07a Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Tue, 9 Jan 2024 21:18:38 -0600 Subject: [PATCH 09/27] Relax naming rules to allow valid java bean properties as jsproperties (#9875) The old implementation only allowed a capital letter as the first character of a bean-like property, which isn't sufficient. Instead, we need to support cases where the first character is *not* lower case, so that non-letters that are valid for the first character are permitted. Fixes #9554 --- .../com/google/gwt/dev/jjs/ast/HasJsInfo.java | 2 +- .../src/com/google/gwt/dev/js/JsUtils.java | 2 +- .../impl/JsInteropRestrictionCheckerTest.java | 86 +++++++++++++++---- 3 files changed, 73 insertions(+), 17 deletions(-) diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/HasJsInfo.java b/dev/core/src/com/google/gwt/dev/jjs/ast/HasJsInfo.java index 23e01968f0..05a6f9e8dd 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/ast/HasJsInfo.java +++ b/dev/core/src/com/google/gwt/dev/jjs/ast/HasJsInfo.java @@ -117,7 +117,7 @@ public String computeName(JMember member) { private static boolean startsWithCamelCase(String string, String prefix) { return string.length() > prefix.length() && string.startsWith(prefix) - && Character.isUpperCase(string.charAt(prefix.length())); + && !Character.isLowerCase(string.charAt(prefix.length())); } } diff --git a/dev/core/src/com/google/gwt/dev/js/JsUtils.java b/dev/core/src/com/google/gwt/dev/js/JsUtils.java index 4e964d24c5..3b6063478b 100644 --- a/dev/core/src/com/google/gwt/dev/js/JsUtils.java +++ b/dev/core/src/com/google/gwt/dev/js/JsUtils.java @@ -480,7 +480,7 @@ public static JsFunction isFunctionDeclaration(JsStatement stmt) { /** * A JavaScript identifier contains only letters, numbers, _, $ and does not begin with a number. * There are actually other valid identifiers, such as ones that contain escaped Unicode - * characters but we disallow those for the time being. + * characters, but we disallow those for the time being. */ public static boolean isValidJsIdentifier(String name) { return JAVASCRIPT_VALID_IDENTIFIER_PATTERN.matcher(name).matches(); diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java index 1eb65dd756..118ed75a72 100644 --- a/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java +++ b/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java @@ -17,7 +17,6 @@ import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.dev.MinimalRebuildCache; -import com.google.gwt.dev.javac.testing.impl.MockJavaResource; import com.google.gwt.dev.jjs.ast.JMethod; import com.google.gwt.dev.jjs.ast.JProgram; @@ -1268,6 +1267,77 @@ public void testJsNameGlobalNamespacesSucceeds() throws Exception { assertBuggySucceeds(); } + public void testJsMethodWithDollarsign() throws Exception { + addSnippetImport("jsinterop.annotations.JsType"); + addSnippetImport("jsinterop.annotations.JsMethod"); + addSnippetImport("jsinterop.annotations.JsProperty"); + addSnippetImport("jsinterop.annotations.JsPackage"); + addSnippetClassDecl( + "@JsType public static class Buggy {", + " public void $() {", + " }", + " public void $method(String l) {", + " }", + " public void method$(String l) {", + " }", + " public void method$name(String l) {", + " }", + "}"); + assertBuggySucceeds(); + } + + public void testJsFieldWithDollarsign() throws Exception { + addSnippetImport("jsinterop.annotations.JsType"); + addSnippetImport("jsinterop.annotations.JsMethod"); + addSnippetImport("jsinterop.annotations.JsProperty"); + addSnippetImport("jsinterop.annotations.JsPackage"); + addSnippetClassDecl( + "@JsType public static class Buggy {", + " public String $;", + " public String $field;", + " public String field$;", + " public String field$name;", + "}"); + assertBuggySucceeds(); + } + + public void testJsPropertyWithDollarsign() throws Exception { + addSnippetImport("jsinterop.annotations.JsType"); + addSnippetImport("jsinterop.annotations.JsProperty"); + addSnippetClassDecl( + "@JsType public static class Buggy {", + " @JsProperty", + " public String get$() {", + " return null;", + " }", + " @JsProperty", + " public void set$(String value) {", + " }", + " @JsProperty", + " public String get$1() {", + " return null;", + " }", + " @JsProperty", + " public void set$1(String value) {", + " }", + " @JsProperty", + " public String getVal$() {", + " return null;", + " }", + " @JsProperty", + " public void setVal$(String value) {", + " }", + " @JsProperty", + " public String getVal$1() {", + " return null;", + " }", + " @JsProperty", + " public void setVal$1(String value) {", + " }", + "}"); + assertBuggySucceeds(); + } + public void testSingleJsTypeSucceeds() throws Exception { addSnippetImport("jsinterop.annotations.JsType"); addSnippetClassDecl( @@ -2555,20 +2625,6 @@ public void testUnusableByJsSyntheticMembersSucceeds() throws Exception { assertBuggySucceeds(); } - private static final MockJavaResource jsFunctionInterface = new MockJavaResource( - "test.MyJsFunctionInterface") { - @Override - public CharSequence getContent() { - StringBuilder code = new StringBuilder(); - code.append("package test;\n"); - code.append("import jsinterop.annotations.JsFunction;\n"); - code.append("@JsFunction public interface MyJsFunctionInterface {\n"); - code.append("int foo(int x);\n"); - code.append("}\n"); - return code; - } - }; - public final void assertBuggySucceeds(String... expectedWarnings) throws Exception { Result result = assertCompileSucceeds("Buggy buggy = null;", expectedWarnings); From e981e97325e0bbf8b16b407143ac297d7f07be01 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 13:20:51 -0600 Subject: [PATCH 10/27] Bump mikepenz/action-junit-report from 4.0.3 to 4.0.4 (#9900) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 4.0.3 to 4.0.4.

Release notes

Sourced from mikepenz/action-junit-report's releases.

v4.0.4

🚀 Features

  • Add input to truncate stack traces in annotations

📦 Dependencies

  • Dependency upgrades 20240112
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=mikepenz/action-junit-report&package-manager=github_actions&previous-version=4.0.3&new-version=4.0.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/full-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/full-check.yml b/.github/workflows/full-check.yml index 5e5110f795..8ceb98ba94 100644 --- a/.github/workflows/full-check.yml +++ b/.github/workflows/full-check.yml @@ -57,7 +57,7 @@ jobs: -Dtest.emma.htmlunit.disable=true - name: Report test results - uses: mikepenz/action-junit-report@v4.0.3 + uses: mikepenz/action-junit-report@v4.0.4 if: always() with: report_paths: 'gwt/build/out/**/test/**/reports/TEST-*.xml' From aa3ded03ebacc79207723721db7b956c355335a8 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Thu, 25 Jan 2024 14:37:31 -0600 Subject: [PATCH 11/27] Update ErrorProne to run on Java 21, drop Java 8 support (#9899) This patch updates to the latest version of ErrorProne, which requires dropping support for Java 8 (as planned). This allows us to remove several "is this Java 8" checks in the build. As the new ErrorProne version required adding new suppressions, all existing project-wide suppressions have been removed and distributed to the methods throughout the project that actually need them. We cannot yet add support for running CI on Java 21, that also requires updating asm - otherwise there are a handful of compiler internals tests that will fail when asm interacts with Java's own bytecode (e.g. java.lang.Object). The javac arg `-XDstringConcat=inline` must be added to gwt-user tests when compiled to release=11, as https://bugs.openjdk.org/browse/JDK-8323657 breaks a regression test for JDT, and the class fails to load for the ExtraCompilerSuite. Fixes #9870 Fixes #9859 --- .github/workflows/full-check.yml | 6 +- .github/workflows/quick-check.yml | 4 +- build.xml | 2 +- build_tools/doctool/build.xml | 2 +- common.ant.xml | 39 +++---- dev/build.xml | 32 +----- .../src/com/google/gwt/core/ext/Linker.java | 1 + .../gwt/core/ext/linker/ArtifactSetTest.java | 2 + .../core/ext/linker/TypeIndexedSetTest.java | 1 + .../com/google/gwt/dev/GwtVersionTest.java | 1 + .../javac/GeneratedClassnameFinderTest.java | 1 + .../javac/typemodel/test/GenericClass.java | 1 + .../collections/AbstractTestObject.java | 1 + .../collection/AbstractTestCollection.java | 1 + doc/build.xml | 4 +- user/build.xml | 108 +++--------------- .../google/gwt/cell/client/CheckboxCell.java | 4 +- .../uibinder/elementparsers/BeanParser.java | 1 + .../view/client/DefaultSelectionModel.java | 1 + .../gwt/dev/jjs/test/AnnotationsTest.java | 1 + .../google/gwt/dev/jjs/test/CompilerTest.java | 8 +- .../google/gwt/dev/jjs/test/CoverageTest.java | 2 +- .../gwt/dev/jjs/test/InnerClassTest.java | 1 + .../gwt/dev/jjs/test/JStaticEvalTest.java | 2 + .../com/google/gwt/dev/jjs/test/JsoTest.java | 1 + .../gwt/dev/jjs/test/MethodCallTest.java | 3 + .../gwt/dev/jjs/test/MiscellaneousTest.java | 3 +- .../gwt/dev/jjs/test/NativeLongTest.java | 1 + .../gwt/dev/js/client/CoverageTest.java | 1 + .../gwt/dev/strict/bad/client/BadSource.java | 1 + .../google/gwt/dom/client/ElementTest.java | 1 + .../emultest/java/lang/JsExceptionTest.java | 1 + .../gwt/emultest/java/lang/StringTest.java | 1 + .../gwt/emultest/java/util/ArraysTest.java | 1 + .../gwt/emultest/java/util/ObjectsTest.java | 2 +- .../emultest/java/util/TestCollection.java | 1 + .../gwt/emultest/java/util/TestObject.java | 1 + .../gwt/emultest/java/util/TreeMapTest.java | 7 ++ .../gwt/emultest/java/util/TreeSetTest.java | 1 + .../gwt/emultest/java8/util/OptionalTest.java | 2 + .../java8/util/stream/DoubleStreamTest.java | 3 + .../java8/util/stream/IntStreamTest.java | 3 + .../java8/util/stream/LongStreamTest.java | 3 + .../java8/util/stream/StreamTest.java | 5 + .../gwt/emultest/java9/util/ListTest.java | 1 + .../gwt/emultest/java9/util/MapTest.java | 4 +- .../gwt/emultest/java9/util/OptionalTest.java | 1 + .../gwt/emultest/java9/util/SetTest.java | 1 + .../gwt/junit/client/GWTTestCaseTest.java | 1 + .../gwt/storage/client/MapInterfaceTest.java | 3 + .../elementparsers/MenuItemParserTest.java | 1 + .../gwt/user/client/rpc/CollectionsTest.java | 2 + .../TypeCheckedObjectsTestSetValidator.java | 2 + 53 files changed, 122 insertions(+), 162 deletions(-) diff --git a/.github/workflows/full-check.yml b/.github/workflows/full-check.yml index 8ceb98ba94..491f5d1457 100644 --- a/.github/workflows/full-check.yml +++ b/.github/workflows/full-check.yml @@ -1,4 +1,4 @@ -# Run all tests and builds all aspects of GWT using Java 8, 11, and 17. Runs +# Run all tests and builds all aspects of GWT using Java 11 and 17. Runs # nightly (plus or minus timzeones) on the main branch, and will also run right # away on a push to a release branch. Release zips are uploaded as part of the # build, though maven snapshots are not yet deployed. @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java-version: [ '8', '11', '17' ] + java-version: [ '11', '17' ] steps: - name: Checkout GWT itself into one directory uses: actions/checkout@v4 @@ -32,7 +32,7 @@ jobs: repository: 'gwtproject/tools' path: 'tools' - name: Set up JDK ${{ matrix.java-version }} - # GWT presently requires Java8 to build just the SDK and some tests, or 11 to build everything, but can run on newer Java versions + # GWT requires Java 11+ to build uses: actions/setup-java@v4 with: java-version: ${{ matrix.java-version }} diff --git a/.github/workflows/quick-check.yml b/.github/workflows/quick-check.yml index 6d6eea178d..6b6fa163e4 100644 --- a/.github/workflows/quick-check.yml +++ b/.github/workflows/quick-check.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java-version: ['8', '11', '17'] + java-version: ['11', '17'] steps: - name: Checkout GWT itself into one directory uses: actions/checkout@v4 @@ -22,7 +22,7 @@ jobs: repository: 'gwtproject/tools' path: 'tools' - name: Set up JDK ${{ matrix.java-version }} - # GWT presently requires Java8 to build just the SDK and some tests, or 11+ to build everything, and can run on newer Java versions + # GWT presently requires Java 11+ to build uses: actions/setup-java@v4 with: java-version: ${{ matrix.java-version }} diff --git a/build.xml b/build.xml index 4ab2c6e8f5..c10eea6f2c 100755 --- a/build.xml +++ b/build.xml @@ -98,7 +98,7 @@ - + diff --git a/build_tools/doctool/build.xml b/build_tools/doctool/build.xml index c4870197b6..a210edd478 100644 --- a/build_tools/doctool/build.xml +++ b/build_tools/doctool/build.xml @@ -11,7 +11,7 @@ - + diff --git a/common.ant.xml b/common.ant.xml index 36a56b4882..6193bd3627 100755 --- a/common.ant.xml +++ b/common.ant.xml @@ -27,12 +27,6 @@ message="This build file is in an inconsistent state (${ant.file} != ${test.ant.file})."/> - - - - @@ -66,11 +60,9 @@ - - - - + + @@ -170,20 +162,19 @@ - - - - - - - - - - - + fork="true" excludes="@{excludes}"> + + + + + + + + + + @@ -249,7 +240,7 @@ - + diff --git a/dev/build.xml b/dev/build.xml index 37ffb3ee57..6821a77e2a 100755 --- a/dev/build.xml +++ b/dev/build.xml @@ -22,15 +22,7 @@ - + @@ -40,13 +32,7 @@ + excludes="**/EmulatedCharset.java,**/HashCodes.java,**/ConsoleLogger.java,**/NativeRegExp.java,**/SuperDevModeLogger.java"> @@ -211,12 +197,7 @@ description="Validates that the standalone gwt-compiler project can build."> - + @@ -259,12 +240,7 @@ - + diff --git a/dev/core/src/com/google/gwt/core/ext/Linker.java b/dev/core/src/com/google/gwt/core/ext/Linker.java index 4b81f59ba1..23e87a678c 100644 --- a/dev/core/src/com/google/gwt/core/ext/Linker.java +++ b/dev/core/src/com/google/gwt/core/ext/Linker.java @@ -62,6 +62,7 @@ public abstract class Linker { * intended to support linkers that must compile against older versions of * GWT. */ + @SuppressWarnings("ReturnValueIgnored") public final boolean isShardable() { if (getClass().isAnnotationPresent(Shardable.class)) { return true; diff --git a/dev/core/test/com/google/gwt/core/ext/linker/ArtifactSetTest.java b/dev/core/test/com/google/gwt/core/ext/linker/ArtifactSetTest.java index b7db647e80..cf09f86702 100644 --- a/dev/core/test/com/google/gwt/core/ext/linker/ArtifactSetTest.java +++ b/dev/core/test/com/google/gwt/core/ext/linker/ArtifactSetTest.java @@ -27,6 +27,7 @@ */ public class ArtifactSetTest extends TestCase { + @SuppressWarnings("SelfComparison") public void testScriptOrder() { StandardScriptReference fooScript = new StandardScriptReference("foo", 0); StandardScriptReference barScript = new StandardScriptReference("bar", 1); @@ -65,6 +66,7 @@ public void testScriptOrder() { } } + @SuppressWarnings("SelfComparison") public void testStyleOrder() { StandardStylesheetReference fooStyle = new StandardStylesheetReference( "foo", 0); diff --git a/dev/core/test/com/google/gwt/core/ext/linker/TypeIndexedSetTest.java b/dev/core/test/com/google/gwt/core/ext/linker/TypeIndexedSetTest.java index 752ef60a15..f8a43a2e58 100644 --- a/dev/core/test/com/google/gwt/core/ext/linker/TypeIndexedSetTest.java +++ b/dev/core/test/com/google/gwt/core/ext/linker/TypeIndexedSetTest.java @@ -52,6 +52,7 @@ public int hashCode() { } @Override + @SuppressWarnings("BoxedPrimitiveEquality") public boolean equals(Object o) { return (o instanceof RootComparable) && (((RootComparable) o).value == this.value); } diff --git a/dev/core/test/com/google/gwt/dev/GwtVersionTest.java b/dev/core/test/com/google/gwt/dev/GwtVersionTest.java index 5cc726f5d8..283cbfd27a 100644 --- a/dev/core/test/com/google/gwt/dev/GwtVersionTest.java +++ b/dev/core/test/com/google/gwt/dev/GwtVersionTest.java @@ -39,6 +39,7 @@ public void testCompareEqualsHashCode() { /** * Test that GwtVersion.compareTo produced expected results. */ + @SuppressWarnings("SelfComparison") public void testCompareTo() { GwtVersion v1 = new GwtVersion("0.0.0"); assertEquals(0, v1.compareTo(v1)); diff --git a/dev/core/test/com/google/gwt/dev/javac/GeneratedClassnameFinderTest.java b/dev/core/test/com/google/gwt/dev/javac/GeneratedClassnameFinderTest.java index 3e15454933..b878acf3ec 100644 --- a/dev/core/test/com/google/gwt/dev/javac/GeneratedClassnameFinderTest.java +++ b/dev/core/test/com/google/gwt/dev/javac/GeneratedClassnameFinderTest.java @@ -260,6 +260,7 @@ private void testArrayStore() { assertEquals(g, a); } + @SuppressWarnings("ReturnValueIgnored") private void testDeadTypes() { if (false) { new Object() { diff --git a/dev/core/test/com/google/gwt/dev/javac/typemodel/test/GenericClass.java b/dev/core/test/com/google/gwt/dev/javac/typemodel/test/GenericClass.java index e7d1a094fb..01ea06c01c 100644 --- a/dev/core/test/com/google/gwt/dev/javac/typemodel/test/GenericClass.java +++ b/dev/core/test/com/google/gwt/dev/javac/typemodel/test/GenericClass.java @@ -28,6 +28,7 @@ * follows: class GenericClass> * implements Comparable { ... } */ +@SuppressWarnings("ComparableType") public class GenericClass implements Comparable, Serializable { /** diff --git a/dev/core/test/org/apache/commons/collections/AbstractTestObject.java b/dev/core/test/org/apache/commons/collections/AbstractTestObject.java index 135c7e0d63..4bc2e948a9 100644 --- a/dev/core/test/org/apache/commons/collections/AbstractTestObject.java +++ b/dev/core/test/org/apache/commons/collections/AbstractTestObject.java @@ -120,6 +120,7 @@ public void testObjectHashCodeEqualsSelfHashCode() { assertEquals("hashCode should be repeatable", obj.hashCode(), obj.hashCode()); } + @SuppressWarnings("SelfEquals") public void testObjectHashCodeEqualsContract() { Object obj1 = makeObject(); if (obj1.equals(obj1)) { diff --git a/dev/core/test/org/apache/commons/collections/collection/AbstractTestCollection.java b/dev/core/test/org/apache/commons/collections/collection/AbstractTestCollection.java index 0de0fe304d..48ddd32b4f 100644 --- a/dev/core/test/org/apache/commons/collections/collection/AbstractTestCollection.java +++ b/dev/core/test/org/apache/commons/collections/collection/AbstractTestCollection.java @@ -805,6 +805,7 @@ public void testCollectionIterator() { /** * Tests removals from {@link Collection#iterator()}. */ + @SuppressWarnings("ReturnValueIgnored") public void testCollectionIteratorRemove() { if (!isRemoveSupported()) return; diff --git a/doc/build.xml b/doc/build.xml index 97c85ef8e4..3d0f89d353 100644 --- a/doc/build.xml +++ b/doc/build.xml @@ -90,7 +90,7 @@ - + @@ -124,7 +124,7 @@ - + diff --git a/user/build.xml b/user/build.xml index d627a8078c..f4c409f73e 100755 --- a/user/build.xml +++ b/user/build.xml @@ -14,27 +14,16 @@ - - - - + + - - - - - - + + - - - + @@ -59,7 +48,6 @@ --> - - - - - + + release="11"> + + - - - - - - - - - - - - diff --git a/user/src/com/google/gwt/cell/client/CheckboxCell.java b/user/src/com/google/gwt/cell/client/CheckboxCell.java index 8e9c46200e..77eda41a44 100644 --- a/user/src/com/google/gwt/cell/client/CheckboxCell.java +++ b/user/src/com/google/gwt/cell/client/CheckboxCell.java @@ -46,6 +46,7 @@ public class CheckboxCell extends AbstractEditableCell { /** * Construct a new {@link CheckboxCell}. */ + @SuppressWarnings("BoxedPrimitiveEquality") public CheckboxCell() { this(false); } @@ -91,7 +92,8 @@ public boolean isEditing(Context context, Element parent, Boolean value) { } @Override - public void onBrowserEvent(Context context, Element parent, Boolean value, + @SuppressWarnings("BoxedPrimitiveEquality") + public void onBrowserEvent(Context context, Element parent, Boolean value, NativeEvent event, ValueUpdater valueUpdater) { String type = event.getType(); diff --git a/user/src/com/google/gwt/uibinder/elementparsers/BeanParser.java b/user/src/com/google/gwt/uibinder/elementparsers/BeanParser.java index 730aa37e5b..47e4f357a7 100644 --- a/user/src/com/google/gwt/uibinder/elementparsers/BeanParser.java +++ b/user/src/com/google/gwt/uibinder/elementparsers/BeanParser.java @@ -46,6 +46,7 @@ public class BeanParser implements ElementParser { * methods that extend the normal bean naming pattern. So, that implementations of * {@link IsWidget} behave like UIObjects, they have to be translated. */ + @SuppressWarnings("DoubleBraceInitialization") private static final Map ADD_PROPERTY_TO_SETTER_MAP = new HashMap() { { put("addStyleNames", "addStyleName"); diff --git a/user/src/com/google/gwt/view/client/DefaultSelectionModel.java b/user/src/com/google/gwt/view/client/DefaultSelectionModel.java index 588d1c71dc..f7ac705102 100644 --- a/user/src/com/google/gwt/view/client/DefaultSelectionModel.java +++ b/user/src/com/google/gwt/view/client/DefaultSelectionModel.java @@ -123,6 +123,7 @@ protected Map getExceptions(Map output) { return output; } + @SuppressWarnings("BoxedPrimitiveEquality") private void resolveChanges() { boolean changed = false; for (Map.Entry> entry : selectionChanges.entrySet()) { diff --git a/user/test/com/google/gwt/dev/jjs/test/AnnotationsTest.java b/user/test/com/google/gwt/dev/jjs/test/AnnotationsTest.java index af856a41ee..97aec8316d 100644 --- a/user/test/com/google/gwt/dev/jjs/test/AnnotationsTest.java +++ b/user/test/com/google/gwt/dev/jjs/test/AnnotationsTest.java @@ -24,6 +24,7 @@ */ public class AnnotationsTest extends GWTTestCase { + @SuppressWarnings("BadAnnotationImplementation") private static class Foo implements IFoo { @Override public Class annotationType() { diff --git a/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java b/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java index ad1f54285e..cad90f3977 100644 --- a/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java +++ b/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java @@ -36,6 +36,7 @@ interface MyMap { interface Silly { } + @SuppressWarnings("ComparableType") interface SillyComparable extends Comparable { @Override int compareTo(T obj); @@ -418,6 +419,7 @@ public int compareTo(AbstractFoo o) { } } + @SuppressWarnings("ComparableType") class MyFoo extends AbstractFoo implements Comparable { } @@ -752,6 +754,7 @@ void blah() { }; } + @SuppressWarnings({"ReturnValueIgnored", "IdentityBinaryExpression"}) public void testDeadTypes() { if (false) { new Object() { @@ -771,7 +774,7 @@ void a() { * Development Mode or Production Mode, but the important thing is that the * compiler does not crash. */ - @SuppressWarnings({"divzero", "ConstantOverflow"}) + @SuppressWarnings({"divzero", "ConstantOverflow", "IdentityBinaryExpression"}) public void testDivByZero() { assertTrue(Double.isNaN(0.0 / 0.0)); @@ -806,6 +809,7 @@ public void testDivByZero() { } } + @SuppressWarnings({"IdentityBinaryExpression", "LoopConditionChecker"}) public void testEmptyBlockStatements() { boolean b = false; while (b) { @@ -864,7 +868,7 @@ public native void testEmptyBlockStatementsNative() /*-{ // CHECKSTYLE_OFF - @SuppressWarnings("empty") + @SuppressWarnings({"empty", "LoopConditionChecker"}) public void testEmptyStatements() { boolean b = false; diff --git a/user/test/com/google/gwt/dev/jjs/test/CoverageTest.java b/user/test/com/google/gwt/dev/jjs/test/CoverageTest.java index 88410ff159..c29439f2c8 100644 --- a/user/test/com/google/gwt/dev/jjs/test/CoverageTest.java +++ b/user/test/com/google/gwt/dev/jjs/test/CoverageTest.java @@ -333,7 +333,7 @@ private void testCaseSwitchStatement() { assertEquals(15, i); } - @SuppressWarnings("cast") + @SuppressWarnings({"cast", "SelfAssignment"}) private void testCastExpression() { // CastExpression o = (Super) o; diff --git a/user/test/com/google/gwt/dev/jjs/test/InnerClassTest.java b/user/test/com/google/gwt/dev/jjs/test/InnerClassTest.java index d011912f34..e0ec236088 100644 --- a/user/test/com/google/gwt/dev/jjs/test/InnerClassTest.java +++ b/user/test/com/google/gwt/dev/jjs/test/InnerClassTest.java @@ -26,6 +26,7 @@ public class InnerClassTest extends GWTTestCase { static class OuterRefFromSuperCtorBase { + @SuppressWarnings("ReturnValueIgnored") OuterRefFromSuperCtorBase(Object o) { o.toString(); } diff --git a/user/test/com/google/gwt/dev/jjs/test/JStaticEvalTest.java b/user/test/com/google/gwt/dev/jjs/test/JStaticEvalTest.java index 97c956a255..86aad803ef 100644 --- a/user/test/com/google/gwt/dev/jjs/test/JStaticEvalTest.java +++ b/user/test/com/google/gwt/dev/jjs/test/JStaticEvalTest.java @@ -77,6 +77,7 @@ public void testConditionalExpressions() { * Test "true == booleanField" and permutations, as well as "true == false" * and permutations. */ + @SuppressWarnings("IdentityBinaryExpression") public void testEqualsBool() { assertTrue(fieldTrue == returnTrue()); assertTrue(returnTrue() == fieldTrue); @@ -127,6 +128,7 @@ public void testFlippedIf() { /** * Tests constant folding. */ + @SuppressWarnings("IdentityBinaryExpression") public void testOpsOnLiterals() { assertEquals(10, returnIntFive() + returnIntFive()); assertEquals(0, returnIntFive() - returnIntFive()); diff --git a/user/test/com/google/gwt/dev/jjs/test/JsoTest.java b/user/test/com/google/gwt/dev/jjs/test/JsoTest.java index e9f3f5f00c..93a6699331 100644 --- a/user/test/com/google/gwt/dev/jjs/test/JsoTest.java +++ b/user/test/com/google/gwt/dev/jjs/test/JsoTest.java @@ -639,6 +639,7 @@ public int hashCode() { assertEquals(stringHashCode, o.hashCode()); } + @SuppressWarnings("JUnitAssertSameCheck") public void testIdentity() { JavaScriptObject jso = makeJSO(); assertSame(jso, jso); diff --git a/user/test/com/google/gwt/dev/jjs/test/MethodCallTest.java b/user/test/com/google/gwt/dev/jjs/test/MethodCallTest.java index bdfed103f5..78c27e3b9a 100644 --- a/user/test/com/google/gwt/dev/jjs/test/MethodCallTest.java +++ b/user/test/com/google/gwt/dev/jjs/test/MethodCallTest.java @@ -27,6 +27,7 @@ private static final class MyException extends RuntimeException { private static Object field; + @SuppressWarnings("ReturnValueIgnored") private static void clobberFieldNoInline() { try { field = null; @@ -102,6 +103,7 @@ private static int manyArgs(int i0, int i1, int i2, int i3, int i4, int i5, * o will have been replaced by a direct reference to * {@link #field}. Both the Java and JS inliners must not inline this. */ + @SuppressWarnings("ReturnValueIgnored") private static void shouldNotInline(Object o) { field = null; o.toString(); @@ -111,6 +113,7 @@ private static void shouldNotInline(Object o) { * Same as {@link #shouldNotInline(Object)}, except the field clobber is done * indirectly in a non-inlinable method. */ + @SuppressWarnings("ReturnValueIgnored") private static void shouldNotInline2(Object o) { clobberFieldNoInline(); o.toString(); diff --git a/user/test/com/google/gwt/dev/jjs/test/MiscellaneousTest.java b/user/test/com/google/gwt/dev/jjs/test/MiscellaneousTest.java index 5835a144b7..e0ea32e2ba 100644 --- a/user/test/com/google/gwt/dev/jjs/test/MiscellaneousTest.java +++ b/user/test/com/google/gwt/dev/jjs/test/MiscellaneousTest.java @@ -58,6 +58,7 @@ public static int sfoo() { private static native void clinitInNative() /*-{ }-*/; + @SuppressWarnings("ReturnValueIgnored") private int foo() { this.toString(); return 3; @@ -216,7 +217,7 @@ public void testAssociativityCond() { assertEquals(100, result); } - @SuppressWarnings("cast") + @SuppressWarnings({"cast", "SelfAssignment"}) public void testCasts() { Object o = FALSE ? (Object) new PolyA() : (Object) new PolyB(); assertTrue(o instanceof I); diff --git a/user/test/com/google/gwt/dev/jjs/test/NativeLongTest.java b/user/test/com/google/gwt/dev/jjs/test/NativeLongTest.java index 9b28f6fc81..9e0a4d36e4 100644 --- a/user/test/com/google/gwt/dev/jjs/test/NativeLongTest.java +++ b/user/test/com/google/gwt/dev/jjs/test/NativeLongTest.java @@ -162,6 +162,7 @@ public void testLogicalOr() { assertEquals(3L, LONG_ONE | LONG_THREE); } + @SuppressWarnings("IdentityBinaryExpression") public void testLogicalXor() { assertTrue((255L ^ LONG_5DEECE66D) != 0); diff --git a/user/test/com/google/gwt/dev/js/client/CoverageTest.java b/user/test/com/google/gwt/dev/js/client/CoverageTest.java index 52f5c15efa..54bb33d84d 100644 --- a/user/test/com/google/gwt/dev/js/client/CoverageTest.java +++ b/user/test/com/google/gwt/dev/js/client/CoverageTest.java @@ -28,6 +28,7 @@ * Tests coverage instrumentation. */ public class CoverageTest extends GWTTestCase { + @SuppressWarnings("DoubleBraceInitialization") private static final Map EXPECTED_COVERAGE = new HashMap() { { put("25", 1.0); put("26", 1.0); diff --git a/user/test/com/google/gwt/dev/strict/bad/client/BadSource.java b/user/test/com/google/gwt/dev/strict/bad/client/BadSource.java index daa2153f59..7c30f12a1a 100644 --- a/user/test/com/google/gwt/dev/strict/bad/client/BadSource.java +++ b/user/test/com/google/gwt/dev/strict/bad/client/BadSource.java @@ -19,6 +19,7 @@ * Used by {@link com.google.gwt.dev.StrictModeTest}. */ public class BadSource { + @SuppressWarnings("DeadThread") public void useThread() { new Thread(); } diff --git a/user/test/com/google/gwt/dom/client/ElementTest.java b/user/test/com/google/gwt/dom/client/ElementTest.java index 0b4fafa40c..717448b7a9 100644 --- a/user/test/com/google/gwt/dom/client/ElementTest.java +++ b/user/test/com/google/gwt/dom/client/ElementTest.java @@ -184,6 +184,7 @@ public void testElementAttribute() { * not return a numeric attribute based on the element property. See issue * 3238. */ + @SuppressWarnings("ReturnValueIgnored") public void testElementAttributeNumeric() { DivElement div = Document.get().createDivElement(); Document.get().getBody().appendChild(div); diff --git a/user/test/com/google/gwt/emultest/java/lang/JsExceptionTest.java b/user/test/com/google/gwt/emultest/java/lang/JsExceptionTest.java index 0daaac207e..6aedfd6ad7 100644 --- a/user/test/com/google/gwt/emultest/java/lang/JsExceptionTest.java +++ b/user/test/com/google/gwt/emultest/java/lang/JsExceptionTest.java @@ -120,6 +120,7 @@ public void testTypeError() { } } + @SuppressWarnings("ReturnValueIgnored") private static void throwTypeError() { Object nullObject = null; nullObject.getClass(); diff --git a/user/test/com/google/gwt/emultest/java/lang/StringTest.java b/user/test/com/google/gwt/emultest/java/lang/StringTest.java index 59fe575011..ab16f3125f 100644 --- a/user/test/com/google/gwt/emultest/java/lang/StringTest.java +++ b/user/test/com/google/gwt/emultest/java/lang/StringTest.java @@ -651,6 +651,7 @@ public void testNull() { } } + @SuppressWarnings("ReturnValueIgnored") public void testRegionMatches() { String test = String.valueOf(new char[] {'a', 'b', 'c', 'd', 'e', 'f'}); assertTrue(test.regionMatches(1, "bcd", 0, 3)); diff --git a/user/test/com/google/gwt/emultest/java/util/ArraysTest.java b/user/test/com/google/gwt/emultest/java/util/ArraysTest.java index bed413c995..b62440314f 100644 --- a/user/test/com/google/gwt/emultest/java/util/ArraysTest.java +++ b/user/test/com/google/gwt/emultest/java/util/ArraysTest.java @@ -67,6 +67,7 @@ public String getModuleName() { * embedded null references works properly (and most importantly doesn't * throw an NPE). */ + @SuppressWarnings("ReturnValueIgnored") public void testArraysHashCodeWithNullElements() { String[] a = new String[] { "foo", null, "bar", "baz" }; Arrays.hashCode(a); diff --git a/user/test/com/google/gwt/emultest/java/util/ObjectsTest.java b/user/test/com/google/gwt/emultest/java/util/ObjectsTest.java index 6ad573a3ae..ad89d1dc65 100644 --- a/user/test/com/google/gwt/emultest/java/util/ObjectsTest.java +++ b/user/test/com/google/gwt/emultest/java/util/ObjectsTest.java @@ -32,7 +32,7 @@ public String getModuleName() { public void testCompare() { Comparator intComparator = new Comparator() { - @SuppressWarnings("NumberEquality") + @SuppressWarnings({"NumberEquality", "BoxedPrimitiveEquality"}) @Override public int compare(Integer a, Integer b) { if (a == b) { diff --git a/user/test/com/google/gwt/emultest/java/util/TestCollection.java b/user/test/com/google/gwt/emultest/java/util/TestCollection.java index 5fbf556a57..611f5d95ea 100644 --- a/user/test/com/google/gwt/emultest/java/util/TestCollection.java +++ b/user/test/com/google/gwt/emultest/java/util/TestCollection.java @@ -598,6 +598,7 @@ public void testCollectionIterator() { } /** Tests removals from {@link Collection#iterator()}. */ + @SuppressWarnings("ReturnValueIgnored") public void testCollectionIteratorRemove() { if (!isRemoveSupported()) { return; diff --git a/user/test/com/google/gwt/emultest/java/util/TestObject.java b/user/test/com/google/gwt/emultest/java/util/TestObject.java index 20d9c42c99..63ce3e42a5 100644 --- a/user/test/com/google/gwt/emultest/java/util/TestObject.java +++ b/user/test/com/google/gwt/emultest/java/util/TestObject.java @@ -57,6 +57,7 @@ public void testObjectHashCodeEqualsSelfHashCode() { assertEquals("hashCode should be repeatable", obj.hashCode(), obj.hashCode()); } + @SuppressWarnings("SelfEquals") public void testObjectHashCodeEqualsContract() { Object obj1 = makeObject(); if (obj1.equals(obj1)) { diff --git a/user/test/com/google/gwt/emultest/java/util/TreeMapTest.java b/user/test/com/google/gwt/emultest/java/util/TreeMapTest.java index df8b397403..aec828107a 100644 --- a/user/test/com/google/gwt/emultest/java/util/TreeMapTest.java +++ b/user/test/com/google/gwt/emultest/java/util/TreeMapTest.java @@ -41,6 +41,7 @@ */ abstract class TreeMapTest, V> extends TestMap { + @SuppressWarnings("ComparableType") private static class ConflictingKey implements Comparable { private final String value; @@ -488,6 +489,7 @@ public void testContainsKey_ComparableKey() { * * @see java.util.Map#containsKey(Object) */ + @SuppressWarnings("ReturnValueIgnored") public void testContainsKey_throwsClassCastException() { K[] keys = getKeys(); V[] values = getValues(); @@ -549,6 +551,7 @@ public void testContainsValue() { * * @see java.util.Map#containsValue(Object) */ + @SuppressWarnings("ReturnValueIgnored") public void testContainsValue_throwsClassCastException() { K[] keys = getKeys(); V[] values = getValues(); @@ -759,6 +762,7 @@ public V setValue(V value) { } } + @SuppressWarnings("ReturnValueIgnored") public void testEntrySet() { K[] keys = getSortedKeys(); V[] values = getSortedValues(); @@ -2155,6 +2159,7 @@ public void testPut_entries3() { * * @see java.util.Map#put(Object, Object) */ + @SuppressWarnings("ReturnValueIgnored") public void testPut_nullKey() { K[] keys = getSortedKeys(); V[] values = getSortedValues(); @@ -2874,6 +2879,7 @@ public void testSubMap_empty() { assertTrue(subMap.values().isEmpty()); } + @SuppressWarnings("ReturnValueIgnored") public void testSubMap_entrySet() { K[] keys = getSortedKeys(); V[] values = getSortedValues(); @@ -3311,6 +3317,7 @@ public void testToString() { * * @see java.util.Map#values() */ + @SuppressWarnings("ReturnValueIgnored") public void testValues() { K[] keys = getSortedKeys(); V[] values = getSortedValues(); diff --git a/user/test/com/google/gwt/emultest/java/util/TreeSetTest.java b/user/test/com/google/gwt/emultest/java/util/TreeSetTest.java index 4b5ab8cd03..e2f939a5b8 100644 --- a/user/test/com/google/gwt/emultest/java/util/TreeSetTest.java +++ b/user/test/com/google/gwt/emultest/java/util/TreeSetTest.java @@ -588,6 +588,7 @@ public void testContains() { * * @see java.util.Set#contains(Object) */ + @SuppressWarnings("ReturnValueIgnored") public void testContains_throwsClassCastException() { Set set = createSet(); set.add(getKeys()[0]); diff --git a/user/test/com/google/gwt/emultest/java8/util/OptionalTest.java b/user/test/com/google/gwt/emultest/java8/util/OptionalTest.java index 67907033ed..551a51d9bf 100644 --- a/user/test/com/google/gwt/emultest/java8/util/OptionalTest.java +++ b/user/test/com/google/gwt/emultest/java8/util/OptionalTest.java @@ -139,6 +139,7 @@ public void testFilter() { assertFalse(filtered.isPresent()); } + @SuppressWarnings("ReturnValueIgnored") public void testMap() { // empty case try { @@ -167,6 +168,7 @@ public void testMap() { assertEquals(REFERENCE.toString(), mapped.get()); } + @SuppressWarnings("ReturnValueIgnored") public void testFlatMap() { // empty case try { diff --git a/user/test/com/google/gwt/emultest/java8/util/stream/DoubleStreamTest.java b/user/test/com/google/gwt/emultest/java8/util/stream/DoubleStreamTest.java index 1cc6fbce97..10619532ea 100644 --- a/user/test/com/google/gwt/emultest/java8/util/stream/DoubleStreamTest.java +++ b/user/test/com/google/gwt/emultest/java8/util/stream/DoubleStreamTest.java @@ -181,6 +181,7 @@ public void testReduce() { assertFalse(maybe.isPresent()); } + @SuppressWarnings("ReturnValueIgnored") public void testFilter() { // unconsumed stream never runs filter boolean[] data = {false}; @@ -210,6 +211,7 @@ public void testFilter() { DoubleStream.of(1d, 2d, 3d, 4d, 3d).filter(a -> true).toArray()); } + @SuppressWarnings("ReturnValueIgnored") public void testMap() { // unconsumed stream never runs map int[] data = {0}; @@ -219,6 +221,7 @@ public void testMap() { assertEquals(new double[] {2d, 4d, 6d}, DoubleStream.of(1d, 2d, 3d).map(i -> i * 2).toArray()); } + @SuppressWarnings("ReturnValueIgnored") public void testPeek() { // unconsumed stream never peeks boolean[] data = {false}; diff --git a/user/test/com/google/gwt/emultest/java8/util/stream/IntStreamTest.java b/user/test/com/google/gwt/emultest/java8/util/stream/IntStreamTest.java index d9b4ebb830..9a5e19bb74 100644 --- a/user/test/com/google/gwt/emultest/java8/util/stream/IntStreamTest.java +++ b/user/test/com/google/gwt/emultest/java8/util/stream/IntStreamTest.java @@ -194,6 +194,7 @@ public void testReduce() { assertFalse(maybe.isPresent()); } + @SuppressWarnings("ReturnValueIgnored") public void testFilter() { // unconsumed stream never runs filter boolean[] data = {false}; @@ -219,6 +220,7 @@ public void testFilter() { new int[] {1, 2, 3, 4, 3}, IntStream.of(1, 2, 3, 4, 3).filter(a -> true).toArray()); } + @SuppressWarnings("ReturnValueIgnored") public void testMap() { // unconsumed stream never runs map int[] data = {0}; @@ -228,6 +230,7 @@ public void testMap() { assertEquals(new int[] {2, 4, 6}, IntStream.of(1, 2, 3).map(i -> i * 2).toArray()); } + @SuppressWarnings("ReturnValueIgnored") public void testPeek() { // unconsumed stream never peeks boolean[] data = {false}; diff --git a/user/test/com/google/gwt/emultest/java8/util/stream/LongStreamTest.java b/user/test/com/google/gwt/emultest/java8/util/stream/LongStreamTest.java index 6297afdf71..3720165cac 100644 --- a/user/test/com/google/gwt/emultest/java8/util/stream/LongStreamTest.java +++ b/user/test/com/google/gwt/emultest/java8/util/stream/LongStreamTest.java @@ -193,6 +193,7 @@ public void testReduce() { assertFalse(maybe.isPresent()); } + @SuppressWarnings("ReturnValueIgnored") public void testFilter() { // unconsumed stream never runs filter boolean[] data = {false}; @@ -220,6 +221,7 @@ public void testFilter() { LongStream.of(1L, 2L, 3L, 4L, 3L).filter(a -> true).toArray()); } + @SuppressWarnings("ReturnValueIgnored") public void testMap() { // unconsumed stream never runs map int[] data = {0}; @@ -229,6 +231,7 @@ public void testMap() { assertEquals(new long[] {2L, 4L, 6L}, LongStream.of(1L, 2L, 3L).map(i -> i * 2).toArray()); } + @SuppressWarnings("ReturnValueIgnored") public void testPeek() { // unconsumed stream never peeks boolean[] data = {false}; diff --git a/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java b/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java index f1aea123f0..9e3926413d 100644 --- a/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java +++ b/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java @@ -243,6 +243,7 @@ public void testCollect() { assertEquals(asList(values), collectedList); } + @SuppressWarnings("ReturnValueIgnored") public void testFilter() { // unconsumed stream never runs filter boolean[] data = {false}; @@ -277,6 +278,7 @@ public void testFilter() { Stream.of("a", "b", "c", "d", "c").filter(a -> true).collect(Collectors.toList())); } + @SuppressWarnings("ReturnValueIgnored") public void testMap() { // unconsumed stream never runs map boolean[] data = {false}; @@ -288,6 +290,7 @@ public void testMap() { Stream.of(1, 2, 3).map(i -> "#" + i).collect(Collectors.toList())); } + @SuppressWarnings("ReturnValueIgnored") public void testPeek() { // unconsumed stream never peeks boolean[] data = {false}; @@ -471,6 +474,7 @@ public void testCountLimitSkip() { // This frustrating test was written first on the JVM stream to discover the basic behavior before // trying to implement it in GWT. As far as I can tell, none of this is clearly described in // javadoc. Also note that it is *not* required to use the returned stream from calling onClose + @SuppressWarnings("ReturnValueIgnored") public void testCloseQuirks() { // all subclasses use the same close()/onClose(...) impl, just test once with Stream.empty() @@ -562,6 +566,7 @@ public void testClose() { assertEquals(1, calledCount[0]); } + @SuppressWarnings("ReturnValueIgnored") public void testCloseException() { // Try a single exception, confirm we catch it Stream s = Stream.of(1, 2, 3); diff --git a/user/test/com/google/gwt/emultest/java9/util/ListTest.java b/user/test/com/google/gwt/emultest/java9/util/ListTest.java index d1487a477f..a60237dd9b 100644 --- a/user/test/com/google/gwt/emultest/java9/util/ListTest.java +++ b/user/test/com/google/gwt/emultest/java9/util/ListTest.java @@ -25,6 +25,7 @@ */ public class ListTest extends EmulTestBase { + @SuppressWarnings("ReturnValueIgnored") public void testOf() { assertIsImmutableListOf(List.of()); assertIsImmutableListOf(List.of("a"), "a"); diff --git a/user/test/com/google/gwt/emultest/java9/util/MapTest.java b/user/test/com/google/gwt/emultest/java9/util/MapTest.java index 9d1356f9ca..69913223db 100644 --- a/user/test/com/google/gwt/emultest/java9/util/MapTest.java +++ b/user/test/com/google/gwt/emultest/java9/util/MapTest.java @@ -24,6 +24,7 @@ */ public class MapTest extends EmulTestBase { + @SuppressWarnings("ReturnValueIgnored") public void testOf() { assertIsImmutableMapOf(Map.of()); assertIsImmutableMapOf(Map.of("a", 1), "a"); @@ -151,6 +152,7 @@ protected static void assertIsImmutableMapOf(Map map, String... } } + @SuppressWarnings("ReturnValueIgnored") public void testEntry() { Map.Entry entry = Map.entry("a", "b"); @@ -172,7 +174,7 @@ public void testEntry() { }); } - @SuppressWarnings("DuplicateMapKeys") + @SuppressWarnings({"DuplicateMapKeys", "ReturnValueIgnored"}) public void testOfEntries() { Map map = Map.ofEntries( Map.entry("a", 1), diff --git a/user/test/com/google/gwt/emultest/java9/util/OptionalTest.java b/user/test/com/google/gwt/emultest/java9/util/OptionalTest.java index e7befa7724..50252d0a02 100644 --- a/user/test/com/google/gwt/emultest/java9/util/OptionalTest.java +++ b/user/test/com/google/gwt/emultest/java9/util/OptionalTest.java @@ -40,6 +40,7 @@ public void testIfPresentOrElse() { assertEquals(1, called[0]); } + @SuppressWarnings("ReturnValueIgnored") public void testOr() { Optional or = Optional.of("value").or(() -> Optional.of("replacement")); assertTrue(or.isPresent()); diff --git a/user/test/com/google/gwt/emultest/java9/util/SetTest.java b/user/test/com/google/gwt/emultest/java9/util/SetTest.java index 88b1b1bad5..0a24cbbb20 100644 --- a/user/test/com/google/gwt/emultest/java9/util/SetTest.java +++ b/user/test/com/google/gwt/emultest/java9/util/SetTest.java @@ -26,6 +26,7 @@ */ public class SetTest extends EmulTestBase { + @SuppressWarnings("ReturnValueIgnored") public void testOf() { assertIsImmutableSetOf(Set.of()); assertIsImmutableSetOf(Set.of("a"), "a"); diff --git a/user/test/com/google/gwt/junit/client/GWTTestCaseTest.java b/user/test/com/google/gwt/junit/client/GWTTestCaseTest.java index ff89b0e4f9..4468137967 100644 --- a/user/test/com/google/gwt/junit/client/GWTTestCaseTest.java +++ b/user/test/com/google/gwt/junit/client/GWTTestCaseTest.java @@ -243,6 +243,7 @@ public void testAssertNullFailWithMessage() { assertNull("msg", "Hello"); } + @SuppressWarnings("JUnitAssertSameCheck") public void testAssertSame() { assertSame(obj1, obj1); assertSame("msg", obj1, obj1); diff --git a/user/test/com/google/gwt/storage/client/MapInterfaceTest.java b/user/test/com/google/gwt/storage/client/MapInterfaceTest.java index eae46222cb..bb866bb92a 100644 --- a/user/test/com/google/gwt/storage/client/MapInterfaceTest.java +++ b/user/test/com/google/gwt/storage/client/MapInterfaceTest.java @@ -133,6 +133,7 @@ protected Map makeEitherMap() { } } + @SuppressWarnings("ReturnValueIgnored") protected final boolean supportsValuesHashCode(Map map) { // get the first non-null value Collection values = map.values(); @@ -274,6 +275,7 @@ public void testClear() { assertInvariants(map); } + @SuppressWarnings("ReturnValueIgnored") public void testContainsKey() { final Map map; final K unmappedKey; @@ -297,6 +299,7 @@ public void testContainsKey() { assertInvariants(map); } + @SuppressWarnings("ReturnValueIgnored") public void testContainsValue() { final Map map; final V unmappedValue; diff --git a/user/test/com/google/gwt/uibinder/elementparsers/MenuItemParserTest.java b/user/test/com/google/gwt/uibinder/elementparsers/MenuItemParserTest.java index f0e9b2e9dc..468be439d4 100644 --- a/user/test/com/google/gwt/uibinder/elementparsers/MenuItemParserTest.java +++ b/user/test/com/google/gwt/uibinder/elementparsers/MenuItemParserTest.java @@ -172,6 +172,7 @@ private void assertStatements(String... expected) { * Containers method to reference types referenced only from JavaDoc, used to * prevent CheckStyle errors. */ + @SuppressWarnings("ReturnValueIgnored") public void unusedReferences(XMLElement p1, MenuBar p2) { p1.hashCode(); p2.hashCode(); diff --git a/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java b/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java index 92aa9d2203..ff8fc27fee 100644 --- a/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java +++ b/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java @@ -559,6 +559,7 @@ public void onFailure(Throwable caught) { } @Override + @SuppressWarnings("CollectionIncompatibleType") public void onSuccess( LinkedHashMap result) { assertNotNull(result); @@ -586,6 +587,7 @@ public void onFailure(Throwable caught) { } @Override + @SuppressWarnings("CollectionIncompatibleType") public void onSuccess( LinkedHashMap actual) { assertNotNull(actual); diff --git a/user/test/com/google/gwt/user/client/rpc/TypeCheckedObjectsTestSetValidator.java b/user/test/com/google/gwt/user/client/rpc/TypeCheckedObjectsTestSetValidator.java index 64cde649bd..046be6fc9f 100644 --- a/user/test/com/google/gwt/user/client/rpc/TypeCheckedObjectsTestSetValidator.java +++ b/user/test/com/google/gwt/user/client/rpc/TypeCheckedObjectsTestSetValidator.java @@ -28,11 +28,13 @@ public class TypeCheckedObjectsTestSetValidator { public static final Integer markerKey = 12345; public static final String markerValue = "Marker"; + @SuppressWarnings("DoubleBraceInitialization") public static final HashSet invalidMarkerKey = new HashSet() { { add(12345); } }; + @SuppressWarnings("DoubleBraceInitialization") public static final HashSet invalidMarkerValue = new HashSet() { { add("Marker"); From f05b257fb480707aac412b227907a0383c913e70 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Mon, 29 Jan 2024 10:21:00 -0600 Subject: [PATCH 12/27] Add Java 10 Collections APIs (#9904) Java 10 added copyOf static factory methods to produce immutable List/Set/Map instances that contain no nulls. Follow-up #9547 --- .../com/google/gwt/emul/java/util/List.java | 6 ++ .../com/google/gwt/emul/java/util/Map.java | 7 ++ .../com/google/gwt/emul/java/util/Set.java | 7 ++ .../google/gwt/emultest/EmulJava10Suite.java | 6 ++ .../gwt/emultest/java10/util/ListTest.java | 57 +++++++++++++++++ .../gwt/emultest/java10/util/MapTest.java | 64 +++++++++++++++++++ .../gwt/emultest/java10/util/SetTest.java | 60 +++++++++++++++++ .../gwt/emultest/java9/util/ListTest.java | 2 +- .../gwt/emultest/java9/util/MapTest.java | 2 +- .../gwt/emultest/java9/util/SetTest.java | 2 +- 10 files changed, 210 insertions(+), 3 deletions(-) create mode 100644 user/test/com/google/gwt/emultest/java10/util/ListTest.java create mode 100644 user/test/com/google/gwt/emultest/java10/util/MapTest.java create mode 100644 user/test/com/google/gwt/emultest/java10/util/SetTest.java diff --git a/user/super/com/google/gwt/emul/java/util/List.java b/user/super/com/google/gwt/emul/java/util/List.java index d1d20110b8..6cb9dd1dd3 100644 --- a/user/super/com/google/gwt/emul/java/util/List.java +++ b/user/super/com/google/gwt/emul/java/util/List.java @@ -19,6 +19,7 @@ import java.util.function.UnaryOperator; import javaemul.internal.ArrayHelper; +import java.util.stream.Collectors; import jsinterop.annotations.JsIgnore; import jsinterop.annotations.JsMethod; @@ -164,4 +165,9 @@ default Spliterator spliterator() { } @JsNonNull List subList(int fromIndex, int toIndex); + + static List copyOf(Collection coll) { + // TODO if the given collection is immutable and has no nulls, return it + return coll.stream().collect(Collectors.toUnmodifiableList()); + } } 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 fd3178b041..8afd7d51bb 100644 --- a/user/super/com/google/gwt/emul/java/util/Map.java +++ b/user/super/com/google/gwt/emul/java/util/Map.java @@ -22,6 +22,7 @@ import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Function; +import java.util.stream.Collectors; import jsinterop.annotations.JsIgnore; import jsinterop.annotations.JsNonNull; @@ -412,4 +413,10 @@ default void replaceAll(BiFunction function) int size(); @JsNonNull Collection values(); + + static Map copyOf(Map map) { + // TODO if the given map is immutable and has no nulls, return it + return map.entrySet().stream().collect(Collectors.toUnmodifiableMap(Entry::getKey, + Entry::getValue)); + } } diff --git a/user/super/com/google/gwt/emul/java/util/Set.java b/user/super/com/google/gwt/emul/java/util/Set.java index eddd4dffe9..498a14af87 100644 --- a/user/super/com/google/gwt/emul/java/util/Set.java +++ b/user/super/com/google/gwt/emul/java/util/Set.java @@ -18,6 +18,8 @@ import static javaemul.internal.InternalPreconditions.checkArgument; import static javaemul.internal.InternalPreconditions.checkNotNull; +import java.util.stream.Collectors; + import jsinterop.annotations.JsIgnore; import jsinterop.annotations.JsType; @@ -98,4 +100,9 @@ static Set of(E... elements) { default Spliterator spliterator() { return Spliterators.spliterator(this, Spliterator.DISTINCT); } + + static Set copyOf(Collection coll) { + // TODO if the given collection is immutable and has no nulls, return it + return coll.stream().collect(Collectors.toUnmodifiableSet()); + } } diff --git a/user/test/com/google/gwt/emultest/EmulJava10Suite.java b/user/test/com/google/gwt/emultest/EmulJava10Suite.java index 2cd6369bb8..5a4f28e052 100644 --- a/user/test/com/google/gwt/emultest/EmulJava10Suite.java +++ b/user/test/com/google/gwt/emultest/EmulJava10Suite.java @@ -19,6 +19,9 @@ import com.google.gwt.emultest.java10.util.OptionalIntTest; import com.google.gwt.emultest.java10.util.OptionalLongTest; import com.google.gwt.emultest.java10.util.OptionalTest; +import com.google.gwt.emultest.java10.util.ListTest; +import com.google.gwt.emultest.java10.util.MapTest; +import com.google.gwt.emultest.java10.util.SetTest; import com.google.gwt.emultest.java10.util.stream.CollectorsTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; @@ -28,10 +31,13 @@ @RunWith(Suite.class) @SuiteClasses({ CollectorsTest.class, + ListTest.class, + MapTest.class, OptionalDoubleTest.class, OptionalIntTest.class, OptionalLongTest.class, OptionalTest.class, + SetTest.class, }) public class EmulJava10Suite { } diff --git a/user/test/com/google/gwt/emultest/java10/util/ListTest.java b/user/test/com/google/gwt/emultest/java10/util/ListTest.java new file mode 100644 index 0000000000..4fcb3f5ecd --- /dev/null +++ b/user/test/com/google/gwt/emultest/java10/util/ListTest.java @@ -0,0 +1,57 @@ +/* + * 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.java10.util; + +import static com.google.gwt.emultest.java9.util.ListTest.assertIsImmutableListOf; + +import com.google.gwt.emultest.java.util.EmulTestBase; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Tests for java.util.List Java 10 API emulation. + */ +public class ListTest extends EmulTestBase { + public void testCopyOf() { + assertIsImmutableListOf(List.copyOf(List.of("a", "b")), "a", "b"); + assertIsImmutableListOf(List.copyOf(Arrays.asList("a", "b")), "a", "b"); + + ArrayList arrayList = new ArrayList<>(); + arrayList.add("a"); + arrayList.add("b"); + List copy = List.copyOf(arrayList); + assertIsImmutableListOf(copy, "a", "b"); + + // verify that mutating the original doesn't affect the copy + arrayList.add("c"); + assertEquals(2, copy.size()); + assertFalse(copy.contains("c")); + + arrayList.remove(0); + assertEquals(2, copy.size()); + assertTrue(copy.contains("a")); + + // ensure that null values in the collection result in a NPE + try { + List.copyOf(Arrays.asList("a", null)); + fail("Expected NullPointerException passing copy a collection with a null value"); + } catch (NullPointerException ignore) { + // expected + } + } +} diff --git a/user/test/com/google/gwt/emultest/java10/util/MapTest.java b/user/test/com/google/gwt/emultest/java10/util/MapTest.java new file mode 100644 index 0000000000..0d09a2d7bc --- /dev/null +++ b/user/test/com/google/gwt/emultest/java10/util/MapTest.java @@ -0,0 +1,64 @@ +/* + * 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.java10.util; + +import static com.google.gwt.emultest.java9.util.MapTest.assertIsImmutableMapOf; + +import com.google.gwt.emultest.java.util.EmulTestBase; + +import java.util.HashMap; +import java.util.Map; + +/** + * Tests for java.util.Map Java 10 API emulation. + */ +public class MapTest extends EmulTestBase { + public void testCopyOf() { + assertIsImmutableMapOf(Map.copyOf(Map.of("a", 1)), "a"); + + HashMap hashMap = new HashMap<>(); + hashMap.put("a", 1); + Map copy = Map.copyOf(hashMap); + assertIsImmutableMapOf(copy, "a"); + + // verify that mutating the original has no effect on the copy + hashMap.put("b", 2); + assertFalse(copy.containsKey("b")); + assertEquals(1, copy.size()); + + hashMap.put("a", 5); + assertEquals(1, (int) copy.get("a")); + + // ensure that null values result in a NPE + HashMap mapWithNullKey = new HashMap<>(); + mapWithNullKey.put(null, 1); + try { + Map.copyOf(mapWithNullKey); + fail("expected NullPointerException from copyOf with a null key"); + } catch (NullPointerException ignored) { + // expected + } + + HashMap mapWithNullValue = new HashMap<>(); + mapWithNullValue.put("key", null); + try { + Map.copyOf(mapWithNullValue); + fail("expected NullPointerException from copyOf with a null value"); + } catch (NullPointerException ignored) { + // expected + } + } +} diff --git a/user/test/com/google/gwt/emultest/java10/util/SetTest.java b/user/test/com/google/gwt/emultest/java10/util/SetTest.java new file mode 100644 index 0000000000..17e37618b1 --- /dev/null +++ b/user/test/com/google/gwt/emultest/java10/util/SetTest.java @@ -0,0 +1,60 @@ +/* + * 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.java10.util; + +import static com.google.gwt.emultest.java9.util.SetTest.assertIsImmutableSetOf; + +import com.google.gwt.emultest.java.util.EmulTestBase; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * Tests for java.util.Set Java 10 API emulation. + */ +public class SetTest extends EmulTestBase { + public void testCopyOf() { + assertIsImmutableSetOf(Set.copyOf(Set.of("a", "b")), "a", "b"); + assertIsImmutableSetOf(Set.copyOf(Arrays.asList("a", "b")), "a", "b"); + + HashSet hashSet = new HashSet<>(); + hashSet.add("a"); + hashSet.add("b"); + Set copy = Set.copyOf(hashSet); + assertIsImmutableSetOf(copy, "a", "b"); + + // verify that mutating the original has no effect on the copy + hashSet.add("c"); + assertEquals(2, copy.size()); + assertFalse(copy.contains("c")); + + hashSet.remove("a"); + assertEquals(2, copy.size()); + assertTrue(copy.contains("a")); + + // ensure that null value result in a NPE + try { + Set.copyOf(Arrays.asList("a", null)); + fail("Expected NullPointerException from null item in collection passed to copyOf"); + } catch (NullPointerException ignored) { + // expected + } + + // ensure that duplicate values result in smaller output + assertIsImmutableSetOf(Set.copyOf(Arrays.asList("a", "a")), "a"); + } +} diff --git a/user/test/com/google/gwt/emultest/java9/util/ListTest.java b/user/test/com/google/gwt/emultest/java9/util/ListTest.java index a60237dd9b..07afcb8db2 100644 --- a/user/test/com/google/gwt/emultest/java9/util/ListTest.java +++ b/user/test/com/google/gwt/emultest/java9/util/ListTest.java @@ -84,7 +84,7 @@ public void testOf() { assertNPE("of", () -> List.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", null)); } - protected static void assertIsImmutableListOf(List list, String... contents) { + public static void assertIsImmutableListOf(List list, String... contents) { assertEquals(contents, list); // quick test that the list impl is sane diff --git a/user/test/com/google/gwt/emultest/java9/util/MapTest.java b/user/test/com/google/gwt/emultest/java9/util/MapTest.java index 69913223db..50127d4366 100644 --- a/user/test/com/google/gwt/emultest/java9/util/MapTest.java +++ b/user/test/com/google/gwt/emultest/java9/util/MapTest.java @@ -110,7 +110,7 @@ public void testOf() { "h", 8, "i", 9, "a", 10)); } - protected static void assertIsImmutableMapOf(Map map, String... contents) { + public static void assertIsImmutableMapOf(Map map, String... contents) { assertEquals(contents.length, map.size()); for (int i = 0; i < contents.length; i++) { assertTrue(map.containsKey(contents[i])); diff --git a/user/test/com/google/gwt/emultest/java9/util/SetTest.java b/user/test/com/google/gwt/emultest/java9/util/SetTest.java index 0a24cbbb20..49f1674a81 100644 --- a/user/test/com/google/gwt/emultest/java9/util/SetTest.java +++ b/user/test/com/google/gwt/emultest/java9/util/SetTest.java @@ -97,7 +97,7 @@ public void testOf() { assertIAE("Set.of(...)", () -> Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "a")); } - protected static void assertIsImmutableSetOf(Set set, String... contents) { + public static void assertIsImmutableSetOf(Set set, String... contents) { assertEquals(contents.length, set.size()); for (int i = 0; i < contents.length; i++) { assertTrue(set.contains(contents[i])); From 5d1078a8753d251df988fb858e4e90d560939b18 Mon Sep 17 00:00:00 2001 From: "Ahmad K. Bawaneh" Date: Wed, 31 Jan 2024 18:21:55 +0300 Subject: [PATCH 13/27] ProxyAutoBean should be able to handle List in Java 21 (#9905) Fix request factory tests fails with errors under java 21 due to added apis to the List class `getLast`, `getFirst`, `isEmpty` which are causing ProxyAutoBean treats the list as a traversable object. Fix #9902 --- .../autobean/vm/impl/ProxyAutoBean.java | 56 ++++++++++--------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/user/src/com/google/web/bindery/autobean/vm/impl/ProxyAutoBean.java b/user/src/com/google/web/bindery/autobean/vm/impl/ProxyAutoBean.java index fd9816e931..620b796ee0 100644 --- a/user/src/com/google/web/bindery/autobean/vm/impl/ProxyAutoBean.java +++ b/user/src/com/google/web/bindery/autobean/vm/impl/ProxyAutoBean.java @@ -112,34 +112,38 @@ private static Map calculateData(Class beanType) { if (toReturn == null) { Map getters = new HashMap(); List setters = new ArrayList(); - for (Method method : beanType.getMethods()) { - if (BeanMethod.GET.matches(method)) { - // match methods on their name for now, to find the most specific - // override - String name = method.getName(); - - Type genericReturnType = TypeUtils.resolveGenerics(beanType, method.getGenericReturnType()); - Class returnType = TypeUtils.ensureBaseType(genericReturnType); - - Data data = getters.get(name); - if (data == null || data.type.isAssignableFrom(returnType)) { - // no getter seen yet for the property, or a less specific one - PropertyType propertyType; - if (TypeUtils.isValueType(returnType)) { - propertyType = PropertyType.VALUE; - } else if (Collection.class.isAssignableFrom(returnType)) { - propertyType = PropertyType.COLLECTION; - } else if (Map.class.isAssignableFrom(returnType)) { - propertyType = PropertyType.MAP; - } else { - propertyType = PropertyType.REFERENCE; + if (!(Collection.class.isAssignableFrom(beanType) + || Map.class.isAssignableFrom(beanType))) { + for (Method method : beanType.getMethods()) { + if (BeanMethod.GET.matches(method)) { + // match methods on their name for now, to find the most specific + // override + String name = method.getName(); + + Type genericReturnType = TypeUtils.resolveGenerics(beanType, + method.getGenericReturnType()); + Class returnType = TypeUtils.ensureBaseType(genericReturnType); + + Data data = getters.get(name); + if (data == null || data.type.isAssignableFrom(returnType)) { + // no getter seen yet for the property, or a less specific one + PropertyType propertyType; + if (TypeUtils.isValueType(returnType)) { + propertyType = PropertyType.VALUE; + } else if (Collection.class.isAssignableFrom(returnType)) { + propertyType = PropertyType.COLLECTION; + } else if (Map.class.isAssignableFrom(returnType)) { + propertyType = PropertyType.MAP; + } else { + propertyType = PropertyType.REFERENCE; + } + data = new Data(method, genericReturnType, returnType, propertyType); + + getters.put(name, data); } - data = new Data(method, genericReturnType, returnType, propertyType); - - getters.put(name, data); + } else if (BeanMethod.SET.matches(method) || BeanMethod.SET_BUILDER.matches(method)) { + setters.add(method); } - } else if (BeanMethod.SET.matches(method) || BeanMethod.SET_BUILDER.matches(method)) { - setters.add(method); } } From 9d247312a88cae98e2995d0e60690b992f8d0a12 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Sun, 4 Feb 2024 20:33:21 -0600 Subject: [PATCH 14/27] GWT-RPC's type signature for java.lang.Enum should be consistent (#9914) In Java 21 a new field was added to Enum, making it incompatible with gwt-rpc clients (and older servers). This patch hardcodes the expected fields for java.lang.Enum so that changes of this nature cannot change the type signature. Fixes #9912 --- .../user/server/rpc/impl/SerializabilityUtil.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/user/src/com/google/gwt/user/server/rpc/impl/SerializabilityUtil.java b/user/src/com/google/gwt/user/server/rpc/impl/SerializabilityUtil.java index febcb1a863..be87067105 100644 --- a/user/src/com/google/gwt/user/server/rpc/impl/SerializabilityUtil.java +++ b/user/src/com/google/gwt/user/server/rpc/impl/SerializabilityUtil.java @@ -915,6 +915,19 @@ private static void generateSerializationSignature(Class instanceType, CRC32 for (Enum constant : constants) { crc.update(constant.name().getBytes(StandardCharsets.UTF_8)); } + } else if (Enum.class.equals(instanceType)) { + // Edge case around Java 21 where a new non-final field was added to Enum. While the Enum + // class is rarely serialized itself (see the block above to deal with enum types), it can + // happen - this code ensures that the server always treats the Enum type the same way, + // regardless of JRE changes. + // See https://github.com/gwtproject/gwt/issues/9912 + if (policy.shouldSerializeFinalFields()) { + crc.update("name".getBytes(StandardCharsets.UTF_8)); + crc.update(getSerializedTypeName(String.class).getBytes(StandardCharsets.UTF_8)); + crc.update("ordinal".getBytes(StandardCharsets.UTF_8)); + crc.update(getSerializedTypeName(int.class).getBytes(StandardCharsets.UTF_8)); + } + generateSerializationSignature(Object.class, crc, policy); } else if (!instanceType.isPrimitive()) { Field[] fields = applyFieldSerializationPolicy(instanceType, policy); Set clientFieldNames = policy.getClientFieldNamesForEnhancedClass(instanceType); From 89c3aaf68588cad317432b3a77f6b8c5a222696b Mon Sep 17 00:00:00 2001 From: "Ahmad K. Bawaneh" Date: Tue, 6 Feb 2024 01:27:14 +0300 Subject: [PATCH 15/27] Update JDT and asm for Java 17 language support (#9911) Update build scripts to point to the latest JDT [3.36.0.v20231115-1055] and the latest asm 9.6. Updating beyond this would drop support for running compiler/devmode on Java 11. fix #9871 --- .github/workflows/full-check.yml | 8 +- .github/workflows/quick-check.yml | 8 +- dev/build.xml | 30 ++-- .../com/google/gwt/dev/javac/JdtCompiler.java | 3 +- .../gwt/dev/jjs/impl/GwtAstBuilder.java | 36 +++- .../google/gwt/dev/util/arg/SourceLevel.java | 3 +- ...yTypeReferenceRestrictionsCheckerTest.java | 11 ++ .../gwt/dev/jjs/impl/Java17AstTest.java | 159 ++++++++++++++++++ maven/google-poms/gwt/pom-template.xml | 2 +- maven/poms/gwt/pom-template.xml | 2 +- user/build.xml | 4 +- .../google/gwt/dev/jjs/test/Java17Test.java | 79 +++++++++ .../com/google/gwt/dev/jjs/CompilerSuite.java | 2 + .../com/google/gwt/dev/jjs/Java17Test.gwt.xml | 19 +++ .../google/gwt/dev/jjs/test/Java17Test.java | 56 ++++++ 15 files changed, 388 insertions(+), 34 deletions(-) create mode 100644 dev/core/test/com/google/gwt/dev/jjs/impl/Java17AstTest.java create mode 100644 user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java17Test.java create mode 100644 user/test/com/google/gwt/dev/jjs/Java17Test.gwt.xml create mode 100644 user/test/com/google/gwt/dev/jjs/test/Java17Test.java diff --git a/.github/workflows/full-check.yml b/.github/workflows/full-check.yml index 491f5d1457..8d09500c3b 100644 --- a/.github/workflows/full-check.yml +++ b/.github/workflows/full-check.yml @@ -1,4 +1,4 @@ -# Run all tests and builds all aspects of GWT using Java 11 and 17. Runs +# Run all tests and builds all aspects of GWT using Java 11, 17, and 21. Runs # nightly (plus or minus timzeones) on the main branch, and will also run right # away on a push to a release branch. Release zips are uploaded as part of the # build, though maven snapshots are not yet deployed. @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java-version: [ '11', '17' ] + java-version: [ '11', '17', '21' ] steps: - name: Checkout GWT itself into one directory uses: actions/checkout@v4 @@ -83,7 +83,7 @@ jobs: - name: Set up sonatype credentials # Using the same java version as above, set up a settings.xml file uses: actions/setup-java@v4 - if: ${{ github.event_name == 'schedule' && github.repository_owner == 'gwtproject' && matrix.java-version == '17' }} + if: ${{ github.event_name == 'schedule' && github.repository_owner == 'gwtproject' && matrix.java-version == '21' }} with: java-version: ${{ matrix.java-version }} distribution: 'temurin' @@ -93,7 +93,7 @@ jobs: server-password: SONATYPE_PASSWORD - name: Nightly builds should be deployed as snapshots to sonatype - if: ${{ github.event_name == 'schedule' && github.repository_owner == 'gwtproject' && matrix.java-version == '17' }} + if: ${{ github.event_name == 'schedule' && github.repository_owner == 'gwtproject' && matrix.java-version == '21' }} env: SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} diff --git a/.github/workflows/quick-check.yml b/.github/workflows/quick-check.yml index 6b6fa163e4..5dfdfd55cc 100644 --- a/.github/workflows/quick-check.yml +++ b/.github/workflows/quick-check.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java-version: ['11', '17'] + java-version: ['11', '17', '21'] steps: - name: Checkout GWT itself into one directory uses: actions/checkout@v4 @@ -44,8 +44,8 @@ jobs: ANT_OPTS=-Xmx2g ant clean dist doc checkstyle apicheck - - name: Create pull request comments/annotations for checkstyle from the java 17 build, even on failure - if: ${{ always() && github.event_name == 'pull_request' && matrix.java-version == '17' }} + - name: Create pull request comments/annotations for checkstyle from the java 21 build, even on failure + if: ${{ always() && github.event_name == 'pull_request' && matrix.java-version == '21' }} env: REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -58,7 +58,7 @@ jobs: done - name: Upload checkstyle xml for manual review uses: actions/upload-artifact@v4 - if: ${{ matrix.java-version == '17' }} + if: ${{ matrix.java-version == '21' }} with: name: checkstyle-reports-java${{ matrix.java-version }} path: 'gwt/build/out/**/checkstyle*.xml' diff --git a/dev/build.xml b/dev/build.xml index 6821a77e2a..1b5a2ac9ff 100755 --- a/dev/build.xml +++ b/dev/build.xml @@ -63,11 +63,11 @@ - - - - - + + + + + @@ -119,16 +119,16 @@ - - - + + + + src="${gwt.tools.lib}/eclipse/org.eclipse.jdt.core_3.32.0.v20221108-1853.jar"/> + src="${gwt.tools.lib}/eclipse/jdtCompilerAdapter_3.32.0.v20221108-1853.jar"/> - - - + + + + location="${gwt.tools.lib}/eclipse/org.eclipse.jdt.core_3.32.0.v20221108-1853.jar"/> + location="${gwt.tools.lib}/eclipse/jdtCompilerAdapter_3.32.0.v20221108-1853.jar"/> diff --git a/dev/core/src/com/google/gwt/dev/javac/JdtCompiler.java b/dev/core/src/com/google/gwt/dev/javac/JdtCompiler.java index c0e5748c23..c63a0132b7 100644 --- a/dev/core/src/com/google/gwt/dev/javac/JdtCompiler.java +++ b/dev/core/src/com/google/gwt/dev/javac/JdtCompiler.java @@ -787,7 +787,8 @@ private static void resolveRecursive(ReferenceBinding outerType) { SourceLevel.JAVA8, ClassFileConstants.JDK1_8, SourceLevel.JAVA9, ClassFileConstants.JDK9, SourceLevel.JAVA10, ClassFileConstants.JDK10, - SourceLevel.JAVA11, ClassFileConstants.JDK11); + SourceLevel.JAVA11, ClassFileConstants.JDK11, + SourceLevel.JAVA17, ClassFileConstants.JDK17); public JdtCompiler(CompilerContext compilerContext, UnitProcessor processor) { this.compilerContext = compilerContext; diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java index 58334327c2..a52a889761 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java @@ -194,6 +194,7 @@ import org.eclipse.jdt.internal.compiler.ast.StringLiteral; import org.eclipse.jdt.internal.compiler.ast.StringLiteralConcatenation; import org.eclipse.jdt.internal.compiler.ast.SuperReference; +import org.eclipse.jdt.internal.compiler.ast.SwitchExpression; import org.eclipse.jdt.internal.compiler.ast.SwitchStatement; import org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement; import org.eclipse.jdt.internal.compiler.ast.ThisReference; @@ -537,13 +538,25 @@ public void endVisit(BreakStatement x, BlockScope scope) { @Override public void endVisit(CaseStatement x, BlockScope scope) { + if (x.isExpr) { + InternalCompilerException exception = + new InternalCompilerException("Switch expressions not yet supported"); + exception.addNode(new JCaseStatement(makeSourceInfo(x), null)); + throw exception; + } try { SourceInfo info = makeSourceInfo(x); - JExpression caseExpression = pop(x.constantExpression); - if (caseExpression != null && x.constantExpression.resolvedType.isEnum()) { - caseExpression = synthesizeCallToOrdinal(scope, info, caseExpression); + if (x.constantExpressions == null) { + push(new JCaseStatement(info, null)); + } else { + for (Expression constantExpression : x.constantExpressions) { + JExpression caseExpression = pop(constantExpression); + if (caseExpression != null && caseExpression.getType().isEnumOrSubclass() != null) { + caseExpression = synthesizeCallToOrdinal(scope, info, caseExpression); + } + push(new JCaseStatement(info, caseExpression)); + } } - push(new JCaseStatement(info, caseExpression)); } catch (Throwable e) { throw translateException(x, e); } @@ -2534,6 +2547,14 @@ public boolean visit(Initializer x, MethodScope scope) { } } + @Override + public boolean visit(SwitchExpression x, BlockScope blockScope) { + InternalCompilerException exception = + new InternalCompilerException("Switch expressions not yet supported"); + exception.addNode(new JCaseStatement(makeSourceInfo(x), null)); + throw exception; + } + @Override public boolean visit(LocalDeclaration x, BlockScope scope) { try { @@ -2752,6 +2773,12 @@ protected void pushBinaryOp(BinaryExpression x, JBinaryOperator op) { } protected boolean visit(TypeDeclaration x) { + if (x.isRecord()) { + InternalCompilerException exception = + new InternalCompilerException("Records not yet supported"); + exception.addNode(new JClassType(makeSourceInfo(x), intern(x.name), false, false)); + throw exception; + } JDeclaredType type = (JDeclaredType) typeMap.get(x.binding); assert !type.isExternal(); classStack.push(curClass); @@ -3706,7 +3733,6 @@ private JType[] processCastType(TypeBinding type) { } } - private boolean isFunctionalInterfaceWithMethod(ReferenceBinding referenceBinding, Scope scope, String samSignature) { if (!referenceBinding.isInterface()) { diff --git a/dev/core/src/com/google/gwt/dev/util/arg/SourceLevel.java b/dev/core/src/com/google/gwt/dev/util/arg/SourceLevel.java index d07680b3e1..821628fc86 100644 --- a/dev/core/src/com/google/gwt/dev/util/arg/SourceLevel.java +++ b/dev/core/src/com/google/gwt/dev/util/arg/SourceLevel.java @@ -26,7 +26,8 @@ public enum SourceLevel { JAVA8("1.8", "8"), JAVA9("9", "1.9"), JAVA10("10", "1.10"), - JAVA11("11", "1.11"); + JAVA11("11", "1.11"), + JAVA17("17", "1.17"); /** * The default java sourceLevel. diff --git a/dev/core/test/com/google/gwt/dev/javac/BinaryTypeReferenceRestrictionsCheckerTest.java b/dev/core/test/com/google/gwt/dev/javac/BinaryTypeReferenceRestrictionsCheckerTest.java index a5feaf6b91..f6e7bc1b4b 100644 --- a/dev/core/test/com/google/gwt/dev/javac/BinaryTypeReferenceRestrictionsCheckerTest.java +++ b/dev/core/test/com/google/gwt/dev/javac/BinaryTypeReferenceRestrictionsCheckerTest.java @@ -37,6 +37,7 @@ import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType; import org.eclipse.jdt.internal.compiler.env.IBinaryType; import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation; +import org.eclipse.jdt.internal.compiler.env.IRecordComponent; import org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding; @@ -181,6 +182,16 @@ public ITypeAnnotationWalker enrichWithExternalAnnotationsFor( public ExternalAnnotationStatus getExternalAnnotationStatus() { return null; } + + @Override + public IRecordComponent[] getRecordComponents() { + return null; + } + + @Override + public boolean isRecord() { + return false; + } } private static final String BINARY_TYPE_NAME = "BinaryType"; diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/Java17AstTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/Java17AstTest.java new file mode 100644 index 0000000000..f5cb61c0bd --- /dev/null +++ b/dev/core/test/com/google/gwt/dev/jjs/impl/Java17AstTest.java @@ -0,0 +1,159 @@ +/* + * Copyright 2024 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.dev.jjs.impl; + +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.dev.javac.testing.impl.JavaResourceBase; +import com.google.gwt.dev.jjs.InternalCompilerException; +import com.google.gwt.dev.jjs.ast.JInterfaceType; +import com.google.gwt.dev.jjs.ast.JProgram; +import com.google.gwt.dev.jjs.ast.JStringLiteral; +import java.util.Arrays; +import java.util.List; + +/** + * Tests that {@link GwtAstBuilder} correctly builds the AST for + * features introduced in Java 17. + */ +public class Java17AstTest extends FullCompileTestBase { + + @Override + public void setUp() throws Exception { + super.setUp(); + addAll(JavaResourceBase.createMockJavaResource("test.TextBlock", + "package test;", + "public interface TextBlock {", + "String text =\"\"\"", + "line 1", + "line 2", + "line 3", + "\"\"\";", + "}" + )); + + addAll(JavaResourceBase.createMockJavaResource("test.Shape", + "package test;", + "public sealed class Shape permits Square, Circle {", + "}" + )); + + addAll(JavaResourceBase.createMockJavaResource("test.Square", + "package test;", + "public final class Square extends Shape {", + "}" + )); + + addAll(JavaResourceBase.createMockJavaResource("test.Circle", + "package test;", + "public final class Circle extends Shape {", + "}" + )); + + addAll(JavaResourceBase.createMockJavaResource("test.Months", + "package test;", + "public enum Months {", + "JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER;", + "}" + )); + } + + public void testTextBlocks() throws Exception { + JProgram program = compileSnippet("void", "new TextBlock(){};"); + JInterfaceType textBlock = (JInterfaceType) findType(program, "TextBlock"); + JStringLiteral initializer = (JStringLiteral) textBlock.getFields().get(0).getInitializer(); + String multiLineString = initializer.getValue(); + List lines = Arrays.asList(multiLineString.split("\n")); + assertEquals(3, lines.size()); + assertEquals("line 1", lines.get(0)); + assertEquals("line 2", lines.get(1)); + assertEquals("line 3", lines.get(2)); + } + + public void testSealedClassesPermitted() throws Exception { + compileSnippet("void", "Shape square = new Square();"); + compileSnippet("void", "Shape circle = new Circle();"); + } + + public void testSealedClassesNotPermitted() { + try { + addSnippetClassDecl("public final class Rectangle extends Shape {" + + "}"); + compileSnippet("void", "Shape rectangle = new Rectangle();"); + fail("Compile should have failed but succeeded."); + } catch (Exception e) { + if (!(e.getCause() instanceof UnableToCompleteException) + && !(e instanceof UnableToCompleteException)) { + e.printStackTrace(); + fail(); + } + } + } + + public void testRecordsNotSupported() { + try { + addSnippetClassDecl("public record Point(int x, int y) {}"); + compileSnippet("void", "Point rectangle = new Point(0, 0);"); + fail("Compile should have failed but succeeded."); + } catch (Exception e) { + if (!(e.getCause() instanceof UnableToCompleteException) + && !(e instanceof UnableToCompleteException)) { + e.printStackTrace(); + fail(); + } + } + } + + public void testSwitchExpressionsNotSupported() { + try { + compileSnippet("void", "var month = Months.JUNE;" + + "var result = switch(month) {\n" + + " case JANUARY, JUNE, JULY -> 3;\n" + + " case FEBRUARY, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER -> 1;\n" + + " case MARCH, MAY, APRIL, AUGUST -> 2;\n" + + " default -> 0;" + + "};"); + fail("Compile should have failed but succeeded, switch expression is not supported."); + } catch (Exception e) { + if (!(e.getCause() instanceof InternalCompilerException) + && !(e instanceof InternalCompilerException)) { + e.printStackTrace(); + fail(); + } + assertEquals("Switch expressions not yet supported", e.getMessage()); + } + } + + public void testSwitchExpressionsInitializerShouldFail() { + try { + compileSnippet("void", " int i = switch(1) {\n" + + " case 1:\n" + + " yield 2;\n" + + " default:\n" + + " yield 7;\n" + + " };"); + fail("Compile should have failed but succeeded, switch expressions as initializer should fail."); + } catch (Exception e) { + if (!(e.getCause() instanceof InternalCompilerException) + && !(e instanceof InternalCompilerException)) { + e.printStackTrace(); + fail(); + } + assertEquals("Switch expressions not yet supported", e.getMessage()); + } + } + + @Override + protected void optimizeJava() { + } +} diff --git a/maven/google-poms/gwt/pom-template.xml b/maven/google-poms/gwt/pom-template.xml index dc7f26bd3d..777f51ed37 100644 --- a/maven/google-poms/gwt/pom-template.xml +++ b/maven/google-poms/gwt/pom-template.xml @@ -22,7 +22,7 @@ 9.4.44.v20210927 - 9.2 + 9.6 diff --git a/maven/poms/gwt/pom-template.xml b/maven/poms/gwt/pom-template.xml index 0f288bae1e..0825e6cf47 100644 --- a/maven/poms/gwt/pom-template.xml +++ b/maven/poms/gwt/pom-template.xml @@ -22,7 +22,7 @@ 9.4.44.v20210927 - 9.2 + 9.6 diff --git a/user/build.xml b/user/build.xml index f4c409f73e..2af156012f 100755 --- a/user/build.xml +++ b/user/build.xml @@ -61,8 +61,8 @@ - - + + lines = Arrays.asList(TextBlock.text.split("\n")); + assertEquals(3, lines.size()); + assertEquals("line 1", lines.get(0)); + assertEquals("line 2", lines.get(1)); + assertEquals("line 3", lines.get(2)); + } + + public void testSealedClassesPermitted() { + Shape square = new Square(); + Shape circle = new Circle(); + + checkIfCompiled(square, circle); + } + + private void checkIfCompiled(Shape square, Shape circle) { + assertTrue(square instanceof Square); + assertTrue(circle instanceof Circle); + } +} diff --git a/user/test/com/google/gwt/dev/jjs/CompilerSuite.java b/user/test/com/google/gwt/dev/jjs/CompilerSuite.java index 56e49ff62a..68ebcd76cb 100644 --- a/user/test/com/google/gwt/dev/jjs/CompilerSuite.java +++ b/user/test/com/google/gwt/dev/jjs/CompilerSuite.java @@ -29,6 +29,7 @@ import com.google.gwt.dev.jjs.test.InnerOuterSuperTest; import com.google.gwt.dev.jjs.test.Java10Test; import com.google.gwt.dev.jjs.test.Java11Test; +import com.google.gwt.dev.jjs.test.Java17Test; import com.google.gwt.dev.jjs.test.Java7Test; import com.google.gwt.dev.jjs.test.Java8Test; import com.google.gwt.dev.jjs.test.Java9Test; @@ -77,6 +78,7 @@ public static Test suite() { suite.addTestSuite(Java9Test.class); suite.addTestSuite(Java10Test.class); suite.addTestSuite(Java11Test.class); + suite.addTestSuite(Java17Test.class); suite.addTestSuite(JavaAccessFromJavaScriptTest.class); suite.addTestSuite(JsniConstructorTest.class); suite.addTestSuite(JsniDispatchTest.class); diff --git a/user/test/com/google/gwt/dev/jjs/Java17Test.gwt.xml b/user/test/com/google/gwt/dev/jjs/Java17Test.gwt.xml new file mode 100644 index 0000000000..a73ecb58ee --- /dev/null +++ b/user/test/com/google/gwt/dev/jjs/Java17Test.gwt.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/user/test/com/google/gwt/dev/jjs/test/Java17Test.java b/user/test/com/google/gwt/dev/jjs/test/Java17Test.java new file mode 100644 index 0000000000..4413e90efa --- /dev/null +++ b/user/test/com/google/gwt/dev/jjs/test/Java17Test.java @@ -0,0 +1,56 @@ +/* + * Copyright 2019 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.dev.jjs.test; + +import com.google.gwt.dev.util.arg.SourceLevel; +import com.google.gwt.junit.DoNotRunWith; +import com.google.gwt.junit.JUnitShell; +import com.google.gwt.junit.Platform; +import com.google.gwt.junit.client.GWTTestCase; + +/** + * Dummy test case. Java17Test is super sourced so that GWT can be compiled by Java 8. + * + * NOTE: Make sure this class has the same test methods of its supersourced variant. + */ +@DoNotRunWith(Platform.Devel) +public class Java17Test extends GWTTestCase { + + @Override + public String getModuleName() { + return "com.google.gwt.dev.jjs.Java17Test"; + } + + @Override + public void runTest() throws Throwable { + // Only run these tests if -sourceLevel 17 (or greater) is enabled. + if (isGwtSourceLevel17()) { + super.runTest(); + } + } + + public void testTextBlocks() { + assertFalse(isGwtSourceLevel17()); + } + + public void testSealedClassesPermitted() { + assertFalse(isGwtSourceLevel17()); + } + + private boolean isGwtSourceLevel17() { + return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA17) >= 0; + } +} From 7c9a4c430224077382ab2c31e9d0ab2dd569e637 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Feb 2024 18:39:39 -0600 Subject: [PATCH 16/27] Bump mikepenz/action-junit-report from 4.0.4 to 4.1.0 (#9910) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 4.0.4 to 4.1.0.
Release notes

Sourced from mikepenz/action-junit-report's releases.

v4.1.0

🚀 Features

  • Introduce setting to disable annotations for checks

📦 Dependencies

  • Upgrade dev dependencies
Commits
  • 5f47764 Merge pull request #1027 from mikepenz/feature/update_dependencies_20240129
  • aac5ac7 - npm upgrade
  • 576acf6 Update dev dependencies
  • 2d2e937 Merge pull request #1024 from mikepenz/feature/1020_2
  • 21fada7 - introduce new setting to disable annotations for checks
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=mikepenz/action-junit-report&package-manager=github_actions&previous-version=4.0.4&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/full-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/full-check.yml b/.github/workflows/full-check.yml index 8d09500c3b..ebb06f57ad 100644 --- a/.github/workflows/full-check.yml +++ b/.github/workflows/full-check.yml @@ -57,7 +57,7 @@ jobs: -Dtest.emma.htmlunit.disable=true - name: Report test results - uses: mikepenz/action-junit-report@v4.0.4 + uses: mikepenz/action-junit-report@v4.1.0 if: always() with: report_paths: 'gwt/build/out/**/test/**/reports/TEST-*.xml' From 3e8458260cae857560d8e94cf445c67bc3274954 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Wed, 7 Feb 2024 20:10:51 -0600 Subject: [PATCH 17/27] Support "GWT Project Authors" as copyright owner and update checkstyle (#9916) Updates checkstyle to the current latest, requiring a few small changes in configuration. A few updates were also made to fix minor style points brought up in the update. Fixes #9823 --- common.ant.xml | 8 +- .../google/gwt/dev/javac/MemoryUnitCache.java | 1 - .../gwt/dev/jjs/impl/MethodInliner.java | 3 +- .../impl/ResolveRuntimeTypeReferences.java | 2 + .../google/gwt/dev/shell/BrowserChannel.java | 2 + .../gwt-checkstyle-suppressions.xml | 20 ----- .../code-style/gwt-checkstyle-tests.xml | 57 ++++++--------- .../settings/code-style/gwt-checkstyle.xml | 73 +++++++++---------- .../gwt/i18n/shared/DateTimeFormat.java | 3 +- .../google/gwt/emul/java/lang/Boolean.java | 2 +- .../com/google/gwt/emul/java/lang/Double.java | 2 +- .../google/gwt/dev/jjs/test/Java10Test.java | 2 +- .../google/gwt/dev/jjs/test/Java9Test.java | 2 +- 13 files changed, 73 insertions(+), 104 deletions(-) delete mode 100644 eclipse/settings/code-style/gwt-checkstyle-suppressions.xml diff --git a/common.ant.xml b/common.ant.xml index 6193bd3627..d64cd0898a 100755 --- a/common.ant.xml +++ b/common.ant.xml @@ -337,8 +337,8 @@ - + @@ -357,8 +357,8 @@ - + the runtime type to use when replacing a type id */ public interface TypeMapper { T getOrCreateTypeId(JType type); diff --git a/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java b/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java index 1fed6e5185..4b4455f3ef 100644 --- a/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java +++ b/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java @@ -198,6 +198,8 @@ public interface RemoteObjectRef { /** * Hook interface for responding to messages. + * + * @param the BrowserChannel type this implementation is built to handle. */ public abstract static class SessionHandler { diff --git a/eclipse/settings/code-style/gwt-checkstyle-suppressions.xml b/eclipse/settings/code-style/gwt-checkstyle-suppressions.xml deleted file mode 100644 index c5181f9688..0000000000 --- a/eclipse/settings/code-style/gwt-checkstyle-suppressions.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/eclipse/settings/code-style/gwt-checkstyle-tests.xml b/eclipse/settings/code-style/gwt-checkstyle-tests.xml index a9b5a73977..7e09ce4d5b 100644 --- a/eclipse/settings/code-style/gwt-checkstyle-tests.xml +++ b/eclipse/settings/code-style/gwt-checkstyle-tests.xml @@ -7,13 +7,13 @@ Checkstyle-Configuration: GWT Checks for Tests Description: A more lenient set of style checks for test cases, needed because test often need to do funkier stuff. --> - + - + @@ -23,7 +23,6 @@ A more lenient set of style checks for test cases, needed because test often nee - @@ -90,14 +89,9 @@ A more lenient set of style checks for test cases, needed because test often nee - - + - - - - @@ -215,33 +209,30 @@ A more lenient set of style checks for test cases, needed because test often nee + + + + + + + + + + + + + + + + + + - - - - + - - - - - - - - - - - - - - - - - - - - + + diff --git a/eclipse/settings/code-style/gwt-checkstyle.xml b/eclipse/settings/code-style/gwt-checkstyle.xml index 2455ce28a6..87aa00c369 100644 --- a/eclipse/settings/code-style/gwt-checkstyle.xml +++ b/eclipse/settings/code-style/gwt-checkstyle.xml @@ -7,13 +7,13 @@ Checkstyle-Configuration: GWT Checks Description: --> - + - + @@ -21,13 +21,12 @@ Description: + + + + - - - - - - + @@ -40,6 +39,7 @@ Description: + @@ -53,7 +53,7 @@ Description: - + @@ -86,14 +86,9 @@ Description: - - + - - - - @@ -198,33 +193,31 @@ Description: - - - - + - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - + + + - - - - - + + - - - diff --git a/user/src/com/google/gwt/i18n/shared/DateTimeFormat.java b/user/src/com/google/gwt/i18n/shared/DateTimeFormat.java index 59c8fdb125..f66fe02cb2 100644 --- a/user/src/com/google/gwt/i18n/shared/DateTimeFormat.java +++ b/user/src/com/google/gwt/i18n/shared/DateTimeFormat.java @@ -1906,9 +1906,10 @@ private boolean subParse(String text, int[] pos, PatternPart part, cal.setTzOffset(0); return true; } - // $FALL-THROUGH$ + // CHECKSTYLE_OFF: Fall through case 'z': // time zone offset case 'v': // time zone generic + // CHECKSTYLE_ON return subParseTimeZoneInGMT(text, start, pos, cal); default: return false; diff --git a/user/super/com/google/gwt/emul/java/lang/Boolean.java b/user/super/com/google/gwt/emul/java/lang/Boolean.java index af7a3ae180..4596b7f8a7 100644 --- a/user/super/com/google/gwt/emul/java/lang/Boolean.java +++ b/user/super/com/google/gwt/emul/java/lang/Boolean.java @@ -125,5 +125,5 @@ public String toString() { protected static boolean $isInstance(Object instance) { return "boolean".equals(JsUtils.typeOf(instance)); } - //CHECKSTYLE_ON: End utility methods + // CHECKSTYLE_ON: End utility methods } diff --git a/user/super/com/google/gwt/emul/java/lang/Double.java b/user/super/com/google/gwt/emul/java/lang/Double.java index 8efc156ff9..44f250523d 100644 --- a/user/super/com/google/gwt/emul/java/lang/Double.java +++ b/user/super/com/google/gwt/emul/java/lang/Double.java @@ -219,5 +219,5 @@ public String toString() { protected static boolean $isInstance(Object instance) { return "number".equals(JsUtils.typeOf(instance)); } - //CHECKSTYLE_ON: End utility methods + // CHECKSTYLE_ON: End utility methods } diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java10Test.java b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java10Test.java index 165815343b..1eb6875da6 100644 --- a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java10Test.java +++ b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java10Test.java @@ -51,7 +51,7 @@ public void testLocalVarType_DenotableTypes() { Supplier initializer = () -> "37"; var s2 = initializer.get(); - //to be sure that s2 was inferred as a string and not an Object + // to be sure that s2 was inferred as a string and not an Object String s3 = s2; assertEquals("37", s3); } diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java9Test.java b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java9Test.java index e6ff6d29d3..f9fcab9e87 100644 --- a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java9Test.java +++ b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java9Test.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 GwtProject contributors + * Copyright 2023 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 b5dc7f6f0ce94250b622769bdfefb4e960d53544 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Mon, 12 Feb 2024 06:23:48 -0600 Subject: [PATCH 18/27] Checkstyle import rules should be consistent with the codebase (#9920) The old checkstyle was similar but not identical to the Google Java Style Guide, and it seems that checkstyle updates have changed import behaviors in a way to make them incompatible with those conventions (but more compatible with the Google style). These new rules are a close approximation to the old convention, with a few exceptions, mostly that imports are all listed at the top. There were also some inconsistencies, such as grouping jsinterop and javaemul with java packages - those have been resolved as simply as possible, with checkstyle rules to enforce this. --- .../com/google/gwt/dev/javac/UnitCacheSingleton.java | 1 - dev/core/src/com/google/gwt/dev/js/JsUtils.java | 1 - .../google/gwt/dev/shell/StaticResourceServer.java | 1 + .../gwt/dev/shell/jetty/JettyLauncherUtils.java | 1 + .../google/gwt/dev/shell/jetty/JettyTreeLogger.java | 1 + dev/core/test/com/google/gwt/dev/CompilerTest.java | 1 + .../com/google/gwt/dev/jjs/impl/Java17AstTest.java | 1 + .../gwt/dev/resource/impl/DefaultFiltersTest.java | 3 +-- eclipse/settings/code-style/gwt-checkstyle-tests.xml | 10 ++++++---- eclipse/settings/code-style/gwt-checkstyle.xml | 10 ++++++---- .../google/gwt/sample/validation/shared/Person.java | 1 - .../gwt/tools/apichecker/ApiCompatibilityChecker.java | 3 +-- .../server/RequestFactoryJarExtractor.java | 1 - user/super/com/google/gwt/emul/java/lang/Boolean.java | 2 -- .../com/google/gwt/emul/java/lang/CharSequence.java | 2 -- user/super/com/google/gwt/emul/java/lang/Class.java | 1 - .../com/google/gwt/emul/java/lang/Comparable.java | 1 - user/super/com/google/gwt/emul/java/lang/Enum.java | 1 + .../com/google/gwt/emul/java/lang/Throwable.java | 2 -- .../com/google/gwt/emul/java/math/MathContext.java | 1 - .../com/google/gwt/emul/java/util/Collection.java | 1 - .../com/google/gwt/emul/java/util/Collections.java | 1 - user/super/com/google/gwt/emul/java/util/Date.java | 1 - user/super/com/google/gwt/emul/java/util/List.java | 3 +-- user/super/com/google/gwt/emul/java/util/Map.java | 1 - user/super/com/google/gwt/emul/java/util/Set.java | 1 - user/super/com/google/gwt/emul/java/util/Vector.java | 1 - .../gwt/emul/java/util/function/BinaryOperator.java | 4 ++-- .../google/gwt/emul/java/util/function/Predicate.java | 4 ++-- .../gwt/core/client/impl/StackTraceEmulTest.java | 2 +- .../gwt/core/interop/ElementLikeNativeInterface.java | 1 - user/test/com/google/gwt/core/interop/JsTypeTest.java | 1 - .../gwt/dev/jjs/optimized/CastOptimizationTest.java | 1 - .../jjs/optimized/UncheckedCastOptimizationTest.java | 1 - .../gwt/dev/jjs/test/CompilerMiscRegressionTest.java | 1 - .../com/google/gwt/emultest/CollectionsSuite.java | 1 + .../test/com/google/gwt/emultest/EmulJava10Suite.java | 5 +++-- .../test/com/google/gwt/emultest/EmulJava11Suite.java | 1 + user/test/com/google/gwt/emultest/EmulJava9Suite.java | 11 ++++++----- user/test/com/google/gwt/emultest/EmulSuite.java | 1 + .../gwt/emultest/java/internal/CoercionsTest.java | 1 - .../gwt/emultest/java/io/BufferedWriterTest.java | 1 + .../gwt/emultest/java/io/OutputStreamWriterTest.java | 1 + .../google/gwt/emultest/java/io/PrintStreamTest.java | 1 + .../google/gwt/emultest/java/lang/CharacterTest.java | 1 + .../gwt/emultest/java/lang/JsExceptionTest.java | 1 + .../com/google/gwt/emultest/java/lang/StringTest.java | 1 + .../google/gwt/emultest/java/lang/ThrowableTest.java | 1 + .../gwt/emultest/java/lang/ThrowableTestBase.java | 1 + .../java/math/BigIntegerConstructorsTest.java | 1 + .../gwt/emultest/java/nio/charset/CharsetTest.java | 1 + .../com/google/gwt/emultest/java/sql/SqlDateTest.java | 1 + .../google/gwt/emultest/java/util/ArrayDequeTest.java | 1 + .../emultest/java/util/ArraysDoubleSemanticsTest.java | 1 + .../emultest/java/util/ArraysFloatSemanticsTest.java | 1 + .../com/google/gwt/emultest/java/util/DateTest.java | 1 + .../gwt/emultest/java/util/IdentityHashMapTest.java | 1 + .../gwt/emultest/java/util/LinkedHashMapTest.java | 1 + .../com/google/gwt/emultest/java/util/TestMap.java | 1 + .../google/gwt/emultest/java/util/TreeMapTest.java | 1 + .../google/gwt/emultest/java/util/TreeSetTest.java | 1 + .../emultest/java11/util/function/PredicateTest.java | 1 + .../java8/util/DoubleSummaryStatisticsTest.java | 3 ++- .../emultest/java8/util/IntSummaryStatisticsTest.java | 4 ++-- .../java8/util/LongSummaryStatisticsTest.java | 4 ++-- .../gwt/emultest/java8/util/stream/StreamTest.java | 1 - .../rebind/ConstantsWithLookupImplCreatorTest.java | 8 ++++---- .../gwt/i18n/rebind/LookupMethodCreatorTest.java | 4 ++-- .../google/gwt/resources/rg/CssOutputTestCase.java | 10 +++++----- .../gwt/uibinder/rebind/HandlerEvaluatorTest.java | 6 +++--- .../google/gwt/user/client/rpc/TestSetValidator.java | 10 +++++----- 71 files changed, 84 insertions(+), 76 deletions(-) diff --git a/dev/core/src/com/google/gwt/dev/javac/UnitCacheSingleton.java b/dev/core/src/com/google/gwt/dev/javac/UnitCacheSingleton.java index fb272cd490..3532013288 100644 --- a/dev/core/src/com/google/gwt/dev/javac/UnitCacheSingleton.java +++ b/dev/core/src/com/google/gwt/dev/javac/UnitCacheSingleton.java @@ -17,7 +17,6 @@ import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.UnableToCompleteException; - import com.google.gwt.dev.jjs.JJSOptions; import com.google.gwt.thirdparty.guava.common.base.Joiner; import com.google.gwt.util.tools.shared.Md5Utils; diff --git a/dev/core/src/com/google/gwt/dev/js/JsUtils.java b/dev/core/src/com/google/gwt/dev/js/JsUtils.java index 3b6063478b..dbad2c108a 100644 --- a/dev/core/src/com/google/gwt/dev/js/JsUtils.java +++ b/dev/core/src/com/google/gwt/dev/js/JsUtils.java @@ -47,7 +47,6 @@ import java.util.Collections; import java.util.List; - import java.util.regex.Pattern; /** diff --git a/dev/core/src/com/google/gwt/dev/shell/StaticResourceServer.java b/dev/core/src/com/google/gwt/dev/shell/StaticResourceServer.java index df95aeb993..e4fdb9fea4 100644 --- a/dev/core/src/com/google/gwt/dev/shell/StaticResourceServer.java +++ b/dev/core/src/com/google/gwt/dev/shell/StaticResourceServer.java @@ -23,6 +23,7 @@ import com.google.gwt.dev.shell.jetty.JettyLauncherUtils; import com.google.gwt.dev.shell.jetty.JettyTreeLogger; import com.google.gwt.dev.shell.jetty.SslConfiguration; + import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; diff --git a/dev/core/src/com/google/gwt/dev/shell/jetty/JettyLauncherUtils.java b/dev/core/src/com/google/gwt/dev/shell/jetty/JettyLauncherUtils.java index 212c71ffd0..944c1b152f 100644 --- a/dev/core/src/com/google/gwt/dev/shell/jetty/JettyLauncherUtils.java +++ b/dev/core/src/com/google/gwt/dev/shell/jetty/JettyLauncherUtils.java @@ -16,6 +16,7 @@ package com.google.gwt.dev.shell.jetty; import com.google.gwt.core.ext.TreeLogger; + import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.SecureRequestCustomizer; diff --git a/dev/core/src/com/google/gwt/dev/shell/jetty/JettyTreeLogger.java b/dev/core/src/com/google/gwt/dev/shell/jetty/JettyTreeLogger.java index bd7952fb1f..c31ca4b5ee 100644 --- a/dev/core/src/com/google/gwt/dev/shell/jetty/JettyTreeLogger.java +++ b/dev/core/src/com/google/gwt/dev/shell/jetty/JettyTreeLogger.java @@ -16,6 +16,7 @@ package com.google.gwt.dev.shell.jetty; import com.google.gwt.core.ext.TreeLogger; + import org.eclipse.jetty.util.log.Logger; /** diff --git a/dev/core/test/com/google/gwt/dev/CompilerTest.java b/dev/core/test/com/google/gwt/dev/CompilerTest.java index 0176bb029c..b88089b73e 100644 --- a/dev/core/test/com/google/gwt/dev/CompilerTest.java +++ b/dev/core/test/com/google/gwt/dev/CompilerTest.java @@ -39,6 +39,7 @@ import com.google.gwt.thirdparty.guava.common.collect.Sets; import com.google.gwt.thirdparty.guava.common.io.Files; import com.google.gwt.util.tools.Utility; + import java.io.File; import java.io.IOException; import java.util.Arrays; diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/Java17AstTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/Java17AstTest.java index f5cb61c0bd..9665ab535c 100644 --- a/dev/core/test/com/google/gwt/dev/jjs/impl/Java17AstTest.java +++ b/dev/core/test/com/google/gwt/dev/jjs/impl/Java17AstTest.java @@ -19,6 +19,7 @@ import com.google.gwt.dev.jjs.ast.JInterfaceType; import com.google.gwt.dev.jjs.ast.JProgram; import com.google.gwt.dev.jjs.ast.JStringLiteral; + import java.util.Arrays; import java.util.List; diff --git a/dev/core/test/com/google/gwt/dev/resource/impl/DefaultFiltersTest.java b/dev/core/test/com/google/gwt/dev/resource/impl/DefaultFiltersTest.java index 1f84956eae..d6dd76099b 100644 --- a/dev/core/test/com/google/gwt/dev/resource/impl/DefaultFiltersTest.java +++ b/dev/core/test/com/google/gwt/dev/resource/impl/DefaultFiltersTest.java @@ -16,11 +16,10 @@ package com.google.gwt.dev.resource.impl; import com.google.gwt.dev.resource.impl.DefaultFilters.FilterFileType; +import com.google.gwt.thirdparty.apache.ant.types.ZipScanner; import junit.framework.TestCase; -import com.google.gwt.thirdparty.apache.ant.types.ZipScanner; - import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/eclipse/settings/code-style/gwt-checkstyle-tests.xml b/eclipse/settings/code-style/gwt-checkstyle-tests.xml index 7e09ce4d5b..9b6bfb18dd 100644 --- a/eclipse/settings/code-style/gwt-checkstyle-tests.xml +++ b/eclipse/settings/code-style/gwt-checkstyle-tests.xml @@ -94,10 +94,12 @@ A more lenient set of style checks for test cases, needed because test often nee - - - - + + + + + + diff --git a/eclipse/settings/code-style/gwt-checkstyle.xml b/eclipse/settings/code-style/gwt-checkstyle.xml index 87aa00c369..222dfb5b7f 100644 --- a/eclipse/settings/code-style/gwt-checkstyle.xml +++ b/eclipse/settings/code-style/gwt-checkstyle.xml @@ -91,10 +91,12 @@ Description: - - - - + + + + + + diff --git a/samples/validation/src/main/java/com/google/gwt/sample/validation/shared/Person.java b/samples/validation/src/main/java/com/google/gwt/sample/validation/shared/Person.java index c24ef952c1..6724a112a5 100644 --- a/samples/validation/src/main/java/com/google/gwt/sample/validation/shared/Person.java +++ b/samples/validation/src/main/java/com/google/gwt/sample/validation/shared/Person.java @@ -16,7 +16,6 @@ package com.google.gwt.sample.validation.shared; import com.google.gwt.sample.validation.server.ServerConstraint; - import com.google.gwt.user.client.rpc.IsSerializable; import java.util.Map; diff --git a/tools/api-checker/src/com/google/gwt/tools/apichecker/ApiCompatibilityChecker.java b/tools/api-checker/src/com/google/gwt/tools/apichecker/ApiCompatibilityChecker.java index 313037c1aa..2bfe463048 100644 --- a/tools/api-checker/src/com/google/gwt/tools/apichecker/ApiCompatibilityChecker.java +++ b/tools/api-checker/src/com/google/gwt/tools/apichecker/ApiCompatibilityChecker.java @@ -24,12 +24,11 @@ import com.google.gwt.dev.util.arg.SourceLevel; import com.google.gwt.dev.util.log.AbstractTreeLogger; import com.google.gwt.dev.util.log.PrintWriterTreeLogger; +import com.google.gwt.thirdparty.apache.ant.types.ZipScanner; import com.google.gwt.util.tools.ArgHandlerFlag; import com.google.gwt.util.tools.ArgHandlerString; import com.google.gwt.util.tools.ToolBase; -import com.google.gwt.thirdparty.apache.ant.types.ZipScanner; - import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; diff --git a/user/src/com/google/web/bindery/requestfactory/server/RequestFactoryJarExtractor.java b/user/src/com/google/web/bindery/requestfactory/server/RequestFactoryJarExtractor.java index c7628acdc1..daeb5a2fde 100644 --- a/user/src/com/google/web/bindery/requestfactory/server/RequestFactoryJarExtractor.java +++ b/user/src/com/google/web/bindery/requestfactory/server/RequestFactoryJarExtractor.java @@ -18,7 +18,6 @@ import com.google.gwt.dev.util.Name; import com.google.gwt.dev.util.Name.SourceOrBinaryName; import com.google.gwt.dev.util.Util; - import com.google.web.bindery.event.shared.SimpleEventBus; import com.google.web.bindery.requestfactory.apt.RfValidator; import com.google.web.bindery.requestfactory.apt.ValidationTool; diff --git a/user/super/com/google/gwt/emul/java/lang/Boolean.java b/user/super/com/google/gwt/emul/java/lang/Boolean.java index 4596b7f8a7..4aafa9c1c6 100644 --- a/user/super/com/google/gwt/emul/java/lang/Boolean.java +++ b/user/super/com/google/gwt/emul/java/lang/Boolean.java @@ -18,9 +18,7 @@ import static javaemul.internal.InternalPreconditions.checkNotNull; import java.io.Serializable; - import javaemul.internal.JsUtils; - import jsinterop.annotations.JsMethod; /** 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 dc76d004e3..560bd9f875 100644 --- a/user/super/com/google/gwt/emul/java/lang/CharSequence.java +++ b/user/super/com/google/gwt/emul/java/lang/CharSequence.java @@ -22,9 +22,7 @@ import java.util.Spliterators; import java.util.stream.IntStream; import java.util.stream.StreamSupport; - import javaemul.internal.JsUtils; - import jsinterop.annotations.JsMethod; /** diff --git a/user/super/com/google/gwt/emul/java/lang/Class.java b/user/super/com/google/gwt/emul/java/lang/Class.java index fbca4e7aa1..c59eed0b6c 100644 --- a/user/super/com/google/gwt/emul/java/lang/Class.java +++ b/user/super/com/google/gwt/emul/java/lang/Class.java @@ -18,7 +18,6 @@ import com.google.gwt.core.client.JavaScriptObject; import java.lang.reflect.Type; - import javaemul.internal.annotations.DoNotInline; /** diff --git a/user/super/com/google/gwt/emul/java/lang/Comparable.java b/user/super/com/google/gwt/emul/java/lang/Comparable.java index 73191d04f1..d54dac3142 100644 --- a/user/super/com/google/gwt/emul/java/lang/Comparable.java +++ b/user/super/com/google/gwt/emul/java/lang/Comparable.java @@ -16,7 +16,6 @@ package java.lang; import javaemul.internal.JsUtils; - import jsinterop.annotations.JsMethod; /** diff --git a/user/super/com/google/gwt/emul/java/lang/Enum.java b/user/super/com/google/gwt/emul/java/lang/Enum.java index 13d01144e8..b044a57b6c 100644 --- a/user/super/com/google/gwt/emul/java/lang/Enum.java +++ b/user/super/com/google/gwt/emul/java/lang/Enum.java @@ -19,6 +19,7 @@ import static javaemul.internal.InternalPreconditions.checkNotNull; import com.google.gwt.core.client.JavaScriptObject; + import java.io.Serializable; import jsinterop.annotations.JsIgnore; import jsinterop.annotations.JsNonNull; diff --git a/user/super/com/google/gwt/emul/java/lang/Throwable.java b/user/super/com/google/gwt/emul/java/lang/Throwable.java index 60c8a1208c..1492bb0f00 100644 --- a/user/super/com/google/gwt/emul/java/lang/Throwable.java +++ b/user/super/com/google/gwt/emul/java/lang/Throwable.java @@ -21,9 +21,7 @@ import java.io.PrintStream; import java.io.Serializable; - import javaemul.internal.annotations.DoNotInline; - import jsinterop.annotations.JsMethod; import jsinterop.annotations.JsNonNull; import jsinterop.annotations.JsPackage; diff --git a/user/super/com/google/gwt/emul/java/math/MathContext.java b/user/super/com/google/gwt/emul/java/math/MathContext.java index 3522877af3..fa04a4d86b 100644 --- a/user/super/com/google/gwt/emul/java/math/MathContext.java +++ b/user/super/com/google/gwt/emul/java/math/MathContext.java @@ -38,7 +38,6 @@ import static javaemul.internal.InternalPreconditions.checkNotNull; import java.io.Serializable; - import javaemul.internal.NativeRegExp; /** diff --git a/user/super/com/google/gwt/emul/java/util/Collection.java b/user/super/com/google/gwt/emul/java/util/Collection.java index 583efd50ce..15c10ba8ed 100644 --- a/user/super/com/google/gwt/emul/java/util/Collection.java +++ b/user/super/com/google/gwt/emul/java/util/Collection.java @@ -20,7 +20,6 @@ import java.util.function.Predicate; import java.util.stream.Stream; import java.util.stream.StreamSupport; - import jsinterop.annotations.JsIgnore; import jsinterop.annotations.JsType; diff --git a/user/super/com/google/gwt/emul/java/util/Collections.java b/user/super/com/google/gwt/emul/java/util/Collections.java index ec35c32684..a5bfd207a4 100644 --- a/user/super/com/google/gwt/emul/java/util/Collections.java +++ b/user/super/com/google/gwt/emul/java/util/Collections.java @@ -23,7 +23,6 @@ import java.io.Serializable; import java.util.function.Predicate; import java.util.function.UnaryOperator; - import jsinterop.annotations.JsNonNull; /** diff --git a/user/super/com/google/gwt/emul/java/util/Date.java b/user/super/com/google/gwt/emul/java/util/Date.java index fe19568d63..67a72fb905 100644 --- a/user/super/com/google/gwt/emul/java/util/Date.java +++ b/user/super/com/google/gwt/emul/java/util/Date.java @@ -16,7 +16,6 @@ package java.util; import java.io.Serializable; - import jsinterop.annotations.JsPackage; import jsinterop.annotations.JsType; diff --git a/user/super/com/google/gwt/emul/java/util/List.java b/user/super/com/google/gwt/emul/java/util/List.java index 6cb9dd1dd3..115195390c 100644 --- a/user/super/com/google/gwt/emul/java/util/List.java +++ b/user/super/com/google/gwt/emul/java/util/List.java @@ -18,9 +18,8 @@ import static javaemul.internal.InternalPreconditions.checkNotNull; import java.util.function.UnaryOperator; -import javaemul.internal.ArrayHelper; import java.util.stream.Collectors; - +import javaemul.internal.ArrayHelper; import jsinterop.annotations.JsIgnore; import jsinterop.annotations.JsMethod; import jsinterop.annotations.JsNonNull; 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 8afd7d51bb..06d057017b 100644 --- a/user/super/com/google/gwt/emul/java/util/Map.java +++ b/user/super/com/google/gwt/emul/java/util/Map.java @@ -23,7 +23,6 @@ import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Collectors; - import jsinterop.annotations.JsIgnore; import jsinterop.annotations.JsNonNull; import jsinterop.annotations.JsType; diff --git a/user/super/com/google/gwt/emul/java/util/Set.java b/user/super/com/google/gwt/emul/java/util/Set.java index 498a14af87..6ec721d989 100644 --- a/user/super/com/google/gwt/emul/java/util/Set.java +++ b/user/super/com/google/gwt/emul/java/util/Set.java @@ -19,7 +19,6 @@ import static javaemul.internal.InternalPreconditions.checkNotNull; import java.util.stream.Collectors; - import jsinterop.annotations.JsIgnore; import jsinterop.annotations.JsType; diff --git a/user/super/com/google/gwt/emul/java/util/Vector.java b/user/super/com/google/gwt/emul/java/util/Vector.java index a71b5e3b33..a43c07209a 100644 --- a/user/super/com/google/gwt/emul/java/util/Vector.java +++ b/user/super/com/google/gwt/emul/java/util/Vector.java @@ -21,7 +21,6 @@ import java.util.function.Consumer; import java.util.function.Predicate; import java.util.function.UnaryOperator; - import jsinterop.annotations.JsNonNull; /** diff --git a/user/super/com/google/gwt/emul/java/util/function/BinaryOperator.java b/user/super/com/google/gwt/emul/java/util/function/BinaryOperator.java index caf01d201e..a7d21ffa43 100644 --- a/user/super/com/google/gwt/emul/java/util/function/BinaryOperator.java +++ b/user/super/com/google/gwt/emul/java/util/function/BinaryOperator.java @@ -15,10 +15,10 @@ */ package java.util.function; -import java.util.Comparator; - import static javaemul.internal.InternalPreconditions.checkCriticalNotNull; +import java.util.Comparator; + /** * See * the official Java API doc for details. diff --git a/user/super/com/google/gwt/emul/java/util/function/Predicate.java b/user/super/com/google/gwt/emul/java/util/function/Predicate.java index b9ad769b30..1e8caa6fb3 100644 --- a/user/super/com/google/gwt/emul/java/util/function/Predicate.java +++ b/user/super/com/google/gwt/emul/java/util/function/Predicate.java @@ -15,10 +15,10 @@ */ package java.util.function; -import java.util.Objects; - import static javaemul.internal.InternalPreconditions.checkCriticalNotNull; +import java.util.Objects; + /** * See * the official Java API doc for details. diff --git a/user/test/com/google/gwt/core/client/impl/StackTraceEmulTest.java b/user/test/com/google/gwt/core/client/impl/StackTraceEmulTest.java index b15ce7563b..6a3822ac06 100644 --- a/user/test/com/google/gwt/core/client/impl/StackTraceEmulTest.java +++ b/user/test/com/google/gwt/core/client/impl/StackTraceEmulTest.java @@ -67,7 +67,7 @@ public void testJavaLineNumbers() { String[] methodNames = getTraceJava(); StackTraceElement[] expectedTrace = new StackTraceElement[] { - createSTE(methodNames[0], "Throwable.java", 68), + createSTE(methodNames[0], "Throwable.java", 66), createSTE(methodNames[1], "Exception.java", 29), createSTE(methodNames[2], "StackTraceExamples.java", 57), createSTE(methodNames[3], "StackTraceExamples.java", 52), diff --git a/user/test/com/google/gwt/core/interop/ElementLikeNativeInterface.java b/user/test/com/google/gwt/core/interop/ElementLikeNativeInterface.java index 6d6ac09108..f50d78cc45 100644 --- a/user/test/com/google/gwt/core/interop/ElementLikeNativeInterface.java +++ b/user/test/com/google/gwt/core/interop/ElementLikeNativeInterface.java @@ -15,7 +15,6 @@ */ package com.google.gwt.core.interop; - import jsinterop.annotations.JsProperty; import jsinterop.annotations.JsType; diff --git a/user/test/com/google/gwt/core/interop/JsTypeTest.java b/user/test/com/google/gwt/core/interop/JsTypeTest.java index 8fd9ddd56b..9b42fa0c28 100644 --- a/user/test/com/google/gwt/core/interop/JsTypeTest.java +++ b/user/test/com/google/gwt/core/interop/JsTypeTest.java @@ -21,7 +21,6 @@ import com.google.gwt.junit.client.GWTTestCase; import java.util.Iterator; - import jsinterop.annotations.JsFunction; import jsinterop.annotations.JsMethod; import jsinterop.annotations.JsPackage; diff --git a/user/test/com/google/gwt/dev/jjs/optimized/CastOptimizationTest.java b/user/test/com/google/gwt/dev/jjs/optimized/CastOptimizationTest.java index 5d27b57a4a..cdf343486d 100644 --- a/user/test/com/google/gwt/dev/jjs/optimized/CastOptimizationTest.java +++ b/user/test/com/google/gwt/dev/jjs/optimized/CastOptimizationTest.java @@ -20,7 +20,6 @@ import com.google.gwt.junit.Platform; import java.util.Random; - import jsinterop.annotations.JsPackage; import jsinterop.annotations.JsType; diff --git a/user/test/com/google/gwt/dev/jjs/optimized/UncheckedCastOptimizationTest.java b/user/test/com/google/gwt/dev/jjs/optimized/UncheckedCastOptimizationTest.java index 021beed102..efc39acbfa 100644 --- a/user/test/com/google/gwt/dev/jjs/optimized/UncheckedCastOptimizationTest.java +++ b/user/test/com/google/gwt/dev/jjs/optimized/UncheckedCastOptimizationTest.java @@ -19,7 +19,6 @@ import com.google.gwt.junit.Platform; import javaemul.internal.annotations.UncheckedCast; - import jsinterop.annotations.JsPackage; import jsinterop.annotations.JsType; diff --git a/user/test/com/google/gwt/dev/jjs/test/CompilerMiscRegressionTest.java b/user/test/com/google/gwt/dev/jjs/test/CompilerMiscRegressionTest.java index 4ec71bcec9..0864c717ea 100644 --- a/user/test/com/google/gwt/dev/jjs/test/CompilerMiscRegressionTest.java +++ b/user/test/com/google/gwt/dev/jjs/test/CompilerMiscRegressionTest.java @@ -34,7 +34,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; - import javaemul.internal.annotations.DoNotInline; import jsinterop.annotations.JsMethod; import jsinterop.annotations.JsOverlay; diff --git a/user/test/com/google/gwt/emultest/CollectionsSuite.java b/user/test/com/google/gwt/emultest/CollectionsSuite.java index a273ee038b..24821cf12c 100644 --- a/user/test/com/google/gwt/emultest/CollectionsSuite.java +++ b/user/test/com/google/gwt/emultest/CollectionsSuite.java @@ -40,6 +40,7 @@ import com.google.gwt.emultest.java.util.TreeSetIntegerTest; import com.google.gwt.emultest.java.util.TreeSetIntegerWithComparatorTest; import com.google.gwt.emultest.java.util.VectorTest; + import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; diff --git a/user/test/com/google/gwt/emultest/EmulJava10Suite.java b/user/test/com/google/gwt/emultest/EmulJava10Suite.java index 5a4f28e052..06881ab9b8 100644 --- a/user/test/com/google/gwt/emultest/EmulJava10Suite.java +++ b/user/test/com/google/gwt/emultest/EmulJava10Suite.java @@ -15,14 +15,15 @@ */ package com.google.gwt.emultest; +import com.google.gwt.emultest.java10.util.ListTest; +import com.google.gwt.emultest.java10.util.MapTest; import com.google.gwt.emultest.java10.util.OptionalDoubleTest; import com.google.gwt.emultest.java10.util.OptionalIntTest; import com.google.gwt.emultest.java10.util.OptionalLongTest; import com.google.gwt.emultest.java10.util.OptionalTest; -import com.google.gwt.emultest.java10.util.ListTest; -import com.google.gwt.emultest.java10.util.MapTest; import com.google.gwt.emultest.java10.util.SetTest; import com.google.gwt.emultest.java10.util.stream.CollectorsTest; + import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; diff --git a/user/test/com/google/gwt/emultest/EmulJava11Suite.java b/user/test/com/google/gwt/emultest/EmulJava11Suite.java index 5e2ad3ab17..01b44205b8 100644 --- a/user/test/com/google/gwt/emultest/EmulJava11Suite.java +++ b/user/test/com/google/gwt/emultest/EmulJava11Suite.java @@ -20,6 +20,7 @@ import com.google.gwt.emultest.java11.util.OptionalLongTest; import com.google.gwt.emultest.java11.util.OptionalTest; import com.google.gwt.emultest.java11.util.function.PredicateTest; + import org.junit.runner.RunWith; import org.junit.runners.Suite; diff --git a/user/test/com/google/gwt/emultest/EmulJava9Suite.java b/user/test/com/google/gwt/emultest/EmulJava9Suite.java index b2f81570e3..0a28abdf88 100644 --- a/user/test/com/google/gwt/emultest/EmulJava9Suite.java +++ b/user/test/com/google/gwt/emultest/EmulJava9Suite.java @@ -15,11 +15,6 @@ */ package com.google.gwt.emultest; -import com.google.gwt.emultest.java9.util.stream.CollectorsTest; -import com.google.gwt.emultest.java9.util.stream.DoubleStreamTest; -import com.google.gwt.emultest.java9.util.stream.IntStreamTest; -import com.google.gwt.emultest.java9.util.stream.LongStreamTest; -import com.google.gwt.emultest.java9.util.stream.StreamTest; import com.google.gwt.emultest.java9.util.ListTest; import com.google.gwt.emultest.java9.util.MapTest; import com.google.gwt.emultest.java9.util.OptionalDoubleTest; @@ -27,6 +22,12 @@ import com.google.gwt.emultest.java9.util.OptionalLongTest; import com.google.gwt.emultest.java9.util.OptionalTest; import com.google.gwt.emultest.java9.util.SetTest; +import com.google.gwt.emultest.java9.util.stream.CollectorsTest; +import com.google.gwt.emultest.java9.util.stream.DoubleStreamTest; +import com.google.gwt.emultest.java9.util.stream.IntStreamTest; +import com.google.gwt.emultest.java9.util.stream.LongStreamTest; +import com.google.gwt.emultest.java9.util.stream.StreamTest; + import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; diff --git a/user/test/com/google/gwt/emultest/EmulSuite.java b/user/test/com/google/gwt/emultest/EmulSuite.java index f6de1407b7..a8deb3049c 100644 --- a/user/test/com/google/gwt/emultest/EmulSuite.java +++ b/user/test/com/google/gwt/emultest/EmulSuite.java @@ -62,6 +62,7 @@ import com.google.gwt.emultest.java.util.DateTest; import com.google.gwt.emultest.java.util.ObjectsTest; import com.google.gwt.emultest.java.util.RandomTest; + import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; diff --git a/user/test/com/google/gwt/emultest/java/internal/CoercionsTest.java b/user/test/com/google/gwt/emultest/java/internal/CoercionsTest.java index 20b252f6e7..9e07ac2886 100644 --- a/user/test/com/google/gwt/emultest/java/internal/CoercionsTest.java +++ b/user/test/com/google/gwt/emultest/java/internal/CoercionsTest.java @@ -18,7 +18,6 @@ import com.google.gwt.junit.client.GWTTestCase; import java.util.Random; - import javaemul.internal.Coercions; /** diff --git a/user/test/com/google/gwt/emultest/java/io/BufferedWriterTest.java b/user/test/com/google/gwt/emultest/java/io/BufferedWriterTest.java index 38b9a28abb..6f0626c52f 100644 --- a/user/test/com/google/gwt/emultest/java/io/BufferedWriterTest.java +++ b/user/test/com/google/gwt/emultest/java/io/BufferedWriterTest.java @@ -16,6 +16,7 @@ package com.google.gwt.emultest.java.io; import com.google.gwt.junit.client.GWTTestCase; + import java.io.BufferedWriter; import java.io.IOException; import java.io.Writer; diff --git a/user/test/com/google/gwt/emultest/java/io/OutputStreamWriterTest.java b/user/test/com/google/gwt/emultest/java/io/OutputStreamWriterTest.java index a9b9e25d3b..5e1a9761bb 100644 --- a/user/test/com/google/gwt/emultest/java/io/OutputStreamWriterTest.java +++ b/user/test/com/google/gwt/emultest/java/io/OutputStreamWriterTest.java @@ -18,6 +18,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.gwt.junit.client.GWTTestCase; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; diff --git a/user/test/com/google/gwt/emultest/java/io/PrintStreamTest.java b/user/test/com/google/gwt/emultest/java/io/PrintStreamTest.java index a0dabfe530..bdfeb4921c 100644 --- a/user/test/com/google/gwt/emultest/java/io/PrintStreamTest.java +++ b/user/test/com/google/gwt/emultest/java/io/PrintStreamTest.java @@ -18,6 +18,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.gwt.junit.client.GWTTestCase; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; diff --git a/user/test/com/google/gwt/emultest/java/lang/CharacterTest.java b/user/test/com/google/gwt/emultest/java/lang/CharacterTest.java index 426e81744e..41c6f247ec 100644 --- a/user/test/com/google/gwt/emultest/java/lang/CharacterTest.java +++ b/user/test/com/google/gwt/emultest/java/lang/CharacterTest.java @@ -16,6 +16,7 @@ package com.google.gwt.emultest.java.lang; import com.google.gwt.junit.client.GWTTestCase; + import java.util.Arrays; /** diff --git a/user/test/com/google/gwt/emultest/java/lang/JsExceptionTest.java b/user/test/com/google/gwt/emultest/java/lang/JsExceptionTest.java index 6aedfd6ad7..503d3ecd15 100644 --- a/user/test/com/google/gwt/emultest/java/lang/JsExceptionTest.java +++ b/user/test/com/google/gwt/emultest/java/lang/JsExceptionTest.java @@ -14,6 +14,7 @@ package com.google.gwt.emultest.java.lang; import com.google.gwt.testing.TestUtils; + import jsinterop.annotations.JsMethod; import jsinterop.annotations.JsPackage; import jsinterop.annotations.JsType; diff --git a/user/test/com/google/gwt/emultest/java/lang/StringTest.java b/user/test/com/google/gwt/emultest/java/lang/StringTest.java index ab16f3125f..4b08a45eee 100644 --- a/user/test/com/google/gwt/emultest/java/lang/StringTest.java +++ b/user/test/com/google/gwt/emultest/java/lang/StringTest.java @@ -18,6 +18,7 @@ import com.google.gwt.core.client.JavaScriptException; import com.google.gwt.junit.client.GWTTestCase; import com.google.gwt.testing.TestUtils; + import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.util.Arrays; diff --git a/user/test/com/google/gwt/emultest/java/lang/ThrowableTest.java b/user/test/com/google/gwt/emultest/java/lang/ThrowableTest.java index f1f369321b..a30ea5466d 100644 --- a/user/test/com/google/gwt/emultest/java/lang/ThrowableTest.java +++ b/user/test/com/google/gwt/emultest/java/lang/ThrowableTest.java @@ -16,6 +16,7 @@ package com.google.gwt.emultest.java.lang; import com.google.gwt.testing.TestUtils; + import java.io.IOException; import jsinterop.annotations.JsType; diff --git a/user/test/com/google/gwt/emultest/java/lang/ThrowableTestBase.java b/user/test/com/google/gwt/emultest/java/lang/ThrowableTestBase.java index 0397350f9b..4b2324299d 100644 --- a/user/test/com/google/gwt/emultest/java/lang/ThrowableTestBase.java +++ b/user/test/com/google/gwt/emultest/java/lang/ThrowableTestBase.java @@ -16,6 +16,7 @@ package com.google.gwt.emultest.java.lang; import com.google.gwt.junit.client.GWTTestCase; + import jsinterop.annotations.JsFunction; import jsinterop.annotations.JsMethod; import jsinterop.annotations.JsPackage; diff --git a/user/test/com/google/gwt/emultest/java/math/BigIntegerConstructorsTest.java b/user/test/com/google/gwt/emultest/java/math/BigIntegerConstructorsTest.java index c3992e527e..a32f0d24c8 100644 --- a/user/test/com/google/gwt/emultest/java/math/BigIntegerConstructorsTest.java +++ b/user/test/com/google/gwt/emultest/java/math/BigIntegerConstructorsTest.java @@ -38,6 +38,7 @@ package com.google.gwt.emultest.java.math; import com.google.gwt.emultest.java.util.EmulTestBase; + import java.math.BigInteger; import java.util.Random; diff --git a/user/test/com/google/gwt/emultest/java/nio/charset/CharsetTest.java b/user/test/com/google/gwt/emultest/java/nio/charset/CharsetTest.java index 8811f06da4..2b9c274e6d 100644 --- a/user/test/com/google/gwt/emultest/java/nio/charset/CharsetTest.java +++ b/user/test/com/google/gwt/emultest/java/nio/charset/CharsetTest.java @@ -17,6 +17,7 @@ package com.google.gwt.emultest.java.nio.charset; import com.google.gwt.emultest.java.util.EmulTestBase; + import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; diff --git a/user/test/com/google/gwt/emultest/java/sql/SqlDateTest.java b/user/test/com/google/gwt/emultest/java/sql/SqlDateTest.java index f6a344bdef..48003358d0 100644 --- a/user/test/com/google/gwt/emultest/java/sql/SqlDateTest.java +++ b/user/test/com/google/gwt/emultest/java/sql/SqlDateTest.java @@ -16,6 +16,7 @@ package com.google.gwt.emultest.java.sql; import com.google.gwt.junit.client.GWTTestCase; + import java.sql.Date; /** diff --git a/user/test/com/google/gwt/emultest/java/util/ArrayDequeTest.java b/user/test/com/google/gwt/emultest/java/util/ArrayDequeTest.java index be4db76ed3..4f939bf1e1 100644 --- a/user/test/com/google/gwt/emultest/java/util/ArrayDequeTest.java +++ b/user/test/com/google/gwt/emultest/java/util/ArrayDequeTest.java @@ -19,6 +19,7 @@ import com.google.gwt.core.client.JavaScriptException; import com.google.gwt.testing.TestUtils; + import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; diff --git a/user/test/com/google/gwt/emultest/java/util/ArraysDoubleSemanticsTest.java b/user/test/com/google/gwt/emultest/java/util/ArraysDoubleSemanticsTest.java index 42d9b2fd97..6b83c1129c 100644 --- a/user/test/com/google/gwt/emultest/java/util/ArraysDoubleSemanticsTest.java +++ b/user/test/com/google/gwt/emultest/java/util/ArraysDoubleSemanticsTest.java @@ -16,6 +16,7 @@ package com.google.gwt.emultest.java.util; import com.google.gwt.testing.TestUtils; + import java.util.Arrays; /** Tests {@link Arrays} (incorrect) Double semantics. */ diff --git a/user/test/com/google/gwt/emultest/java/util/ArraysFloatSemanticsTest.java b/user/test/com/google/gwt/emultest/java/util/ArraysFloatSemanticsTest.java index 2c38e2a284..be30d20670 100644 --- a/user/test/com/google/gwt/emultest/java/util/ArraysFloatSemanticsTest.java +++ b/user/test/com/google/gwt/emultest/java/util/ArraysFloatSemanticsTest.java @@ -16,6 +16,7 @@ package com.google.gwt.emultest.java.util; import com.google.gwt.testing.TestUtils; + import java.util.Arrays; /** Tests {@link Arrays} (incorrect) Float semantics. */ diff --git a/user/test/com/google/gwt/emultest/java/util/DateTest.java b/user/test/com/google/gwt/emultest/java/util/DateTest.java index e987c2ce11..452e1f53f9 100644 --- a/user/test/com/google/gwt/emultest/java/util/DateTest.java +++ b/user/test/com/google/gwt/emultest/java/util/DateTest.java @@ -17,6 +17,7 @@ import com.google.gwt.junit.client.GWTTestCase; import com.google.gwt.testing.TestUtils; + import java.util.ArrayList; import java.util.Date; diff --git a/user/test/com/google/gwt/emultest/java/util/IdentityHashMapTest.java b/user/test/com/google/gwt/emultest/java/util/IdentityHashMapTest.java index d4957bb906..c0d1299d2c 100644 --- a/user/test/com/google/gwt/emultest/java/util/IdentityHashMapTest.java +++ b/user/test/com/google/gwt/emultest/java/util/IdentityHashMapTest.java @@ -16,6 +16,7 @@ package com.google.gwt.emultest.java.util; import com.google.gwt.testing.TestUtils; + import java.util.Collection; import java.util.HashMap; import java.util.IdentityHashMap; diff --git a/user/test/com/google/gwt/emultest/java/util/LinkedHashMapTest.java b/user/test/com/google/gwt/emultest/java/util/LinkedHashMapTest.java index e6a11a2d1f..80594bca67 100644 --- a/user/test/com/google/gwt/emultest/java/util/LinkedHashMapTest.java +++ b/user/test/com/google/gwt/emultest/java/util/LinkedHashMapTest.java @@ -16,6 +16,7 @@ package com.google.gwt.emultest.java.util; import com.google.gwt.testing.TestUtils; + import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; diff --git a/user/test/com/google/gwt/emultest/java/util/TestMap.java b/user/test/com/google/gwt/emultest/java/util/TestMap.java index bded458177..b38929e826 100644 --- a/user/test/com/google/gwt/emultest/java/util/TestMap.java +++ b/user/test/com/google/gwt/emultest/java/util/TestMap.java @@ -18,6 +18,7 @@ package com.google.gwt.emultest.java.util; import com.google.gwt.testing.TestUtils; + import java.util.Arrays; import java.util.Collection; import java.util.ConcurrentModificationException; diff --git a/user/test/com/google/gwt/emultest/java/util/TreeMapTest.java b/user/test/com/google/gwt/emultest/java/util/TreeMapTest.java index aec828107a..372a24887c 100644 --- a/user/test/com/google/gwt/emultest/java/util/TreeMapTest.java +++ b/user/test/com/google/gwt/emultest/java/util/TreeMapTest.java @@ -16,6 +16,7 @@ package com.google.gwt.emultest.java.util; import com.google.gwt.testing.TestUtils; + import java.util.AbstractMap.SimpleEntry; import java.util.ArrayList; import java.util.Collection; diff --git a/user/test/com/google/gwt/emultest/java/util/TreeSetTest.java b/user/test/com/google/gwt/emultest/java/util/TreeSetTest.java index e2f939a5b8..b9cd81d12a 100644 --- a/user/test/com/google/gwt/emultest/java/util/TreeSetTest.java +++ b/user/test/com/google/gwt/emultest/java/util/TreeSetTest.java @@ -16,6 +16,7 @@ package com.google.gwt.emultest.java.util; import com.google.gwt.testing.TestUtils; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; diff --git a/user/test/com/google/gwt/emultest/java11/util/function/PredicateTest.java b/user/test/com/google/gwt/emultest/java11/util/function/PredicateTest.java index e2bf74df73..271a00bb63 100644 --- a/user/test/com/google/gwt/emultest/java11/util/function/PredicateTest.java +++ b/user/test/com/google/gwt/emultest/java11/util/function/PredicateTest.java @@ -16,6 +16,7 @@ package com.google.gwt.emultest.java11.util.function; import com.google.gwt.emultest.java.util.EmulTestBase; + import java.util.function.Predicate; /** diff --git a/user/test/com/google/gwt/emultest/java8/util/DoubleSummaryStatisticsTest.java b/user/test/com/google/gwt/emultest/java8/util/DoubleSummaryStatisticsTest.java index 191f3acfb3..6317d90fd4 100644 --- a/user/test/com/google/gwt/emultest/java8/util/DoubleSummaryStatisticsTest.java +++ b/user/test/com/google/gwt/emultest/java8/util/DoubleSummaryStatisticsTest.java @@ -16,7 +16,6 @@ package com.google.gwt.emultest.java8.util; -import com.google.gwt.emultest.java.util.EmulTestBase; import static java.lang.Double.MAX_VALUE; import static java.lang.Double.MIN_VALUE; @@ -24,6 +23,8 @@ import static java.lang.Double.NaN; import static java.lang.Double.POSITIVE_INFINITY; +import com.google.gwt.emultest.java.util.EmulTestBase; + import java.util.Arrays; import java.util.DoubleSummaryStatistics; import java.util.List; diff --git a/user/test/com/google/gwt/emultest/java8/util/IntSummaryStatisticsTest.java b/user/test/com/google/gwt/emultest/java8/util/IntSummaryStatisticsTest.java index e1a49d28bb..35a016c160 100644 --- a/user/test/com/google/gwt/emultest/java8/util/IntSummaryStatisticsTest.java +++ b/user/test/com/google/gwt/emultest/java8/util/IntSummaryStatisticsTest.java @@ -16,11 +16,11 @@ package com.google.gwt.emultest.java8.util; -import com.google.gwt.emultest.java.util.EmulTestBase; - import static java.lang.Integer.MAX_VALUE; import static java.lang.Integer.MIN_VALUE; +import com.google.gwt.emultest.java.util.EmulTestBase; + import java.util.IntSummaryStatistics; /** diff --git a/user/test/com/google/gwt/emultest/java8/util/LongSummaryStatisticsTest.java b/user/test/com/google/gwt/emultest/java8/util/LongSummaryStatisticsTest.java index 518351c5f9..f35fb47559 100644 --- a/user/test/com/google/gwt/emultest/java8/util/LongSummaryStatisticsTest.java +++ b/user/test/com/google/gwt/emultest/java8/util/LongSummaryStatisticsTest.java @@ -16,11 +16,11 @@ package com.google.gwt.emultest.java8.util; -import com.google.gwt.emultest.java.util.EmulTestBase; - import static java.lang.Long.MAX_VALUE; import static java.lang.Long.MIN_VALUE; +import com.google.gwt.emultest.java.util.EmulTestBase; + import java.util.LongSummaryStatistics; /** diff --git a/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java b/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java index 9e3926413d..d6f8eea8b9 100644 --- a/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java +++ b/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java @@ -19,7 +19,6 @@ import static java.util.Arrays.asList; import com.google.gwt.emultest.java.util.EmulTestBase; - import com.google.gwt.testing.TestUtils; import java.util.ArrayList; diff --git a/user/test/com/google/gwt/i18n/rebind/ConstantsWithLookupImplCreatorTest.java b/user/test/com/google/gwt/i18n/rebind/ConstantsWithLookupImplCreatorTest.java index ca23f82ac7..ef4d40c1cb 100644 --- a/user/test/com/google/gwt/i18n/rebind/ConstantsWithLookupImplCreatorTest.java +++ b/user/test/com/google/gwt/i18n/rebind/ConstantsWithLookupImplCreatorTest.java @@ -15,6 +15,10 @@ */ package com.google.gwt.i18n.rebind; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.core.ext.typeinfo.JClassType; @@ -35,10 +39,6 @@ import junit.framework.TestCase; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/user/test/com/google/gwt/i18n/rebind/LookupMethodCreatorTest.java b/user/test/com/google/gwt/i18n/rebind/LookupMethodCreatorTest.java index 3fb045b0b0..565f652263 100644 --- a/user/test/com/google/gwt/i18n/rebind/LookupMethodCreatorTest.java +++ b/user/test/com/google/gwt/i18n/rebind/LookupMethodCreatorTest.java @@ -15,6 +15,8 @@ */ package com.google.gwt.i18n.rebind; +import static org.mockito.Mockito.mock; + import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.core.ext.typeinfo.JClassType; @@ -35,8 +37,6 @@ import junit.framework.TestCase; -import static org.mockito.Mockito.mock; - import java.util.List; /** diff --git a/user/test/com/google/gwt/resources/rg/CssOutputTestCase.java b/user/test/com/google/gwt/resources/rg/CssOutputTestCase.java index 2f1d9742c2..9e87f0a21a 100644 --- a/user/test/com/google/gwt/resources/rg/CssOutputTestCase.java +++ b/user/test/com/google/gwt/resources/rg/CssOutputTestCase.java @@ -15,6 +15,11 @@ */ package com.google.gwt.resources.rg; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + import com.google.gwt.core.ext.GeneratorContext; import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.core.ext.linker.GeneratedResource; @@ -25,11 +30,6 @@ import junit.framework.TestCase; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.util.HashMap; diff --git a/user/test/com/google/gwt/uibinder/rebind/HandlerEvaluatorTest.java b/user/test/com/google/gwt/uibinder/rebind/HandlerEvaluatorTest.java index ebaa500e50..294f04aa35 100644 --- a/user/test/com/google/gwt/uibinder/rebind/HandlerEvaluatorTest.java +++ b/user/test/com/google/gwt/uibinder/rebind/HandlerEvaluatorTest.java @@ -15,6 +15,9 @@ */ package com.google.gwt.uibinder.rebind; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import com.google.gwt.core.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.TypeOracle; import com.google.gwt.dev.util.log.PrintWriterTreeLogger; @@ -24,9 +27,6 @@ import junit.framework.TestCase; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - import java.io.PrintWriter; import java.io.StringWriter; diff --git a/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java b/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java index d398bdab4a..0dccfa203c 100644 --- a/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java +++ b/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java @@ -15,6 +15,11 @@ */ package com.google.gwt.user.client.rpc; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertSame; + import com.google.gwt.event.shared.UmbrellaException; import com.google.gwt.user.client.rpc.FinalFieldsTestService.FinalFieldsNode; import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeEmptyKey; @@ -33,11 +38,6 @@ import com.google.gwt.user.client.rpc.TestSetFactory.SerializablePrivateNoArg; import com.google.gwt.user.client.rpc.TestSetFactory.SerializableWithTwoArrays; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertSame; - import java.util.ArrayList; import java.util.EnumMap; import java.util.HashMap; From a848ffa3a30d1a62ecc201b2c592164edba1dfd0 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Mon, 12 Feb 2024 09:59:55 -0600 Subject: [PATCH 19/27] Un-supersource Java 8-11 tests (#9918) Simplify test setup, as these tests no longer need to use supersource. --- .../google/gwt/dev/jjs/test/Java10Test.java | 162 -- .../google/gwt/dev/jjs/test/Java11Test.java | 59 - .../google/gwt/dev/jjs/test/Java8Test.java | 2044 ----------------- .../google/gwt/dev/jjs/test/Java9Test.java | 99 - .../com/google/gwt/dev/jjs/CompilerSuite.java | 4 +- .../com/google/gwt/dev/jjs/Java10Test.gwt.xml | 2 +- .../com/google/gwt/dev/jjs/Java11Test.gwt.xml | 2 +- .../com/google/gwt/dev/jjs/Java8Test.gwt.xml | 2 +- .../com/google/gwt/dev/jjs/Java9Test.gwt.xml | 2 +- .../google/gwt/dev/jjs/test/Java10Test.java | 123 +- .../google/gwt/dev/jjs/test/Java11Test.java | 37 +- .../google/gwt/dev/jjs/test/Java8Test.java | 1907 ++++++++++++++- .../google/gwt/dev/jjs/test/Java9Test.java | 82 +- ...WithDefaultMethodAndStaticInitializer.java | 0 .../jjs/test/defaultmethods/SomeClass.java | 0 ...WithDefaultMethodAndStaticInitializer.java | 0 .../gwt/dev/jjs/test/package1/SimpleA.java | 0 .../gwt/dev/jjs/test/package1/SimpleD.java | 0 .../gwt/dev/jjs/test/package2/SimpleB.java | 0 .../gwt/dev/jjs/test/package3/SimpleC.java | 0 20 files changed, 1988 insertions(+), 2537 deletions(-) delete mode 100644 user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java10Test.java delete mode 100644 user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java11Test.java delete mode 100644 user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java8Test.java delete mode 100644 user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java9Test.java rename user/{test-super/com/google/gwt/dev/jjs/super => test}/com/google/gwt/dev/jjs/test/defaultmethods/ImplementsWithDefaultMethodAndStaticInitializer.java (100%) rename user/{test-super/com/google/gwt/dev/jjs/super => test}/com/google/gwt/dev/jjs/test/defaultmethods/SomeClass.java (100%) rename user/{test-super/com/google/gwt/dev/jjs/super => test}/com/google/gwt/dev/jjs/test/defaultmethods/WithDefaultMethodAndStaticInitializer.java (100%) rename user/{test-super/com/google/gwt/dev/jjs/super => test}/com/google/gwt/dev/jjs/test/package1/SimpleA.java (100%) rename user/{test-super/com/google/gwt/dev/jjs/super => test}/com/google/gwt/dev/jjs/test/package1/SimpleD.java (100%) rename user/{test-super/com/google/gwt/dev/jjs/super => test}/com/google/gwt/dev/jjs/test/package2/SimpleB.java (100%) rename user/{test-super/com/google/gwt/dev/jjs/super => test}/com/google/gwt/dev/jjs/test/package3/SimpleC.java (100%) diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java10Test.java b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java10Test.java deleted file mode 100644 index 1eb6875da6..0000000000 --- a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java10Test.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2018 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.dev.jjs.test; - -import com.google.gwt.core.client.GwtScriptOnly; -import com.google.gwt.junit.client.GWTTestCase; - -import java.util.ArrayList; -import java.util.function.Supplier; - -import java.io.Serializable; - -/** - * Tests Java 10 features. It is super sourced so that gwt can be compiled under Java 7. - * - * IMPORTANT: For each test here there must exist the corresponding method in the non super sourced - * version. - * - * Eventually this test will graduate and not be super sourced. - */ -@GwtScriptOnly -public class Java10Test extends GWTTestCase { - - interface VarArgsFunction { - R apply(T... args); - } - - @Override - public String getModuleName() { - return "com.google.gwt.dev.jjs.Java10Test"; - } - - public void testLocalVarType_DenotableTypes() { - var i = 42; - assertEquals(42, i); - var s = "42"; - assertEquals("42", s); - - Supplier initializer = () -> "37"; - var s2 = initializer.get(); - // to be sure that s2 was inferred as a string and not an Object - String s3 = s2; - assertEquals("37", s3); - } - - public void testLocalVarType_Anonymous() { - var o = new Object() { - int i; - String s; - }; - o.i = 42; - o.s = "42"; - assertEquals(42, o.i); - assertEquals("42", o.s); - } - - public void testLocalVarType_Ternary() { - var value = true ? "a" : 'c'; - checkSerializableDispatch(value); - checkComparableDispatch(value); - assertEquals("a", value.toString()); - } - - private void checkSerializableDispatch(Object fail) { - fail("should not be treated as object"); - } - - private void checkSerializableDispatch(Serializable pass) { - // pass - } - - private void checkComparableDispatch(Object fail) { - fail("should not be treated as object"); - } - - private void checkComparableDispatch(Comparable pass) { - // pass - } - - public void testLocalVarType_LambdaCapture() { - var s = "42"; - Supplier supplier = () -> s; - assertEquals("42", supplier.get()); - } - - public void testLocalVarType_VarArg() { - var args = new String[] {"4", "2"}; - VarArgsFunction f = arr -> arr[0] + arr[1]; - assertEquals("42", f.apply(args)); - } - - public void testLocalVarType_LocalClass() { - var i = 37; - class Local { - int m() { - var i = 40; - return i + 2; - } - - int fromOuterScope() { - return i; - } - } - - var l = new Local(); - assertEquals(37, l.fromOuterScope()); - assertEquals(42, l.m()); - } - - public void testLocalVarType_ForLoop() { - var a = new String[] {"4", "2"}; - var s = ""; - for (var i = 0; i < a.length; i++) { - s += a[i]; - } - assertEquals("42", s); - } - - public void testLocalVarType_EnhancedForLoopArray() { - var a = new String[] {"4", "2"}; - var str = ""; - for (var s : a) { - str += s; - } - assertEquals("42", str); - } - - public void testLocalVarType_EnhancedNestedForLoopArray() { - var m = new int[][] {{1, 2}, {3, 4}}; - var summ = 0; - for (var row : m) { - for (var cell : row) { - summ += cell; - } - } - assertEquals(10, summ); - } - - public void testLocalVarType_EnhancedForLoopIterable() { - var list = new ArrayList(); - list.add("4"); - list.add("2"); - var str = ""; - for (var s : list) { - str += s; - } - assertEquals("42", str); - } -} diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java11Test.java b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java11Test.java deleted file mode 100644 index 9e9c8f662c..0000000000 --- a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java11Test.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2019 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.dev.jjs.test; - -import com.google.gwt.core.client.GwtScriptOnly; -import com.google.gwt.junit.client.GWTTestCase; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Tests Java 11 features. It is super sourced so that gwt can be compiles under Java 8. - * - * IMPORTANT: For each test here there must exist the corresponding method in the non super sourced - * version. - * - * Eventually this test will graduate and not be super sourced. - */ -@GwtScriptOnly -public class Java11Test extends GWTTestCase { - - @interface NotNull { - } - - interface Lambda { - T run(T a, T b); - } - - @Override - public String getModuleName() { - return "com.google.gwt.dev.jjs.Java11Test"; - } - - public void testLambdaParametersVarType() { - Lambda l = (@NotNull var x, var y) -> x + y; - assertEquals("12", l.run("1", "2")); - } - - public void testLambdaParametersVarType_function() { - List l = Arrays.asList("a", "b"); - l = l.stream().map((var s) -> s.toUpperCase()).collect(Collectors.toList()); - assertEquals("A", l.get(0)); - assertEquals("B", l.get(1)); - } -} diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java8Test.java b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java8Test.java deleted file mode 100644 index 9f3c4e0289..0000000000 --- a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java8Test.java +++ /dev/null @@ -1,2044 +0,0 @@ -/* - * Copyright 2014 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.dev.jjs.test; - -import com.google.gwt.core.client.GwtScriptOnly; -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.core.client.JsonUtils; -import com.google.gwt.dev.jjs.test.defaultmethods.ImplementsWithDefaultMethodAndStaticInitializer; -import com.google.gwt.dev.jjs.test.defaultmethods.SomeClass; -import com.google.gwt.junit.client.GWTTestCase; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.function.BiFunction; -import java.util.function.IntFunction; -import java.util.function.Predicate; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -import jsinterop.annotations.JsFunction; -import jsinterop.annotations.JsOverlay; -import jsinterop.annotations.JsPackage; -import jsinterop.annotations.JsProperty; -import jsinterop.annotations.JsType; - -/** - * Tests Java 8 features. It is super sourced so that gwt can be compiles under Java 7. - * - * IMPORTANT: For each test here there must exist the corresponding method in the non super sourced - * version. - * - * Eventually this test will graduate and not be super sourced. - */ -@GwtScriptOnly -public class Java8Test extends GWTTestCase { - int local = 42; - - static abstract class SameClass { - public int method1() { return 10; } - public abstract int method2(); - } - - interface Lambda { - T run(int a, int b); - } - - interface Lambda2 { - boolean run(String a, String b); - } - - interface Lambda3 { - boolean run(String a); - } - - class AcceptsLambda { - public T accept(Lambda foo) { - return foo.run(10, 20); - } - public boolean accept2(Lambda2 foo) { - return foo.run("a", "b"); - } - public boolean accept3(Lambda3 foo) { - return foo.run("hello"); - } - } - - class Pojo { - private final int x; - private final int y; - - public Pojo(int x, int y) { - this.x = x; - this.y = y; - } - - public int fooInstance(int a, int b) { - return a + b + x + y; - } - } - - interface DefaultInterface { - void method1(); - // CHECKSTYLE_OFF - default int method2() { return 42; } - default int redeclaredAsAbstract() { - return 88; - } - default Integer addInts(int x, int y) { return x + y; } - default String print() { return "DefaultInterface"; } - // CHECKSTYLE_ON - } - - interface DefaultInterface2 { - void method3(); - // CHECKSTYLE_OFF - default int method4() { return 23; } - default int redeclaredAsAbstract() { - return 77; - } - // CHECKSTYLE_ON - } - - interface DefaultInterfaceSubType extends DefaultInterface { - // CHECKSTYLE_OFF - default int method2() { return 43; } - default String print() { - return "DefaultInterfaceSubType " + DefaultInterface.super.print(); - } - // CHECKSTYLE_ON - } - - static abstract class DualImplementorSuper implements DefaultInterface { - public void method1() { - } - - public abstract int redeclaredAsAbstract(); - } - - static class DualImplementorBoth extends VirtualUpRef implements DefaultInterface, - DefaultInterface2 { - public void method1() { - } - public void method3() { - } - } - - static class DualImplementor extends DualImplementorSuper implements DefaultInterface2 { - public void method3() { - } - - public int redeclaredAsAbstract() { - return DefaultInterface2.super.redeclaredAsAbstract(); - } - } - - // this doesn't implement DefaultInterface, but will provide implementation in subclasses - static class VirtualUpRef { - public int method2() { - return 99; - } - public int redeclaredAsAbstract() { - return 44; - } - } - - class Inner { - int local = 22; - public void run() { - assertEquals(94, new AcceptsLambda().accept((a,b) -> Java8Test.this.local + local + a + b).intValue()); - } - } - - static class Static { - static int staticField; - static { - staticField = 99; - } - static Integer staticMethod(int x, int y) { return x + y + staticField; } - } - - static class StaticFailIfClinitRuns { - static { - fail("clinit() shouldn't run from just taking a reference to a method"); - } - - public static Integer staticMethod(int x, int y) { - return null; - } - } - - static class DefaultInterfaceImpl implements DefaultInterface { - public void method1() { - } - } - - static class DefaultInterfaceImpl2 implements DefaultInterface { - public void method1() { - } - public int method2() { - return 100; - } - } - - static class DefaultInterfaceImplVirtualUpRef extends VirtualUpRef implements DefaultInterface { - public void method1() { - } - } - - static class DefaultInterfaceImplVirtualUpRefTwoInterfaces extends VirtualUpRef - implements DefaultInterfaceSubType { - public void method1() { - } - // CHECKSTYLE_OFF - public String print() { return "DefaultInterfaceImplVirtualUpRefTwoInterfaces"; } - // CHECKSTYLE_ON - } - - @Override - public String getModuleName() { - return "com.google.gwt.dev.jjs.Java8Test"; - } - - public void testLambdaNoCapture() { - assertEquals(30, new AcceptsLambda().accept((a, b) -> a + b).intValue()); - } - - public void testLambdaCaptureLocal() { - int x = 10; - assertEquals(40, new AcceptsLambda().accept((a,b) -> x + a + b).intValue()); - } - - public void testLambdaCaptureLocalWithInnerClass() { - int x = 10; - Lambda l = (a,b) -> new Lambda() { - @Override public Integer run(int a, int b) { - int t = x; - return t + a + b; - } - }.run(a,b); - assertEquals(40, new AcceptsLambda().accept(l).intValue()); - } - - public void testLambdaCaptureLocalAndField() { - int x = 10; - assertEquals(82, new AcceptsLambda().accept((a,b) -> x + local + a + b).intValue()); - } - - public void testLambdaCaptureLocalAndFieldWithInnerClass() { - int x = 10; - Lambda l = (a,b) -> new Lambda() { - @Override public Integer run(int j, int k) { - int t = x; - int s = local; - return t + s + a + b; - } - }.run(a,b); - assertEquals(82, new AcceptsLambda().accept(l).intValue()); - } - - public void testCompileLambdaCaptureOuterInnerField() throws Exception { - new Inner().run(); - } - - public void testStaticReferenceBinding() throws Exception { - assertEquals(129, new AcceptsLambda().accept(Static::staticMethod).intValue()); - // if this next line runs a clinit, it fails - Lambda l = dummyMethodToMakeCheckStyleHappy(StaticFailIfClinitRuns::staticMethod); - try { - // but now it should fail - l.run(1,2); - fail("Clinit should have run for the first time"); - } catch (AssertionError ae) { - // success, it was supposed to throw! - } - } - - private static Lambda dummyMethodToMakeCheckStyleHappy(Lambda l) { - return l; - } - - public void testInstanceReferenceBinding() throws Exception { - Pojo instance1 = new Pojo(1, 2); - Pojo instance2 = new Pojo(3, 4); - assertEquals(33, new AcceptsLambda().accept(instance1::fooInstance).intValue()); - assertEquals(37, new AcceptsLambda().accept(instance2::fooInstance).intValue()); - } - - public void testImplicitQualifierReferenceBinding() throws Exception { - assertFalse(new AcceptsLambda().accept2(String::equalsIgnoreCase)); - assertTrue(new AcceptsLambda().accept3("hello world"::contains)); - } - - public void testConstructorReferenceBinding() { - assertEquals(30, new AcceptsLambda().accept(Pojo::new).fooInstance(0, 0)); - } - - public void testStaticInterfaceMethod() { - assertEquals(99, (int) Static.staticMethod(0, 0)); - } - - interface ArrayCtor { - ArrayElem [][][] copy(int i); - } - - interface ArrayCtorBoxed { - ArrayElem [][][] copy(Integer i); - } - - static class ArrayElem { - } - - public void testArrayConstructorReference() { - ArrayCtor ctor = ArrayElem[][][]::new; - ArrayElem[][][] array = ctor.copy(100); - assertEquals(100, array.length); - } - - public void testArrayConstructorReferenceBoxed() { - ArrayCtorBoxed ctor = ArrayElem[][][]::new; - ArrayElem[][][] array = ctor.copy(100); - assertEquals(100, array.length); - } - - interface ThreeArgs { - int foo(int x, int y, int z); - } - - interface ThreeVarArgs { - int foo(int x, int y, int... z); - } - - public static int addMany(int x, int y, int... nums) { - int sum = x + y; - for (int num : nums) { - sum += num; - } - return sum; - } - - public void testVarArgsReferenceBinding() { - ThreeArgs t = Java8Test::addMany; - assertEquals(6, t.foo(1,2,3)); - } - - public void testVarArgsPassthroughReferenceBinding() { - ThreeVarArgs t = Java8Test::addMany; - assertEquals(6, t.foo(1,2,3)); - } - - public void testVarArgsPassthroughReferenceBindingProvidedArray() { - ThreeVarArgs t = Java8Test::addMany; - assertEquals(6, t.foo(1,2, new int[] {3})); - } - - interface I { - int foo(Integer i); - } - - public void testSuperReferenceExpression() { - class Y { - int foo(Integer i) { - return 42; - } - } - - class X extends Y { - int foo(Integer i) { - return 23; - } - - int goo() { - I i = super::foo; - return i.foo(0); - } - } - - assertEquals(42, new X().goo()); - } - - public void testQualifiedSuperReferenceExpression() { - class Y { - int foo(Integer i) { - return 42; - } - } - - class X extends Y { - int foo(Integer i) { - return 23; - } - - int goo() { - I i = X.super::foo; - return i.foo(0); - } - } - - assertEquals(42, new X().goo()); - } - - static class X2 { - protected int field; - void foo() { - int local; - class Y extends X2 { - class Z extends X2 { - void f() { - Ctor c = X2::new; - X2 x = c.makeX(123456); - assertEquals(123456, x.field); - c = Y::new; - x = c.makeX(987654); - x = new Y(987654); - assertEquals(987655, x.field); - c = Z::new; - x = c.makeX(456789); - x = new Z(456789); - assertEquals(456791, x.field); - } - private Z(int z) { - super(z + 2); - } - Z() { - } - } - - private Y(int y) { - super(y + 1); - } - - private Y() { - } - } - new Y().new Z().f(); - } - - private X2(int x) { - this.field = x; - } - X2() { - } - } - - public void testSuperReferenceExpressionWithVarArgs() { - class Base { - int foo(Object... objects) { - return 0; - } - } - - class X extends Base { - int foo(Object... objects) { - throw new AssertionError(); - } - - void goo() { - I i = super::foo; - i.foo(10); - } - } - new X().goo(); - } - - interface Ctor { - X2 makeX(int x); - } - - public void testPrivateConstructorReference() { - new X2().foo(); - } - - public void testDefaultInterfaceMethod() { - assertEquals(42, new DefaultInterfaceImpl().method2()); - } - - public void testDefaultInterfaceMethodVirtualUpRef() { - assertEquals(99, new DefaultInterfaceImplVirtualUpRef().method2()); - assertEquals(99, new DefaultInterfaceImplVirtualUpRefTwoInterfaces().method2()); - assertEquals("SimpleB", new com.google.gwt.dev.jjs.test.package3.SimpleC().m()); - assertEquals("SimpleASimpleB", new com.google.gwt.dev.jjs.test.package1.SimpleD().m()); - } - - public void testDefaultInterfaceMethodMultiple() { - assertEquals(42, new DualImplementor().method2()); - assertEquals(23, new DualImplementor().method4()); - assertEquals(77, new DualImplementor().redeclaredAsAbstract()); - assertEquals(44, new DualImplementorBoth().redeclaredAsAbstract()); - DefaultInterfaceImplVirtualUpRefTwoInterfaces instanceImplementInterfaceSubType = - new DefaultInterfaceImplVirtualUpRefTwoInterfaces(); - DefaultInterfaceSubType interfaceSubType1 = instanceImplementInterfaceSubType; - assertEquals("DefaultInterfaceImplVirtualUpRefTwoInterfaces", - instanceImplementInterfaceSubType.print()); - assertEquals("DefaultInterfaceImplVirtualUpRefTwoInterfaces", interfaceSubType1.print()); - DefaultInterfaceSubType interfaceSubType2 = new DefaultInterfaceSubType() { - @Override - public void method1() { } - }; - assertEquals("DefaultInterfaceSubType DefaultInterface", - interfaceSubType2.print()); - DefaultInterfaceSubType interfaceSubType3 = () -> { }; - assertEquals("DefaultInterfaceSubType DefaultInterface", - interfaceSubType3.print()); - } - - public void testDefenderMethodByInterfaceInstance() { - DefaultInterfaceImpl2 interfaceImpl2 = new DefaultInterfaceImpl2(); - DefaultInterface interface1 = interfaceImpl2; - assertEquals(100, interfaceImpl2.method2()); - assertEquals(100, interface1.method2()); - } - - public void testDefaultMethodReference() { - DefaultInterfaceImplVirtualUpRef x = new DefaultInterfaceImplVirtualUpRef(); - assertEquals(30, (int) new AcceptsLambda().accept(x::addInts)); - } - - interface InterfaceWithTwoDefenderMethods { - // CHECKSTYLE_OFF - default String foo() { return "interface.foo"; } - default String bar() { return this.foo() + " " + foo(); } - // CHECKSTYLE_ON - } - - class ClassImplementOneDefenderMethod implements InterfaceWithTwoDefenderMethods { - public String foo() { - return "class.foo"; - } - } - - public void testThisRefInDefenderMethod() { - ClassImplementOneDefenderMethod c = new ClassImplementOneDefenderMethod(); - InterfaceWithTwoDefenderMethods i1 = c; - InterfaceWithTwoDefenderMethods i2 = new InterfaceWithTwoDefenderMethods() { }; - assertEquals("class.foo class.foo", c.bar()); - assertEquals("class.foo class.foo", i1.bar()); - assertEquals("interface.foo interface.foo", i2.bar()); - } - - interface InterfaceImplementOneDefenderMethod extends InterfaceWithTwoDefenderMethods { - // CHECKSTYLE_OFF - default String foo() { return "interface1.foo"; } - // CHECKSTYLE_ON - } - - interface InterfaceImplementZeroDefenderMethod extends InterfaceWithTwoDefenderMethods { - } - - class ClassImplementsTwoInterfaces implements InterfaceImplementOneDefenderMethod, - InterfaceImplementZeroDefenderMethod { - } - - public void testClassImplementsTwoInterfacesWithSameDefenderMethod() { - ClassImplementsTwoInterfaces c = new ClassImplementsTwoInterfaces(); - assertEquals("interface1.foo", c.foo()); - } - - abstract class AbstractClass implements InterfaceWithTwoDefenderMethods { - } - - class Child1 extends AbstractClass { - public String foo() { - return super.foo() + " child1.foo"; - } - } - - class Child2 extends AbstractClass { - } - - public void testAbstractClassImplementsInterface() { - Child1 child1 = new Child1(); - Child2 child2 = new Child2(); - assertEquals("interface.foo child1.foo", child1.foo()); - assertEquals("interface.foo", child2.foo()); - } - - interface InterfaceI { - // CHECKSTYLE_OFF - default String print() { return "interface1"; } - // CHECKSTYLE_ON - } - interface InterfaceII { - // CHECKSTYLE_OFF - default String print() { return "interface2"; } - // CHECKSTYLE_ON - } - class ClassI { - public String print() { - return "class1"; - } - } - class ClassII extends ClassI implements InterfaceI, InterfaceII { - public String print() { - return super.print() + " " + InterfaceI.super.print() + " " + InterfaceII.super.print(); - } - } - - public void testSuperRefInDefenderMethod() { - ClassII c = new ClassII(); - assertEquals("class1 interface1 interface2", c.print()); - } - - interface II { - // CHECKSTYLE_OFF - default String fun() { return "fun() in i: " + this.foo(); }; - default String foo() { return "foo() in i.\n"; }; - // CHECKSTYLE_ON - } - interface JJ extends II { - // CHECKSTYLE_OFF - default String fun() { return "fun() in j: " + this.foo() + II.super.fun(); }; - default String foo() { return "foo() in j.\n"; } - // CHECKSTYLE_ON - } - class AA { - public String fun() { - return "fun() in a: " + this.foo(); - } - public String foo() { - return "foo() in a.\n"; - } - } - class BB extends AA implements JJ { - public String fun() { - return "fun() in b: " + this.foo() + super.fun() + JJ.super.fun(); - } - public String foo() { - return "foo() in b.\n"; - } - } - class CC extends BB implements JJ { - public String fun() { - return "fun() in c: " + super.fun(); - } - } - - public void testSuperThisRefsInDefenderMethod() { - CC c = new CC(); - II i1 = c; - JJ j1 = c; - BB b = new BB(); - II i2 = b; - JJ j2 = b; - JJ j3 = new JJ() { }; - II i3 = j3; - II i4 = new II() { }; - String c_fun = "fun() in c: fun() in b: foo() in b.\n" - + "fun() in a: foo() in b.\n" - + "fun() in j: foo() in b.\n" - + "fun() in i: foo() in b.\n"; - String b_fun = "fun() in b: foo() in b.\n" - + "fun() in a: foo() in b.\n" - + "fun() in j: foo() in b.\n" - + "fun() in i: foo() in b.\n"; - String j_fun = "fun() in j: foo() in j.\n" - + "fun() in i: foo() in j.\n"; - String i_fun = "fun() in i: foo() in i.\n"; - assertEquals(c_fun, c.fun()); - assertEquals(c_fun, i1.fun()); - assertEquals(c_fun, j1.fun()); - assertEquals(b_fun, b.fun()); - assertEquals(b_fun, i2.fun()); - assertEquals(b_fun, j2.fun()); - assertEquals(j_fun, j3.fun()); - assertEquals(j_fun, i3.fun()); - assertEquals(i_fun, i4.fun()); - } - - interface OuterInterface { - // CHECKSTYLE_OFF - default String m() { - return "I.m;" + new InnerClass().n(); - } - default String n() { - return "I.n;" + this.m(); - } - // CHECKSTYLE_ON - class InnerClass { - public String n() { - return "A.n;" + m(); - } - public String m() { - return "A.m;"; - } - } - } - class OuterClass { - public String m() { - return "B.m;"; - } - public String n1() { - OuterInterface i = new OuterInterface() { }; - return "B.n1;" + i.n() + OuterClass.this.m(); - } - public String n2() { - OuterInterface i = new OuterInterface() { - @Override - public String n() { - return this.m() + OuterClass.this.m(); - } - }; - return "B.n2;" + i.n() + OuterClass.this.m(); - } - } - public void testNestedInterfaceClass() { - OuterClass outerClass = new OuterClass(); - assertEquals("B.n1;I.n;I.m;A.n;A.m;B.m;", outerClass.n1()); - assertEquals("B.n2;I.m;A.n;A.m;B.m;B.m;", outerClass.n2()); - } - - class EmptyA { } - interface EmptyI { } - interface EmptyJ { } - class EmptyB extends EmptyA implements EmptyI { } - class EmptyC extends EmptyA implements EmptyI, EmptyJ { } - public void testBaseIntersectionCast() { - EmptyA localB = new EmptyB(); - EmptyA localC = new EmptyC(); - EmptyB b2BI = (EmptyB & EmptyI) localB; - EmptyC c2CIJ = (EmptyC & EmptyI & EmptyJ) localC; - EmptyI ii1 = (EmptyB & EmptyI) localB; - EmptyI ii2 = (EmptyC & EmptyI) localC; - EmptyI ii3 = (EmptyC & EmptyJ) localC; - EmptyI ii4 = (EmptyC & EmptyI & EmptyJ) localC; - EmptyJ jj1 = (EmptyC & EmptyI & EmptyJ) localC; - EmptyJ jj2 = (EmptyC & EmptyI) localC; - EmptyJ jj3 = (EmptyC & EmptyJ) localC; - EmptyJ jj4 = (EmptyI & EmptyJ) localC; - - try { - EmptyC b2CIJ = (EmptyC & EmptyI & EmptyJ) localB; - fail("Should have thrown a ClassCastException"); - } catch (ClassCastException e) { - // Expected. - } - try { - EmptyB c2BI = (EmptyB & EmptyI) localC; - fail("Should have thrown a ClassCastException"); - } catch (ClassCastException e) { - // Expected. - } - try { - EmptyJ jj = (EmptyB & EmptyJ) localB; - fail("Should have thrown a ClassCastException"); - } catch (ClassCastException e) { - // Expected. - } - } - - interface SimpleI { - int fun(); - } - interface SimpleK { - } - public void testIntersectionCastWithLambdaExpr() { - SimpleI simpleI1 = (SimpleI & EmptyI) () -> 11; - assertEquals(11, simpleI1.fun()); - SimpleI simpleI2 = (EmptyI & SimpleI) () -> 22; - assertEquals(22, simpleI2.fun()); - EmptyI emptyI = (EmptyI & SimpleI) () -> 33; - assertEquals(55, ((SimpleI & SimpleK) () -> 55).fun()); - } - - class SimpleA { - public int bar() { - return 11; - } - } - - class SimpleB extends SimpleA implements SimpleI { - public int fun() { - return 22; - } - } - - class SimpleC extends SimpleA implements SimpleI { - public int fun() { - return 33; - } - - public int bar() { - return 44; - } - } - - public void testIntersectionCastPolymorphism() { - SimpleA bb = new SimpleB(); - assertEquals(22, ((SimpleB & SimpleI) bb).fun()); - assertEquals(11, ((SimpleB & SimpleI) bb).bar()); - SimpleA cc = new SimpleC(); - assertEquals(33, ((SimpleC & SimpleI) cc).fun()); - assertEquals(44, ((SimpleC & SimpleI) cc).bar()); - assertEquals(33, ((SimpleA & SimpleI) cc).fun()); - SimpleI ii = (SimpleC & SimpleI) cc; - assertEquals(33, ii.fun()); - } - - interface ClickHandler { - int onClick(int a); - } - private int addClickHandler(ClickHandler clickHandler) { - return clickHandler.onClick(1); - } - private int addClickHandler(int a) { - return addClickHandler(x -> { int temp = a; return temp; }); - } - public void testLambdaCaptureParameter() { - assertEquals(2, addClickHandler(2)); - } - - interface TestLambda_Inner { - void f(); - } - interface TestLambda_Outer { - void accept(TestLambda_Inner t); - } - public void testLambda_call(TestLambda_Outer a) { - a.accept(() -> { }); - } - public void testLambdaNestingCaptureLocal() { - int[] success = new int[] {0}; - testLambda_call(sam1 -> { testLambda_call(sam2 -> { success[0] = 10; }); }); - assertEquals(10, success[0]); - } - - public void testLambdaNestingInAnonymousCaptureLocal() { - int[] x = new int[] {42}; - new Runnable() { - public void run() { - Lambda l = (a, b) -> x[0] = x[0] + a + b; - l.run(1, 2); - } - }.run(); - assertEquals(45, x[0]); - } - - public void testLambdaNestingInMultipleMixedAnonymousCaptureLocal() { - // checks that lambda has access to local variable and arguments when placed in mixed scopes - // Local Class -> Local Class -> Local Anonymous -> lambda -> Local Anonymous - class A { - int a() { - int[] x = new int[] {42}; - class B { - void b() { - I i = new I() { - public int foo(Integer arg) { - Runnable r = () -> { - new Runnable() { - public void run() { - Lambda l = (a, b) -> x[0] = x[0] + a + b + arg; - l.run(1, 2); - } - }.run(); - }; - r.run(); - return x[0]; - } - }; - i.foo(1); - } - } - B b = new B(); - b.b(); - return x[0]; - } - } - A a = new A(); - assertEquals(46, a.a()); - } - - public void testLambdaNestingInMultipleMixedAnonymousCaptureLocal_withInterference() { - // checks that lambda has access to NEAREST local variable and arguments when placed in mixed - // scopes Local Class -> Local Class -> Local Anonymous -> lambda -> Local Anonymous - class A { - int a() { - int[] x = new int[] {42}; - class B { - int b() { - int[] x = new int[] {22}; - I i = new I() { - public int foo(Integer arg) { - Runnable r = () -> { - new Runnable() { - public void run() { - Lambda l = (a, b) -> x[0] = x[0] + a + b + arg; - l.run(1, 2); - } - }.run(); - }; - r.run(); - return x[0]; - } - }; - return i.foo(1); - } - } - B b = new B(); - return b.b(); - } - } - A a = new A(); - assertEquals(26, a.a()); - } - - public void testLambdaNestingInMultipleMixedAnonymousCaptureLocalAndField() { - // checks that lambda has access to local variable, field and arguments when placed in mixed - // scopes - Local Class -> Local Class -> Local Anonymous -> lambda -> Local Anonymous - class A { - int fA = 1; - - int a() { - int[] x = new int[] {42}; - class B { - int fB = 2; - - int b() { - I i = new I() { - int fI = 3; - - public int foo(Integer arg) { - Runnable r = () -> { - new Runnable() { - public void run() { - Lambda l = (a, b) -> x[0] = x[0] + a + b + arg + fA + fB + fI; - l.run(1, 2); - } - }.run(); - }; - r.run(); - return x[0]; - } - }; - return i.foo(1); - } - } - B b = new B(); - return b.b(); - } - } - A a = new A(); - assertEquals(52, a.a()); - } - - public void testLambdaNestingInMultipleAnonymousCaptureLocal() { - // checks that lambda has access to local variable and arguments when placed in local anonymous - // class with multile nesting - int[] x = new int[] {42}; - int result = new I() { - public int foo(Integer i1) { - return new I() { - public int foo(Integer i2) { - return new I() { - public int foo(Integer i3) { - Lambda l = (a, b) -> x[0] = x[0] + a + b + i1 + i2 + i3; - return l.run(1, 2); - } - }.foo(3); - } - }.foo(2); - } - }.foo(1); - assertEquals(51, x[0]); - } - - static class TestLambda_ClassA { - int[] f = new int[] {42}; - - class B { - void m() { - Runnable r = () -> f[0] = f[0] + 1; - r.run(); - } - } - - int a() { - B b = new B(); - b.m(); - return f[0]; - } - } - - public void testLambdaNestingCaptureField_InnerClassCapturingOuterClassVariable() { - TestLambda_ClassA a = new TestLambda_ClassA(); - assertEquals(43, a.a()); - } - - public void testInnerClassCaptureLocalFromOuterLambda() { - int[] x = new int[] {42}; - Lambda l = (a, b) -> { - int[] x1 = new int[] {32}; - Lambda r = (rA, rB) -> { - int[] x2 = new int[] {22}; - I i = new I() { - public int foo(Integer arg) { - x1[0] = x1[0] + 1; - x[0] = x[0] + 1; - return x2[0] = x2[0] + rA + rB + a + b; - } - }; - return i.foo(1); - }; - return r.run(3, 4) + x1[0]; - }; - - // x1[0](32) + 1 + x2[0](22) + rA(3) + rB(4) + a(1) + b(2) - assertEquals(65, l.run(1, 2).intValue()); - assertEquals(43, x[0]); - } - - static class TestLambda_Class { - public int[] s = new int[] {0}; - public void call(TestLambda_Outer a) { - a.accept(() -> { }); - } - class TestLambda_InnerClass { - public int[] s = new int[] {0}; - public int test() { - int[] s = new int[] {0}; - TestLambda_Class.this.call( - sam0 -> TestLambda_Class.this.call( - sam1 -> { - TestLambda_Class.this.call( - sam2 -> { - TestLambda_Class.this.s[0] = 10; - this.s[0] = 20; - s[0] = 30; - }); - })); - return s[0]; - } - } - } - - public void testLambdaNestingCaptureField() { - TestLambda_Class a = new TestLambda_Class(); - a.call(sam1 -> { a.call(sam2 -> { a.s[0] = 20; }); }); - assertEquals(20, a.s[0]); - } - - public void testLambdaMultipleNestingCaptureFieldAndLocal() { - TestLambda_Class a = new TestLambda_Class(); - TestLambda_Class b = new TestLambda_Class(); - int [] s = new int [] {0}; - b.call(sam0 -> a.call(sam1 -> { a.call(sam2 -> { a.s[0] = 20; b.s[0] = 30; s[0] = 40; }); })); - assertEquals(20, a.s[0]); - assertEquals(30, b.s[0]); - assertEquals(40, s[0]); - } - - public void testLambdaMultipleNestingCaptureFieldAndLocalInnerClass() { - TestLambda_Class a = new TestLambda_Class(); - TestLambda_Class.TestLambda_InnerClass b = a.new TestLambda_InnerClass(); - int result = b.test(); - assertEquals(10, a.s[0]); - assertEquals(20, b.s[0]); - assertEquals(30, result); - } - - static class TestMF_A { - public static String getId() { - return "A"; - } - public int getIdx() { - return 1; - } - } - static class TestMF_B { - public static String getId() { - return "B"; - } - public int getIdx() { - return 2; - } - } - interface Function { - T apply(); - } - private String f(Function arg) { - return arg.apply(); - } - private int g(Function arg) { - return arg.apply().intValue(); - } - - public void testMethodRefWithSameName() { - assertEquals("A", f(TestMF_A::getId)); - assertEquals("B", f(TestMF_B::getId)); - TestMF_A a = new TestMF_A(); - TestMF_B b = new TestMF_B(); - assertEquals(1, g(a::getIdx)); - assertEquals(2, g(b::getIdx)); - } - - // Test particular scenarios involving multiple path to inherit defaults. - interface ITop { - default String m() { - return "ITop.m()"; - } - } - - interface IRight extends ITop { - default String m() { - return "IRight.m()"; - } - } - - interface ILeft extends ITop { } - - public void testMultipleDefaults_fromInterfaces_left() { - class A implements ILeft, IRight { } - - assertEquals("IRight.m()", new A().m()); - } - - public void testMultipleDefaults_fromInterfaces_right() { - class A implements IRight, ILeft { } - - assertEquals("IRight.m()", new A().m()); - } - - public void testMultipleDefaults_superclass_left() { - class A implements ITop { } - class B extends A implements ILeft, IRight { } - - assertEquals("IRight.m()", new B().m()); - } - - public void testMultipleDefaults_superclass_right() { - class A implements ITop { } - class B extends A implements IRight, ILeft { } - - assertEquals("IRight.m()", new B().m()); - } - - static class DefaultTrumpsOverSyntheticAbstractStub { - interface SuperInterface { - String m(); - } - - interface SubInterface extends SuperInterface { - default String m() { - return "SubInterface.m()"; - } - } - } - - public void testMultipleDefaults_defaultShadowsOverSyntheticAbstractStub() { - abstract class A implements DefaultTrumpsOverSyntheticAbstractStub.SuperInterface { } - class B extends A implements DefaultTrumpsOverSyntheticAbstractStub.SubInterface { } - - assertEquals("SubInterface.m()", new B().m()); - } - - static class DefaultTrumpsOverDefaultOnSuperAbstract { - interface SuperInterface { - default String m() { - return "SuperInterface.m()"; - } - } - - interface SubInterface extends SuperInterface { - default String m() { - return "SubInterface.m()"; - } - } - } - - public void testMultipleDefaults_defaultShadowsOverDefaultOnSuperAbstract() { - abstract class A implements DefaultTrumpsOverDefaultOnSuperAbstract.SuperInterface { } - class B extends A implements DefaultTrumpsOverDefaultOnSuperAbstract.SubInterface { } - - assertEquals("SubInterface.m()", new B().m()); - } - - interface InterfaceWithThisReference { - default String n() { - return "default n"; - } - default String callNUnqualified() { - class Super implements InterfaceWithThisReference { - public String n() { - return "super n"; - } - } - return new Super() { - public String callNUnqualified() { - return "Object " + n(); - } - }.callNUnqualified(); - } - default String callNWithThis() { - class Super implements InterfaceWithThisReference { - public String n() { - return "super n"; - } - } - return new Super() { - public String callNWithThis() { - return "Object " + this.n(); - } - }.callNWithThis(); - } - default String callNWithInterfaceThis() { - class Super implements InterfaceWithThisReference { - public String n() { - return "super n"; - } - } - return new Super() { - public String callNWithInterfaceThis() { - // In this method this has interface Test as its type, but it refers to outer n(); - return "Object " + InterfaceWithThisReference.this.n(); - } - }.callNWithInterfaceThis(); - } - default String callNWithSuper() { - class Super implements InterfaceWithThisReference { - public String n() { - return "super n"; - } - } - return new Super() { - public String callNWithSuper() { - // In this method this has interface Test as its type. - return "Object " + super.n(); - } - }.callNWithSuper(); - } - default String callNWithInterfaceSuper() { - return new InterfaceWithThisReference() { - public String n() { - return "this n"; - } - public String callNWithInterfaceSuper() { - // In this method this has interface Test as its type and refers to default n(); - return "Object " + InterfaceWithThisReference.super.n(); - } - }.callNWithInterfaceSuper(); - } - } - - public void testInterfaceThis() { - class A implements InterfaceWithThisReference { - public String n() { - return "n"; - } - } - assertEquals("Object super n", new A().callNUnqualified()); - assertEquals("Object super n", new A().callNWithThis()); - assertEquals("Object n", new A().callNWithInterfaceThis()); - assertEquals("Object super n", new A().callNWithSuper()); - assertEquals("Object default n", new A().callNWithInterfaceSuper()); - } - - private static List initializationOrder; - - private static int get(String s) { - initializationOrder.add(s); - return 1; - } - - interface A1 { - int fa1 = get("A1"); - - default void a1() { } - } - - interface A2 { - int fa2 = get("A2"); - - default void a2() { } - } - - interface A3 { - int fa3 = get("A3"); - - default void a3() { } - } - - interface B1 extends A1 { - int fb1 = get("B1"); - - default void b1() { } - } - - interface B2 extends A2 { - int fb2 = get("B2"); - - default void b2() { } - } - - interface B3 extends A3 { - int fb3 = get("B3"); - } - - static class C implements B1, A2 { - static { - get("C"); - } - } - - static class D extends C implements B2, B3 { - static { - get("D"); - } - } - - public void testInterfaceWithDefaultMethodsInitialization() { - initializationOrder = new ArrayList(); - new D(); - assertContentsInOrder(initializationOrder, "A1", "B1", "A2", "C", "B2", "A3", "D"); - } - - /** - * Regression test for issue 9214. - */ - interface P { - boolean apply(T obj); - } - - static class B { - public boolean getTrue() { - return true; - } - } - private static String getClassName(T obj) { - return obj.getClass().getSimpleName(); - } - - public void testMethodReference_generics() { - P p = B::getTrue; - assertTrue(p.apply(new B())); - // The next two method references must result in two different lambda implementations due - // to generics, see bug # 9333. - MyFunction1 f1 = Java8Test::getClassName; - MyFunction1 f2 = Java8Test::getClassName; - - assertEquals(B.class.getSimpleName(), f1.apply(new B())); - assertEquals(Double.class.getSimpleName(), f2.apply(new Double(2))); - } - - public void testDefaultMethod_staticInitializer() { - SomeClass.initializationOrder = new ArrayList(); - Object object = ImplementsWithDefaultMethodAndStaticInitializer.someClass; - assertContentsInOrder(SomeClass.initializationOrder, "1", "2", "3", "4"); - } - - private void assertContentsInOrder(Iterable contents, String... elements) { - assertEquals(Arrays.asList(elements).toString(), contents.toString()); - } - - @JsType(isNative = true) - interface NativeJsTypeInterfaceWithStaticInitializationAndFieldAccess { - @JsOverlay - Object object = new Integer(3); - } - - @JsType(isNative = true) - interface NativeJsTypeInterfaceWithStaticInitializationAndStaticOverlayMethod { - @JsOverlay - Object object = new Integer(4); - - @JsOverlay - static Object getObject() { - return object; - } - } - - @JsType(isNative = true) - interface NativeJsTypeInterfaceWithStaticInitializationAndInstanceOverlayMethod { - @JsOverlay - Object object = new Integer(5); - - int getA(); - - @JsOverlay - default Object getObject() { - return ((int) object) + this.getA(); - } - } - - private native NativeJsTypeInterfaceWithStaticInitializationAndInstanceOverlayMethod - createNativeJsTypeInterfaceWithStaticInitializationAndInstanceOverlayMethod() /*-{ - return { getA: function() { return 1; } }; - }-*/; - - @JsType(isNative = true) - interface NativeJsTypeInterfaceWithStaticInitialization { - @JsOverlay - Object object = new Integer(6); - } - - @JsType(isNative = true) - interface NativeJsTypeInterfaceWithComplexStaticInitialization { - @JsOverlay - Object object = (Integer) (((int) NativeJsTypeInterfaceWithStaticInitialization.object) + 1); - } - - static class JavaTypeImplementingNativeJsTypeInterceWithDefaultMethod implements - NativeJsTypeInterfaceWithStaticInitializationAndInstanceOverlayMethod { - public int getA() { - return 4; - } - } - - public void testNativeJsTypeWithStaticInitializer() { - assertEquals(3, NativeJsTypeInterfaceWithStaticInitializationAndFieldAccess.object); - assertEquals( - 4, NativeJsTypeInterfaceWithStaticInitializationAndStaticOverlayMethod.getObject()); - assertEquals(6, - createNativeJsTypeInterfaceWithStaticInitializationAndInstanceOverlayMethod() - .getObject()); - assertEquals(7, NativeJsTypeInterfaceWithComplexStaticInitialization.object); - assertEquals(9, new JavaTypeImplementingNativeJsTypeInterceWithDefaultMethod().getObject()); - } - - @JsFunction - interface VarargsFunction { - String f(int i, String... args); - } - - private static native String callFromJSNI(VarargsFunction f) /*-{ - return f(2, "a", "b", "c"); - }-*/; - - public void testJsVarargsLambda() { - VarargsFunction function = (i, args) -> args[i]; - assertSame("b", function.f(1, "a", "b", "c")); - assertSame("c", callFromJSNI(function)); - String[] pars = new String[] {"a", "b", "c"}; - assertSame("a", function.f(0, pars)); - } - - private static T m(T s) { - return s; - } - - static class Some { - T s; - MyFunction2 combine; - Some(T s, MyFunction2 combine) { - this.s = s; - this.combine = combine; - } - public T m(T s2) { - return combine.apply(s, s2); - } - public T m1() { - return s; - } - } - - @FunctionalInterface - interface MyFunction1 { - U apply(T t); - } - - @FunctionalInterface - interface MyFunction2 { - V apply(T t, U u); - } - - @FunctionalInterface - interface MyFunction3 { - W apply(T t, U u, V v); - } - - @FunctionalInterface - interface IntFunction1 { - U apply(int t); - } - - @FunctionalInterface - interface IntFunction2 { - V apply(int t, int u); - } - - @FunctionalInterface - interface IntFunction3 { - W apply(int t, int u, int v); - } - - public void testMethodReference_implementedInSuperclass() { - MyFunction1 toString = StringBuilder::toString; - assertEquals("Hello", toString.apply(new StringBuilder("Hello"))); - } - - static MyFunction2 concat = (s,t) -> s + t; - - public void testMethodReference_genericTypeParameters() { - testMethodReference_genericTypeParameters( - new Some("Hell", concat), "Hell", "o", concat); - } - - static String concat(String... strs) { - String result = ""; - for (String s : strs) { - result += s; - } - return result; - } - - static String anotherConcat(String s1, String s2, String... strs) { - String result = s1 + s2; - for (String s : strs) { - result += s; - } - return result; - } - - public String instanceConcat(String... strs) { - String result = ""; - for (String s : strs) { - result += s; - } - return result; - } - - public String anotherInstanceConcat(String s1, String... strs) { - String result = s1; - for (String s : strs) { - result += s; - } - return result; - } - - private static class ClassWithVarArgsConstructor { - private class Inner { - private int sum; - Inner(int i, Integer... nums) { - this.sum = ClassWithVarArgsConstructor.this.sum + i; - for (Integer n: nums) { - sum += n; - } - } - } - - private int sum; - ClassWithVarArgsConstructor(int i, Integer... nums) { - sum = i; - for (Integer n: nums) { - sum += n; - } - } - - private MyFunction1 createInner1Param() { - return (MyFunction1) Inner::new; - } - - private MyFunction2 createInner2Param() { - return (MyFunction2) Inner::new; - } - - private MyFunction3 createInner3Param() { - return (MyFunction3) Inner::new; - } - - private MyFunction2 createInner2ParamArray() { - return (MyFunction2) Inner::new; - } - - private IntFunction1 createInner1IntParam() { - return (IntFunction1) Inner::new; - } - - private IntFunction2 createInner2IntParam() { - return (IntFunction2) Inner::new; - } - - private IntFunction3 createInner3IntParam() { - return (IntFunction3) Inner::new; - } - } - - public void testMethodReference_varargs() { - // More functional arguments than varargs - MyFunction2 concat = Java8Test::concat; - assertEquals("ab", concat.apply("a", "b")); - - // Less functional arguments than varargs - MyFunction2 anotherConcat = Java8Test::anotherConcat; - assertEquals("ab", anotherConcat.apply("a", "b")); - - MyFunction2 instanceConcat = Java8Test::instanceConcat; - assertEquals("a", instanceConcat.apply(this, "a")); - - MyFunction2 anotherInstanceConcat = Java8Test::anotherInstanceConcat; - assertEquals("a", anotherInstanceConcat.apply(this, "a")); - - // constructor varargs - MyFunction1 constructor1Param = - ClassWithVarArgsConstructor::new; - assertEquals(1, constructor1Param.apply(1).sum); - - MyFunction2 constructor2Param = - ClassWithVarArgsConstructor::new; - assertEquals(3, constructor2Param.apply(1, 2).sum); - - MyFunction3 constructor3Param = - ClassWithVarArgsConstructor::new; - assertEquals(6, constructor3Param.apply(1, 2, 3).sum); - - MyFunction2 constructor2ParamArray = - ClassWithVarArgsConstructor::new; - assertEquals(6, constructor2ParamArray.apply(1, new Integer[] {2, 3}).sum); - - // constructor varargs + autoboxing - IntFunction1 constructor1IntParam = - ClassWithVarArgsConstructor::new; - assertEquals(1, constructor1IntParam.apply(1).sum); - - IntFunction2 constructor2IntParam = - ClassWithVarArgsConstructor::new; - assertEquals(3, constructor2IntParam.apply(1, 2).sum); - - IntFunction3 constructor3IntParam = - ClassWithVarArgsConstructor::new; - assertEquals(6, constructor3IntParam.apply(1, 2, 3).sum); - - ClassWithVarArgsConstructor outer = new ClassWithVarArgsConstructor(1); - - // inner class constructor varargs - assertEquals(2, outer.createInner1Param().apply(1).sum); - assertEquals(4, outer.createInner2Param().apply(1, 2).sum); - assertEquals(7, outer.createInner3Param().apply(1, 2, 3).sum); - assertEquals(7, outer.createInner2ParamArray().apply(1, new Integer[] {2, 3}).sum); - - // inner class constructor varargs + autoboxing - assertEquals(2, outer.createInner1IntParam().apply(1).sum); - assertEquals(4, outer.createInner2IntParam().apply(1, 2).sum); - assertEquals(7, outer.createInner3IntParam().apply(1, 2, 3).sum); - } - - private static void testMethodReference_genericTypeParameters( - Some some, T t1, T t2, MyFunction2 combine) { - T t1t2 = combine.apply(t1, t2); - - // Test all 4 flavours of methodReference - // 1. Static method - assertEquals(t1t2, ((MyFunction1) Java8Test::m).apply(t1t2)); - // 2. Qualified instance method - assertEquals(t1t2, ((MyFunction1) some::m).apply(t2)); - // 3. Unqualified instance method - assertEquals(t1, ((MyFunction1, T>) Some::m1).apply(some)); - assertEquals("Hello", - ((MyFunction1, String>) - Some::m1).apply(new Some<>("Hello", concat))); - // 4. Constructor reference. - assertEquals(t1t2, - ((MyFunction2, Some>) Some::new).apply(t1t2, combine).m1()); - } - - static MyFunction2 addInteger = (s,t) -> s + t; - - @FunctionalInterface - interface MyIntFunction1 { - int apply(int t); - } - - @FunctionalInterface - interface MyIntFunction2 { - int apply(int t, int u); - } - - @FunctionalInterface - interface MyIntFuncToSomeIntegeFunction2 { - SomeInteger apply(int t, MyFunction2 u); - } - - @FunctionalInterface - interface MySomeIntegerFunction1 { - int apply(SomeInteger t); - } - - @FunctionalInterface - interface MySomeIntegerIntFunction2 { - int apply(SomeInteger t, int u); - } - - static MyIntFunction2 addint = (s,t) -> s + t; - - static class SomeInteger { - int s; - MyFunction2 combine; - SomeInteger(int s, MyFunction2 combine) { - this.s = s; - this.combine = combine; - } - public int m(int s2) { - return combine.apply(s, s2); - } - public int m1() { - return s; - } - } - - public void testMethodReference_autoboxing() { - SomeInteger some = new SomeInteger(3, addInteger); - - // Test all 4 flavours of methodReference autoboxing parameters. - // 1. Static method - assertEquals((Integer) 5, ((MyFunction1) Java8Test::m).apply(5)); - // 2. Qualified instance method - assertEquals((Integer) 5, ((MyFunction1) some::m).apply(2)); - // 3. Unqualified instance method - assertEquals((Integer) 3, ((MyFunction1) SomeInteger::m1).apply(some)); - assertEquals((Integer) 5, ((MyFunction2) - SomeInteger::m).apply(some, 2)); - assertEquals((Integer) 5, - ((MyFunction1) - SomeInteger::m1).apply(new SomeInteger(5, addInteger))); - // 4. Constructor reference. - assertEquals(5, - ((MyFunction2, SomeInteger>) - SomeInteger::new).apply(5, addInteger).m1()); - - // Test all 4 flavours of methodReference (interface unboxed) - // 1. Static method - assertEquals(5, ((MyIntFunction1) Java8Test::m).apply(5)); - // 2. Qualified instance method - assertEquals(5, ((MyIntFunction1) some::m).apply(2)); - // 3. Unqualified instance method - assertEquals(3, ((MySomeIntegerFunction1) SomeInteger::m1).apply(some)); - // The next expression was the one that triggered bug #9346 where decisions on whether to - // box/unbox were decided incorrectly due to differring number of parameters in the method - // reference and the functional interface method. - assertEquals(5, ((MySomeIntegerIntFunction2) SomeInteger::m).apply(some, 2)); - assertEquals(5, - ((MySomeIntegerFunction1) - SomeInteger::m1).apply(new SomeInteger(5, addInteger))); - // 4. Constructor reference. - assertEquals(5, - ((MyIntFuncToSomeIntegeFunction2) SomeInteger::new).apply(5, addInteger).m1()); - } - - @JsType(isNative = true) - private static class NativeClassWithJsOverlay { - @JsOverlay - public static String m(String s) { - MyFunction1 id = (a) -> a; - return id.apply(s); - } - } - public void testNativeJsOverlay_lambda() { - assertSame("Hello", NativeClassWithJsOverlay.m("Hello")); - } - - interface IntefaceWithDefaultMethodAndLambda { - boolean f(); - - default BooleanPredicate fAsPredicate() { - // This lambda will be defined as an instance method in the enclosing class, which is an - // interface. In this case the methdod will be devirtualized. - return () -> this.f(); - } - } - - interface BooleanPredicate { - boolean apply(); - } - - public void testLambdaCapturingThis_onDefaultMethod() { - assertTrue( - new IntefaceWithDefaultMethodAndLambda() { - @Override - public boolean f() { - return true; - } - }.fAsPredicate().apply()); - } - - @JsFunction - interface MyJsFunctionInterface { - int foo(int a); - } - - public void testJsFunction_lambda() { - MyJsFunctionInterface jsFunctionInterface = a -> a + 2; - assertEquals(12, callAsFunction(jsFunctionInterface, 10)); - assertEquals(12, jsFunctionInterface.foo(10)); - } - - private static native int callAsFunction(Object fn, int arg) /*-{ - return fn(arg); - }-*/; - - @JsFunction - interface MyJsFunctionInterfaceWithOverlay { - Double m(); - @JsOverlay - default Double callM() { - return this.m(); - } - } - - private static native MyJsFunctionInterfaceWithOverlay createNative() /*-{ - return function () { return 5; }; - }-*/; - - public void testJsFunction_withOverlay() { - MyJsFunctionInterfaceWithOverlay f = new MyJsFunctionInterfaceWithOverlay() { - @Override - public Double m() { - return new Double(2.0); - } - }; - assertEquals(2, f.callM().intValue()); - assertEquals(5, createNative().callM().intValue()); - } - - interface FunctionalExpressionBridges_I { - T apply(T t); - // TODO(rluble): uncomment the line below to when bridges for default methods are created - // in functional expressions - FunctionalExpressionBridges_I m(T t); - } - - @FunctionalInterface - interface FunctionalExpressionBridges_J - extends FunctionalExpressionBridges_I { - T apply(T t); - - // Overrides I.m() and specializes return type - default FunctionalExpressionBridges_J m(T t) { - return this; - } - } - - public static String identity(String s) { - return s; - } - - public void testFunctionalExpressionBridges() { - FunctionalExpressionBridges_J ann = new FunctionalExpressionBridges_J() { - @Override - public String apply(String string) { - return string; - } - }; - - assertBrigdeDispatchIsCorrect(ann); - assertBrigdeDispatchIsCorrect((String s) -> s + ""); - assertBrigdeDispatchIsCorrect(Java8Test::identity); - } - - private void assertBrigdeDispatchIsCorrect( - FunctionalExpressionBridges_J functionalExpression) { - assertEquals("Hello", functionalExpression.m(null).apply("Hello")); - assertEquals("Hello", functionalExpression.apply("Hello")); - assertEquals("Hello", - ((FunctionalExpressionBridges_I) functionalExpression).apply("Hello")); - } - - static class ClassWithAVeryLoooooooooooooooooooooooooooooooooooongName { - public static String m() { - return null; - } - } - - // Regression test for bug: #9426. - public void testCorrectNaming() { - Function f = ClassWithAVeryLoooooooooooooooooooooooooooooooooooongName::m; - assertNotNull(f); - } - - @JsType(isNative = true) - interface InterfaceWithOverlay { - - @JsProperty - int getLength(); - - @JsOverlay - default int len() { - return this.getLength(); - } - } - - @JsType(isNative = true, name = "Object", namespace = JsPackage.GLOBAL) - static abstract class SubclassImplementingInterfaceWithOverlay implements InterfaceWithOverlay { - } - - // Regression test for bug: #9440 - public void testInterfaceWithOverlayAndNativeSubclass() { - SubclassImplementingInterfaceWithOverlay object = - (SubclassImplementingInterfaceWithOverlay) (Object) new int[]{1, 2, 3}; - assertEquals(3, object.len()); - } - - interface Producer { - T get(); - } - - private static Producer createInnerClassProducer() { - class InnerClass { - } - return (Producer) InnerClass::new; - } - - public void testLocalClassConstructorReferenceInStaticMethod() { - assertTrue(createInnerClassProducer().get() != null); - } - - // NOTE: DO NOT reorder the following classes, bug #9453 is only reproducible in certain - // orderings. - interface SubSub_SuperDefaultMethodDevirtualizationOrder - extends Sub_SuperDefaultMethodDevirtualizationOrder { - default String m() { - return Sub_SuperDefaultMethodDevirtualizationOrder.super.m(); - } - } - - interface Sub_SuperDefaultMethodDevirtualizationOrder - extends Super_SuperDefaultMethodDevirtualizationOrder { - @Override - default String m() { - return Super_SuperDefaultMethodDevirtualizationOrder.super.m(); - } - } - - interface Super_SuperDefaultMethodDevirtualizationOrder { - default String m() { - return "Hi"; - } - } - - // Regression test for bug #9453. - public void testDefaultMethodDevirtualizationOrder() { - assertEquals("Hi", new SubSub_SuperDefaultMethodDevirtualizationOrder() { - }.m()); - } - - private static String first(String... strings) { - return strings[0]; - } - - // Regresion test for https://github.com/gwtproject/gwt/issues/9497 - public void testVarargsFunctionalConversion() { - java.util.function.Function function = Java8Test::first; - assertEquals("Hello", function.apply(new String[] {"Hello", "GoodBye"})); - } - - interface SingleJsoImplA { - String getAData(); - - List getListOfB(); - } - - interface SingleJsoImplB { - String getBData(); - } - - private static final class AOverlay extends JavaScriptObject implements SingleJsoImplA { - protected AOverlay() { } - - @Override - public native String getAData() /*-{ - return this.data; - }-*/; - - @Override - public native List getListOfB() /*-{ - return @java.util.Arrays::asList(*)(this.listOfb); - }-*/; - } - - private static final class BOverlay extends JavaScriptObject implements SingleJsoImplB { - protected BOverlay() { } - - @Override - public native String getBData() /*-{ - return this.data; - }-*/; - } - - private static SingleJsoImplA createA() { - return JsonUtils.safeEval( - "{\"data\":\"a value\",\"listOfb\":[{\"data\":\"b1\"},{\"data\":\"b2\"}]}"); - } - - // Regression for issue #9558 - public void testJSOLivenessSingleImplErasure() { - SingleJsoImplA a = createA(); - String result = a.getListOfB().stream() - .map(SingleJsoImplB::getBData).collect(Collectors.joining(",")); - assertEquals("b1,b2", result); - result = a.getListOfB().stream() - .map(b -> b.getBData()).collect(Collectors.joining(",")); - assertEquals("b1,b2", result); - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - public void testLambdaErasureCasts() { - List list = new ArrayList(); - list.add("2"); - try { - ((List) list).stream().map(n -> n.intValue() == 2).findAny(); - fail("Should have thrown."); - } catch (ClassCastException expected) { - } - } - - public void testLambdaBoxing() { - BiFunction equals = (i, j) -> i + 0 == j; - assertTrue(equals.apply(1,1)); - assertTrue(equals.apply(new Integer(2),2)); - assertTrue(equals.apply(new Integer(3), new Integer(3))); - - IntFunction unboxBox = i -> i; - assertEquals(2, (int) unboxBox.apply(2)); - assertEquals(2, (int) unboxBox.apply(new Integer(2))); - } - - // Regression tests for #9598 - public void testImproperMethodResolution() { - Predicate p = o -> true; - assertTrue(p.test(null)); - } - - interface I2 { public T foo(T arg); } - - interface I1 extends I2 { public String foo(String arg0); } - - @SuppressWarnings({"rawtypes", "unchecked"}) - public void testIntersectionCastLambda() { - - Object instance = (I1 & I2) val -> "#" + val; - - assertTrue(instance instanceof I1); - assertTrue(instance instanceof I2); - - I1 lambda = (I1) instance; - I2 raw = lambda; - assertEquals("#1", raw.foo("1")); // tests that the bridge exists and is correct - assertEquals("#2", lambda.foo("2")); - } - - static class C2 { public static String append(String str) { return "#" + str; } } - @SuppressWarnings({"rawtypes", "unchecked"}) - public void testIntersectionCastMethodReference() { - - Object instance = (I1 & I2) C2::append; - - assertTrue(instance instanceof I1); - assertTrue(instance instanceof I2); - - I1 lambda = (I1) instance; - I2 raw = lambda; - assertEquals("#1", raw.foo("1")); // tests that the bridge exists and is correct - assertEquals("#2", lambda.foo("2")); - } -} diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java9Test.java b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java9Test.java deleted file mode 100644 index f9fcab9e87..0000000000 --- a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java9Test.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2023 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.dev.jjs.test; - -import com.google.gwt.core.client.GwtScriptOnly; -import com.google.gwt.junit.client.GWTTestCase; - -import java.util.function.Predicate; -import java.util.function.Supplier; - -@GwtScriptOnly -public class Java9Test extends GWTTestCase { - - @Override - public String getModuleName() { - return "com.google.gwt.dev.jjs.Java9Test"; - } - - class Resource implements AutoCloseable { - boolean isOpen = true; - - public void close() { - this.isOpen = false; - } - } - - public void testTryWithResourcesJava9() { - Resource r1 = new Resource(); - assertTrue(r1.isOpen); - Resource r2Copy; - try (r1; Resource r2 = new Resource()) { - assertTrue(r1.isOpen); - assertTrue(r2.isOpen); - r2Copy = r2; - } - assertFalse(r1.isOpen); - assertFalse(r2Copy.isOpen); - } - - interface Selector extends Predicate { - @Override - boolean test(String object); - - default Selector trueSelector() { - // Unused variable that creates a lambda with a bridge for the method test. The bug #9598 - // was caused by GwtAstBuilder associating the bridge method Lambda.test(Object) on the - // lambda below to the method Predicate.test(Object), causing the method resolution in the - // code that refers to the Predicate.test(Object) in the test below to refer to - // Lambda.test(Object) which is the wrong method. - return receiver -> true; - } - } - - private interface InterfaceWithPrivateMethods { - int implementedMethod(); - - default int defaultMethod() { - return privateMethod(); - } - - private int privateMethod() { - return implementedMethod(); - } - - private int staticPrivateMethod() { - return 42; - } - } - - public void testInterfacePrivateMethodsJava9() { - InterfaceWithPrivateMethods implementor = () -> 50; - assertEquals(50, implementor.implementedMethod()); - assertEquals(50, implementor.defaultMethod()); - assertEquals(42, implementor.staticPrivateMethod()); - } - - public void testAnonymousDiamondJava9() { - Supplier helloSupplier = new Supplier<>() { - @Override - public String get() { - return "hello"; - } - }; - assertEquals("hello", helloSupplier.get()); - } -} \ No newline at end of file diff --git a/user/test/com/google/gwt/dev/jjs/CompilerSuite.java b/user/test/com/google/gwt/dev/jjs/CompilerSuite.java index 68ebcd76cb..28076f9483 100644 --- a/user/test/com/google/gwt/dev/jjs/CompilerSuite.java +++ b/user/test/com/google/gwt/dev/jjs/CompilerSuite.java @@ -72,12 +72,12 @@ public static Test suite() { suite.addTestSuite(InnerClassTest.class); suite.addTestSuite(InnerOuterSuperTest.class); suite.addTestSuite(Java7Test.class); - // Java8Test cannot be the first one in a suite. It uses a hack - // to avoid executing if not in a Java 8+ environment. suite.addTestSuite(Java8Test.class); suite.addTestSuite(Java9Test.class); suite.addTestSuite(Java10Test.class); suite.addTestSuite(Java11Test.class); + // Java17Test cannot be the first one in a suite. It uses a hack + // to avoid executing if not in a Java 17+ environment. suite.addTestSuite(Java17Test.class); suite.addTestSuite(JavaAccessFromJavaScriptTest.class); suite.addTestSuite(JsniConstructorTest.class); diff --git a/user/test/com/google/gwt/dev/jjs/Java10Test.gwt.xml b/user/test/com/google/gwt/dev/jjs/Java10Test.gwt.xml index f16a361df4..282caab62f 100644 --- a/user/test/com/google/gwt/dev/jjs/Java10Test.gwt.xml +++ b/user/test/com/google/gwt/dev/jjs/Java10Test.gwt.xml @@ -15,5 +15,5 @@ - + \ No newline at end of file diff --git a/user/test/com/google/gwt/dev/jjs/Java11Test.gwt.xml b/user/test/com/google/gwt/dev/jjs/Java11Test.gwt.xml index a73ecb58ee..6b07de0693 100644 --- a/user/test/com/google/gwt/dev/jjs/Java11Test.gwt.xml +++ b/user/test/com/google/gwt/dev/jjs/Java11Test.gwt.xml @@ -15,5 +15,5 @@ - + \ No newline at end of file diff --git a/user/test/com/google/gwt/dev/jjs/Java8Test.gwt.xml b/user/test/com/google/gwt/dev/jjs/Java8Test.gwt.xml index ff61d0dc3c..426982b9e3 100644 --- a/user/test/com/google/gwt/dev/jjs/Java8Test.gwt.xml +++ b/user/test/com/google/gwt/dev/jjs/Java8Test.gwt.xml @@ -15,5 +15,5 @@ - + \ No newline at end of file diff --git a/user/test/com/google/gwt/dev/jjs/Java9Test.gwt.xml b/user/test/com/google/gwt/dev/jjs/Java9Test.gwt.xml index ff61d0dc3c..426982b9e3 100644 --- a/user/test/com/google/gwt/dev/jjs/Java9Test.gwt.xml +++ b/user/test/com/google/gwt/dev/jjs/Java9Test.gwt.xml @@ -15,5 +15,5 @@ - + \ No newline at end of file diff --git a/user/test/com/google/gwt/dev/jjs/test/Java10Test.java b/user/test/com/google/gwt/dev/jjs/test/Java10Test.java index 07b6bd72ca..375313e86c 100644 --- a/user/test/com/google/gwt/dev/jjs/test/Java10Test.java +++ b/user/test/com/google/gwt/dev/jjs/test/Java10Test.java @@ -15,74 +15,143 @@ */ package com.google.gwt.dev.jjs.test; -import com.google.gwt.dev.util.arg.SourceLevel; import com.google.gwt.junit.DoNotRunWith; -import com.google.gwt.junit.JUnitShell; import com.google.gwt.junit.Platform; import com.google.gwt.junit.client.GWTTestCase; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.function.Supplier; + /** - * Dummy test case. Java10Test is super sourced so that GWT can be compiled by Java 8. - * - * NOTE: Make sure this class has the same test methods of its supersourced variant. + * Tests Java 10 features. */ @DoNotRunWith(Platform.Devel) public class Java10Test extends GWTTestCase { - @Override - public String getModuleName() { - return "com.google.gwt.dev.jjs.Java10Test"; + interface VarArgsFunction { + R apply(T... args); } @Override - public void runTest() throws Throwable { - // Only run these tests if -sourceLevel 10 (or greater) is enabled. - if (isGwtSourceLevel10()) { - super.runTest(); - } + public String getModuleName() { + return "com.google.gwt.dev.jjs.Java10Test"; } public void testLocalVarType_DenotableTypes() { - assertFalse(isGwtSourceLevel10()); + var i = 42; + assertEquals(42, i); + var s = "42"; + assertEquals("42", s); + + Supplier initializer = () -> "37"; + var s2 = initializer.get(); + // to be sure that s2 was inferred as a string and not an Object + String s3 = s2; + assertEquals("37", s3); } public void testLocalVarType_Anonymous() { - assertFalse(isGwtSourceLevel10()); + var o = new Object() { + int i; + String s; + }; + o.i = 42; + o.s = "42"; + assertEquals(42, o.i); + assertEquals("42", o.s); } public void testLocalVarType_Ternary() { - assertFalse(isGwtSourceLevel10()); + var value = true ? "a" : 'c'; + checkSerializableDispatch(value); + checkComparableDispatch(value); + assertEquals("a", value.toString()); + } + + private void checkSerializableDispatch(Object fail) { + fail("should not be treated as object"); + } + + private void checkSerializableDispatch(Serializable pass) { + // pass + } + + private void checkComparableDispatch(Object fail) { + fail("should not be treated as object"); + } + + private void checkComparableDispatch(Comparable pass) { + // pass } public void testLocalVarType_LambdaCapture() { - assertFalse(isGwtSourceLevel10()); + var s = "42"; + Supplier supplier = () -> s; + assertEquals("42", supplier.get()); } public void testLocalVarType_VarArg() { - assertFalse(isGwtSourceLevel10()); + var args = new String[] {"4", "2"}; + VarArgsFunction f = arr -> arr[0] + arr[1]; + assertEquals("42", f.apply(args)); } public void testLocalVarType_LocalClass() { - assertFalse(isGwtSourceLevel10()); + var i = 37; + class Local { + int m() { + var i = 40; + return i + 2; + } + + int fromOuterScope() { + return i; + } + } + + var l = new Local(); + assertEquals(37, l.fromOuterScope()); + assertEquals(42, l.m()); } public void testLocalVarType_ForLoop() { - assertFalse(isGwtSourceLevel10()); + var a = new String[] {"4", "2"}; + var s = ""; + for (var i = 0; i < a.length; i++) { + s += a[i]; + } + assertEquals("42", s); } public void testLocalVarType_EnhancedForLoopArray() { - assertFalse(isGwtSourceLevel10()); + var a = new String[] {"4", "2"}; + var str = ""; + for (var s : a) { + str += s; + } + assertEquals("42", str); } public void testLocalVarType_EnhancedNestedForLoopArray() { - assertFalse(isGwtSourceLevel10()); + var m = new int[][] {{1, 2}, {3, 4}}; + var summ = 0; + for (var row : m) { + for (var cell : row) { + summ += cell; + } + } + assertEquals(10, summ); } public void testLocalVarType_EnhancedForLoopIterable() { - assertFalse(isGwtSourceLevel10()); - } - - private boolean isGwtSourceLevel10() { - return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA10) >= 0; + var list = new ArrayList(); + list.add("4"); + list.add("2"); + var str = ""; + for (var s : list) { + str += s; + } + assertEquals("42", str); } } diff --git a/user/test/com/google/gwt/dev/jjs/test/Java11Test.java b/user/test/com/google/gwt/dev/jjs/test/Java11Test.java index 446c487f75..eed3c58795 100644 --- a/user/test/com/google/gwt/dev/jjs/test/Java11Test.java +++ b/user/test/com/google/gwt/dev/jjs/test/Java11Test.java @@ -15,42 +15,41 @@ */ package com.google.gwt.dev.jjs.test; -import com.google.gwt.dev.util.arg.SourceLevel; import com.google.gwt.junit.DoNotRunWith; -import com.google.gwt.junit.JUnitShell; import com.google.gwt.junit.Platform; import com.google.gwt.junit.client.GWTTestCase; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + /** - * Dummy test case. Java11Test is super sourced so that GWT can be compiled by Java 8. - * - * NOTE: Make sure this class has the same test methods of its supersourced variant. + * Tests Java 11 features. */ @DoNotRunWith(Platform.Devel) public class Java11Test extends GWTTestCase { - @Override - public String getModuleName() { - return "com.google.gwt.dev.jjs.Java11Test"; + @interface NotNull { + } + + interface Lambda { + T run(T a, T b); } @Override - public void runTest() throws Throwable { - // Only run these tests if -sourceLevel 11 (or greater) is enabled. - if (isGwtSourceLevel11()) { - super.runTest(); - } + public String getModuleName() { + return "com.google.gwt.dev.jjs.Java11Test"; } public void testLambdaParametersVarType() { - assertFalse(isGwtSourceLevel11()); + Lambda l = (@NotNull var x, var y) -> x + y; + assertEquals("12", l.run("1", "2")); } public void testLambdaParametersVarType_function() { - assertFalse(isGwtSourceLevel11()); - } - - private boolean isGwtSourceLevel11() { - return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA11) >= 0; + List l = Arrays.asList("a", "b"); + l = l.stream().map((var s) -> s.toUpperCase()).collect(Collectors.toList()); + assertEquals("A", l.get(0)); + assertEquals("B", l.get(1)); } } diff --git a/user/test/com/google/gwt/dev/jjs/test/Java8Test.java b/user/test/com/google/gwt/dev/jjs/test/Java8Test.java index ed2e5d20d2..81ac455d8b 100644 --- a/user/test/com/google/gwt/dev/jjs/test/Java8Test.java +++ b/user/test/com/google/gwt/dev/jjs/test/Java8Test.java @@ -15,348 +15,2051 @@ */ package com.google.gwt.dev.jjs.test; -import com.google.gwt.dev.util.arg.SourceLevel; +import com.google.gwt.core.client.JavaScriptObject; +import com.google.gwt.core.client.JsonUtils; +import com.google.gwt.dev.jjs.test.defaultmethods.ImplementsWithDefaultMethodAndStaticInitializer; +import com.google.gwt.dev.jjs.test.defaultmethods.SomeClass; import com.google.gwt.junit.DoNotRunWith; -import com.google.gwt.junit.JUnitShell; import com.google.gwt.junit.Platform; import com.google.gwt.junit.client.GWTTestCase; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.IntFunction; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import jsinterop.annotations.JsFunction; +import jsinterop.annotations.JsOverlay; +import jsinterop.annotations.JsPackage; +import jsinterop.annotations.JsProperty; +import jsinterop.annotations.JsType; + /** - * Dummy test case. Java8Test was historically super sourced so that GWT can be compiled by Java 6. - * - * NOTE: Make sure this class has the same test methods of its supersourced variant. + * Tests Java 8 features. */ @DoNotRunWith(Platform.Devel) public class Java8Test extends GWTTestCase { + int local = 42; - @Override - public String getModuleName() { - return "com.google.gwt.dev.jjs.Java8Test"; + static abstract class SameClass { + public int method1() { + return 10; + } + public abstract int method2(); } - @Override - public void runTest() throws Throwable { - // Only run these tests if -sourceLevel 8 (or greater) is enabled. - if (isGwtSourceLevel8()) { - super.runTest(); + interface Lambda { + T run(int a, int b); + } + + interface Lambda2 { + boolean run(String a, String b); + } + + interface Lambda3 { + boolean run(String a); + } + + class AcceptsLambda { + public T accept(Lambda foo) { + return foo.run(10, 20); + } + public boolean accept2(Lambda2 foo) { + return foo.run("a", "b"); + } + public boolean accept3(Lambda3 foo) { + return foo.run("hello"); } } + class Pojo { + private final int x; + private final int y; + + Pojo(int x, int y) { + this.x = x; + this.y = y; + } + + public int fooInstance(int a, int b) { + return a + b + x + y; + } + } + + interface DefaultInterface { + void method1(); + // CHECKSTYLE_OFF + default int method2() { return 42; } + default int redeclaredAsAbstract() { + return 88; + } + default Integer addInts(int x, int y) { return x + y; } + default String print() { return "DefaultInterface"; } + // CHECKSTYLE_ON + } + + interface DefaultInterface2 { + void method3(); + // CHECKSTYLE_OFF + default int method4() { return 23; } + default int redeclaredAsAbstract() { + return 77; + } + // CHECKSTYLE_ON + } + + interface DefaultInterfaceSubType extends DefaultInterface { + // CHECKSTYLE_OFF + default int method2() { return 43; } + default String print() { + return "DefaultInterfaceSubType " + DefaultInterface.super.print(); + } + // CHECKSTYLE_ON + } + + static abstract class DualImplementorSuper implements DefaultInterface { + public void method1() { + } + + public abstract int redeclaredAsAbstract(); + } + + static class DualImplementorBoth extends VirtualUpRef implements DefaultInterface, + DefaultInterface2 { + public void method1() { + } + public void method3() { + } + } + + static class DualImplementor extends DualImplementorSuper implements DefaultInterface2 { + public void method3() { + } + + public int redeclaredAsAbstract() { + return DefaultInterface2.super.redeclaredAsAbstract(); + } + } + + // this doesn't implement DefaultInterface, but will provide implementation in subclasses + static class VirtualUpRef { + public int method2() { + return 99; + } + public int redeclaredAsAbstract() { + return 44; + } + } + + class Inner { + int local = 22; + public void run() { + assertEquals(94, new AcceptsLambda().accept((a,b) -> Java8Test.this.local + local + a + b).intValue()); + } + } + + static class Static { + static int staticField; + static { + staticField = 99; + } + static Integer staticMethod(int x, int y) { + return x + y + staticField; + } + } + + private static void throwInClinit() { + throw new RuntimeException("clinit() shouldn't run from just taking a reference to a method"); + } + static class StaticFailIfClinitRuns { + static { + throwInClinit(); + } + + public static Integer staticMethod(int x, int y) { + return null; + } + } + + static class DefaultInterfaceImpl implements DefaultInterface { + public void method1() { + } + } + + static class DefaultInterfaceImpl2 implements DefaultInterface { + public void method1() { + } + public int method2() { + return 100; + } + } + + static class DefaultInterfaceImplVirtualUpRef extends VirtualUpRef implements DefaultInterface { + public void method1() { + } + } + + static class DefaultInterfaceImplVirtualUpRefTwoInterfaces extends VirtualUpRef + implements DefaultInterfaceSubType { + public void method1() { + } + // CHECKSTYLE_OFF + public String print() { return "DefaultInterfaceImplVirtualUpRefTwoInterfaces"; } + // CHECKSTYLE_ON + } + + @Override + public String getModuleName() { + return "com.google.gwt.dev.jjs.Java8Test"; + } + public void testLambdaNoCapture() { - // Make sure we are using the right Java8Test if the source compatibility level is set to Java 8 - // or above. - assertFalse(isGwtSourceLevel8()); + assertEquals(30, new AcceptsLambda().accept((a, b) -> a + b).intValue()); } public void testLambdaCaptureLocal() { - assertFalse(isGwtSourceLevel8()); + int x = 10; + assertEquals(40, new AcceptsLambda().accept((a,b) -> x + a + b).intValue()); } public void testLambdaCaptureLocalWithInnerClass() { - assertFalse(isGwtSourceLevel8()); + int x = 10; + Lambda l = (a,b) -> new Lambda() { + @Override public Integer run(int a, int b) { + int t = x; + return t + a + b; + } + }.run(a,b); + assertEquals(40, new AcceptsLambda().accept(l).intValue()); } public void testLambdaCaptureLocalAndField() { - assertFalse(isGwtSourceLevel8()); + int x = 10; + assertEquals(82, new AcceptsLambda().accept((a,b) -> x + local + a + b).intValue()); } public void testLambdaCaptureLocalAndFieldWithInnerClass() { - assertFalse(isGwtSourceLevel8()); + int x = 10; + Lambda l = (a,b) -> new Lambda() { + @Override public Integer run(int j, int k) { + int t = x; + int s = local; + return t + s + a + b; + } + }.run(a,b); + assertEquals(82, new AcceptsLambda().accept(l).intValue()); } public void testCompileLambdaCaptureOuterInnerField() throws Exception { - assertFalse(isGwtSourceLevel8()); + new Inner().run(); } public void testStaticReferenceBinding() throws Exception { - assertFalse(isGwtSourceLevel8()); + assertEquals(129, new AcceptsLambda().accept(Static::staticMethod).intValue()); + // if this next line runs a clinit, it fails + Lambda l = dummyMethodToMakeCheckStyleHappy(StaticFailIfClinitRuns::staticMethod); + try { + // but now it should fail + l.run(1,2); + fail("Clinit should have run for the first time"); + } catch (RuntimeException ignored) { + // success, it was supposed to throw! + } + } + + private static Lambda dummyMethodToMakeCheckStyleHappy(Lambda l) { + return l; } public void testInstanceReferenceBinding() throws Exception { - assertFalse(isGwtSourceLevel8()); + Pojo instance1 = new Pojo(1, 2); + Pojo instance2 = new Pojo(3, 4); + assertEquals(33, new AcceptsLambda().accept(instance1::fooInstance).intValue()); + assertEquals(37, new AcceptsLambda().accept(instance2::fooInstance).intValue()); } public void testImplicitQualifierReferenceBinding() throws Exception { - assertFalse(isGwtSourceLevel8()); + assertFalse(new AcceptsLambda().accept2(String::equalsIgnoreCase)); + assertTrue(new AcceptsLambda().accept3("hello world"::contains)); } public void testConstructorReferenceBinding() { - assertFalse(isGwtSourceLevel8()); + assertEquals(30, new AcceptsLambda().accept(Pojo::new).fooInstance(0, 0)); } public void testStaticInterfaceMethod() { - assertFalse(isGwtSourceLevel8()); + assertEquals(99, (int) Static.staticMethod(0, 0)); + } + + interface ArrayCtor { + ArrayElem [][][] copy(int i); + } + + interface ArrayCtorBoxed { + ArrayElem [][][] copy(Integer i); + } + + static class ArrayElem { } public void testArrayConstructorReference() { - assertFalse(isGwtSourceLevel8()); + ArrayCtor ctor = ArrayElem[][][]::new; + ArrayElem[][][] array = ctor.copy(100); + assertEquals(100, array.length); } public void testArrayConstructorReferenceBoxed() { - assertFalse(isGwtSourceLevel8()); + ArrayCtorBoxed ctor = ArrayElem[][][]::new; + ArrayElem[][][] array = ctor.copy(100); + assertEquals(100, array.length); + } + + interface ThreeArgs { + int foo(int x, int y, int z); + } + + interface ThreeVarArgs { + int foo(int x, int y, int... z); + } + + public static int addMany(int x, int y, int... nums) { + int sum = x + y; + for (int num : nums) { + sum += num; + } + return sum; } public void testVarArgsReferenceBinding() { - assertFalse(isGwtSourceLevel8()); + ThreeArgs t = Java8Test::addMany; + assertEquals(6, t.foo(1,2,3)); } public void testVarArgsPassthroughReferenceBinding() { - assertFalse(isGwtSourceLevel8()); + ThreeVarArgs t = Java8Test::addMany; + assertEquals(6, t.foo(1,2,3)); } public void testVarArgsPassthroughReferenceBindingProvidedArray() { - assertFalse(isGwtSourceLevel8()); + ThreeVarArgs t = Java8Test::addMany; + assertEquals(6, t.foo(1,2, new int[] {3})); + } + + interface I { + int foo(Integer i); } public void testSuperReferenceExpression() { - assertFalse(isGwtSourceLevel8()); + class Y { + int foo(Integer i) { + return 42; + } + } + + class X extends Y { + int foo(Integer i) { + return 23; + } + + int goo() { + I i = super::foo; + return i.foo(0); + } + } + + assertEquals(42, new X().goo()); } public void testQualifiedSuperReferenceExpression() { - assertFalse(isGwtSourceLevel8()); + class Y { + int foo(Integer i) { + return 42; + } + } + + class X extends Y { + int foo(Integer i) { + return 23; + } + + int goo() { + I i = X.super::foo; + return i.foo(0); + } + } + + assertEquals(42, new X().goo()); + } + + static class X2 { + protected int field; + void foo() { + int local; + class Y extends X2 { + class Z extends X2 { + void f() { + Ctor c = X2::new; + X2 x = c.makeX(123456); + assertEquals(123456, x.field); + c = Y::new; + x = c.makeX(987654); + x = new Y(987654); + assertEquals(987655, x.field); + c = Z::new; + x = c.makeX(456789); + x = new Z(456789); + assertEquals(456791, x.field); + } + private Z(int z) { + super(z + 2); + } + Z() { + } + } + + private Y(int y) { + super(y + 1); + } + + private Y() { + } + } + new Y().new Z().f(); + } + + private X2(int x) { + this.field = x; + } + X2() { + } } public void testSuperReferenceExpressionWithVarArgs() { - assertFalse(isGwtSourceLevel8()); + class Base { + int foo(Object... objects) { + return 0; + } + } + + class X extends Base { + int foo(Object... objects) { + throw new AssertionError(); + } + + void goo() { + I i = super::foo; + i.foo(10); + } + } + new X().goo(); + } + + interface Ctor { + X2 makeX(int x); } public void testPrivateConstructorReference() { - assertFalse(isGwtSourceLevel8()); + new X2().foo(); } public void testDefaultInterfaceMethod() { - assertFalse(isGwtSourceLevel8()); + assertEquals(42, new DefaultInterfaceImpl().method2()); } public void testDefaultInterfaceMethodVirtualUpRef() { - assertFalse(isGwtSourceLevel8()); + assertEquals(99, new DefaultInterfaceImplVirtualUpRef().method2()); + assertEquals(99, new DefaultInterfaceImplVirtualUpRefTwoInterfaces().method2()); + assertEquals("SimpleB", new com.google.gwt.dev.jjs.test.package3.SimpleC().m()); + assertEquals("SimpleASimpleB", new com.google.gwt.dev.jjs.test.package1.SimpleD().m()); } - public void testInterfaceWithDefaultMethodsInitialization() { - assertFalse(isGwtSourceLevel8()); + public void testDefaultInterfaceMethodMultiple() { + assertEquals(42, new DualImplementor().method2()); + assertEquals(23, new DualImplementor().method4()); + assertEquals(77, new DualImplementor().redeclaredAsAbstract()); + assertEquals(44, new DualImplementorBoth().redeclaredAsAbstract()); + DefaultInterfaceImplVirtualUpRefTwoInterfaces instanceImplementInterfaceSubType = + new DefaultInterfaceImplVirtualUpRefTwoInterfaces(); + DefaultInterfaceSubType interfaceSubType1 = instanceImplementInterfaceSubType; + assertEquals("DefaultInterfaceImplVirtualUpRefTwoInterfaces", + instanceImplementInterfaceSubType.print()); + assertEquals("DefaultInterfaceImplVirtualUpRefTwoInterfaces", interfaceSubType1.print()); + DefaultInterfaceSubType interfaceSubType2 = new DefaultInterfaceSubType() { + @Override + public void method1() { } + }; + assertEquals("DefaultInterfaceSubType DefaultInterface", + interfaceSubType2.print()); + DefaultInterfaceSubType interfaceSubType3 = () -> { }; + assertEquals("DefaultInterfaceSubType DefaultInterface", + interfaceSubType3.print()); } - public void testDefaultInterfaceMethodMultiple() { - assertFalse(isGwtSourceLevel8()); + public void testDefenderMethodByInterfaceInstance() { + DefaultInterfaceImpl2 interfaceImpl2 = new DefaultInterfaceImpl2(); + DefaultInterface interface1 = interfaceImpl2; + assertEquals(100, interfaceImpl2.method2()); + assertEquals(100, interface1.method2()); } public void testDefaultMethodReference() { - assertFalse(isGwtSourceLevel8()); + DefaultInterfaceImplVirtualUpRef x = new DefaultInterfaceImplVirtualUpRef(); + assertEquals(30, (int) new AcceptsLambda().accept(x::addInts)); } - public void testDefenderMethodByInterfaceInstance() { - assertFalse(isGwtSourceLevel8()); + interface InterfaceWithTwoDefenderMethods { + // CHECKSTYLE_OFF + default String foo() { return "interface.foo"; } + default String bar() { return this.foo() + " " + foo(); } + // CHECKSTYLE_ON } - public void testDefaultMethod_staticInitializer() { - assertFalse(isGwtSourceLevel8()); + class ClassImplementOneDefenderMethod implements InterfaceWithTwoDefenderMethods { + public String foo() { + return "class.foo"; + } } public void testThisRefInDefenderMethod() { - assertFalse(isGwtSourceLevel8()); + ClassImplementOneDefenderMethod c = new ClassImplementOneDefenderMethod(); + InterfaceWithTwoDefenderMethods i1 = c; + InterfaceWithTwoDefenderMethods i2 = new InterfaceWithTwoDefenderMethods() { }; + assertEquals("class.foo class.foo", c.bar()); + assertEquals("class.foo class.foo", i1.bar()); + assertEquals("interface.foo interface.foo", i2.bar()); + } + + interface InterfaceImplementOneDefenderMethod extends InterfaceWithTwoDefenderMethods { + // CHECKSTYLE_OFF + default String foo() { return "interface1.foo"; } + // CHECKSTYLE_ON + } + + interface InterfaceImplementZeroDefenderMethod extends InterfaceWithTwoDefenderMethods { + } + + class ClassImplementsTwoInterfaces implements InterfaceImplementOneDefenderMethod, + InterfaceImplementZeroDefenderMethod { } public void testClassImplementsTwoInterfacesWithSameDefenderMethod() { - assertFalse(isGwtSourceLevel8()); + ClassImplementsTwoInterfaces c = new ClassImplementsTwoInterfaces(); + assertEquals("interface1.foo", c.foo()); + } + + abstract class AbstractClass implements InterfaceWithTwoDefenderMethods { + } + + class Child1 extends AbstractClass { + public String foo() { + return super.foo() + " child1.foo"; + } + } + + class Child2 extends AbstractClass { } public void testAbstractClassImplementsInterface() { - assertFalse(isGwtSourceLevel8()); + Child1 child1 = new Child1(); + Child2 child2 = new Child2(); + assertEquals("interface.foo child1.foo", child1.foo()); + assertEquals("interface.foo", child2.foo()); + } + + interface InterfaceI { + // CHECKSTYLE_OFF + default String print() { return "interface1"; } + // CHECKSTYLE_ON + } + interface InterfaceII { + // CHECKSTYLE_OFF + default String print() { return "interface2"; } + // CHECKSTYLE_ON + } + class ClassI { + public String print() { + return "class1"; + } + } + class ClassII extends ClassI implements InterfaceI, InterfaceII { + public String print() { + return super.print() + " " + InterfaceI.super.print() + " " + InterfaceII.super.print(); + } } public void testSuperRefInDefenderMethod() { - assertFalse(isGwtSourceLevel8()); + ClassII c = new ClassII(); + assertEquals("class1 interface1 interface2", c.print()); } - public void testSuperThisRefsInDefenderMethod() { - assertFalse(isGwtSourceLevel8()); + interface II { + // CHECKSTYLE_OFF + default String fun() { return "fun() in i: " + this.foo(); }; + default String foo() { return "foo() in i.\n"; }; + // CHECKSTYLE_ON + } + interface JJ extends II { + // CHECKSTYLE_OFF + default String fun() { return "fun() in j: " + this.foo() + II.super.fun(); }; + default String foo() { return "foo() in j.\n"; } + // CHECKSTYLE_ON + } + class AA { + public String fun() { + return "fun() in a: " + this.foo(); + } + public String foo() { + return "foo() in a.\n"; + } + } + class BB extends AA implements JJ { + public String fun() { + return "fun() in b: " + this.foo() + super.fun() + JJ.super.fun(); + } + public String foo() { + return "foo() in b.\n"; + } + } + class CC extends BB implements JJ { + public String fun() { + return "fun() in c: " + super.fun(); + } } + public void testSuperThisRefsInDefenderMethod() { + CC c = new CC(); + II i1 = c; + JJ j1 = c; + BB b = new BB(); + II i2 = b; + JJ j2 = b; + JJ j3 = new JJ() { }; + II i3 = j3; + II i4 = new II() { }; + String c_fun = "fun() in c: fun() in b: foo() in b.\n" + + "fun() in a: foo() in b.\n" + + "fun() in j: foo() in b.\n" + + "fun() in i: foo() in b.\n"; + String b_fun = "fun() in b: foo() in b.\n" + + "fun() in a: foo() in b.\n" + + "fun() in j: foo() in b.\n" + + "fun() in i: foo() in b.\n"; + String j_fun = "fun() in j: foo() in j.\n" + + "fun() in i: foo() in j.\n"; + String i_fun = "fun() in i: foo() in i.\n"; + assertEquals(c_fun, c.fun()); + assertEquals(c_fun, i1.fun()); + assertEquals(c_fun, j1.fun()); + assertEquals(b_fun, b.fun()); + assertEquals(b_fun, i2.fun()); + assertEquals(b_fun, j2.fun()); + assertEquals(j_fun, j3.fun()); + assertEquals(j_fun, i3.fun()); + assertEquals(i_fun, i4.fun()); + } + + interface OuterInterface { + // CHECKSTYLE_OFF + default String m() { + return "I.m;" + new InnerClass().n(); + } + default String n() { + return "I.n;" + this.m(); + } + // CHECKSTYLE_ON + class InnerClass { + public String n() { + return "A.n;" + m(); + } + public String m() { + return "A.m;"; + } + } + } + class OuterClass { + public String m() { + return "B.m;"; + } + public String n1() { + OuterInterface i = new OuterInterface() { }; + return "B.n1;" + i.n() + OuterClass.this.m(); + } + public String n2() { + OuterInterface i = new OuterInterface() { + @Override + public String n() { + return this.m() + OuterClass.this.m(); + } + }; + return "B.n2;" + i.n() + OuterClass.this.m(); + } + } public void testNestedInterfaceClass() { - assertFalse(isGwtSourceLevel8()); + OuterClass outerClass = new OuterClass(); + assertEquals("B.n1;I.n;I.m;A.n;A.m;B.m;", outerClass.n1()); + assertEquals("B.n2;I.m;A.n;A.m;B.m;B.m;", outerClass.n2()); } + class EmptyA { } + interface EmptyI { } + interface EmptyJ { } + class EmptyB extends EmptyA implements EmptyI { } + class EmptyC extends EmptyA implements EmptyI, EmptyJ { } public void testBaseIntersectionCast() { - assertFalse(isGwtSourceLevel8()); + EmptyA localB = new EmptyB(); + EmptyA localC = new EmptyC(); + EmptyB b2BI = (EmptyB & EmptyI) localB; + EmptyC c2CIJ = (EmptyC & EmptyI & EmptyJ) localC; + EmptyI ii1 = (EmptyB & EmptyI) localB; + EmptyI ii2 = (EmptyC & EmptyI) localC; + EmptyI ii3 = (EmptyC & EmptyJ) localC; + EmptyI ii4 = (EmptyC & EmptyI & EmptyJ) localC; + EmptyJ jj1 = (EmptyC & EmptyI & EmptyJ) localC; + EmptyJ jj2 = (EmptyC & EmptyI) localC; + EmptyJ jj3 = (EmptyC & EmptyJ) localC; + EmptyJ jj4 = (EmptyI & EmptyJ) localC; + + try { + EmptyC b2CIJ = (EmptyC & EmptyI & EmptyJ) localB; + fail("Should have thrown a ClassCastException"); + } catch (ClassCastException e) { + // Expected. + } + try { + EmptyB c2BI = (EmptyB & EmptyI) localC; + fail("Should have thrown a ClassCastException"); + } catch (ClassCastException e) { + // Expected. + } + try { + EmptyJ jj = (EmptyB & EmptyJ) localB; + fail("Should have thrown a ClassCastException"); + } catch (ClassCastException e) { + // Expected. + } } + interface SimpleI { + int fun(); + } + interface SimpleK { + } public void testIntersectionCastWithLambdaExpr() { - assertFalse(isGwtSourceLevel8()); + SimpleI simpleI1 = (SimpleI & EmptyI) () -> 11; + assertEquals(11, simpleI1.fun()); + SimpleI simpleI2 = (EmptyI & SimpleI) () -> 22; + assertEquals(22, simpleI2.fun()); + EmptyI emptyI = (EmptyI & SimpleI) () -> 33; + assertEquals(55, ((SimpleI & SimpleK) () -> 55).fun()); + } + + class SimpleA { + public int bar() { + return 11; + } + } + + class SimpleB extends SimpleA implements SimpleI { + public int fun() { + return 22; + } + } + + class SimpleC extends SimpleA implements SimpleI { + public int fun() { + return 33; + } + + public int bar() { + return 44; + } } public void testIntersectionCastPolymorphism() { - assertFalse(isGwtSourceLevel8()); + SimpleA bb = new SimpleB(); + assertEquals(22, ((SimpleB & SimpleI) bb).fun()); + assertEquals(11, ((SimpleB & SimpleI) bb).bar()); + SimpleA cc = new SimpleC(); + assertEquals(33, ((SimpleC & SimpleI) cc).fun()); + assertEquals(44, ((SimpleC & SimpleI) cc).bar()); + assertEquals(33, ((SimpleA & SimpleI) cc).fun()); + SimpleI ii = (SimpleC & SimpleI) cc; + assertEquals(33, ii.fun()); } + interface ClickHandler { + int onClick(int a); + } + private int addClickHandler(ClickHandler clickHandler) { + return clickHandler.onClick(1); + } + private int addClickHandler(int a) { + return addClickHandler(x -> { + int temp = a; return temp; + }); + } public void testLambdaCaptureParameter() { - assertFalse(isGwtSourceLevel8()); + assertEquals(2, addClickHandler(2)); } + interface TestLambda_Inner { + void f(); + } + interface TestLambda_Outer { + void accept(TestLambda_Inner t); + } + public void testLambda_call(TestLambda_Outer a) { + a.accept(() -> { }); + } public void testLambdaNestingCaptureLocal() { - assertFalse(isGwtSourceLevel8()); + int[] success = new int[] {0}; + testLambda_call(sam1 -> { + testLambda_call(sam2 -> { + success[0] = 10; + }); + }); + assertEquals(10, success[0]); } public void testLambdaNestingInAnonymousCaptureLocal() { - assertFalse(isGwtSourceLevel8()); + int[] x = new int[] {42}; + new Runnable() { + public void run() { + Lambda l = (a, b) -> x[0] = x[0] + a + b; + l.run(1, 2); + } + }.run(); + assertEquals(45, x[0]); } public void testLambdaNestingInMultipleMixedAnonymousCaptureLocal() { - assertFalse(isGwtSourceLevel8()); + // checks that lambda has access to local variable and arguments when placed in mixed scopes + // Local Class -> Local Class -> Local Anonymous -> lambda -> Local Anonymous + class A { + int a() { + int[] x = new int[] {42}; + class B { + void b() { + I i = new I() { + public int foo(Integer arg) { + Runnable r = () -> { + new Runnable() { + public void run() { + Lambda l = (a, b) -> x[0] = x[0] + a + b + arg; + l.run(1, 2); + } + }.run(); + }; + r.run(); + return x[0]; + } + }; + i.foo(1); + } + } + B b = new B(); + b.b(); + return x[0]; + } + } + A a = new A(); + assertEquals(46, a.a()); } public void testLambdaNestingInMultipleMixedAnonymousCaptureLocal_withInterference() { - assertFalse(isGwtSourceLevel8()); + // checks that lambda has access to NEAREST local variable and arguments when placed in mixed + // scopes Local Class -> Local Class -> Local Anonymous -> lambda -> Local Anonymous + class A { + int a() { + int[] x = new int[] {42}; + class B { + int b() { + int[] x = new int[] {22}; + I i = new I() { + public int foo(Integer arg) { + Runnable r = () -> { + new Runnable() { + public void run() { + Lambda l = (a, b) -> x[0] = x[0] + a + b + arg; + l.run(1, 2); + } + }.run(); + }; + r.run(); + return x[0]; + } + }; + return i.foo(1); + } + } + B b = new B(); + return b.b(); + } + } + A a = new A(); + assertEquals(26, a.a()); } public void testLambdaNestingInMultipleMixedAnonymousCaptureLocalAndField() { - assertFalse(isGwtSourceLevel8()); + // checks that lambda has access to local variable, field and arguments when placed in mixed + // scopes - Local Class -> Local Class -> Local Anonymous -> lambda -> Local Anonymous + class A { + int fA = 1; + + int a() { + int[] x = new int[] {42}; + class B { + int fB = 2; + + int b() { + I i = new I() { + int fI = 3; + + public int foo(Integer arg) { + Runnable r = () -> { + new Runnable() { + public void run() { + Lambda l = (a, b) -> x[0] = x[0] + a + b + arg + fA + fB + fI; + l.run(1, 2); + } + }.run(); + }; + r.run(); + return x[0]; + } + }; + return i.foo(1); + } + } + B b = new B(); + return b.b(); + } + } + A a = new A(); + assertEquals(52, a.a()); } public void testLambdaNestingInMultipleAnonymousCaptureLocal() { - assertFalse(isGwtSourceLevel8()); + // checks that lambda has access to local variable and arguments when placed in local anonymous + // class with multile nesting + int[] x = new int[] {42}; + int result = new I() { + public int foo(Integer i1) { + return new I() { + public int foo(Integer i2) { + return new I() { + public int foo(Integer i3) { + Lambda l = (a, b) -> x[0] = x[0] + a + b + i1 + i2 + i3; + return l.run(1, 2); + } + }.foo(3); + } + }.foo(2); + } + }.foo(1); + assertEquals(51, x[0]); + } + + static class TestLambda_ClassA { + int[] f = new int[] {42}; + + class B { + void m() { + Runnable r = () -> f[0] = f[0] + 1; + r.run(); + } + } + + int a() { + B b = new B(); + b.m(); + return f[0]; + } } public void testLambdaNestingCaptureField_InnerClassCapturingOuterClassVariable() { - assertFalse(isGwtSourceLevel8()); + TestLambda_ClassA a = new TestLambda_ClassA(); + assertEquals(43, a.a()); } public void testInnerClassCaptureLocalFromOuterLambda() { - assertFalse(isGwtSourceLevel8()); + int[] x = new int[] {42}; + Lambda l = (a, b) -> { + int[] x1 = new int[] {32}; + Lambda r = (rA, rB) -> { + int[] x2 = new int[] {22}; + I i = new I() { + public int foo(Integer arg) { + x1[0] = x1[0] + 1; + x[0] = x[0] + 1; + return x2[0] = x2[0] + rA + rB + a + b; + } + }; + return i.foo(1); + }; + return r.run(3, 4) + x1[0]; + }; + + // x1[0](32) + 1 + x2[0](22) + rA(3) + rB(4) + a(1) + b(2) + assertEquals(65, l.run(1, 2).intValue()); + assertEquals(43, x[0]); + } + + static class TestLambda_Class { + public int[] s = new int[] {0}; + public void call(TestLambda_Outer a) { + a.accept(() -> { }); + } + class TestLambda_InnerClass { + public int[] s = new int[] {0}; + public int test() { + int[] s = new int[] {0}; + TestLambda_Class.this.call( + sam0 -> TestLambda_Class.this.call( + sam1 -> { + TestLambda_Class.this.call( + sam2 -> { + TestLambda_Class.this.s[0] = 10; + this.s[0] = 20; + s[0] = 30; + }); + })); + return s[0]; + } + } } public void testLambdaNestingCaptureField() { - assertFalse(isGwtSourceLevel8()); + TestLambda_Class a = new TestLambda_Class(); + a.call(sam1 -> { + a.call(sam2 -> { + a.s[0] = 20; + }); + }); + assertEquals(20, a.s[0]); } public void testLambdaMultipleNestingCaptureFieldAndLocal() { - assertFalse(isGwtSourceLevel8()); + TestLambda_Class a = new TestLambda_Class(); + TestLambda_Class b = new TestLambda_Class(); + int [] s = new int [] {0}; + b.call(sam0 -> a.call(sam1 -> { + a.call(sam2 -> { + a.s[0] = 20; + b.s[0] = 30; + s[0] = 40; + }); + })); + assertEquals(20, a.s[0]); + assertEquals(30, b.s[0]); + assertEquals(40, s[0]); } public void testLambdaMultipleNestingCaptureFieldAndLocalInnerClass() { - assertFalse(isGwtSourceLevel8()); + TestLambda_Class a = new TestLambda_Class(); + TestLambda_Class.TestLambda_InnerClass b = a.new TestLambda_InnerClass(); + int result = b.test(); + assertEquals(10, a.s[0]); + assertEquals(20, b.s[0]); + assertEquals(30, result); + } + + static class TestMF_A { + public static String getId() { + return "A"; + } + public int getIdx() { + return 1; + } + } + static class TestMF_B { + public static String getId() { + return "B"; + } + public int getIdx() { + return 2; + } + } + interface Function { + T apply(); + } + private String f(Function arg) { + return arg.apply(); + } + private int g(Function arg) { + return arg.apply().intValue(); } public void testMethodRefWithSameName() { - assertFalse(isGwtSourceLevel8()); + assertEquals("A", f(TestMF_A::getId)); + assertEquals("B", f(TestMF_B::getId)); + TestMF_A a = new TestMF_A(); + TestMF_B b = new TestMF_B(); + assertEquals(1, g(a::getIdx)); + assertEquals(2, g(b::getIdx)); + } + + // Test particular scenarios involving multiple path to inherit defaults. + interface ITop { + default String m() { + return "ITop.m()"; + } + } + + interface IRight extends ITop { + default String m() { + return "IRight.m()"; + } } + interface ILeft extends ITop { } + public void testMultipleDefaults_fromInterfaces_left() { - assertFalse(isGwtSourceLevel8()); + class A implements ILeft, IRight { } + + assertEquals("IRight.m()", new A().m()); } public void testMultipleDefaults_fromInterfaces_right() { - assertFalse(isGwtSourceLevel8()); + class A implements IRight, ILeft { } + + assertEquals("IRight.m()", new A().m()); } public void testMultipleDefaults_superclass_left() { - assertFalse(isGwtSourceLevel8()); + class A implements ITop { } + class B extends A implements ILeft, IRight { } + + assertEquals("IRight.m()", new B().m()); } public void testMultipleDefaults_superclass_right() { - assertFalse(isGwtSourceLevel8()); + class A implements ITop { } + class B extends A implements IRight, ILeft { } + + assertEquals("IRight.m()", new B().m()); + } + + static class DefaultTrumpsOverSyntheticAbstractStub { + interface SuperInterface { + String m(); + } + + interface SubInterface extends SuperInterface { + default String m() { + return "SubInterface.m()"; + } + } } public void testMultipleDefaults_defaultShadowsOverSyntheticAbstractStub() { - assertFalse(isGwtSourceLevel8()); + abstract class A implements DefaultTrumpsOverSyntheticAbstractStub.SuperInterface { } + class B extends A implements DefaultTrumpsOverSyntheticAbstractStub.SubInterface { } + + assertEquals("SubInterface.m()", new B().m()); + } + + static class DefaultTrumpsOverDefaultOnSuperAbstract { + interface SuperInterface { + default String m() { + return "SuperInterface.m()"; + } + } + + interface SubInterface extends SuperInterface { + default String m() { + return "SubInterface.m()"; + } + } } public void testMultipleDefaults_defaultShadowsOverDefaultOnSuperAbstract() { - assertFalse(isGwtSourceLevel8()); + abstract class A implements DefaultTrumpsOverDefaultOnSuperAbstract.SuperInterface { } + class B extends A implements DefaultTrumpsOverDefaultOnSuperAbstract.SubInterface { } + + assertEquals("SubInterface.m()", new B().m()); + } + + interface InterfaceWithThisReference { + default String n() { + return "default n"; + } + default String callNUnqualified() { + class Super implements InterfaceWithThisReference { + public String n() { + return "super n"; + } + } + return new Super() { + public String callNUnqualified() { + return "Object " + n(); + } + }.callNUnqualified(); + } + default String callNWithThis() { + class Super implements InterfaceWithThisReference { + public String n() { + return "super n"; + } + } + return new Super() { + public String callNWithThis() { + return "Object " + this.n(); + } + }.callNWithThis(); + } + default String callNWithInterfaceThis() { + class Super implements InterfaceWithThisReference { + public String n() { + return "super n"; + } + } + return new Super() { + public String callNWithInterfaceThis() { + // In this method this has interface Test as its type, but it refers to outer n(); + return "Object " + InterfaceWithThisReference.this.n(); + } + }.callNWithInterfaceThis(); + } + default String callNWithSuper() { + class Super implements InterfaceWithThisReference { + public String n() { + return "super n"; + } + } + return new Super() { + public String callNWithSuper() { + // In this method this has interface Test as its type. + return "Object " + super.n(); + } + }.callNWithSuper(); + } + default String callNWithInterfaceSuper() { + return new InterfaceWithThisReference() { + public String n() { + return "this n"; + } + public String callNWithInterfaceSuper() { + // In this method this has interface Test as its type and refers to default n(); + return "Object " + InterfaceWithThisReference.super.n(); + } + }.callNWithInterfaceSuper(); + } } public void testInterfaceThis() { - assertFalse(isGwtSourceLevel8()); + class A implements InterfaceWithThisReference { + public String n() { + return "n"; + } + } + assertEquals("Object super n", new A().callNUnqualified()); + assertEquals("Object super n", new A().callNWithThis()); + assertEquals("Object n", new A().callNWithInterfaceThis()); + assertEquals("Object super n", new A().callNWithSuper()); + assertEquals("Object default n", new A().callNWithInterfaceSuper()); + } + + private static List initializationOrder; + + private static int get(String s) { + initializationOrder.add(s); + return 1; + } + + interface A1 { + int fa1 = get("A1"); + + default void a1() { } + } + + interface A2 { + int fa2 = get("A2"); + + default void a2() { } + } + + interface A3 { + int fa3 = get("A3"); + + default void a3() { } + } + + interface B1 extends A1 { + int fb1 = get("B1"); + + default void b1() { } + } + + interface B2 extends A2 { + int fb2 = get("B2"); + + default void b2() { } + } + + interface B3 extends A3 { + int fb3 = get("B3"); + } + + static class C implements B1, A2 { + static { + get("C"); + } + } + + static class D extends C implements B2, B3 { + static { + get("D"); + } + } + + public void testInterfaceWithDefaultMethodsInitialization() { + initializationOrder = new ArrayList(); + new D(); + assertContentsInOrder(initializationOrder, "A1", "B1", "A2", "C", "B2", "A3", "D"); + } + + /** + * Regression test for issue 9214. + */ + interface P { + boolean apply(T obj); + } + + static class B { + public boolean getTrue() { + return true; + } + } + private static String getClassName(T obj) { + return obj.getClass().getSimpleName(); } public void testMethodReference_generics() { - assertFalse(isGwtSourceLevel8()); + P p = B::getTrue; + assertTrue(p.apply(new B())); + // The next two method references must result in two different lambda implementations due + // to generics, see bug # 9333. + MyFunction1 f1 = Java8Test::getClassName; + MyFunction1 f2 = Java8Test::getClassName; + + assertEquals(B.class.getSimpleName(), f1.apply(new B())); + assertEquals(Double.class.getSimpleName(), f2.apply(new Double(2))); + } + + public void testDefaultMethod_staticInitializer() { + SomeClass.initializationOrder = new ArrayList(); + Object object = ImplementsWithDefaultMethodAndStaticInitializer.someClass; + assertContentsInOrder(SomeClass.initializationOrder, "1", "2", "3", "4"); + } + + private void assertContentsInOrder(Iterable contents, String... elements) { + assertEquals(Arrays.asList(elements).toString(), contents.toString()); + } + + @JsType(isNative = true) + interface NativeJsTypeInterfaceWithStaticInitializationAndFieldAccess { + @JsOverlay + Object object = new Integer(3); + } + + @JsType(isNative = true) + interface NativeJsTypeInterfaceWithStaticInitializationAndStaticOverlayMethod { + @JsOverlay + Object object = new Integer(4); + + @JsOverlay + static Object getObject() { + return object; + } + } + + @JsType(isNative = true) + interface NativeJsTypeInterfaceWithStaticInitializationAndInstanceOverlayMethod { + @JsOverlay + Object object = new Integer(5); + + int getA(); + + @JsOverlay + default Object getObject() { + return ((int) object) + this.getA(); + } + } + + private native NativeJsTypeInterfaceWithStaticInitializationAndInstanceOverlayMethod + createNativeJsTypeInterfaceWithStaticInitializationAndInstanceOverlayMethod() /*-{ + return { getA: function() { return 1; } }; + }-*/; + + @JsType(isNative = true) + interface NativeJsTypeInterfaceWithStaticInitialization { + @JsOverlay + Object object = new Integer(6); + } + + @JsType(isNative = true) + interface NativeJsTypeInterfaceWithComplexStaticInitialization { + @JsOverlay + Object object = (Integer) (((int) NativeJsTypeInterfaceWithStaticInitialization.object) + 1); + } + + static class JavaTypeImplementingNativeJsTypeInterceWithDefaultMethod implements + NativeJsTypeInterfaceWithStaticInitializationAndInstanceOverlayMethod { + public int getA() { + return 4; + } } public void testNativeJsTypeWithStaticInitializer() { - assertFalse(isGwtSourceLevel8()); + assertEquals(3, NativeJsTypeInterfaceWithStaticInitializationAndFieldAccess.object); + assertEquals( + 4, NativeJsTypeInterfaceWithStaticInitializationAndStaticOverlayMethod.getObject()); + assertEquals(6, + createNativeJsTypeInterfaceWithStaticInitializationAndInstanceOverlayMethod() + .getObject()); + assertEquals(7, NativeJsTypeInterfaceWithComplexStaticInitialization.object); + assertEquals(9, new JavaTypeImplementingNativeJsTypeInterceWithDefaultMethod().getObject()); + } + + @JsFunction + interface VarargsFunction { + String f(int i, String... args); } + private static native String callFromJSNI(VarargsFunction f) /*-{ + return f(2, "a", "b", "c"); + }-*/; + public void testJsVarargsLambda() { - assertFalse(isGwtSourceLevel8()); + VarargsFunction function = (i, args) -> args[i]; + assertSame("b", function.f(1, "a", "b", "c")); + assertSame("c", callFromJSNI(function)); + String[] pars = new String[] {"a", "b", "c"}; + assertSame("a", function.f(0, pars)); + } + + private static T m(T s) { + return s; + } + + static class Some { + T s; + MyFunction2 combine; + Some(T s, MyFunction2 combine) { + this.s = s; + this.combine = combine; + } + public T m(T s2) { + return combine.apply(s, s2); + } + public T m1() { + return s; + } + } + + @FunctionalInterface + interface MyFunction1 { + U apply(T t); + } + + @FunctionalInterface + interface MyFunction2 { + V apply(T t, U u); + } + + @FunctionalInterface + interface MyFunction3 { + W apply(T t, U u, V v); + } + + @FunctionalInterface + interface IntFunction1 { + U apply(int t); + } + + @FunctionalInterface + interface IntFunction2 { + V apply(int t, int u); + } + + @FunctionalInterface + interface IntFunction3 { + W apply(int t, int u, int v); } public void testMethodReference_implementedInSuperclass() { - assertFalse(isGwtSourceLevel8()); + MyFunction1 toString = StringBuilder::toString; + assertEquals("Hello", toString.apply(new StringBuilder("Hello"))); } + static MyFunction2 concat = (s,t) -> s + t; + public void testMethodReference_genericTypeParameters() { - assertFalse(isGwtSourceLevel8()); + testMethodReference_genericTypeParameters( + new Some("Hell", concat), "Hell", "o", concat); } - public void testMethodReference_autoboxing() { - assertFalse(isGwtSourceLevel8()); + static String concat(String... strs) { + String result = ""; + for (String s : strs) { + result += s; + } + return result; + } + + static String anotherConcat(String s1, String s2, String... strs) { + String result = s1 + s2; + for (String s : strs) { + result += s; + } + return result; + } + + public String instanceConcat(String... strs) { + String result = ""; + for (String s : strs) { + result += s; + } + return result; + } + + public String anotherInstanceConcat(String s1, String... strs) { + String result = s1; + for (String s : strs) { + result += s; + } + return result; + } + + private static class ClassWithVarArgsConstructor { + private class Inner { + private int sum; + Inner(int i, Integer... nums) { + this.sum = ClassWithVarArgsConstructor.this.sum + i; + for (Integer n: nums) { + sum += n; + } + } + } + + private int sum; + ClassWithVarArgsConstructor(int i, Integer... nums) { + sum = i; + for (Integer n: nums) { + sum += n; + } + } + + private MyFunction1 createInner1Param() { + return (MyFunction1) Inner::new; + } + + private MyFunction2 createInner2Param() { + return (MyFunction2) Inner::new; + } + + private MyFunction3 createInner3Param() { + return (MyFunction3) Inner::new; + } + + private MyFunction2 createInner2ParamArray() { + return (MyFunction2) Inner::new; + } + + private IntFunction1 createInner1IntParam() { + return (IntFunction1) Inner::new; + } + + private IntFunction2 createInner2IntParam() { + return (IntFunction2) Inner::new; + } + + private IntFunction3 createInner3IntParam() { + return (IntFunction3) Inner::new; + } } public void testMethodReference_varargs() { - assertFalse(isGwtSourceLevel8()); + // More functional arguments than varargs + MyFunction2 concat = Java8Test::concat; + assertEquals("ab", concat.apply("a", "b")); + + // Less functional arguments than varargs + MyFunction2 anotherConcat = Java8Test::anotherConcat; + assertEquals("ab", anotherConcat.apply("a", "b")); + + MyFunction2 instanceConcat = Java8Test::instanceConcat; + assertEquals("a", instanceConcat.apply(this, "a")); + + MyFunction2 anotherInstanceConcat = Java8Test::anotherInstanceConcat; + assertEquals("a", anotherInstanceConcat.apply(this, "a")); + + // constructor varargs + MyFunction1 constructor1Param = + ClassWithVarArgsConstructor::new; + assertEquals(1, constructor1Param.apply(1).sum); + + MyFunction2 constructor2Param = + ClassWithVarArgsConstructor::new; + assertEquals(3, constructor2Param.apply(1, 2).sum); + + MyFunction3 constructor3Param = + ClassWithVarArgsConstructor::new; + assertEquals(6, constructor3Param.apply(1, 2, 3).sum); + + MyFunction2 constructor2ParamArray = + ClassWithVarArgsConstructor::new; + assertEquals(6, constructor2ParamArray.apply(1, new Integer[] {2, 3}).sum); + + // constructor varargs + autoboxing + IntFunction1 constructor1IntParam = + ClassWithVarArgsConstructor::new; + assertEquals(1, constructor1IntParam.apply(1).sum); + + IntFunction2 constructor2IntParam = + ClassWithVarArgsConstructor::new; + assertEquals(3, constructor2IntParam.apply(1, 2).sum); + + IntFunction3 constructor3IntParam = + ClassWithVarArgsConstructor::new; + assertEquals(6, constructor3IntParam.apply(1, 2, 3).sum); + + ClassWithVarArgsConstructor outer = new ClassWithVarArgsConstructor(1); + + // inner class constructor varargs + assertEquals(2, outer.createInner1Param().apply(1).sum); + assertEquals(4, outer.createInner2Param().apply(1, 2).sum); + assertEquals(7, outer.createInner3Param().apply(1, 2, 3).sum); + assertEquals(7, outer.createInner2ParamArray().apply(1, new Integer[] {2, 3}).sum); + + // inner class constructor varargs + autoboxing + assertEquals(2, outer.createInner1IntParam().apply(1).sum); + assertEquals(4, outer.createInner2IntParam().apply(1, 2).sum); + assertEquals(7, outer.createInner3IntParam().apply(1, 2, 3).sum); + } + + private static void testMethodReference_genericTypeParameters( + Some some, T t1, T t2, MyFunction2 combine) { + T t1t2 = combine.apply(t1, t2); + + // Test all 4 flavours of methodReference + // 1. Static method + assertEquals(t1t2, ((MyFunction1) Java8Test::m).apply(t1t2)); + // 2. Qualified instance method + assertEquals(t1t2, ((MyFunction1) some::m).apply(t2)); + // 3. Unqualified instance method + assertEquals(t1, ((MyFunction1, T>) Some::m1).apply(some)); + assertEquals("Hello", + ((MyFunction1, String>) + Some::m1).apply(new Some<>("Hello", concat))); + // 4. Constructor reference. + assertEquals(t1t2, + ((MyFunction2, Some>) Some::new).apply(t1t2, combine).m1()); + } + + static MyFunction2 addInteger = (s,t) -> s + t; + + @FunctionalInterface + interface MyIntFunction1 { + int apply(int t); + } + + @FunctionalInterface + interface MyIntFunction2 { + int apply(int t, int u); + } + + @FunctionalInterface + interface MyIntFuncToSomeIntegeFunction2 { + SomeInteger apply(int t, MyFunction2 u); + } + + @FunctionalInterface + interface MySomeIntegerFunction1 { + int apply(SomeInteger t); } + @FunctionalInterface + interface MySomeIntegerIntFunction2 { + int apply(SomeInteger t, int u); + } + + static MyIntFunction2 addint = (s,t) -> s + t; + + static class SomeInteger { + int s; + MyFunction2 combine; + SomeInteger(int s, MyFunction2 combine) { + this.s = s; + this.combine = combine; + } + public int m(int s2) { + return combine.apply(s, s2); + } + public int m1() { + return s; + } + } + + public void testMethodReference_autoboxing() { + SomeInteger some = new SomeInteger(3, addInteger); + + // Test all 4 flavours of methodReference autoboxing parameters. + // 1. Static method + assertEquals((Integer) 5, ((MyFunction1) Java8Test::m).apply(5)); + // 2. Qualified instance method + assertEquals((Integer) 5, ((MyFunction1) some::m).apply(2)); + // 3. Unqualified instance method + assertEquals((Integer) 3, ((MyFunction1) SomeInteger::m1).apply(some)); + assertEquals((Integer) 5, ((MyFunction2) + SomeInteger::m).apply(some, 2)); + assertEquals((Integer) 5, + ((MyFunction1) + SomeInteger::m1).apply(new SomeInteger(5, addInteger))); + // 4. Constructor reference. + assertEquals(5, + ((MyFunction2, SomeInteger>) + SomeInteger::new).apply(5, addInteger).m1()); + + // Test all 4 flavours of methodReference (interface unboxed) + // 1. Static method + assertEquals(5, ((MyIntFunction1) Java8Test::m).apply(5)); + // 2. Qualified instance method + assertEquals(5, ((MyIntFunction1) some::m).apply(2)); + // 3. Unqualified instance method + assertEquals(3, ((MySomeIntegerFunction1) SomeInteger::m1).apply(some)); + // The next expression was the one that triggered bug #9346 where decisions on whether to + // box/unbox were decided incorrectly due to differring number of parameters in the method + // reference and the functional interface method. + assertEquals(5, ((MySomeIntegerIntFunction2) SomeInteger::m).apply(some, 2)); + assertEquals(5, + ((MySomeIntegerFunction1) + SomeInteger::m1).apply(new SomeInteger(5, addInteger))); + // 4. Constructor reference. + assertEquals(5, + ((MyIntFuncToSomeIntegeFunction2) SomeInteger::new).apply(5, addInteger).m1()); + } + + @JsType(isNative = true) + private static class NativeClassWithJsOverlay { + @JsOverlay + public static String m(String s) { + MyFunction1 id = (a) -> a; + return id.apply(s); + } + } public void testNativeJsOverlay_lambda() { - assertFalse(isGwtSourceLevel8()); + assertSame("Hello", NativeClassWithJsOverlay.m("Hello")); + } + + interface IntefaceWithDefaultMethodAndLambda { + boolean f(); + + default BooleanPredicate fAsPredicate() { + // This lambda will be defined as an instance method in the enclosing class, which is an + // interface. In this case the methdod will be devirtualized. + return () -> this.f(); + } + } + + interface BooleanPredicate { + boolean apply(); } public void testLambdaCapturingThis_onDefaultMethod() { - assertFalse(isGwtSourceLevel8()); + assertTrue( + new IntefaceWithDefaultMethodAndLambda() { + @Override + public boolean f() { + return true; + } + }.fAsPredicate().apply()); + } + + @JsFunction + interface MyJsFunctionInterface { + int foo(int a); + } + + public void testJsFunction_lambda() { + MyJsFunctionInterface jsFunctionInterface = a -> a + 2; + assertEquals(12, callAsFunction(jsFunctionInterface, 10)); + assertEquals(12, jsFunctionInterface.foo(10)); } + private static native int callAsFunction(Object fn, int arg) /*-{ + return fn(arg); + }-*/; + + @JsFunction + interface MyJsFunctionInterfaceWithOverlay { + Double m(); + @JsOverlay + default Double callM() { + return this.m(); + } + } + + private static native MyJsFunctionInterfaceWithOverlay createNative() /*-{ + return function () { return 5; }; + }-*/; + public void testJsFunction_withOverlay() { - assertFalse(isGwtSourceLevel8()); + MyJsFunctionInterfaceWithOverlay f = new MyJsFunctionInterfaceWithOverlay() { + @Override + public Double m() { + return new Double(2.0); + } + }; + assertEquals(2, f.callM().intValue()); + assertEquals(5, createNative().callM().intValue()); + } + + interface FunctionalExpressionBridges_I { + T apply(T t); + // TODO(rluble): uncomment the line below to when bridges for default methods are created + // in functional expressions + FunctionalExpressionBridges_I m(T t); + } + + @FunctionalInterface + interface FunctionalExpressionBridges_J + extends FunctionalExpressionBridges_I { + T apply(T t); + + // Overrides I.m() and specializes return type + default FunctionalExpressionBridges_J m(T t) { + return this; + } + } + + public static String identity(String s) { + return s; } public void testFunctionalExpressionBridges() { - assertFalse(isGwtSourceLevel8()); + FunctionalExpressionBridges_J ann = new FunctionalExpressionBridges_J() { + @Override + public String apply(String string) { + return string; + } + }; + + assertBrigdeDispatchIsCorrect(ann); + assertBrigdeDispatchIsCorrect((String s) -> s + ""); + assertBrigdeDispatchIsCorrect(Java8Test::identity); + } + + private void assertBrigdeDispatchIsCorrect( + FunctionalExpressionBridges_J functionalExpression) { + assertEquals("Hello", functionalExpression.m(null).apply("Hello")); + assertEquals("Hello", functionalExpression.apply("Hello")); + assertEquals("Hello", + ((FunctionalExpressionBridges_I) functionalExpression).apply("Hello")); + } + + static class ClassWithAVeryLoooooooooooooooooooooooooooooooooooongName { + public static String m() { + return null; + } } + // Regression test for bug: #9426. public void testCorrectNaming() { - assertFalse(isGwtSourceLevel8()); + Function f = ClassWithAVeryLoooooooooooooooooooooooooooooooooooongName::m; + assertNotNull(f); + } + + @JsType(isNative = true) + interface InterfaceWithOverlay { + + @JsProperty + int getLength(); + + @JsOverlay + default int len() { + return this.getLength(); + } + } + + @JsType(isNative = true, name = "Object", namespace = JsPackage.GLOBAL) + static abstract class SubclassImplementingInterfaceWithOverlay implements InterfaceWithOverlay { } + // Regression test for bug: #9440 public void testInterfaceWithOverlayAndNativeSubclass() { - assertFalse(isGwtSourceLevel8()); + SubclassImplementingInterfaceWithOverlay object = + (SubclassImplementingInterfaceWithOverlay) (Object) new int[]{1, 2, 3}; + assertEquals(3, object.len()); + } + + interface Producer { + T get(); + } + + private static Producer createInnerClassProducer() { + class InnerClass { + } + return (Producer) InnerClass::new; } public void testLocalClassConstructorReferenceInStaticMethod() { - assertFalse(isGwtSourceLevel8()); + assertTrue(createInnerClassProducer().get() != null); + } + + // NOTE: DO NOT reorder the following classes, bug #9453 is only reproducible in certain + // orderings. + interface SubSub_SuperDefaultMethodDevirtualizationOrder + extends Sub_SuperDefaultMethodDevirtualizationOrder { + default String m() { + return Sub_SuperDefaultMethodDevirtualizationOrder.super.m(); + } + } + + interface Sub_SuperDefaultMethodDevirtualizationOrder + extends Super_SuperDefaultMethodDevirtualizationOrder { + @Override + default String m() { + return Super_SuperDefaultMethodDevirtualizationOrder.super.m(); + } + } + + interface Super_SuperDefaultMethodDevirtualizationOrder { + default String m() { + return "Hi"; + } } + // Regression test for bug #9453. public void testDefaultMethodDevirtualizationOrder() { - assertFalse(isGwtSourceLevel8()); + assertEquals("Hi", new SubSub_SuperDefaultMethodDevirtualizationOrder() { + }.m()); } + private static String first(String... strings) { + return strings[0]; + } + + // Regresion test for https://github.com/gwtproject/gwt/issues/9497 public void testVarargsFunctionalConversion() { - assertFalse(isGwtSourceLevel8()); + java.util.function.Function function = Java8Test::first; + assertEquals("Hello", function.apply(new String[] {"Hello", "GoodBye"})); + } + + interface SingleJsoImplA { + String getAData(); + + List getListOfB(); + } + + interface SingleJsoImplB { + String getBData(); + } + + private static final class AOverlay extends JavaScriptObject implements SingleJsoImplA { + protected AOverlay() { } + + @Override + public native String getAData() /*-{ + return this.data; + }-*/; + + @Override + public native List getListOfB() /*-{ + return @java.util.Arrays::asList(*)(this.listOfb); + }-*/; + } + + private static final class BOverlay extends JavaScriptObject implements SingleJsoImplB { + protected BOverlay() { } + + @Override + public native String getBData() /*-{ + return this.data; + }-*/; } + private static SingleJsoImplA createA() { + return JsonUtils.safeEval( + "{\"data\":\"a value\",\"listOfb\":[{\"data\":\"b1\"},{\"data\":\"b2\"}]}"); + } + + // Regression for issue #9558 public void testJSOLivenessSingleImplErasure() { - assertFalse(isGwtSourceLevel8()); + SingleJsoImplA a = createA(); + String result = a.getListOfB().stream() + .map(SingleJsoImplB::getBData).collect(Collectors.joining(",")); + assertEquals("b1,b2", result); + result = a.getListOfB().stream() + .map(b -> b.getBData()).collect(Collectors.joining(",")); + assertEquals("b1,b2", result); } + @SuppressWarnings({"rawtypes", "unchecked"}) public void testLambdaErasureCasts() { - assertFalse(isGwtSourceLevel8()); + List list = new ArrayList(); + list.add("2"); + try { + ((List) list).stream().map(n -> n.intValue() == 2).findAny(); + fail("Should have thrown."); + } catch (ClassCastException expected) { + } } public void testLambdaBoxing() { - assertFalse(isGwtSourceLevel8()); + BiFunction equals = (i, j) -> i + 0 == j; + assertTrue(equals.apply(1,1)); + assertTrue(equals.apply(new Integer(2),2)); + assertTrue(equals.apply(new Integer(3), new Integer(3))); + + IntFunction unboxBox = i -> i; + assertEquals(2, (int) unboxBox.apply(2)); + assertEquals(2, (int) unboxBox.apply(new Integer(2))); } + // Regression tests for #9598 public void testImproperMethodResolution() { - assertFalse(isGwtSourceLevel8()); + Predicate p = o -> true; + assertTrue(p.test(null)); } + interface I2 { T foo(T arg); } + + interface I1 extends I2 { String foo(String arg0); } + + @SuppressWarnings({"rawtypes", "unchecked"}) public void testIntersectionCastLambda() { - assertFalse(isGwtSourceLevel8()); + + Object instance = (I1 & I2) val -> "#" + val; + + assertTrue(instance instanceof I1); + assertTrue(instance instanceof I2); + + I1 lambda = (I1) instance; + I2 raw = lambda; + assertEquals("#1", raw.foo("1")); // tests that the bridge exists and is correct + assertEquals("#2", lambda.foo("2")); } - public void testIntersectionCastMethodReference() { - assertFalse(isGwtSourceLevel8()); + static class C2 { + public static String append(String str) { + return "#" + str; + } } + @SuppressWarnings({"rawtypes", "unchecked"}) + public void testIntersectionCastMethodReference() { + + Object instance = (I1 & I2) C2::append; + + assertTrue(instance instanceof I1); + assertTrue(instance instanceof I2); - private boolean isGwtSourceLevel8() { - return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA8) >= 0; + I1 lambda = (I1) instance; + I2 raw = lambda; + assertEquals("#1", raw.foo("1")); // tests that the bridge exists and is correct + assertEquals("#2", lambda.foo("2")); } } diff --git a/user/test/com/google/gwt/dev/jjs/test/Java9Test.java b/user/test/com/google/gwt/dev/jjs/test/Java9Test.java index 951c8bbcaa..03662b4cb8 100644 --- a/user/test/com/google/gwt/dev/jjs/test/Java9Test.java +++ b/user/test/com/google/gwt/dev/jjs/test/Java9Test.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google Inc. + * Copyright 2023 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 @@ -15,45 +15,89 @@ */ package com.google.gwt.dev.jjs.test; -import com.google.gwt.dev.util.arg.SourceLevel; import com.google.gwt.junit.DoNotRunWith; -import com.google.gwt.junit.JUnitShell; import com.google.gwt.junit.Platform; import com.google.gwt.junit.client.GWTTestCase; +import java.util.function.Predicate; +import java.util.function.Supplier; + /** - * Dummy test case. Java9Test is super sourced so that GWT can be compiled by Java 8. - * - * NOTE: Make sure this class has the same test methods of its supersourced variant. + * Test Java 9 features. */ @DoNotRunWith(Platform.Devel) public class Java9Test extends GWTTestCase { + @Override public String getModuleName() { return "com.google.gwt.dev.jjs.Java9Test"; } - @Override - public void runTest() throws Throwable { - // Only run these tests if -sourceLevel 9 (or greater) is enabled. - if (isGwtSourceLevel9()) { - super.runTest(); + class Resource implements AutoCloseable { + boolean isOpen = true; + + public void close() { + this.isOpen = false; } } public void testTryWithResourcesJava9() { - assertFalse(isGwtSourceLevel9()); + Resource r1 = new Resource(); + assertTrue(r1.isOpen); + Resource r2Copy; + try (r1; Resource r2 = new Resource()) { + assertTrue(r1.isOpen); + assertTrue(r2.isOpen); + r2Copy = r2; + } + assertFalse(r1.isOpen); + assertFalse(r2Copy.isOpen); } - public void testInterfacePrivateMethodsJava9() { - assertFalse(isGwtSourceLevel9()); + interface Selector extends Predicate { + @Override + boolean test(String object); + + default Selector trueSelector() { + // Unused variable that creates a lambda with a bridge for the method test. The bug #9598 + // was caused by GwtAstBuilder associating the bridge method Lambda.test(Object) on the + // lambda below to the method Predicate.test(Object), causing the method resolution in the + // code that refers to the Predicate.test(Object) in the test below to refer to + // Lambda.test(Object) which is the wrong method. + return receiver -> true; + } } - public void testAnonymousDiamondJava9() { - assertFalse(isGwtSourceLevel9()); + private interface InterfaceWithPrivateMethods { + int implementedMethod(); + + default int defaultMethod() { + return privateMethod(); + } + + private int privateMethod() { + return implementedMethod(); + } + + private int staticPrivateMethod() { + return 42; + } } - private boolean isGwtSourceLevel9() { - return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA9) >= 0; + public void testInterfacePrivateMethodsJava9() { + InterfaceWithPrivateMethods implementor = () -> 50; + assertEquals(50, implementor.implementedMethod()); + assertEquals(50, implementor.defaultMethod()); + assertEquals(42, implementor.staticPrivateMethod()); + } + + public void testAnonymousDiamondJava9() { + Supplier helloSupplier = new Supplier<>() { + @Override + public String get() { + return "hello"; + } + }; + assertEquals("hello", helloSupplier.get()); } -} +} \ No newline at end of file diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/defaultmethods/ImplementsWithDefaultMethodAndStaticInitializer.java b/user/test/com/google/gwt/dev/jjs/test/defaultmethods/ImplementsWithDefaultMethodAndStaticInitializer.java similarity index 100% rename from user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/defaultmethods/ImplementsWithDefaultMethodAndStaticInitializer.java rename to user/test/com/google/gwt/dev/jjs/test/defaultmethods/ImplementsWithDefaultMethodAndStaticInitializer.java diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/defaultmethods/SomeClass.java b/user/test/com/google/gwt/dev/jjs/test/defaultmethods/SomeClass.java similarity index 100% rename from user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/defaultmethods/SomeClass.java rename to user/test/com/google/gwt/dev/jjs/test/defaultmethods/SomeClass.java diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/defaultmethods/WithDefaultMethodAndStaticInitializer.java b/user/test/com/google/gwt/dev/jjs/test/defaultmethods/WithDefaultMethodAndStaticInitializer.java similarity index 100% rename from user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/defaultmethods/WithDefaultMethodAndStaticInitializer.java rename to user/test/com/google/gwt/dev/jjs/test/defaultmethods/WithDefaultMethodAndStaticInitializer.java diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/package1/SimpleA.java b/user/test/com/google/gwt/dev/jjs/test/package1/SimpleA.java similarity index 100% rename from user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/package1/SimpleA.java rename to user/test/com/google/gwt/dev/jjs/test/package1/SimpleA.java diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/package1/SimpleD.java b/user/test/com/google/gwt/dev/jjs/test/package1/SimpleD.java similarity index 100% rename from user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/package1/SimpleD.java rename to user/test/com/google/gwt/dev/jjs/test/package1/SimpleD.java diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/package2/SimpleB.java b/user/test/com/google/gwt/dev/jjs/test/package2/SimpleB.java similarity index 100% rename from user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/package2/SimpleB.java rename to user/test/com/google/gwt/dev/jjs/test/package2/SimpleB.java diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/package3/SimpleC.java b/user/test/com/google/gwt/dev/jjs/test/package3/SimpleC.java similarity index 100% rename from user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/package3/SimpleC.java rename to user/test/com/google/gwt/dev/jjs/test/package3/SimpleC.java From d77e85c2a80d086e387d2413932499831c1718ea Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Wed, 14 Feb 2024 09:40:02 -0600 Subject: [PATCH 20/27] Remove unused build property for JNI (#9924) --- common.ant.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/common.ant.xml b/common.ant.xml index d64cd0898a..7f8244aea7 100755 --- a/common.ant.xml +++ b/common.ant.xml @@ -41,7 +41,6 @@ - @@ -49,7 +48,6 @@ - From 63dc05bfc5c96313a4fbaa149501345126c9e143 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Mar 2024 14:09:06 -0500 Subject: [PATCH 21/27] Bump mikepenz/action-junit-report from 4.1.0 to 4.2.1 (#9938) Bumps mikepenz/action-junit-report from 4.1.0 to 4.2.1. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/full-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/full-check.yml b/.github/workflows/full-check.yml index ebb06f57ad..fe3a0829ff 100644 --- a/.github/workflows/full-check.yml +++ b/.github/workflows/full-check.yml @@ -57,7 +57,7 @@ jobs: -Dtest.emma.htmlunit.disable=true - name: Report test results - uses: mikepenz/action-junit-report@v4.1.0 + uses: mikepenz/action-junit-report@v4.2.1 if: always() with: report_paths: 'gwt/build/out/**/test/**/reports/TEST-*.xml' From 34b2a444398b08bab87d95c8a6d85997b32337aa Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Fri, 29 Mar 2024 12:44:30 -0500 Subject: [PATCH 22/27] Allow SDM's web server to reuse a socket without waiting (#9946) This is Jetty's default for a Connector, and reflects the configuration used by the DevMode Jetty app server instance. Fixes #9944 --- .../java/com/google/gwt/dev/codeserver/WebServer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/codeserver/java/com/google/gwt/dev/codeserver/WebServer.java b/dev/codeserver/java/com/google/gwt/dev/codeserver/WebServer.java index 273e63cf4f..de636e8125 100644 --- a/dev/codeserver/java/com/google/gwt/dev/codeserver/WebServer.java +++ b/dev/codeserver/java/com/google/gwt/dev/codeserver/WebServer.java @@ -121,7 +121,7 @@ void start(final TreeLogger logger) throws UnableToCompleteException { ServerConnector connector = new ServerConnector(newServer); connector.setHost(bindAddress); connector.setPort(port); - connector.setReuseAddress(false); + connector.setReuseAddress(true); newServer.addConnector(connector); ServletContextHandler newHandler = new ServletContextHandler(ServletContextHandler.GZIP); From e43a5899e56fe5679cf57243f4c11e288bd4504b Mon Sep 17 00:00:00 2001 From: MCMicS Date: Sun, 7 Apr 2024 21:16:05 +0200 Subject: [PATCH 23/27] Remove first character for delegating args to CodeServer (#9940) fix for #9939 --- .../gwt/dev/shell/SuperDevListener.java | 8 +- .../google/gwt/dev/HostedModeOptionsMock.java | 20 ++ .../gwt/dev/shell/SuperDevListenerTest.java | 184 ++++++++++++++++++ 3 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 dev/core/test/com/google/gwt/dev/HostedModeOptionsMock.java create mode 100644 dev/core/test/com/google/gwt/dev/shell/SuperDevListenerTest.java diff --git a/dev/core/src/com/google/gwt/dev/shell/SuperDevListener.java b/dev/core/src/com/google/gwt/dev/shell/SuperDevListener.java index 76cb5833a5..0a6fb34bd9 100644 --- a/dev/core/src/com/google/gwt/dev/shell/SuperDevListener.java +++ b/dev/core/src/com/google/gwt/dev/shell/SuperDevListener.java @@ -23,6 +23,7 @@ import com.google.gwt.dev.DevMode.HostedModeOptions; import com.google.gwt.dev.cfg.ModuleDef; import com.google.gwt.dev.util.arg.OptionMethodNameDisplayMode; +import com.google.gwt.thirdparty.guava.common.annotations.VisibleForTesting; import com.google.gwt.thirdparty.guava.common.base.Stopwatch; import com.google.gwt.thirdparty.guava.common.collect.ListMultimap; import com.google.gwt.thirdparty.guava.common.collect.Lists; @@ -63,6 +64,11 @@ public int getSocketPort() { return codeServerPort; } + @VisibleForTesting + List getCodeServerArgs() { + return codeServerArgs; + } + @Override public URL makeStartupUrl(String url) throws UnableToCompleteException { try { @@ -174,7 +180,7 @@ private static List makeCodeServerArgs(HostedModeOptions options, int po args.add(regex.substring(1)); } else { args.add("-includeJsInteropExports"); - args.add(regex); + args.add(regex.startsWith("+") ? regex.substring(1) : regex); } } if (!options.isIncrementalCompileEnabled()) { diff --git a/dev/core/test/com/google/gwt/dev/HostedModeOptionsMock.java b/dev/core/test/com/google/gwt/dev/HostedModeOptionsMock.java new file mode 100644 index 0000000000..81e9d583f3 --- /dev/null +++ b/dev/core/test/com/google/gwt/dev/HostedModeOptionsMock.java @@ -0,0 +1,20 @@ +/* + * Copyright 2024 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.dev; + +/** + * Make {@link com.google.gwt.dev.DevMode.HostedModeOptionsImpl} visible as mock for tests.. + */ +public class HostedModeOptionsMock extends DevMode.HostedModeOptionsImpl { +} diff --git a/dev/core/test/com/google/gwt/dev/shell/SuperDevListenerTest.java b/dev/core/test/com/google/gwt/dev/shell/SuperDevListenerTest.java new file mode 100644 index 0000000000..354d04260e --- /dev/null +++ b/dev/core/test/com/google/gwt/dev/shell/SuperDevListenerTest.java @@ -0,0 +1,184 @@ +/* + * Copyright 2024 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.dev.shell; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.dev.DevMode; +import com.google.gwt.dev.HostedModeOptionsMock; +import com.google.gwt.dev.jjs.JsOutputOption; +import com.google.gwt.dev.util.arg.OptionMethodNameDisplayMode; +import com.google.gwt.dev.util.arg.SourceLevel; +import com.google.gwt.thirdparty.guava.common.collect.ImmutableList; +import com.google.gwt.util.regexfilter.WhitelistRegexFilter; + +import junit.framework.TestCase; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; + +/** + * A wide variety of tests on {@link SuperDevListener}. + */ +public class SuperDevListenerTest extends TestCase { + private static final int TEST_PORT = 9998; + private static final String MODULE_NAME = "Test_Module_Name"; + private final TreeLogger treeLogger = new FailErrorLogger(); + private final DevMode.HostedModeOptions options = new HostedModeOptionsMock(); + private final WhitelistRegexFilter whitelistRegexFilter = new WhitelistRegexFilter(); + private File warDir; + @Override + public void setUp() throws IOException { + warDir = Files.createTempDirectory("war-file").toFile(); + warDir.deleteOnExit(); + setUpOptions(options); + } + + private void setUpOptions(DevMode.HostedModeOptions optionsToPrepare) { + optionsToPrepare.setCodeServerPort(TEST_PORT); + optionsToPrepare.setSourceLevel(SourceLevel.JAVA17); + optionsToPrepare.setWarDir(warDir); + optionsToPrepare.setOutput(JsOutputOption.DETAILED); + optionsToPrepare.setGenerateJsInteropExports(false); + optionsToPrepare.setIncrementalCompileEnabled(true); + optionsToPrepare.setMethodNameDisplayMode(OptionMethodNameDisplayMode.Mode.NONE); + optionsToPrepare.setStrict(false); + optionsToPrepare.setModuleNames(ImmutableList.of(MODULE_NAME)); + } + + public void testDefaultArgs() { + final SuperDevListener superDevListener = new SuperDevListener(treeLogger, options); + final List codeServerArgs = superDevListener.getCodeServerArgs(); + assertEquals("Wrong default arguments", 10, codeServerArgs.size()); + assertTrue("Precompile flag should set", codeServerArgs.contains("-noprecompile")); + assertTrue("Port should set", codeServerArgs.contains("-port")); + assertTrue("Port should set", codeServerArgs.contains(Integer.toString(TEST_PORT))); + assertTrue("SourceLevel should set", codeServerArgs.contains("-sourceLevel")); + assertTrue("SourceLevel should set", codeServerArgs.contains(SourceLevel.JAVA17.getStringValue())); + assertTrue("LauncherDir should set", codeServerArgs.contains("-launcherDir")); + assertTrue("LauncherDir should set", codeServerArgs.contains(warDir.getAbsolutePath())); + assertTrue("Style should set", codeServerArgs.contains("-style")); + assertTrue("Style should set", codeServerArgs.contains("DETAILED")); + assertTrue("Module name should set", codeServerArgs.contains(MODULE_NAME)); + } + + public void testDefaultNonSuperDevModePort() { + final int port = 9997; + options.setCodeServerPort(port); + final SuperDevListener superDevListener = new SuperDevListener(treeLogger, options); + final List codeServerArgs = superDevListener.getCodeServerArgs(); + assertTrue("Port should set", codeServerArgs.contains("-port")); + assertTrue("SuperDevMode Default port should set", codeServerArgs.contains("9876")); + } + + public void testWithJsInteropAndSingleIncludeAndExclude() { + options.setGenerateJsInteropExports(true); + options.getJsInteropExportFilter().add("-com.google.gwt.exclude.First"); + options.getJsInteropExportFilter().add("com.google.gwt.include.First"); + + final SuperDevListener superDevListener = new SuperDevListener(treeLogger, options); + final List codeServerArgs = superDevListener.getCodeServerArgs(); + assertTrue("GenerateJsInteropExports should set", codeServerArgs.contains("-generateJsInteropExports")); + assertTrue("ExcludeJsInteropExports should set", codeServerArgs.contains("-excludeJsInteropExports")); + assertTrue("ExcludeJsInteropExports should set", codeServerArgs.contains("com.google.gwt.exclude.First")); + assertTrue("IncludeJsInteropExports should set", codeServerArgs.contains("-includeJsInteropExports")); + assertTrue("IncludeJsInteropExports should set", codeServerArgs.contains("com.google.gwt.include.First")); + } + + public void testWithJsInteropIncludesAndExcludes() { + options.setGenerateJsInteropExports(true); + options.getJsInteropExportFilter().add("-com.google.gwt.exclude.First"); + options.getJsInteropExportFilter().add("com.google.gwt.include.First"); + options.getJsInteropExportFilter().add("-com.google.gwt.exclude.Second"); + options.getJsInteropExportFilter().add("com.google.gwt.include.Second"); + + final SuperDevListener superDevListener = new SuperDevListener(treeLogger, options); + final List codeServerArgs = superDevListener.getCodeServerArgs(); + final int generateJsExportsIndex = codeServerArgs.indexOf("-generateJsInteropExports") + 1; + final List expectedJsExports = createExpectedJsIncludesAndExcludesgetStrings(); + + assertTrue("GenerateJsInteropExports should set", generateJsExportsIndex > 0); + final List actualJsExports = codeServerArgs.subList(generateJsExportsIndex, codeServerArgs.size()); + for (int expectedIndex = 0; expectedIndex < expectedJsExports.size(); expectedIndex++) { + assertEquals("Setting for JS export not found", expectedJsExports.get(expectedIndex), + actualJsExports.get(expectedIndex)); + } + } + + public void testWithJsInteropAndCustomRegexFilter() { + final HostedModeOptionsMockWithCustomRegexFilter customOptions = new HostedModeOptionsMockWithCustomRegexFilter(); + setUpOptions(customOptions); + customOptions.setGenerateJsInteropExports(true); + customOptions.getJsInteropExportFilter().add("-com.google.gwt.exclude.First"); + customOptions.getJsInteropExportFilter().add("com.google.gwt.include.First"); + customOptions.getJsInteropExportFilter().add("-com.google.gwt.exclude.Second"); + customOptions.getJsInteropExportFilter().add("com.google.gwt.include.Second"); + customOptions.getJsInteropExportFilter().add("+com.google.gwt.include.Third"); + customOptions.getJsInteropExportFilter().add("*com.google.gwt.include.Fourth"); + + final SuperDevListener superDevListener = new SuperDevListener(treeLogger, customOptions); + final List codeServerArgs = superDevListener.getCodeServerArgs(); + final int generateJsExportsIndex = codeServerArgs.indexOf("-generateJsInteropExports") + 1; + final List expectedJsExports = createExpectedJsIncludesAndExcludesgetStrings(); + expectedJsExports.add("-includeJsInteropExports"); + expectedJsExports.add("com.google.gwt.include.Third"); + expectedJsExports.add("-includeJsInteropExports"); + expectedJsExports.add("*com.google.gwt.include.Fourth"); + + assertTrue("GenerateJsInteropExports should set", generateJsExportsIndex > 0); + final List actualJsExports = codeServerArgs.subList(generateJsExportsIndex, codeServerArgs.size()); + for (int expectedIndex = 0; expectedIndex < expectedJsExports.size(); expectedIndex++) { + assertEquals("Setting for JS export not found", expectedJsExports.get(expectedIndex), + actualJsExports.get(expectedIndex)); + } + } + + private static List createExpectedJsIncludesAndExcludesgetStrings() { + final List expectedJsExports = new ArrayList<>(); + expectedJsExports.add("-excludeJsInteropExports"); + expectedJsExports.add("com.google.gwt.exclude.First"); + expectedJsExports.add("-includeJsInteropExports"); + expectedJsExports.add("com.google.gwt.include.First"); + expectedJsExports.add("-excludeJsInteropExports"); + expectedJsExports.add("com.google.gwt.exclude.Second"); + expectedJsExports.add("-includeJsInteropExports"); + expectedJsExports.add("com.google.gwt.include.Second"); + return expectedJsExports; + } + + private static class HostedModeOptionsMockWithCustomRegexFilter extends HostedModeOptionsMock { + private final WhitelistRegexFilter whitelistRegexFilter = new CustomWhitelistRegexFilter(); + @Override + public WhitelistRegexFilter getJsInteropExportFilter() { + return whitelistRegexFilter; + } + } + private static class CustomWhitelistRegexFilter extends WhitelistRegexFilter { + private final List values = new ArrayList<>(); + @Override + public List getValues() { + return values; + } + @Override + public void add(String regex) { + values.add(regex); + } + @Override + public void addAll(List newValues) { + values.addAll(newValues); + } + } +} From b67c30842d6a5784e5f0f341f719cbdf185aa106 Mon Sep 17 00:00:00 2001 From: Dmitrii Tikhomirov Date: Wed, 17 Apr 2024 10:20:10 -0700 Subject: [PATCH 24/27] =?UTF-8?q?Each=20mapped=20stream=20must=20be=20clos?= =?UTF-8?q?ed=20after=20its=20contents=20have=20been=20placed=E2=80=A6=20(?= =?UTF-8?q?#9949)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … downstream --- .../com/google/gwt/emul/java/util/stream/Collectors.java | 3 ++- .../gwt/emultest/java9/util/stream/CollectorsTest.java | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) 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 0509fb2fe8..519b375422 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 @@ -177,13 +177,14 @@ public static Collector joining(CharSequence delimiter) { return new CollectorImpl<>( downstream.supplier(), (A a, T t) -> { - Stream stream = mapper.apply(t); + try (Stream stream = mapper.apply(t)) { if (stream == null) { return; } stream.forEach(u -> { downstream.accumulator().accept(a, u); }); + } }, downstream.combiner(), downstream.finisher() diff --git a/user/test/com/google/gwt/emultest/java9/util/stream/CollectorsTest.java b/user/test/com/google/gwt/emultest/java9/util/stream/CollectorsTest.java index 1e7adea081..c2d38e0b4a 100644 --- a/user/test/com/google/gwt/emultest/java9/util/stream/CollectorsTest.java +++ b/user/test/com/google/gwt/emultest/java9/util/stream/CollectorsTest.java @@ -49,6 +49,11 @@ public void testFlatMapping() { return items.stream(); }, toList()); applyItems(Arrays.asList("a"), flatMappingToNull, Arrays.asList("a"), Arrays.asList("b", "c")); + + int[] calledCount = {0}; + Stream mapped = Stream.of("x").onClose(() -> calledCount[0]++); + Stream.of(1).collect(flatMapping(x -> mapped, toList())); + assertEquals(1, calledCount[0]); } public void testFiltering() { From 9be71961ce8cecf5e69d921b4bfd8b0306d4a14e Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Wed, 17 Apr 2024 16:16:17 -0500 Subject: [PATCH 25/27] Add missing import, fix errorprone error (#9950) Follow-up #9949 --- .../google/gwt/emultest/java9/util/stream/CollectorsTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/user/test/com/google/gwt/emultest/java9/util/stream/CollectorsTest.java b/user/test/com/google/gwt/emultest/java9/util/stream/CollectorsTest.java index c2d38e0b4a..15f67118c9 100644 --- a/user/test/com/google/gwt/emultest/java9/util/stream/CollectorsTest.java +++ b/user/test/com/google/gwt/emultest/java9/util/stream/CollectorsTest.java @@ -27,6 +27,7 @@ import java.util.Collections; import java.util.List; import java.util.stream.Collector; +import java.util.stream.Stream; /** * Tests for java.util.stream.Collectors Java 9 API emulation. @@ -49,7 +50,10 @@ public void testFlatMapping() { return items.stream(); }, toList()); applyItems(Arrays.asList("a"), flatMappingToNull, Arrays.asList("a"), Arrays.asList("b", "c")); + } + @SuppressWarnings("ReturnValueIgnored") + public void testFlatMappingClose() { int[] calledCount = {0}; Stream mapped = Stream.of("x").onClose(() -> calledCount[0]++); Stream.of(1).collect(flatMapping(x -> mapped, toList())); From 468bf52fb75a66f5d86f76ff9ad20a7553122f2a Mon Sep 17 00:00:00 2001 From: "Ahmad K. Bawaneh" Date: Sat, 11 May 2024 04:42:39 +0300 Subject: [PATCH 26/27] Undo the disable of source maps for non-chrome browsers (#9941) Nowadays, all modern browsers support sourcemaps by default, so there is no need to have exception configuration anymore. Fixes #9759 --- .../google/gwt/core/CoreWithUserAgent.gwt.xml | 16 ---------------- user/src/com/google/gwt/core/StackTrace.gwt.xml | 7 ++++++- .../com/google/gwt/user/LoggingRPCSuite.gwt.xml | 5 +---- 3 files changed, 7 insertions(+), 21 deletions(-) diff --git a/user/src/com/google/gwt/core/CoreWithUserAgent.gwt.xml b/user/src/com/google/gwt/core/CoreWithUserAgent.gwt.xml index 48fa48ed1d..38a9dbe1f5 100644 --- a/user/src/com/google/gwt/core/CoreWithUserAgent.gwt.xml +++ b/user/src/com/google/gwt/core/CoreWithUserAgent.gwt.xml @@ -15,20 +15,4 @@ - - - - - - - - - - - - - - - - diff --git a/user/src/com/google/gwt/core/StackTrace.gwt.xml b/user/src/com/google/gwt/core/StackTrace.gwt.xml index 879dbe4216..024183c50d 100644 --- a/user/src/com/google/gwt/core/StackTrace.gwt.xml +++ b/user/src/com/google/gwt/core/StackTrace.gwt.xml @@ -45,9 +45,14 @@ - + + + + + + diff --git a/user/test/com/google/gwt/user/LoggingRPCSuite.gwt.xml b/user/test/com/google/gwt/user/LoggingRPCSuite.gwt.xml index c50cd919ff..77164ca0ba 100644 --- a/user/test/com/google/gwt/user/LoggingRPCSuite.gwt.xml +++ b/user/test/com/google/gwt/user/LoggingRPCSuite.gwt.xml @@ -30,12 +30,9 @@ + with one that does something --> - - From 89d06d61e2e7ee3007d4cbeabe60e0f28da18467 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Sun, 12 May 2024 14:01:43 -0500 Subject: [PATCH 27/27] Update assumptions in LoggingRPCSuite and fix missing class name (#9955) CollectorChrome was renamed about 10 years ago, and sourcemaps are well supported now, so this test can be adjusted to always handle the optimized case. Fixes the recent build failure. --- .../google/gwt/user/LoggingRPCSuite.gwt.xml | 21 +++++++------------ .../gwt/user/client/rpc/LoggingRPCTest.java | 2 +- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/user/test/com/google/gwt/user/LoggingRPCSuite.gwt.xml b/user/test/com/google/gwt/user/LoggingRPCSuite.gwt.xml index 77164ca0ba..ef64d4cb5a 100644 --- a/user/test/com/google/gwt/user/LoggingRPCSuite.gwt.xml +++ b/user/test/com/google/gwt/user/LoggingRPCSuite.gwt.xml @@ -19,21 +19,16 @@ + + + - - - - - - - - - - + + - + - diff --git a/user/test/com/google/gwt/user/client/rpc/LoggingRPCTest.java b/user/test/com/google/gwt/user/client/rpc/LoggingRPCTest.java index 40b368fc5a..be9ba70180 100644 --- a/user/test/com/google/gwt/user/client/rpc/LoggingRPCTest.java +++ b/user/test/com/google/gwt/user/client/rpc/LoggingRPCTest.java @@ -179,7 +179,7 @@ public void onSuccess(LogRecord record) { break; } } - assertTrue(found); + assertTrue("expected frame found in stack trace", found); finishTest(); } });