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(),