Fix doclava to preserve annotations on fields and methods

The android.jar stubs file used in the SDK was missing @Deprecated
annotations on methods and fields.

This changeset updates doclava to write annotations on methods and
fields as well, and to also add a @Deprecated annotation for APIs that
were marked deprecated but missing an annotation (presumably because
they only used the @deprecated doc comment; there are about 30 such
APIs out of 800+ deprecation usages.)

This fixes
http://code.google.com/p/android/issues/detail?id=26173

Change-Id: Iad675d4cfdf650165bfb7050cdcc0978c3a72d55
diff --git a/android-changes.txt b/android-changes.txt
new file mode 100644
index 0000000..025bcd8
--- /dev/null
+++ b/android-changes.txt
@@ -0,0 +1,12 @@
+Changes in this version relative to http://doclava.googlecode.com/
+------------------------------------------------------------------
+
+* Modified the Java stub generator code to write out annotations for
+  methods and fields as well, not just classes. This meant adding a
+  writeAnnotations call to writeMethod and to writeField
+
+* Modified the writeAnnotations method to take a "isDeprecated"
+  parameter, which when set adds a @Deprecated annotation if one
+  doesn't already exist. This ensures that APIs only marked with a
+  @deprecated documentation comment will also be marked as
+  @Deprecated. Also strips out @Override annotations.
diff --git a/src/com/google/doclava/Stubs.java b/src/com/google/doclava/Stubs.java
index c83731a..b493aa0 100644
--- a/src/com/google/doclava/Stubs.java
+++ b/src/com/google/doclava/Stubs.java
@@ -324,7 +324,7 @@
   }
 
   static void writeClass(PrintStream stream, HashSet<ClassInfo> notStrippable, ClassInfo cl) {
-    writeAnnotations(stream, cl.annotations());
+    writeAnnotations(stream, cl.annotations(), cl.isDeprecated());
 
     stream.print(cl.scope() + " ");
     if (cl.isAbstract() && !cl.isAnnotation() && !cl.isInterface()) {
@@ -498,6 +498,8 @@
   static void writeMethod(PrintStream stream, MethodInfo method, boolean isConstructor) {
     String comma;
 
+    writeAnnotations(stream, method.annotations(), method.isDeprecated());
+
     stream.print(method.scope() + " ");
     if (method.isStatic()) {
       stream.print("static ");
@@ -560,6 +562,8 @@
   }
 
   static void writeField(PrintStream stream, FieldInfo field) {
+    writeAnnotations(stream, field.annotations(), field.isDeprecated());
+
     stream.print(field.scope() + " ");
     if (field.isStatic()) {
       stream.print("static ");
@@ -712,12 +716,35 @@
     }
   }
 
-  static void writeAnnotations(PrintStream stream, ArrayList<AnnotationInstanceInfo> annotations) {
+    /**
+     * Write out the given list of annotations. If the {@code isDeprecated}
+     * flag is true also write out a {@code @Deprecated} annotation if it did not
+     * already appear in the list of annotations. (This covers APIs that mention
+     * {@code @deprecated} in their documentation but fail to add
+     * {@code @Deprecated} as an annotation.
+     * <p>
+     * {@code @Override} annotations are deliberately skipped.
+     */
+  static void writeAnnotations(PrintStream stream, List<AnnotationInstanceInfo> annotations,
+          boolean isDeprecated) {
+    assert annotations != null;
     for (AnnotationInstanceInfo ann : annotations) {
+      // Skip @Override annotations: the stubs do not need it and in some cases it leads
+      // to compilation errors with the way the stubs are generated
+      if (ann.type() != null && ann.type().qualifiedName().equals("java.lang.Override")) {
+        continue;
+      }
       if (!ann.type().isHidden()) {
         stream.println(ann.toString());
+        if (isDeprecated && ann.type() != null
+            && ann.type().qualifiedName().equals("java.lang.Deprecated")) {
+          isDeprecated = false; // Prevent duplicate annotations
+        }
       }
     }
+    if (isDeprecated) {
+      stream.println("@Deprecated");
+    }
   }
 
   static void writeAnnotationElement(PrintStream stream, MethodInfo ann) {