From 5222a7c0c03dd4c60a8ebd2ac05d964583f9f6d7 Mon Sep 17 00:00:00 2001 From: Roberto Lublinerman Date: Mon, 3 Oct 2016 21:13:35 -0700 Subject: [PATCH] Allow native classes implement native interfaces with overlays. Native classes implementing interfaces with overlays triggerred a compiler error due to the fact that overlays in native intefaces are "default" methods and that the strategy of implementing them consists in creating the corresponding synthetic override in classes that don't explicitly implement the method. Bug: #9440 Bug-Link: https://github.com/gwtproject/gwt/issues/9440 Change-Id: I30a100c4d83f13df61fed57a54afb3b25a153250 --- .../jjs/impl/JsInteropRestrictionChecker.java | 2 +- .../impl/JsInteropRestrictionCheckerTest.java | 28 +++++++++++++++++-- .../google/gwt/dev/jjs/test/Java8Test.java | 28 ++++++++++++++++++- .../google/gwt/dev/jjs/test/Java8Test.java | 4 +++ 4 files changed, 57 insertions(+), 5 deletions(-) diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java index f204bd06dee..23f52db12fe 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java @@ -285,7 +285,7 @@ private void checkIllegalOverrides(JMember member) { } private void checkJsOverlay(JMember member) { - if (member.getEnclosingType().isJsoType()) { + if (member.getEnclosingType().isJsoType() || member.isSynthetic()) { return; } 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 f7991aae9c1..f1546d5c641 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 @@ -1613,7 +1613,7 @@ public void testNativeJsTypeInterfaceExtendsNonJsTypeFails() { "Line 6: Native JsType ''EntryPoint.Buggy'' can only extend native JsType interfaces."); } - public void testNativeJsTypeInterfaceDefenderMethodsFails() { + public void testNativeJsTypeInterfaceDefaultMethodsFails() { addSnippetImport("jsinterop.annotations.JsType"); addSnippetImport("jsinterop.annotations.JsOverlay"); addSnippetClassDecl( @@ -1626,6 +1626,11 @@ public void testNativeJsTypeInterfaceDefenderMethodsFails() { "@JsType(isNative=true) public interface Buggy extends Interface {", " default void someMethod(){}", " void someOtherMethod();", + "}", + "public static class SomeOtherClass implements Interface {", + "}", + "public static class ClassOverridingOverlayTransitively extends SomeOtherClass {", + " public void someOtherMethod() {}", "}"); assertBuggyFails( @@ -1634,7 +1639,9 @@ public void testNativeJsTypeInterfaceDefenderMethodsFails() { "Line 12: Native JsType method 'void EntryPoint.Buggy.someMethod()' should be native " + "or abstract.", "Line 13: Method 'void EntryPoint.Buggy.someOtherMethod()' cannot override a JsOverlay" - + " method 'void EntryPoint.Interface.someOtherMethod()'."); + + " method 'void EntryPoint.Interface.someOtherMethod()'.", + "Line 18: Method 'void EntryPoint.ClassOverridingOverlayTransitively.someOtherMethod()' " + + "cannot override a JsOverlay method 'void EntryPoint.Interface.someOtherMethod()'."); } public void testJsOptionalSucceeds() throws Exception { @@ -2190,13 +2197,28 @@ public void testNonJsTypeExtendingNativeJsTypeWithInstanceMethodSucceeds() throw " public native void m(Object o);", " public native void m(Object[] o);", "}", - "@JsType public static class Buggy extends Super {", + "public static class Buggy extends Super {", " public void n(Object o) { }", "}"); assertBuggySucceeds(); } + public void testClassesExtendingNativeJsTypeInterfaceWithOverlaySucceeds() throws Exception { + addSnippetImport("jsinterop.annotations.JsOverlay"); + addSnippetImport("jsinterop.annotations.JsType"); + addSnippetClassDecl( + "@JsType(isNative=true) interface Super {", + " @JsOverlay default void fun() {}", + "}", + "@JsType(isNative=true) abstract static class Buggy implements Super {", + "}", + "static class JavaSubclass implements Super {", + "}"); + + assertBuggySucceeds(); + } + public void testNonJsTypeExtendingNativeJsTypeWithInstanceMethodOverloadsFails() { addSnippetImport("jsinterop.annotations.JsType"); addSnippetClassDecl( 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 index 8d896cb282b..6684445a322 100644 --- 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 @@ -26,6 +26,8 @@ import jsinterop.annotations.JsFunction; import jsinterop.annotations.JsOverlay; +import jsinterop.annotations.JsPackage; +import jsinterop.annotations.JsProperty; import jsinterop.annotations.JsType; /** @@ -1672,10 +1674,34 @@ public static String m() { return null; } } - // Regression test for bug: #9426. + + // 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()); + } } 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 ff90ce90575..3cf89d1b345 100644 --- a/user/test/com/google/gwt/dev/jjs/test/Java8Test.java +++ b/user/test/com/google/gwt/dev/jjs/test/Java8Test.java @@ -308,6 +308,10 @@ public void testCorrectNaming() { assertFalse(isGwtSourceLevel8()); } + public void testInterfaceWithOverlayAndNativeSubclass() { + assertFalse(isGwtSourceLevel8()); + } + private boolean isGwtSourceLevel8() { return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA8) >= 0; }