Add annotation inheritance for i18n generators.
Patch by: jat
Review by: rjrjr
git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/1.6@3874 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/i18n/rebind/AbstractLocalizableImplCreator.java b/user/src/com/google/gwt/i18n/rebind/AbstractLocalizableImplCreator.java
index 71b44e2..8852eb9 100644
--- a/user/src/com/google/gwt/i18n/rebind/AbstractLocalizableImplCreator.java
+++ b/user/src/com/google/gwt/i18n/rebind/AbstractLocalizableImplCreator.java
@@ -15,6 +15,8 @@
*/
package com.google.gwt.i18n.rebind;
+import static com.google.gwt.i18n.rebind.AnnotationUtil.getClassAnnotation;
+
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
@@ -139,7 +141,7 @@
context.commit(logger, pw);
}
// Generate a translatable output file if requested.
- Generate generate = targetClass.getAnnotation(Generate.class);
+ Generate generate = getClassAnnotation(targetClass, Generate.class);
if (generate != null) {
String path = generate.fileName();
if (Generate.DEFAULT.equals(path)) {
diff --git a/user/src/com/google/gwt/i18n/rebind/AnnotationUtil.java b/user/src/com/google/gwt/i18n/rebind/AnnotationUtil.java
new file mode 100644
index 0000000..21fbbd6
--- /dev/null
+++ b/user/src/com/google/gwt/i18n/rebind/AnnotationUtil.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.i18n.rebind;
+
+import com.google.gwt.core.ext.typeinfo.JClassType;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Utility class for i18n-related annotation manipulation routines.
+ */
+public class AnnotationUtil {
+
+ /**
+ * Find an instance of the specified annotation, walking up the inheritance
+ * tree if necessary.
+ *
+ * <p>Note that i18n annotations may appear on classes as well as interfaces
+ * (a concrete implementation can be supplied rather than just an interface
+ * and this is the normal way of using generic Localizable interfaces), so
+ * we have to search the super chain as well as other interfaces.
+ *
+ * <p>The super chain is walked first, so if an ancestor superclass has the
+ * requested annotation, it will be preferred over a directly implemented
+ * interface.
+ *
+ * @param <T> Annotation type to search for
+ * @param clazz root class to search, may be null
+ * @param annotationClass class object of Annotation subclass to search for
+ * @return the requested annotation or null if none
+ */
+ static <T extends Annotation> T getClassAnnotation(JClassType clazz,
+ Class<T> annotationClass) {
+ if (clazz == null) {
+ return null;
+ }
+ T annot = clazz.getAnnotation(annotationClass);
+ if (annot == null) {
+ annot = getClassAnnotation(clazz.getSuperclass(), annotationClass);
+ if (annot != null) {
+ return annot;
+ }
+ for (JClassType intf : clazz.getImplementedInterfaces()) {
+ annot = getClassAnnotation(intf, annotationClass);
+ if (annot != null) {
+ return annot;
+ }
+ }
+ }
+ return annot;
+ }
+
+}
diff --git a/user/src/com/google/gwt/i18n/rebind/AnnotationsResource.java b/user/src/com/google/gwt/i18n/rebind/AnnotationsResource.java
index 87b9d05..9e5cc4e 100644
--- a/user/src/com/google/gwt/i18n/rebind/AnnotationsResource.java
+++ b/user/src/com/google/gwt/i18n/rebind/AnnotationsResource.java
@@ -13,9 +13,10 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-
package com.google.gwt.i18n.rebind;
+import static com.google.gwt.i18n.rebind.AnnotationUtil.getClassAnnotation;
+
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.typeinfo.JArrayType;
import com.google.gwt.core.ext.typeinfo.JClassType;
@@ -167,7 +168,7 @@
*/
public static KeyGenerator getKeyGenerator(JClassType targetClass)
throws AnnotationsError {
- GenerateKeys generator = targetClass.getAnnotation(GenerateKeys.class);
+ GenerateKeys generator = getClassAnnotation(targetClass, GenerateKeys.class);
if (generator != null) {
String className = generator.value();
try {
@@ -377,7 +378,7 @@
KeyGenerator keyGenerator = getKeyGenerator(clazz);
map = new HashMap<String, MethodEntry>();
setPath(clazz.getQualifiedSourceName());
- DefaultLocale defLocale = clazz.getAnnotation(DefaultLocale.class);
+ DefaultLocale defLocale = getClassAnnotation(clazz, DefaultLocale.class);
if (defLocale != null && !ResourceFactory.DEFAULT_TOKEN.equals(locale)
&& !locale.equalsIgnoreCase(defLocale.value())) {
logger.log(TreeLogger.WARN, "@DefaultLocale on "
diff --git a/user/test/com/google/gwt/i18n/client/CommonInterfaceAnnotations.java b/user/test/com/google/gwt/i18n/client/CommonInterfaceAnnotations.java
new file mode 100644
index 0000000..c33704d
--- /dev/null
+++ b/user/test/com/google/gwt/i18n/client/CommonInterfaceAnnotations.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.i18n.client;
+
+import com.google.gwt.i18n.client.LocalizableResource.GenerateKeys;
+
+/**
+ * Base interface to test annotation inheritance.
+ *
+ * <p>This works by setting the key generator to MD5 on this interface,
+ * then verifying that keys in the subinterface are looked up with
+ * MD5 hashes rather than method names.
+ */
+@GenerateKeys("com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator")
+public interface CommonInterfaceAnnotations extends Messages {
+
+ @DefaultMessage("foo")
+ String foo();
+}
diff --git a/user/test/com/google/gwt/i18n/client/I18NTest.java b/user/test/com/google/gwt/i18n/client/I18NTest.java
index f94edb9..5889825 100644
--- a/user/test/com/google/gwt/i18n/client/I18NTest.java
+++ b/user/test/com/google/gwt/i18n/client/I18NTest.java
@@ -126,6 +126,13 @@
m.pluralWidgetsOther(150));
}
+ public void testAnnotationInheritance() {
+ TestAnnotationGrandchild m = GWT.create(TestAnnotationGrandchild.class);
+ assertEquals("foo", m.foo());
+ assertEquals("bar_piglatin", m.bar());
+ assertEquals("baz_piglatin", m.baz());
+ }
+
public void testBindings() {
TestBinding b = (TestBinding) GWT.create(TestBinding.class);
assertEquals("default", b.a());
diff --git a/user/test/com/google/gwt/i18n/client/TestAnnotationGrandchild.java b/user/test/com/google/gwt/i18n/client/TestAnnotationGrandchild.java
new file mode 100644
index 0000000..c69b16d
--- /dev/null
+++ b/user/test/com/google/gwt/i18n/client/TestAnnotationGrandchild.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.i18n.client;
+
+/**
+ * Verifies that class-level annotations on grandparent interface are still honored,
+ * to make sure multiple levels of inheritance are handled.
+ */
+public interface TestAnnotationGrandchild extends TestAnnotationInheritance {
+
+ @DefaultMessage("baz")
+ String baz();
+}
diff --git a/user/test/com/google/gwt/i18n/client/TestAnnotationGrandchild_piglatin.properties b/user/test/com/google/gwt/i18n/client/TestAnnotationGrandchild_piglatin.properties
new file mode 100644
index 0000000..6dda386
--- /dev/null
+++ b/user/test/com/google/gwt/i18n/client/TestAnnotationGrandchild_piglatin.properties
@@ -0,0 +1,4 @@
+# MD5 hash of "bar"
+37B51D194A7513E45B56F6524F2D51F2 = bar_piglatin
+# MD5 hash of "baz"
+73FEFFA4B7F6BB68E44CF984C85F6E88 = baz_piglatin
diff --git a/user/test/com/google/gwt/i18n/client/TestAnnotationInheritance.java b/user/test/com/google/gwt/i18n/client/TestAnnotationInheritance.java
new file mode 100644
index 0000000..92ddcdc
--- /dev/null
+++ b/user/test/com/google/gwt/i18n/client/TestAnnotationInheritance.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.i18n.client;
+
+/**
+ * Verifies that class-level annotations on superinterface are still used
+ * by this interface. In this case, we verify that this interface's keys
+ * are based on the MD5 hash of the default value.
+ */
+public interface TestAnnotationInheritance extends CommonInterfaceAnnotations {
+
+ @DefaultMessage("bar")
+ String bar();
+}