Hide Java 8 interfaces methods to generators.
Current GWT generators do not expect default nor static methods
in interfaces. This patch makes the safest choice which is to hide
those methods.
Bug: #9371
Bug-Link: https://github.com/gwtproject/gwt/issues/9371
Change-Id: I623358e5cd9135e91186dd84e02fb3909a4a8538
diff --git a/dev/core/src/com/google/gwt/dev/javac/CompilationUnitTypeOracleUpdater.java b/dev/core/src/com/google/gwt/dev/javac/CompilationUnitTypeOracleUpdater.java
index f63e037..b4496f1 100644
--- a/dev/core/src/com/google/gwt/dev/javac/CompilationUnitTypeOracleUpdater.java
+++ b/dev/core/src/com/google/gwt/dev/javac/CompilationUnitTypeOracleUpdater.java
@@ -887,6 +887,7 @@
*
* These differences also show up when using java.lang.reflect to look at types.
*/
+ boolean isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
if (signature != null) {
// If we have a signature, use it for superclass and interfaces
SignatureReader reader = new SignatureReader(signature);
@@ -903,7 +904,7 @@
}
} else {
// Set the super type for non-interfaces
- if ((access & Opcodes.ACC_INTERFACE) == 0) {
+ if (!isInterface) {
String superInternalName = classData.getSuperInternalName();
assert Name.isInternalName(superInternalName);
if (superInternalName != null) {
@@ -927,7 +928,7 @@
unresolvedType, (JClassType) possiblySubstituteRawType(interfaceType));
}
}
- if (((access & Opcodes.ACC_INTERFACE) == 0) && unresolvedType.getSuperclass() == null) {
+ if (!isInterface && unresolvedType.getSuperclass() == null) {
// Only Object or interfaces should not have a superclass
assert "java/lang/Object".equals(classData.getInternalName());
}
@@ -935,6 +936,11 @@
// Process methods
for (CollectMethodData method : classData.getMethods()) {
TreeLogger branch = logger.branch(TreeLogger.SPAM, "Resolving method " + method.getName());
+ // TODO(rluble): Allow the users to ask for Java 8 features. For now these are filtered out.
+ if (isInterface && isJava8InterfaceMethod(method)) {
+ logger.log(TreeLogger.Type.SPAM, "Ignoring Java 8 interface method " + method.getName());
+ continue;
+ }
if (!resolveMethod(branch, unresolvedType, method, typeParamLookup, context)) {
// Already logged.
return false;
@@ -951,10 +957,15 @@
return false;
}
}
-
return true;
}
+ private boolean isJava8InterfaceMethod(CollectMethodData method) {
+ // (Normal) interface methods are abstract. Java 8 introduced the ability to declare default
+ // methods and static methods both of which are exposed as non abstract methods.
+ return (method.getAccess() & Opcodes.ACC_ABSTRACT) == 0;
+ }
+
private boolean resolveClass(
TreeLogger logger, JType unresolvedType, TypeOracleBuildContext context) {
if (!(unresolvedType instanceof JClassType)) {
diff --git a/dev/core/test/com/google/gwt/dev/javac/CompilationUnitTypeOracleUpdaterFromSourceTest.java b/dev/core/test/com/google/gwt/dev/javac/CompilationUnitTypeOracleUpdaterFromSourceTest.java
index 6f947c3..568489b 100644
--- a/dev/core/test/com/google/gwt/dev/javac/CompilationUnitTypeOracleUpdaterFromSourceTest.java
+++ b/dev/core/test/com/google/gwt/dev/javac/CompilationUnitTypeOracleUpdaterFromSourceTest.java
@@ -17,6 +17,7 @@
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracleException;
+import com.google.gwt.thirdparty.guava.common.base.Joiner;
/**
* Tests for {@link TypeOracleUpdater} when provided sources.
@@ -183,6 +184,26 @@
assertEquals(1, typeOracle.getTypes().length);
}
+ public void testJava8InterfaceExclusions() throws TypeOracleException {
+ String java8Interface = Joiner.on("\n").join(
+ "package test.java8;",
+ "interface Java8Interface {",
+ " Object field = new Object();",
+ " final int constant = 1;",
+ " void m();",
+ " default void n() {};",
+ " static void o() {};",
+ "}");
+ addResource("test.java8.Java8Interface", java8Interface);
+ resources.add(CU_Object);
+ buildTypeOracle();
+
+ assertEquals(1, typeOracle.findType("test.java8.Java8Interface").getMethods().length);
+ assertEquals("m", typeOracle.findType("test.java8.Java8Interface").getMethods()[0].getName());
+ assertNotNull(typeOracle.findType(CU_Object.getTypeName()));
+ assertEquals(2, typeOracle.getTypes().length);
+ }
+
@Override
protected void buildTypeOracle() throws TypeOracleException {
typeOracle = TypeOracleTestingUtils.buildTypeOracle(createTreeLogger(),