1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Mon Aug 27 10:59:13 2012 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Fri Aug 31 10:37:46 2012 +0100 1.3 @@ -69,7 +69,6 @@ 1.4 private final Infer infer; 1.5 private final Types types; 1.6 private final JCDiagnostic.Factory diags; 1.7 - private final boolean skipAnnotations; 1.8 private boolean warnOnSyntheticConflicts; 1.9 private boolean suppressAbortOnBadClassFile; 1.10 private boolean enableSunApiLintControl; 1.11 @@ -113,7 +112,6 @@ 1.12 allowCovariantReturns = source.allowCovariantReturns(); 1.13 allowSimplifiedVarargs = source.allowSimplifiedVarargs(); 1.14 complexInference = options.isSet("complexinference"); 1.15 - skipAnnotations = options.isSet("skipAnnotations"); 1.16 warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts"); 1.17 suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile"); 1.18 enableSunApiLintControl = options.isSet("enableSunApiLintControl"); 1.19 @@ -2422,14 +2420,13 @@ 1.20 /** Check the annotations of a symbol. 1.21 */ 1.22 public void validateAnnotations(List<JCAnnotation> annotations, Symbol s) { 1.23 - if (skipAnnotations) return; 1.24 for (JCAnnotation a : annotations) 1.25 validateAnnotation(a, s); 1.26 } 1.27 1.28 /** Check an annotation of a symbol. 1.29 */ 1.30 - public void validateAnnotation(JCAnnotation a, Symbol s) { 1.31 + private void validateAnnotation(JCAnnotation a, Symbol s) { 1.32 validateAnnotationTree(a); 1.33 1.34 if (!annotationApplicable(a, s)) 1.35 @@ -2441,6 +2438,215 @@ 1.36 } 1.37 } 1.38 1.39 + /** 1.40 + * Validate the proposed container 'containedBy' on the 1.41 + * annotation type symbol 's'. Report errors at position 1.42 + * 'pos'. 1.43 + * 1.44 + * @param s The (annotation)type declaration annotated with a @ContainedBy 1.45 + * @param containerAnno the @ContainedBy on 's' 1.46 + * @param pos where to report errors 1.47 + */ 1.48 + public void validateContainedBy(TypeSymbol s, Attribute.Compound containedBy, DiagnosticPosition pos) { 1.49 + Assert.check(types.isSameType(containedBy.type, syms.containedByType)); 1.50 + 1.51 + Type t = null; 1.52 + List<Pair<MethodSymbol,Attribute>> l = containedBy.values; 1.53 + if (!l.isEmpty()) { 1.54 + Assert.check(l.head.fst.name == names.value); 1.55 + t = ((Attribute.Class)l.head.snd).getValue(); 1.56 + } 1.57 + 1.58 + if (t == null) { 1.59 + log.error(pos, "invalid.container.wrong.containedby", s, containedBy); 1.60 + return; 1.61 + } 1.62 + 1.63 + validateHasContainerFor(t.tsym, s, pos); 1.64 + validateRetention(t.tsym, s, pos); 1.65 + validateDocumented(t.tsym, s, pos); 1.66 + validateInherited(t.tsym, s, pos); 1.67 + validateTarget(t.tsym, s, pos); 1.68 + } 1.69 + 1.70 + /** 1.71 + * Validate the proposed container 'containerFor' on the 1.72 + * annotation type symbol 's'. Report errors at position 1.73 + * 'pos'. 1.74 + * 1.75 + * @param s The (annotation)type declaration annotated with a @ContainerFor 1.76 + * @param containerFor the @ContainedFor on 's' 1.77 + * @param pos where to report errors 1.78 + */ 1.79 + public void validateContainerFor(TypeSymbol s, Attribute.Compound containerFor, DiagnosticPosition pos) { 1.80 + Assert.check(types.isSameType(containerFor.type, syms.containerForType)); 1.81 + 1.82 + Type t = null; 1.83 + List<Pair<MethodSymbol,Attribute>> l = containerFor.values; 1.84 + if (!l.isEmpty()) { 1.85 + Assert.check(l.head.fst.name == names.value); 1.86 + t = ((Attribute.Class)l.head.snd).getValue(); 1.87 + } 1.88 + 1.89 + if (t == null) { 1.90 + log.error(pos, "invalid.container.wrong.containerfor", s, containerFor); 1.91 + return; 1.92 + } 1.93 + 1.94 + validateHasContainedBy(t.tsym, s, pos); 1.95 + } 1.96 + 1.97 + private void validateHasContainedBy(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { 1.98 + Attribute.Compound containedBy = container.attribute(syms.containedByType.tsym); 1.99 + 1.100 + if (containedBy == null) { 1.101 + log.error(pos, "invalid.container.no.containedby", container, syms.containedByType.tsym); 1.102 + return; 1.103 + } 1.104 + 1.105 + Type t = null; 1.106 + List<Pair<MethodSymbol,Attribute>> l = containedBy.values; 1.107 + if (!l.isEmpty()) { 1.108 + Assert.check(l.head.fst.name == names.value); 1.109 + t = ((Attribute.Class)l.head.snd).getValue(); 1.110 + } 1.111 + 1.112 + if (t == null) { 1.113 + log.error(pos, "invalid.container.wrong.containedby", container, contained); 1.114 + return; 1.115 + } 1.116 + 1.117 + if (!types.isSameType(t, contained.type)) 1.118 + log.error(pos, "invalid.container.wrong.containedby", t.tsym, contained); 1.119 + } 1.120 + 1.121 + private void validateHasContainerFor(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { 1.122 + Attribute.Compound containerFor = container.attribute(syms.containerForType.tsym); 1.123 + 1.124 + if (containerFor == null) { 1.125 + log.error(pos, "invalid.container.no.containerfor", container, syms.containerForType.tsym); 1.126 + return; 1.127 + } 1.128 + 1.129 + Type t = null; 1.130 + List<Pair<MethodSymbol,Attribute>> l = containerFor.values; 1.131 + if (!l.isEmpty()) { 1.132 + Assert.check(l.head.fst.name == names.value); 1.133 + t = ((Attribute.Class)l.head.snd).getValue(); 1.134 + } 1.135 + 1.136 + if (t == null) { 1.137 + log.error(pos, "invalid.container.wrong.containerfor", container, contained); 1.138 + return; 1.139 + } 1.140 + 1.141 + if (!types.isSameType(t, contained.type)) 1.142 + log.error(pos, "invalid.container.wrong.containerfor", t.tsym, contained); 1.143 + } 1.144 + 1.145 + private void validateRetention(Symbol container, Symbol contained, DiagnosticPosition pos) { 1.146 + Attribute.RetentionPolicy containerRetention = types.getRetention(container); 1.147 + Attribute.RetentionPolicy containedRetention = types.getRetention(contained); 1.148 + 1.149 + boolean error = false; 1.150 + switch (containedRetention) { 1.151 + case RUNTIME: 1.152 + if (containerRetention != Attribute.RetentionPolicy.RUNTIME) { 1.153 + error = true; 1.154 + } 1.155 + break; 1.156 + case CLASS: 1.157 + if (containerRetention == Attribute.RetentionPolicy.SOURCE) { 1.158 + error = true; 1.159 + } 1.160 + } 1.161 + if (error ) { 1.162 + log.error(pos, "invalid.containedby.annotation.retention", 1.163 + container, containerRetention, 1.164 + contained, containedRetention); 1.165 + } 1.166 + } 1.167 + 1.168 + private void validateDocumented(Symbol container, Symbol contained, DiagnosticPosition pos) { 1.169 + if (contained.attribute(syms.documentedType.tsym) != null) { 1.170 + if (container.attribute(syms.documentedType.tsym) == null) { 1.171 + log.error(pos, "invalid.containedby.annotation.not.documented", container, contained); 1.172 + } 1.173 + } 1.174 + } 1.175 + 1.176 + private void validateInherited(Symbol container, Symbol contained, DiagnosticPosition pos) { 1.177 + if (contained.attribute(syms.inheritedType.tsym) != null) { 1.178 + if (container.attribute(syms.inheritedType.tsym) == null) { 1.179 + log.error(pos, "invalid.containedby.annotation.not.inherited", container, contained); 1.180 + } 1.181 + } 1.182 + } 1.183 + 1.184 + private void validateTarget(Symbol container, Symbol contained, DiagnosticPosition pos) { 1.185 + Attribute.Array containedTarget = getAttributeTargetAttribute(contained); 1.186 + 1.187 + // If contained has no Target, we are done 1.188 + if (containedTarget == null) { 1.189 + return; 1.190 + } 1.191 + 1.192 + // If contained has Target m1, container must have a Target 1.193 + // annotation, m2, and m2 must be a subset of m1. (This is 1.194 + // trivially true if contained has no target as per above). 1.195 + 1.196 + // contained has target, but container has not, error 1.197 + Attribute.Array containerTarget = getAttributeTargetAttribute(container); 1.198 + if (containerTarget == null) { 1.199 + log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained); 1.200 + return; 1.201 + } 1.202 + 1.203 + Set<Name> containerTargets = new HashSet<Name>(); 1.204 + for (Attribute app : containerTarget.values) { 1.205 + if (!(app instanceof Attribute.Enum)) { 1.206 + continue; // recovery 1.207 + } 1.208 + Attribute.Enum e = (Attribute.Enum)app; 1.209 + containerTargets.add(e.value.name); 1.210 + } 1.211 + 1.212 + Set<Name> containedTargets = new HashSet<Name>(); 1.213 + for (Attribute app : containedTarget.values) { 1.214 + if (!(app instanceof Attribute.Enum)) { 1.215 + continue; // recovery 1.216 + } 1.217 + Attribute.Enum e = (Attribute.Enum)app; 1.218 + containedTargets.add(e.value.name); 1.219 + } 1.220 + 1.221 + if (!isTargetSubset(containedTargets, containerTargets)) { 1.222 + log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained); 1.223 + } 1.224 + } 1.225 + 1.226 + /** Checks that t is a subset of s, with respect to ElementType 1.227 + * semantics, specifically {ANNOTATION_TYPE} is a subset of {TYPE} 1.228 + */ 1.229 + private boolean isTargetSubset(Set<Name> s, Set<Name> t) { 1.230 + // Check that all elements in t are present in s 1.231 + for (Name n2 : t) { 1.232 + boolean currentElementOk = false; 1.233 + for (Name n1 : s) { 1.234 + if (n1 == n2) { 1.235 + currentElementOk = true; 1.236 + break; 1.237 + } else if (n1 == names.TYPE && n2 == names.ANNOTATION_TYPE) { 1.238 + currentElementOk = true; 1.239 + break; 1.240 + } 1.241 + } 1.242 + if (!currentElementOk) 1.243 + return false; 1.244 + } 1.245 + return true; 1.246 + } 1.247 + 1.248 /** Is s a method symbol that overrides a method in a superclass? */ 1.249 boolean isOverrider(Symbol s) { 1.250 if (s.kind != MTH || s.isStatic()) 1.251 @@ -2461,12 +2667,10 @@ 1.252 1.253 /** Is the annotation applicable to the symbol? */ 1.254 boolean annotationApplicable(JCAnnotation a, Symbol s) { 1.255 - Attribute.Compound atTarget = 1.256 - a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym); 1.257 - if (atTarget == null) return true; 1.258 - Attribute atValue = atTarget.member(names.value); 1.259 - if (!(atValue instanceof Attribute.Array)) return true; // error recovery 1.260 - Attribute.Array arr = (Attribute.Array) atValue; 1.261 + Attribute.Array arr = getAttributeTargetAttribute(a.annotationType.type.tsym); 1.262 + if (arr == null) { 1.263 + return true; 1.264 + } 1.265 for (Attribute app : arr.values) { 1.266 if (!(app instanceof Attribute.Enum)) return true; // recovery 1.267 Attribute.Enum e = (Attribute.Enum) app; 1.268 @@ -2508,6 +2712,16 @@ 1.269 return false; 1.270 } 1.271 1.272 + 1.273 + Attribute.Array getAttributeTargetAttribute(Symbol s) { 1.274 + Attribute.Compound atTarget = 1.275 + s.attribute(syms.annotationTargetType.tsym); 1.276 + if (atTarget == null) return null; // ok, is applicable 1.277 + Attribute atValue = atTarget.member(names.value); 1.278 + if (!(atValue instanceof Attribute.Array)) return null; // error recovery 1.279 + return (Attribute.Array) atValue; 1.280 + } 1.281 + 1.282 /** Check an annotation value. 1.283 */ 1.284 public void validateAnnotation(JCAnnotation a) {