2890 if (!(atValue instanceof Attribute.Array)) return null; // error recovery |
2890 if (!(atValue instanceof Attribute.Array)) return null; // error recovery |
2891 return (Attribute.Array) atValue; |
2891 return (Attribute.Array) atValue; |
2892 } |
2892 } |
2893 |
2893 |
2894 /** Check an annotation value. |
2894 /** Check an annotation value. |
2895 */ |
2895 * |
2896 public void validateAnnotation(JCAnnotation a) { |
2896 * @param a The annotation tree to check |
2897 // collect an inventory of the members (sorted alphabetically) |
2897 * @return true if this annotation tree is valid, otherwise false |
2898 Set<MethodSymbol> members = new TreeSet<MethodSymbol>(new Comparator<Symbol>() { |
2898 */ |
2899 public int compare(Symbol t, Symbol t1) { |
2899 public boolean validateAnnotationDeferErrors(JCAnnotation a) { |
2900 return t.name.compareTo(t1.name); |
2900 boolean res = false; |
2901 } |
2901 final Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); |
2902 }); |
2902 try { |
|
2903 res = validateAnnotation(a); |
|
2904 } finally { |
|
2905 log.popDiagnosticHandler(diagHandler); |
|
2906 } |
|
2907 return res; |
|
2908 } |
|
2909 |
|
2910 private boolean validateAnnotation(JCAnnotation a) { |
|
2911 boolean isValid = true; |
|
2912 // collect an inventory of the annotation elements |
|
2913 Set<MethodSymbol> members = new LinkedHashSet<MethodSymbol>(); |
2903 for (Scope.Entry e = a.annotationType.type.tsym.members().elems; |
2914 for (Scope.Entry e = a.annotationType.type.tsym.members().elems; |
2904 e != null; |
2915 e != null; |
2905 e = e.sibling) |
2916 e = e.sibling) |
2906 if (e.sym.kind == MTH) |
2917 if (e.sym.kind == MTH) |
2907 members.add((MethodSymbol) e.sym); |
2918 members.add((MethodSymbol) e.sym); |
2908 |
2919 |
2909 // count them off as they're annotated |
2920 // remove the ones that are assigned values |
2910 for (JCTree arg : a.args) { |
2921 for (JCTree arg : a.args) { |
2911 if (!arg.hasTag(ASSIGN)) continue; // recovery |
2922 if (!arg.hasTag(ASSIGN)) continue; // recovery |
2912 JCAssign assign = (JCAssign) arg; |
2923 JCAssign assign = (JCAssign) arg; |
2913 Symbol m = TreeInfo.symbol(assign.lhs); |
2924 Symbol m = TreeInfo.symbol(assign.lhs); |
2914 if (m == null || m.type.isErroneous()) continue; |
2925 if (m == null || m.type.isErroneous()) continue; |
2915 if (!members.remove(m)) |
2926 if (!members.remove(m)) { |
|
2927 isValid = false; |
2916 log.error(assign.lhs.pos(), "duplicate.annotation.member.value", |
2928 log.error(assign.lhs.pos(), "duplicate.annotation.member.value", |
2917 m.name, a.type); |
2929 m.name, a.type); |
|
2930 } |
2918 } |
2931 } |
2919 |
2932 |
2920 // all the remaining ones better have default values |
2933 // all the remaining ones better have default values |
2921 ListBuffer<Name> missingDefaults = ListBuffer.lb(); |
2934 List<Name> missingDefaults = List.nil(); |
2922 for (MethodSymbol m : members) { |
2935 for (MethodSymbol m : members) { |
2923 if (m.defaultValue == null && !m.type.isErroneous()) { |
2936 if (m.defaultValue == null && !m.type.isErroneous()) { |
2924 missingDefaults.append(m.name); |
2937 missingDefaults = missingDefaults.append(m.name); |
2925 } |
2938 } |
2926 } |
2939 } |
|
2940 missingDefaults = missingDefaults.reverse(); |
2927 if (missingDefaults.nonEmpty()) { |
2941 if (missingDefaults.nonEmpty()) { |
|
2942 isValid = false; |
2928 String key = (missingDefaults.size() > 1) |
2943 String key = (missingDefaults.size() > 1) |
2929 ? "annotation.missing.default.value.1" |
2944 ? "annotation.missing.default.value.1" |
2930 : "annotation.missing.default.value"; |
2945 : "annotation.missing.default.value"; |
2931 log.error(a.pos(), key, a.type, missingDefaults); |
2946 log.error(a.pos(), key, a.type, missingDefaults); |
2932 } |
2947 } |
2933 |
2948 |
2934 // special case: java.lang.annotation.Target must not have |
2949 // special case: java.lang.annotation.Target must not have |
2935 // repeated values in its value member |
2950 // repeated values in its value member |
2936 if (a.annotationType.type.tsym != syms.annotationTargetType.tsym || |
2951 if (a.annotationType.type.tsym != syms.annotationTargetType.tsym || |
2937 a.args.tail == null) |
2952 a.args.tail == null) |
2938 return; |
2953 return isValid; |
2939 |
2954 |
2940 if (!a.args.head.hasTag(ASSIGN)) return; // error recovery |
2955 if (!a.args.head.hasTag(ASSIGN)) return false; // error recovery |
2941 JCAssign assign = (JCAssign) a.args.head; |
2956 JCAssign assign = (JCAssign) a.args.head; |
2942 Symbol m = TreeInfo.symbol(assign.lhs); |
2957 Symbol m = TreeInfo.symbol(assign.lhs); |
2943 if (m.name != names.value) return; |
2958 if (m.name != names.value) return false; |
2944 JCTree rhs = assign.rhs; |
2959 JCTree rhs = assign.rhs; |
2945 if (!rhs.hasTag(NEWARRAY)) return; |
2960 if (!rhs.hasTag(NEWARRAY)) return false; |
2946 JCNewArray na = (JCNewArray) rhs; |
2961 JCNewArray na = (JCNewArray) rhs; |
2947 Set<Symbol> targets = new HashSet<Symbol>(); |
2962 Set<Symbol> targets = new HashSet<Symbol>(); |
2948 for (JCTree elem : na.elems) { |
2963 for (JCTree elem : na.elems) { |
2949 if (!targets.add(TreeInfo.symbol(elem))) { |
2964 if (!targets.add(TreeInfo.symbol(elem))) { |
|
2965 isValid = false; |
2950 log.error(elem.pos(), "repeated.annotation.target"); |
2966 log.error(elem.pos(), "repeated.annotation.target"); |
2951 } |
2967 } |
2952 } |
2968 } |
|
2969 return isValid; |
2953 } |
2970 } |
2954 |
2971 |
2955 void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) { |
2972 void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) { |
2956 if (allowAnnotations && |
2973 if (allowAnnotations && |
2957 lint.isEnabled(LintCategory.DEP_ANN) && |
2974 lint.isEnabled(LintCategory.DEP_ANN) && |