This patch makes three changes:
1. Excludes the client-side validation from being analyzed by api checker. Will
remove this unnecessary exclusion once
http://code.google.com/p/google-web-toolkit/issues/detail?id=5566 is resolved.
Currently, because of this bug there is a lot of console spew from typeOracle
unable to find sources.

2. Removes the unnecessary entry from the white-list. The entry is removed
because even prior to the addition of HTML(SafeHtml ..) call to the HTML class
in 2.1, the class had two constructors, so a call like new HTML(null) wouldn't
have compiled before. There is no API breakage because of this new constructor.

3. Adds a unit test to exercise the case above.

Patch by: amitmanjhi
Review by: jat

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


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9208 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/tools/api-checker/config/gwt20_21userApi.conf b/tools/api-checker/config/gwt20_21userApi.conf
index 697b3cc..b79ca67 100644
--- a/tools/api-checker/config/gwt20_21userApi.conf
+++ b/tools/api-checker/config/gwt20_21userApi.conf
@@ -59,6 +59,8 @@
 :user/super\
 
 #excludedFiles is specified as colon-separated ant patterns
+# The last 3 entries exclude the validation stuff.
+# Bug: http://code.google.com/p/google-web-toolkit/issues/detail?id=5566
 excludedFiles_new user/src/com/google/gwt/benchmarks/BenchmarkReport.java\
 :user/src/com/google/gwt/benchmarks/BenchmarkShell.java\
 :user/src/com/google/gwt/benchmarks/client/Benchmark.java\
@@ -87,6 +89,9 @@
 :user/src/com/google/gwt/uibinder/elementparsers\
 :user/src/com/google/gwt/uibinder/testing\
 :user/src/com/google/gwt/util/regexfilter\
+:user/src/javax\
+:user/src/org\
+:user/src/com/google/gwt/validation/
 
 ##############################################
 #excluded packages
@@ -127,7 +132,6 @@
 com.google.gwt.user.client.ui.CheckBox::setHTML(Ljava/lang/String;) OVERLOADED_METHOD_CALL
 com.google.gwt.user.client.ui.CustomButton::setHTML(Ljava/lang/String;) OVERLOADED_METHOD_CALL
 com.google.gwt.user.client.ui.DialogBox::setHTML(Ljava/lang/String;) OVERLOADED_METHOD_CALL
-com.google.gwt.user.client.ui.HTML::HTML(Ljava/lang/String;Z) OVERLOADED_METHOD_CALL
 com.google.gwt.user.client.ui.HTML::setHTML(Ljava/lang/String;) OVERLOADED_METHOD_CALL
 com.google.gwt.user.client.ui.HTMLPanel::HTMLPanel(Ljava/lang/String;) OVERLOADED_METHOD_CALL
 com.google.gwt.user.client.ui.HTMLTable::setHTML(IILjava/lang/String;) OVERLOADED_METHOD_CALL
diff --git a/tools/api-checker/test/com/google/gwt/tools/apichecker/ApiCompatibilityUnitTest.java b/tools/api-checker/test/com/google/gwt/tools/apichecker/ApiCompatibilityUnitTest.java
index 9e628d2..701446e 100644
--- a/tools/api-checker/test/com/google/gwt/tools/apichecker/ApiCompatibilityUnitTest.java
+++ b/tools/api-checker/test/com/google/gwt/tools/apichecker/ApiCompatibilityUnitTest.java
@@ -101,6 +101,71 @@
   }
 
   /**
+   * Test when constructor overloading results in Api incompatibilities.
+   * <p>
+   * Imagine a class Foo had a constructor Foo(String ..). If in the new Api, a
+   * constructor Foo(Integer ..) is added, ApiChecker should output a
+   * OVERLOADED_METHOD_CALL Api change (because Foo(null) cannot be compiled).
+   * However, if Foo(Object ..) is added, it should be okay since JLS matches
+   * from the most specific to the least specific.
+   */
+  private static class OverloadedConstructorRefactoring {
+    private static String getFirstApiSourceForObject() {
+      StringBuffer sb = new StringBuffer();
+      sb.append("package java.lang;\n");
+      sb.append("public class Object {\n");
+      sb.append("\tpublic static class Foo extends java.lang.Object {\n");
+      sb.append("\tpublic Foo(Foo x){}\n");
+      sb.append("\t}\n");
+      sb.append("\tpublic static class Bar extends java.lang.Object {\n");
+      sb.append("\tpublic Bar(Bar y){}\n");
+      sb.append("\t}\n");
+      sb.append("}\n");
+      return sb.toString();
+    }
+
+    private static String getSecondApiSourceForObject() {
+      StringBuffer sb = new StringBuffer();
+      sb.append("package java.lang;\n");
+      sb.append("public class Object {\n");
+      sb.append("\tpublic static class Foo extends java.lang.Object {\n");
+      sb.append("\tpublic Foo(Foo x){}\n");
+      sb.append("\tpublic Foo(Object x){}\n");
+      sb.append("\t}\n");
+      sb.append("\tpublic static class Bar extends java.lang.Object {\n");
+      sb.append("\tpublic Bar(Bar y){}\n");
+      sb.append("\tpublic Bar(Foo y){}\n");
+      sb.append("\t}\n");
+      sb.append("}\n");
+      return sb.toString();
+    }
+
+    void testBothWays() throws NotFoundException, UnableToCompleteException {
+      Map<String, String> firstApi = new HashMap<String, String>();
+      firstApi.put("java.lang.Object", getFirstApiSourceForObject());
+      Map<String, String> secondApi = new HashMap<String, String>();
+      secondApi.put("java.lang.Object", getSecondApiSourceForObject());
+
+      // firstApi is the reference Api
+      Collection<ApiChange> apiChanges = getApiChanges(firstApi, secondApi);
+      assertEquals(
+          Arrays.asList(new ApiChange[] {new ApiChange(new MockApiElement(
+              "java.lang.Object.Bar::Bar(Ljava/lang/Object$Bar;)"),
+              ApiChange.Status.OVERLOADED_METHOD_CALL),}), apiChanges);
+
+      // secondApi is the reference Api
+      apiChanges = getApiChanges(secondApi, firstApi);
+      assertEquals(Arrays.asList(new ApiChange[] {
+          new ApiChange(new MockApiElement(
+              "java.lang.Object.Foo::Foo(Ljava/lang/Object;)"),
+              ApiChange.Status.MISSING),
+          new ApiChange(new MockApiElement(
+              "java.lang.Object.Bar::Bar(Ljava/lang/Object$Foo;)"),
+              ApiChange.Status.MISSING),}), apiChanges);
+    }
+  }
+  
+  /**
    * Test when method overloading results in Api incompatibilities.
    * <p>
    * Imagine a class Foo had a method foo(String ..). If in the new Api, a
@@ -281,6 +346,11 @@
     return ApiCompatibilityChecker.getApiDiff(newApi, existingApi, emptyList);
   }
 
+  public void testConstructorOverloading() throws NotFoundException,
+      UnableToCompleteException {
+    new OverloadedConstructorRefactoring().testBothWays();
+  }
+  
   public void testFinalKeywordRefactoring() throws NotFoundException,
       UnableToCompleteException {
     new FinalKeywordRefactoring().testBothWays();