Fixes issue 2033.  Leveraged JDT's computed constant value for an expression instead of the actual written expression.  Also dealt with:

* Implicit conversion of primitives in the annotation value expressions.  
* Implicit array initializers in default annotation value expressions.
* Erroneous assertions in the AnnotationProxyInvocationHandler when the return type was a primitive.

Found by: tobyr
Patch by: mmendez
Review by: jat

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1796 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jdt/AnnotationProxyFactory.java b/dev/core/src/com/google/gwt/dev/jdt/AnnotationProxyFactory.java
index c93536a..c7a9e03 100644
--- a/dev/core/src/com/google/gwt/dev/jdt/AnnotationProxyFactory.java
+++ b/dev/core/src/com/google/gwt/dev/jdt/AnnotationProxyFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007 Google Inc.
+ * 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
@@ -40,6 +40,40 @@
   private static class AnnotationProxyInvocationHandler implements
       InvocationHandler {
     /**
+     * Returns <code>true</code> if the expected return type is assignable from 
+     * the actual return type or if the expected return type is a primitive and
+     * the actual return type is the corresponding wrapper type.
+     */
+    private static boolean isValidReturnType(Class<?> expectedReturnType,
+        Class<? extends Object> actualReturnType) {
+      if (expectedReturnType.isAssignableFrom(actualReturnType)) {
+        return true;
+      }
+
+      if (expectedReturnType.isPrimitive()) {
+        if (expectedReturnType == boolean.class) {
+          return actualReturnType == Boolean.class;
+        } else if (expectedReturnType == byte.class) {
+          return actualReturnType == Byte.class;
+        } else if (expectedReturnType == char.class) {
+          return actualReturnType == Character.class;
+        } else if (expectedReturnType == double.class) {
+          return actualReturnType == Double.class;
+        } else if (expectedReturnType == float.class) {
+          return actualReturnType == Float.class;
+        } else if (expectedReturnType == int.class) {
+          return actualReturnType == Integer.class;
+        } else if (expectedReturnType == long.class) {
+          return actualReturnType == Long.class;
+        } else if (expectedReturnType == short.class) {
+          return actualReturnType == Short.class;
+        }
+      }
+      
+      return false;
+    }
+
+    /**
      * The resolved class of this annotation.
      */
     private Class<? extends Annotation> annotationClass;
@@ -183,26 +217,30 @@
 
       String name = method.getName();
 
-      // See if the value was explicitly declared
-      Object value = identifierToValue.get(name);
+      Object value = null;
+      if (identifierToValue.containsKey(name)) {
+        // The value was explicitly provided
+        value = identifierToValue.get(name);
+        assert (value != null);
+      } else {
+        JMethod jMethod = annotationType.findMethod(name, new JType[0]);
+        if (jMethod != null) {
+          // The value will be the default value.
+          JAnnotationMethod annotationMethod = jMethod.isAnnotationMethod();
+          assert (annotationMethod != null);
+          value = annotationMethod.getDefaultValue();
+          assert (value != null);
+        } else if (method.getDeclaringClass() == Annotation.class
+            && "annotationType".equals(method.getName())) {
+          value = annotationClass;
+        }
+      }
+      
       if (value != null) {
-        assert (method.getReturnType().isAssignableFrom(value.getClass()));
+        assert (isValidReturnType(method.getReturnType(), value.getClass()));
         return value;
       }
 
-      // Try to find a method on the interface.
-      JMethod jMethod = annotationType.findMethod(name, new JType[0]);
-      if (jMethod != null) {
-        JAnnotationMethod annotationMethod = jMethod.isAnnotationMethod();
-        assert (annotationMethod != null);
-        return annotationMethod.getDefaultValue();
-      }
-
-      if (method.getDeclaringClass() == Annotation.class
-          && "annotationType".equals(method.getName())) {
-        return annotationClass;
-      }
-
       /*
        * Maybe it's an Object method, just delegate to myself.
        */
diff --git a/dev/core/src/com/google/gwt/dev/jdt/TypeOracleBuilder.java b/dev/core/src/com/google/gwt/dev/jdt/TypeOracleBuilder.java
index 12056ea..2c7f5ec 100644
--- a/dev/core/src/com/google/gwt/dev/jdt/TypeOracleBuilder.java
+++ b/dev/core/src/com/google/gwt/dev/jdt/TypeOracleBuilder.java
@@ -44,8 +44,8 @@
 import com.google.gwt.core.ext.typeinfo.TypeOracle;
 import com.google.gwt.dev.jdt.CacheManager.Mapper;
 import com.google.gwt.dev.util.Empty;
-import com.google.gwt.dev.util.Util;
 import com.google.gwt.dev.util.PerfLogger;
+import com.google.gwt.dev.util.Util;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.IProblem;
@@ -60,21 +60,13 @@
 import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
 import org.eclipse.jdt.internal.compiler.ast.Clinit;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
 import org.eclipse.jdt.internal.compiler.ast.Expression;
-import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Initializer;
 import org.eclipse.jdt.internal.compiler.ast.Javadoc;
-import org.eclipse.jdt.internal.compiler.ast.MagicLiteral;
 import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.NameReference;
-import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
-import org.eclipse.jdt.internal.compiler.ast.NumberLiteral;
-import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
-import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
-import org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
@@ -104,7 +96,6 @@
 import java.io.File;
 import java.io.IOException;
 import java.lang.reflect.Array;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -301,13 +292,6 @@
     }
   }
 
-  /**
-   * Returns the number associated with a JDT numeric literal.
-   */
-  private static Object getNumericLiteralValue(NumberLiteral expression) {
-    return getConstantValue(expression.constant);
-  }
-
   private static boolean isAnnotation(TypeDeclaration typeDecl) {
     if (typeDecl.kind() == IGenericType.ANNOTATION_TYPE_DECL) {
       return true;
@@ -660,32 +644,21 @@
 
       // Value
       Expression expressionValue = mvp.value;
-      Object value = evaluateConstantExpression(logger, expressionValue);
-      if (value == null) {
+      TypeBinding expectedElementValueType = mvp.binding.returnType;
+      Object elementValue = getAnnotationElementValue(logger,
+          expectedElementValueType, expressionValue);
+      if (elementValue == null) {
         return null;
       }
 
-      try {
-        Method method = clazz.getMethod(identifier, new Class[0]);
-        Class<?> expectedClass = method.getReturnType();
-        Class<? extends Object> actualClass = value.getClass();
-        if (expectedClass.isArray() && !actualClass.isArray()) {
-          /*
-           * JSL3 Section 9.7 single element annotations can skip the curly
-           * braces; means we do not get an array
-           */
-          assert (expression instanceof SingleMemberAnnotation);
-          Object array = Array.newInstance(expectedClass.getComponentType(), 1);
-          Array.set(array, 0, value);
-          value = array;
-        }
-      } catch (SecurityException e) {
-        return null;
-      } catch (NoSuchMethodException e) {
-        return null;
-      }
+      /*
+       * If the expected value is supposed to be an array then the element value
+       * had better be an array.
+       */
+      assert (expectedElementValueType.isArrayType() == false || expectedElementValueType.isArrayType()
+          && elementValue.getClass().isArray());
 
-      identifierToValue.put(identifier, value);
+      identifierToValue.put(identifier, elementValue);
     }
 
     // Create the Annotation proxy
@@ -698,43 +671,6 @@
         identifierToValue);
   }
 
-  private Object createArrayConstant(TreeLogger logger,
-      ArrayInitializer arrayInitializer) {
-    Class<?> leafComponentClass = getClassLiteral(logger,
-        arrayInitializer.binding.leafComponentType);
-    if (leafComponentClass == null) {
-      return null;
-    }
-
-    int[] dimensions = new int[arrayInitializer.binding.dimensions];
-
-    Expression[] initExpressions = arrayInitializer.expressions;
-    if (initExpressions != null) {
-      dimensions[0] = initExpressions.length;
-    }
-
-    Object array = Array.newInstance(leafComponentClass, dimensions);
-    boolean failed = false;
-    if (initExpressions != null) {
-      for (int i = 0; i < initExpressions.length; ++i) {
-        Expression arrayInitExp = initExpressions[i];
-        Object value = evaluateConstantExpression(logger, arrayInitExp);
-        if (value != null) {
-          Array.set(array, i, value);
-        } else {
-          failed = true;
-          break;
-        }
-      }
-    }
-
-    if (!failed) {
-      return array;
-    }
-
-    return null;
-  }
-
   private JUpperBound createTypeParameterBounds(TreeLogger logger,
       TypeVariableBinding tvBinding) {
     TypeBinding firstBound = tvBinding.firstBound;
@@ -813,69 +749,136 @@
     return jtypeParamArray;
   }
 
-  private Object evaluateConstantExpression(TreeLogger logger,
-      Expression expression) {
-    if (expression instanceof MagicLiteral) {
-      if (expression instanceof FalseLiteral) {
-        return Boolean.FALSE;
-      } else if (expression instanceof NullLiteral) {
-        // null is not a valid annotation value; JLS Third Ed. Section 9.7
-      } else if (expression instanceof TrueLiteral) {
-        return Boolean.TRUE;
-      }
-    } else if (expression instanceof NumberLiteral) {
-      Object value = getNumericLiteralValue((NumberLiteral) expression);
-      if (value != null) {
-        return value;
-      }
-    } else if (expression instanceof StringLiteral) {
-      StringLiteral stringLiteral = (StringLiteral) expression;
-      return stringLiteral.constant.stringValue();
-    } else if (expression instanceof ClassLiteralAccess) {
-      ClassLiteralAccess classLiteral = (ClassLiteralAccess) expression;
-      Class<?> clazz = getClassLiteral(logger, classLiteral.targetType);
-      if (clazz != null) {
-        return clazz;
-      }
-    } else if (expression instanceof ArrayInitializer) {
-      Object value = createArrayConstant(logger, (ArrayInitializer) expression);
-      if (value != null) {
-        return value;
-      }
-    } else if (expression instanceof NameReference) {
+  /**
+   * Returns an annotation element value as defined in JLS 3.0 section 9.7.
+   * 
+   * @param logger
+   * @param expectedElementValueType the expected element value type
+   * @param elementValueExpression the expression that defines the element value
+   * 
+   * @return annotation element value as defined in JLS 3.0 section 9.7
+   */
+  private Object getAnnotationElementValue(TreeLogger logger,
+      TypeBinding expectedElementValueType, Expression elementValueExpression) {
+
+    Object elementValue = null;
+
+    if (elementValueExpression.constant != null
+        && elementValueExpression.constant != Constant.NotAConstant) {
       /*
-       * This name reference can only be to something that is a constant value,
-       * or an enumerated type since annotation values must be constants.
+       * Rely on JDT's computed constant value to deal with an
+       * AnnotationElementValue expression whose resolved type is a primitive or
+       * a string.
        */
-      NameReference nameRef = (NameReference) expression;
+      Constant constant = elementValueExpression.constant;
+      int expectedTypeId = expectedElementValueType.id;
 
-      if (nameRef.constant != Constant.NotAConstant) {
-        return getConstantValue(nameRef.constant);
-      } else {
-        Class clazz = getClassLiteral(logger, nameRef.actualReceiverType);
-        if (clazz.isEnum()) {
-          String enumName = String.valueOf(nameRef.fieldBinding().name);
-          return Enum.valueOf(clazz, enumName);
-        } else {
-          /*
-           * If this is not an enumeration, then fall through to failure case
-           * below.
-           */
-        }
-      }
-    } else if (expression instanceof Annotation) {
-      Object annotationInstance = createAnnotationInstance(logger, expression);
-      if (annotationInstance != null) {
-        return annotationInstance;
-      }
-    } else if (expression instanceof ConditionalExpression) {
-      ConditionalExpression condExpression = (ConditionalExpression) expression;
-      assert (condExpression.constant != Constant.NotAConstant);
+      if (expectedElementValueType.isArrayType()) {
+        /*
+         * This can happen when an element value is an array with a single
+         * element. In this case JLS 3.0 section 9.7 allows for the
+         * ArrayInitializer expression to be implicit. Since, element values can
+         * only be single dimensional arrays, we take the leaf type of the
+         * expected array type as our resultant element value type.
+         */
+        assert (!elementValueExpression.resolvedType.isArrayType() && expectedElementValueType.dimensions() == 1);
 
-      return getConstantValue(condExpression.constant);
+        expectedTypeId = expectedElementValueType.leafComponentType().id;
+      }
+
+      if (elementValueExpression.resolvedType.id != expectedTypeId) {
+        /*
+         * Narrowing and widening conversions are handled by the following
+         * Constant.castTo call. JDT wants the upper four bits of this mask to
+         * be the target type id and the lower four bits to be the source type
+         * id. See Constant.castTo for more details.
+         */
+        constant = constant.castTo((expectedTypeId << 4)
+            + elementValueExpression.resolvedType.id);
+      }
+
+      elementValue = getConstantValue(constant);
+    } else if (elementValueExpression instanceof ClassLiteralAccess) {
+      ClassLiteralAccess classLiteral = (ClassLiteralAccess) elementValueExpression;
+      elementValue = getClassLiteral(logger, classLiteral.targetType);
+    } else if (elementValueExpression instanceof ArrayInitializer) {
+      elementValue = getAnnotationElementValueArray(logger,
+          (ArrayInitializer) elementValueExpression);
+    } else if (elementValueExpression instanceof NameReference) {
+      /*
+       * Any primitive types, conditionals, strings, arrays and name references
+       * to constant fields will have all been handled by the constant
+       * expression block above. This name reference can only be for an
+       * enumerated type.
+       */
+      NameReference nameRef = (NameReference) elementValueExpression;
+
+      assert (nameRef.constant == null || nameRef.constant == Constant.NotAConstant);
+      assert (nameRef.actualReceiverType.isEnum());
+
+      Class<?> clazz = getClassLiteral(logger, nameRef.actualReceiverType);
+      Class<? extends Enum> enumClass = clazz.asSubclass(Enum.class);
+
+      String enumName = String.valueOf(nameRef.fieldBinding().name);
+      elementValue = Enum.valueOf(enumClass, enumName);
+    } else if (elementValueExpression instanceof Annotation) {
+      elementValue = createAnnotationInstance(logger, elementValueExpression);
+    } else {
+      assert (false);
+      return null;
     }
 
-    assert (false);
+    assert (elementValue != null);
+
+    if (expectedElementValueType.isArrayType()
+        && !elementValue.getClass().isArray()) {
+      /*
+       * Handle single element arrays where no explicit array initializer was
+       * given.
+       */
+      Object array = Array.newInstance(elementValue.getClass(), 1);
+      Array.set(array, 0, elementValue);
+      elementValue = array;
+    }
+
+    return elementValue;
+  }
+
+  /**
+   * Returns an annotation element value array. These arrays can only have a
+   * single dimension.
+   */
+  private Object getAnnotationElementValueArray(TreeLogger logger,
+      ArrayInitializer arrayInitializer) {
+    assert (arrayInitializer.binding.dimensions == 1);
+
+    Class<?> leafComponentClass = getClassLiteral(logger,
+        arrayInitializer.binding.leafComponentType);
+    if (leafComponentClass == null) {
+      return null;
+    }
+
+    Expression[] initExpressions = arrayInitializer.expressions;
+    int arrayLength = initExpressions != null ? initExpressions.length : 0;
+
+    Object array = Array.newInstance(leafComponentClass, arrayLength);
+    boolean failed = false;
+    for (int i = 0; i < arrayLength; ++i) {
+      Expression arrayInitExp = initExpressions[i];
+      Object value = getAnnotationElementValue(logger,
+          arrayInitializer.binding.leafComponentType, arrayInitExp);
+      if (value != null) {
+        Array.set(array, i, value);
+      } else {
+        failed = true;
+        break;
+      }
+    }
+
+    if (!failed) {
+      return array;
+    }
+
     return null;
   }
 
@@ -1209,7 +1212,8 @@
         AnnotationMethodDeclaration annotationMethod = (AnnotationMethodDeclaration) jmethod;
         Object defaultValue = null;
         if (annotationMethod.defaultValue != null) {
-          defaultValue = evaluateConstantExpression(logger,
+          defaultValue = getAnnotationElementValue(logger,
+              annotationMethod.returnType.resolvedType,
               annotationMethod.defaultValue);
         }
         method = new JAnnotationMethod(enclosingType, name, declStart, declEnd,
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/TypeOracleAnnotationSupportTest.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/TypeOracleAnnotationSupportTest.java
index 3158eb9..6da80ab 100644
--- a/dev/core/test/com/google/gwt/core/ext/typeinfo/TypeOracleAnnotationSupportTest.java
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/TypeOracleAnnotationSupportTest.java
@@ -20,6 +20,8 @@
 import com.google.gwt.core.ext.typeinfo.test.AnnotatedClass;
 import com.google.gwt.core.ext.typeinfo.test.ClassAnnotatedWithBinaryOnlyAnnotation;
 import com.google.gwt.core.ext.typeinfo.test.ClassLiteralReferenceAnnotation;
+import com.google.gwt.core.ext.typeinfo.test.PrimitiveValuesAnnotation;
+import com.google.gwt.core.ext.typeinfo.test.PrimitivesAnnotatedClass;
 import com.google.gwt.core.ext.typeinfo.test.TestAnnotation;
 import com.google.gwt.dev.cfg.ModuleDef;
 import com.google.gwt.dev.cfg.ModuleDefLoader;
@@ -73,6 +75,17 @@
 
     // Tests default value that is a class literal.
     assertEquals(realAnnotation.classLiteral(), testAnnotation.classLiteral());
+
+    // Tests implicit array initializers
+    Class<?>[] expectedArrayValue = realAnnotation.arrayWithImplicitArrayInitializer();
+    Class<?>[] actualArrayValue = testAnnotation.arrayWithImplicitArrayInitializer();
+    assertTrue(expectedArrayValue.length > 0);
+    assertEquals(expectedArrayValue.length, actualArrayValue.length);
+    assertEquals(expectedArrayValue[0], actualArrayValue[0]);
+
+    // Tests that empty array initializers are also handled correctly.
+    assertEquals(realAnnotation.emptyArray().length,
+        testAnnotation.emptyArray().length);
   }
 
   private final TreeLogger logger = TreeLogger.NULL;
@@ -191,4 +204,37 @@
 
     assertNull(classType.getAnnotation(BinaryOnlyAnnotation.class));
   }
+
+  /**
+   * Ensures that we properly handle primitive value attributes on annotations.
+   * (Special-cased, because of how JDT handles char/numeric literals)
+   */
+  public void testPrimitiveValuesAnnotations() throws NotFoundException {
+    JClassType primitivesAnnotatedClass = typeOracle.getType(PrimitivesAnnotatedClass.class.getName());
+    PrimitiveValuesAnnotation annotation = primitivesAnnotatedClass.getAnnotation(PrimitiveValuesAnnotation.class);
+
+    boolean bool = annotation.bool();
+    assertTrue(bool);
+
+    byte b = annotation.b();
+    assertTrue(b > 0);
+
+    char c = annotation.c();
+    assertTrue(c > 0);
+
+    double d = annotation.d();
+    assertTrue(d > 0);
+
+    float f = annotation.f();
+    assertTrue(f > 0);
+
+    int i = annotation.i();
+    assertTrue(i > 0);
+
+    long l = annotation.l();
+    assertTrue(l > 0);
+
+    short s = annotation.s();
+    assertTrue(s > 0);
+  }
 }
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/test/PrimitiveValuesAnnotation.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/PrimitiveValuesAnnotation.java
new file mode 100644
index 0000000..22fd71f
--- /dev/null
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/PrimitiveValuesAnnotation.java
@@ -0,0 +1,48 @@
+/*
+ * 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.core.ext.typeinfo.test;
+
+import java.io.Serializable;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Test annotation containing primitive values.
+ *
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface PrimitiveValuesAnnotation {
+  boolean bool() default true;
+  
+  byte b() default 0;
+
+  char c() default '\0';
+
+  short s() default 0;
+
+  int i() default 0;
+
+  long l() default 0;
+
+  float f() default 0;
+
+  double d() default 0;
+
+  int[] ia() default {}; 
+}
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/test/PrimitivesAnnotatedClass.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/PrimitivesAnnotatedClass.java
new file mode 100644
index 0000000..bd4b377
--- /dev/null
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/PrimitivesAnnotatedClass.java
@@ -0,0 +1,28 @@
+/*
+ * 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.core.ext.typeinfo.test;
+
+/**
+ * Test class for annotations with primitive values.
+ * 
+ */
+@PrimitiveValuesAnnotation(b = PrimitivesAnnotatedClass.byteAsInt,
+    c = (byte) 12, s = 'a', i = (short) 1452,
+    l = 12345, f = (byte) 15, d = 123412312L)
+public class PrimitivesAnnotatedClass {
+  static final int byteAsInt = 123;
+}
+
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/test/TestAnnotation.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/TestAnnotation.java
index bb88bfc..e776051 100644
--- a/dev/core/test/com/google/gwt/core/ext/typeinfo/test/TestAnnotation.java
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/TestAnnotation.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007 Google Inc.
+ * 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
@@ -33,16 +33,6 @@
     ElementType.TYPE})
 public @interface TestAnnotation {
   /**
-   * Default value for the annotation.
-   */
-  String value();
-
-  /**
-   * Tests element default values that are themselves annotations.
-   */
-  NestedAnnotation nestedAnnotation() default @NestedAnnotation("Not assigned");
-
-  /**
    * Used to test initialization using conditional statements.
    */
   boolean useMinLong = true;
@@ -51,11 +41,21 @@
    * Used to test initialization using SingleNameReferences.
    */
   String defaultStringValue = "Hello There";
+
+  /**
+   * Tests that implicit array initializers are handled correctly.
+   */
+  Class<?>[] arrayWithImplicitArrayInitializer() default Object.class;
+
+  /**
+   * Tests default value initialization of class literals. 
+   */
+  Class<?> classLiteral() default Object.class;
   
   /**
-   * Tests default values using conditional statements.
+   * Tests that an empty array initializer is handled correctly.
    */
-  long longValue() default useMinLong ? Long.MIN_VALUE : Long.MAX_VALUE;
+  int[] emptyArray() default {};
 
   /**
    * Tests array default values.
@@ -63,13 +63,23 @@
   int[] intArrayValue() default {1,2,3};
 
   /**
+   * Tests default values using conditional statements.
+   */
+  long longValue() default useMinLong ? Long.MIN_VALUE : Long.MAX_VALUE;
+  
+  /**
+   * Tests element default values that are themselves annotations.
+   */
+  NestedAnnotation nestedAnnotation() default @NestedAnnotation("Not assigned");
+  
+  /**
    * Tests default value initialization via a QualifiedNameReference.
    */
   String stringValue() default TestAnnotation.defaultStringValue;
-  
+
   /**
-   * Tests default value initialization of class literals. 
+   * Default value for the annotation.
    */
-  Class<?> classLiteral() default Object.class;
+  String value();
 }