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();