Adds unit tests for extending JavaScriptObject.  Tests a loosening of the
restriction for mulitple JSOs implementing the same interface added in

http://gwt-code-reviews.appspot.com/1373803/

Review at http://gwt-code-reviews.appspot.com/1369805


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9813 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/javac/BytecodeSignatureMaker.java b/dev/core/src/com/google/gwt/dev/javac/BytecodeSignatureMaker.java
index 8664e0e..e8b8003 100644
--- a/dev/core/src/com/google/gwt/dev/javac/BytecodeSignatureMaker.java
+++ b/dev/core/src/com/google/gwt/dev/javac/BytecodeSignatureMaker.java
@@ -190,10 +190,7 @@
    * @return a hex string representing an MD5 digest.
    */
   public static String getCompileDependencySignature(byte[] byteCode) {
-    ClassReader reader = new ClassReader(byteCode);
-    CompileDependencyVisitor v = new CompileDependencyVisitor();
-    reader.accept(v, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG
-        | ClassReader.SKIP_FRAMES);
+    CompileDependencyVisitor v = visitCompileDependenciesInBytecode(byteCode);
     return v.getSignature();
   }
 
@@ -205,11 +202,16 @@
    * @return a human readable string of all public API fields
    */
   static String getCompileDependencyRawSignature(byte[] byteCode) {
+    CompileDependencyVisitor v = visitCompileDependenciesInBytecode(byteCode);
+    return v.getRawString();
+  }
+
+  private static CompileDependencyVisitor visitCompileDependenciesInBytecode(byte[] byteCode) {
     ClassReader reader = new ClassReader(byteCode);
     CompileDependencyVisitor v = new CompileDependencyVisitor();
     reader.accept(v, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG
         | ClassReader.SKIP_FRAMES);
-    return v.getRawString();
+    return v;
   }
 
   private BytecodeSignatureMaker() {
diff --git a/dev/core/test/com/google/gwt/dev/javac/JSORestrictionsTest.java b/dev/core/test/com/google/gwt/dev/javac/JSORestrictionsTest.java
index f6f5ab9..4508f09 100644
--- a/dev/core/test/com/google/gwt/dev/javac/JSORestrictionsTest.java
+++ b/dev/core/test/com/google/gwt/dev/javac/JSORestrictionsTest.java
@@ -29,14 +29,6 @@
  */
 public class JSORestrictionsTest extends TestCase {
 
-  static {
-    // Mac -XstartOnFirstThread bug
-    if (Thread.currentThread().getContextClassLoader() == null) {
-      Thread.currentThread().setContextClassLoader(
-          JSORestrictionsTest.class.getClassLoader());
-    }
-  }
-
   public void testBaseClassFullyImplements() {
     StringBuffer goodCode = new StringBuffer();
     goodCode.append("import com.google.gwt.core.client.JavaScriptObject;\n");
@@ -68,6 +60,32 @@
     shouldGenerateNoError(goodCode);
   }
 
+  /**
+    * Java's version of the 'diamond' type definition pattern. Both a subclass
+    * and superclass implement the same interface via two different chains of
+    * resolution (extended class and inherited interface) Not good style, but
+    * should be allowed.
+    */
+   public void testDiamondInheritance() {
+     StringBuffer goodCode = new StringBuffer();
+     goodCode.append("import com.google.gwt.core.client.JavaScriptObject;\n");
+     goodCode.append("public class Buggy {\n");
+     goodCode.append("  public interface Interface {\n");
+     goodCode.append("    void method();\n");
+     goodCode.append("  }\n");
+     goodCode.append("  public static abstract class CommonBase extends JavaScriptObject \n");
+     goodCode.append("      implements Interface {\n");
+     goodCode.append("    protected CommonBase() {}\n");
+     goodCode.append("  }\n");
+     goodCode.append("  public static class Impl extends CommonBase implements Interface {\n");
+     goodCode.append("    protected Impl() {}\n");
+     goodCode.append("    public final void method() {}\n");
+     goodCode.append("  }\n");
+     goodCode.append("}\n");
+
+     shouldGenerateNoError(goodCode);
+   }
+
   public void testFinalClass() {
     StringBuffer code = new StringBuffer();
     code.append("import com.google.gwt.core.client.JavaScriptObject;\n");
@@ -148,6 +166,36 @@
             "Buggy$Squeaker", "Buggy$Squeaker2"));
   }
 
+  /**
+   * Normally, only a single JSO can implement an interface, but if all the
+   * implementations are in a common base class, that should be allowed.
+   */
+  public void testMultipleImplementationsOk() {
+    StringBuffer goodCode = new StringBuffer();
+    goodCode.append("import com.google.gwt.core.client.JavaScriptObject;\n");
+    goodCode.append("public class Buggy {\n");
+    goodCode.append("  public interface CommonInterface {\n");
+    goodCode.append("    void method();\n");
+    goodCode.append("  }\n");
+    goodCode.append("  public interface CommonInterfaceExtended extends CommonInterface {}\n");
+    goodCode.append("  public static class CommonBase extends JavaScriptObject\n");
+    goodCode.append("      implements CommonInterface {\n");
+    goodCode.append("    protected CommonBase() {}\n");
+    goodCode.append("    public final void method() {}\n");
+    goodCode.append("  }\n");
+    goodCode.append("  public static class Impl1 extends CommonBase\n");
+    goodCode.append("      implements CommonInterfaceExtended {\n");
+    goodCode.append("    protected Impl1() {}\n");
+    goodCode.append("  }\n");
+    goodCode.append("  public static class Impl2 extends CommonBase\n");
+    goodCode.append("      implements CommonInterfaceExtended {\n");
+    goodCode.append("    protected Impl2() {}\n");
+    goodCode.append("  }\n");
+    goodCode.append("}\n");
+
+    shouldGenerateNoError(goodCode);
+  }
+
   public void testNew() {
     StringBuffer buggyCode = new StringBuffer();
     buggyCode.append("import com.google.gwt.core.client.JavaScriptObject;\n");
diff --git a/dev/core/test/com/google/gwt/dev/javac/JavaCompilationSuite.java b/dev/core/test/com/google/gwt/dev/javac/JavaCompilationSuite.java
index 65b3371..dc61d24 100644
--- a/dev/core/test/com/google/gwt/dev/javac/JavaCompilationSuite.java
+++ b/dev/core/test/com/google/gwt/dev/javac/JavaCompilationSuite.java
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.dev.javac;
 
+import com.google.gwt.dev.BootStrapPlatform;
 import com.google.gwt.dev.javac.asm.CollectClassDataTest;
 import com.google.gwt.dev.javac.asm.CollectReferencesVisitorTest;
 import com.google.gwt.dev.javac.asm.ResolveGenericsTest;
@@ -26,6 +27,16 @@
  * Tests script and resource injection.
  */
 public class JavaCompilationSuite {
+  
+  static {
+    /*
+     * Required for OS X Leopard. This call ensures we have a valid context
+     * ClassLoader. Many of the tests test low-level RPC mechanisms and rely on
+     * a ClassLoader to resolve classes and resources.
+     */
+    BootStrapPlatform.applyPlatformHacks();
+  }
+  
   public static Test suite() {
     TestSuite suite = new TestSuite(JavaCompilationSuite.class.getName());