diff options
-rw-r--r-- | android-changes.txt | 6 | ||||
-rw-r--r-- | src/com/google/doclava/ClassInfo.java | 25 | ||||
-rw-r--r-- | src/com/google/doclava/Errors.java | 9 | ||||
-rw-r--r-- | src/com/google/doclava/FieldInfo.java | 10 | ||||
-rw-r--r-- | src/com/google/doclava/MethodInfo.java | 31 |
5 files changed, 63 insertions, 18 deletions
diff --git a/android-changes.txt b/android-changes.txt index 025bcd8..a62b071 100644 --- a/android-changes.txt +++ b/android-changes.txt @@ -1,6 +1,12 @@ Changes in this version relative to http://doclava.googlecode.com/ ------------------------------------------------------------------ +* Added a new command line option -showAnnotation <@interface classname>, + which takes in a fully qualified annotation classname. The specified + annotation will override any @hide annotations within the javadoc. To + specify multiple annotations to override @hide, use multiple + -showAnnotation options. + * 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 diff --git a/src/com/google/doclava/ClassInfo.java b/src/com/google/doclava/ClassInfo.java index 927b240..d3ed434 100644 --- a/src/com/google/doclava/ClassInfo.java +++ b/src/com/google/doclava/ClassInfo.java @@ -247,6 +247,10 @@ public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Sco return mIsFinal; } + public boolean isEffectivelyFinal() { + return mIsFinal || mApiCheckConstructors.isEmpty(); + } + public boolean isIncluded() { return mIsIncluded; } @@ -1694,10 +1698,25 @@ public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Sco + " changed abstract qualifier"); } - if (mIsFinal != cl.mIsFinal) { + if (!mIsFinal && cl.mIsFinal) { + /* + * It is safe to make a class final if it did not previously have any public + * constructors because it was impossible for an application to create a subclass. + */ + if (mApiCheckConstructors.isEmpty()) { + consistent = false; + Errors.error(Errors.ADDED_FINAL_UNINSTANTIABLE, cl.position(), + "Class " + cl.qualifiedName() + " added final qualifier but " + + "was previously uninstantiable and therefore could not be subclassed"); + } else { + consistent = false; + Errors.error(Errors.ADDED_FINAL, cl.position(), "Class " + cl.qualifiedName() + + " added final qualifier"); + } + } else if (mIsFinal && !cl.mIsFinal) { consistent = false; - Errors.error(Errors.CHANGED_FINAL, cl.position(), "Class " + cl.qualifiedName() - + " changed final qualifier"); + Errors.error(Errors.REMOVED_FINAL, cl.position(), "Class " + cl.qualifiedName() + + " removed final qualifier"); } if (mIsStatic != cl.mIsStatic) { diff --git a/src/com/google/doclava/Errors.java b/src/com/google/doclava/Errors.java index 2fc0f0c..e890aa4 100644 --- a/src/com/google/doclava/Errors.java +++ b/src/com/google/doclava/Errors.java @@ -134,7 +134,7 @@ public class Errors { public static Error REMOVED_FIELD = new Error(10, WARNING); public static Error REMOVED_INTERFACE = new Error(11, WARNING); public static Error CHANGED_STATIC = new Error(12, WARNING); - public static Error CHANGED_FINAL = new Error(13, WARNING); + public static Error ADDED_FINAL = new Error(13, WARNING); public static Error CHANGED_TRANSIENT = new Error(14, WARNING); public static Error CHANGED_VOLATILE = new Error(15, WARNING); public static Error CHANGED_TYPE = new Error(16, WARNING); @@ -147,6 +147,8 @@ public class Errors { public static Error CHANGED_CLASS = new Error(23, WARNING); public static Error CHANGED_DEPRECATED = new Error(24, WARNING); public static Error CHANGED_SYNCHRONIZED = new Error(25, ERROR); + public static Error ADDED_FINAL_UNINSTANTIABLE = new Error(26, WARNING); + public static Error REMOVED_FINAL = new Error(27, WARNING); // Errors in javadoc generation public static final Error UNRESOLVED_LINK = new Error(101, WARNING); @@ -175,10 +177,11 @@ public class Errors { UNAVAILABLE_SYMBOL, HIDDEN_SUPERCLASS, DEPRECATED, DEPRECATION_MISMATCH, MISSING_COMMENT, IO_ERROR, NO_SINCE_DATA, NO_FEDERATION_DATA, PARSE_ERROR, ADDED_PACKAGE, ADDED_CLASS, ADDED_METHOD, ADDED_FIELD, ADDED_INTERFACE, REMOVED_PACKAGE, REMOVED_CLASS, - REMOVED_METHOD, REMOVED_FIELD, REMOVED_INTERFACE, CHANGED_STATIC, CHANGED_FINAL, + REMOVED_METHOD, REMOVED_FIELD, REMOVED_INTERFACE, CHANGED_STATIC, ADDED_FINAL, CHANGED_TRANSIENT, CHANGED_VOLATILE, CHANGED_TYPE, CHANGED_VALUE, CHANGED_SUPERCLASS, CHANGED_SCOPE, CHANGED_ABSTRACT, CHANGED_THROWS, CHANGED_NATIVE, CHANGED_CLASS, - CHANGED_DEPRECATED, CHANGED_SYNCHRONIZED, BROKEN_SINCE_FILE, INVALID_CONTENT_TYPE}; + CHANGED_DEPRECATED, CHANGED_SYNCHRONIZED, ADDED_FINAL_UNINSTANTIABLE, REMOVED_FINAL, + BROKEN_SINCE_FILE, INVALID_CONTENT_TYPE}; public static boolean setErrorLevel(int code, int level) { for (Error e : ERRORS) { diff --git a/src/com/google/doclava/FieldInfo.java b/src/com/google/doclava/FieldInfo.java index 0200b95..09391a6 100644 --- a/src/com/google/doclava/FieldInfo.java +++ b/src/com/google/doclava/FieldInfo.java @@ -438,9 +438,13 @@ public class FieldInfo extends MemberInfo { consistent = false; } - if (mIsFinal != fInfo.mIsFinal) { - Errors.error(Errors.CHANGED_FINAL, fInfo.position(), "Field " + fInfo.qualifiedName() - + " has changed 'final' qualifier"); + if (!mIsFinal && fInfo.mIsFinal) { + Errors.error(Errors.ADDED_FINAL, fInfo.position(), "Field " + fInfo.qualifiedName() + + " has added 'final' qualifier"); + consistent = false; + } else if (mIsFinal && !fInfo.mIsFinal) { + Errors.error(Errors.REMOVED_FINAL, fInfo.position(), "Field " + fInfo.qualifiedName() + + " has removed 'final' qualifier"); consistent = false; } diff --git a/src/com/google/doclava/MethodInfo.java b/src/com/google/doclava/MethodInfo.java index db5e0cf..fc8959f 100644 --- a/src/com/google/doclava/MethodInfo.java +++ b/src/com/google/doclava/MethodInfo.java @@ -624,6 +624,17 @@ public class MethodInfo extends MemberInfo implements AbstractMethodInfo, Resolv return mIsVarargs; } + public boolean isEffectivelyFinal() { + if (mIsFinal) { + return true; + } + ClassInfo containingClass = containingClass(); + if (containingClass != null && containingClass.isEffectivelyFinal()) { + return true; + } + return false; + } + @Override public String toString() { return this.name(); @@ -729,17 +740,19 @@ public class MethodInfo extends MemberInfo implements AbstractMethodInfo, Resolv + " has changed 'native' qualifier"); } - if (mIsFinal != mInfo.mIsFinal) { - // Compiler-generated methods vary in their 'final' qual between versions of + if (!mIsStatic) { + // Compiler-generated methods vary in their 'final' qualifier between versions of // the compiler, so this check needs to be quite narrow. A change in 'final' // status of a method is only relevant if (a) the method is not declared 'static' - // and (b) the method's class is not itself 'final'. - if (!mIsStatic) { - if ((containingClass() == null) || (!containingClass().isFinal())) { - consistent = false; - Errors.error(Errors.CHANGED_FINAL, mInfo.position(), "Method " + mInfo.qualifiedName() - + " has changed 'final' qualifier"); - } + // and (b) the method is not already inferred to be 'final' by virtue of its class. + if (!isEffectivelyFinal() && mInfo.isEffectivelyFinal()) { + consistent = false; + Errors.error(Errors.ADDED_FINAL, mInfo.position(), "Method " + mInfo.qualifiedName() + + " has added 'final' qualifier"); + } else if (isEffectivelyFinal() && !mInfo.isEffectivelyFinal()) { + consistent = false; + Errors.error(Errors.REMOVED_FINAL, mInfo.position(), "Method " + mInfo.qualifiedName() + + " has removed 'final' qualifier"); } } |