Inherit JsName from super method if omitted.

Change-Id: Icac72aca9cdb69a95be17a2768616f7fd007c75b
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 6eb4092..f0b70ab 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
@@ -30,7 +30,12 @@
     /**
      * Not a js member.
      */
-    NONE,
+    NONE {
+      @Override
+      public String computeName(JMember member) {
+          return null;
+      }
+    },
     /**
      * A JsConstructor.
      */
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
index 6a850ff..fbfbd0a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
@@ -65,7 +65,7 @@
   @Override
   public void setJsMemberInfo(JsMemberType type, String namespace, String name, boolean exported) {
     this.jsMemberType = type;
-    this.jsName = name != null ? name : type.computeName(this);
+    this.jsName = name;
     this.jsNamespace = namespace;
     this.exported = exported;
   }
@@ -172,14 +172,15 @@
   @Override
   public String getQualifiedJsName() {
     String namespace = getJsNamespace();
-    if (jsName.isEmpty()) {
+    String actualJsName = getJsName();
+    if (actualJsName.isEmpty()) {
       assert !needsDynamicDispatch();
       return namespace;
     } else if (JsInteropUtil.isGlobal(namespace)) {
       assert !needsDynamicDispatch();
-      return jsName;
+      return actualJsName;
     } else {
-      return namespace + (isStatic() ? "." : ".prototype.") + jsName;
+      return namespace + (isStatic() ? "." : ".prototype.") + actualJsName;
     }
   }
 
@@ -190,11 +191,11 @@
         return method.jsName;
       }
     }
-    return null;
+    return getJsMemberType().computeName(this);
   }
 
   public boolean isJsConstructor() {
-    return isConstructor() && jsName != null;
+    return getJsMemberType() == JsMemberType.CONSTRUCTOR;
   }
 
   /**
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 333153d..eb92871 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
@@ -109,6 +109,48 @@
             + "cannot both use the same JavaScript name 'doIt'.");
   }
 
+  public void testOverrideNoNameSucceeds() throws Exception {
+    addSnippetImport("jsinterop.annotations.JsIgnore");
+    addSnippetImport("jsinterop.annotations.JsMethod");
+    addSnippetImport("jsinterop.annotations.JsType");
+    addSnippetClassDecl(
+        "public static class Parent {",
+        "  @JsMethod(name = \"a\")",
+        "  public void ma() {}",
+        "  @JsMethod(name = \"b\")",
+        "  public void mb() {}",
+        "}",
+        "@JsType",
+        "public static class Child1 extends Parent {",
+        "  public void ma() {}",
+        "  public void mb() {}",
+        "}",
+        "public static class Child2 extends Parent {",
+        "  @JsMethod",
+        "  public void ma() {}",
+        "  @JsMethod",
+        "  public void mb() {}",
+        "}",
+        "public static class Child3 extends Parent {",
+        "  public void ma() {}",
+        "  public void mb() {}",
+        "}",
+        "@JsType",
+        "public static class Child4 extends Parent {",
+        "  @JsIgnore",
+        "  public void ma() {}",
+        "  @JsIgnore",
+        "  public void mb() {}",
+        "}",
+        "public static class Buggy extends Parent {",
+        "  Child1 c1;",
+        "  Child2 c2;",
+        "  Child3 c3;",
+        "  Child4 c4;",
+        "}");
+
+    assertBuggySucceeds();
+  }
   public void testCollidingFieldExportsFails() throws Exception {
     addSnippetImport("jsinterop.annotations.JsProperty");
     addSnippetClassDecl(
diff --git a/user/test/com/google/gwt/core/interop/JsTypeTest.java b/user/test/com/google/gwt/core/interop/JsTypeTest.java
index 7ba00a7..bc67cc4 100644
--- a/user/test/com/google/gwt/core/interop/JsTypeTest.java
+++ b/user/test/com/google/gwt/core/interop/JsTypeTest.java
@@ -514,4 +514,32 @@
     assertEquals("foo", callFunction(instance, "foo", null));
     assertEquals("bar", callFunction(instance, "bar", null));
   }
+
+  static class ClassWithJsMethod {
+    @JsMethod(name = "name")
+    public String className() {
+      return ClassWithJsMethod.class.getName();
+    }
+  }
+
+  static class ClassWithJsMethodInheritingName extends ClassWithJsMethod {
+    @JsMethod
+    public String className() {
+      return ClassWithJsMethodInheritingName.class.getName();
+    }
+  }
+
+  private native String callName(Object o) /*-{
+    return o.name();
+  }-*/;
+
+  public void testInheritName() {
+    ClassWithJsMethod object = new ClassWithJsMethod();
+    assertEquals(ClassWithJsMethod.class.getName(), object.className());
+    assertEquals(ClassWithJsMethod.class.getName(), callName(object));
+
+    object = new ClassWithJsMethodInheritingName();
+    assertEquals(ClassWithJsMethodInheritingName.class.getName(), object.className());
+    assertEquals(ClassWithJsMethodInheritingName.class.getName(), callName(object));
+  }
 }