Implement JsOptional test on overrides.

Bug: #9336
Change-Id: Ib99cf99b65a54ab0290a5e925f39e181adbff18a
Bug-Link: https://github.com/gwtproject/gwt/issues/9336
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 81daede..e917cc9 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
@@ -410,6 +410,20 @@
     if (method.isJsMethodVarargs()) {
       checkJsVarargs(method);
     }
+
+    // Check that parameters that are declared JsOptional in overridden methods remain JsOptional.
+    for (JMethod overriddenMethod : method.getOverriddenMethods()) {
+      for (int i = 0; i < overriddenMethod.getParams().size(); i++) {
+        if (overriddenMethod.getParams().get(i).isOptional()) {
+          if (!method.getParams().get(i).isOptional()) {
+            logError(method, "Method %s should declare parameter '%s' as JsOptional",
+                getMemberDescription(method), method.getParams().get(i).getName());
+            return;
+          }
+          break;
+        }
+      }
+    }
   }
 
   private void checkJsVarargs(final JMethod method) {
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 3a35948..46028ce 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
@@ -1523,6 +1523,21 @@
     assertBuggySucceeds();
   }
 
+  public void testJsOptionalNotJsOptionalOverrideFails() throws Exception {
+    addSnippetImport("jsinterop.annotations.JsMethod");
+    addSnippetImport("jsinterop.annotations.JsOptional");
+    addSnippetClassDecl(
+        "interface Interface {",
+        "   @JsMethod void m(@JsOptional Object o);",
+        "}",
+        "public static class Buggy implements Interface {",
+        "   @JsMethod public void m(Object o) {}",
+        "}");
+
+    assertBuggyFails("Line 9: Method 'void EntryPoint.Buggy.m(Object)' should declare "
+        + "parameter 'o' as JsOptional");
+  }
+
   public void testJsOptionalNotAtEndFails() throws Exception {
     addSnippetImport("jsinterop.annotations.JsConstructor");
     addSnippetImport("jsinterop.annotations.JsMethod");