diff -r 3e32f68d2151 -r 99f5e5e97425 langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Tue Oct 15 22:15:35 2013 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Tue Oct 15 15:57:13 2013 -0700 @@ -3534,15 +3534,6 @@ Type normOuter = site; if (normOuter.hasTag(CLASS)) { normOuter = types.asEnclosingSuper(site, ownOuter.tsym); - if (site.isAnnotated()) { - // Propagate any type annotations. - // TODO: should asEnclosingSuper do this? - // Note that the type annotations in site will be updated - // by annotateType. Therefore, modify site instead - // of creating a new AnnotatedType. - ((AnnotatedType)site).underlyingType = normOuter; - normOuter = site; - } } if (normOuter == null) // perhaps from an import normOuter = types.erasure(ownOuter); @@ -3901,12 +3892,6 @@ } } owntype = new ClassType(clazzOuter, actuals, clazztype.tsym); - if (clazztype.isAnnotated()) { - // Use the same AnnotatedType, because it will have - // its annotations set later. - ((AnnotatedType)clazztype).underlyingType = owntype; - owntype = clazztype; - } } else { if (formals.length() != 0) { log.error(tree.pos(), "wrong.number.type.args", @@ -3972,9 +3957,7 @@ TypeVar typeVar = (TypeVar) tree.type; if (tree.annotations != null && tree.annotations.nonEmpty()) { - AnnotatedType antype = new AnnotatedType(typeVar); - annotateType(antype, tree.annotations); - tree.type = antype; + annotateType(tree, tree.annotations); } if (!typeVar.bound.isErroneous()) { @@ -4074,26 +4057,28 @@ public void visitAnnotatedType(JCAnnotatedType tree) { Type underlyingType = attribType(tree.getUnderlyingType(), env); this.attribAnnotationTypes(tree.annotations, env); - AnnotatedType antype = new AnnotatedType(underlyingType); - annotateType(antype, tree.annotations); - result = tree.type = antype; + annotateType(tree, tree.annotations); + result = tree.type = underlyingType; } /** * Apply the annotations to the particular type. */ - public void annotateType(final AnnotatedType type, final List annotations) { - if (annotations.isEmpty()) - return; + public void annotateType(final JCTree tree, final List annotations) { + // Callers ensure this. + // Assert.check(annotations != null && annotations.nonEmpty()); annotate.typeAnnotation(new Annotate.Worker() { @Override public String toString() { - return "annotate " + annotations + " onto " + type; + return "annotate " + annotations + " onto " + tree; } @Override public void run() { List compounds = fromAnnotations(annotations); - type.typeAnnotations = compounds; + if (annotations.size() == compounds.size()) { + // All annotations were successfully converted into compounds + tree.type = tree.type.unannotatedType().annotatedType(compounds); + } } }); } @@ -4432,17 +4417,18 @@ private final class TypeAnnotationsValidator extends TreeScanner { private final boolean sigOnly; - private boolean checkAllAnnotations = false; - public TypeAnnotationsValidator(boolean sigOnly) { this.sigOnly = sigOnly; } public void visitAnnotation(JCAnnotation tree) { - if (tree.hasTag(TYPE_ANNOTATION) || checkAllAnnotations) { - chk.validateTypeAnnotation(tree, false); + chk.validateTypeAnnotation(tree, false); + super.visitAnnotation(tree); + } + public void visitAnnotatedType(JCAnnotatedType tree) { + if (!tree.underlyingType.type.isErroneous()) { + super.visitAnnotatedType(tree); } - super.visitAnnotation(tree); } public void visitTypeParameter(JCTypeParameter tree) { chk.validateTypeAnnotations(tree.annotations, true); @@ -4475,7 +4461,7 @@ } public void visitVarDef(final JCVariableDecl tree) { if (tree.sym != null && tree.sym.type != null) - validateAnnotatedType(tree, tree.sym.type); + validateAnnotatedType(tree.vartype, tree.sym.type); scan(tree.mods); scan(tree.vartype); if (!sigOnly) { @@ -4493,27 +4479,13 @@ super.visitTypeTest(tree); } public void visitNewClass(JCNewClass tree) { - if (tree.clazz.hasTag(ANNOTATED_TYPE)) { - boolean prevCheck = this.checkAllAnnotations; - try { - this.checkAllAnnotations = true; - scan(((JCAnnotatedType)tree.clazz).annotations); - } finally { - this.checkAllAnnotations = prevCheck; - } - } + if (tree.clazz.type != null) + validateAnnotatedType(tree.clazz, tree.clazz.type); super.visitNewClass(tree); } public void visitNewArray(JCNewArray tree) { - if (tree.elemtype != null && tree.elemtype.hasTag(ANNOTATED_TYPE)) { - boolean prevCheck = this.checkAllAnnotations; - try { - this.checkAllAnnotations = true; - scan(((JCAnnotatedType)tree.elemtype).annotations); - } finally { - this.checkAllAnnotations = prevCheck; - } - } + if (tree.elemtype != null && tree.elemtype.type != null) + validateAnnotatedType(tree.elemtype, tree.elemtype.type); super.visitNewArray(tree); } @@ -4549,21 +4521,95 @@ * can occur. */ private void validateAnnotatedType(final JCTree errtree, final Type type) { - if (type.getEnclosingType() != null && - type != type.getEnclosingType()) { - validateEnclosingAnnotatedType(errtree, type.getEnclosingType()); - } - for (Type targ : type.getTypeArguments()) { - validateAnnotatedType(errtree, targ); + // System.out.println("Attr.validateAnnotatedType: " + errtree + " type: " + type); + + if (type.isPrimitiveOrVoid()) { + return; } - } - private void validateEnclosingAnnotatedType(final JCTree errtree, final Type type) { - validateAnnotatedType(errtree, type); - if (type.tsym != null && - type.tsym.isStatic() && - type.getAnnotationMirrors().nonEmpty()) { - // Enclosing static classes cannot have type annotations. - log.error(errtree.pos(), "cant.annotate.static.class"); + + JCTree enclTr = errtree; + Type enclTy = type; + + boolean repeat = true; + while (repeat) { + if (enclTr.hasTag(TYPEAPPLY)) { + List tyargs = enclTy.getTypeArguments(); + List trargs = ((JCTypeApply)enclTr).getTypeArguments(); + if (trargs.length() > 0) { + // Nothing to do for diamonds + if (tyargs.length() == trargs.length()) { + for (int i = 0; i < tyargs.length(); ++i) { + validateAnnotatedType(trargs.get(i), tyargs.get(i)); + } + } + // If the lengths don't match, it's either a diamond + // or some nested type that redundantly provides + // type arguments in the tree. + } + + // Look at the clazz part of a generic type + enclTr = ((JCTree.JCTypeApply)enclTr).clazz; + } + + if (enclTr.hasTag(SELECT)) { + enclTr = ((JCTree.JCFieldAccess)enclTr).getExpression(); + if (enclTy != null && + !enclTy.hasTag(NONE)) { + enclTy = enclTy.getEnclosingType(); + } + } else if (enclTr.hasTag(ANNOTATED_TYPE)) { + JCAnnotatedType at = (JCTree.JCAnnotatedType) enclTr; + if (enclTy == null || + enclTy.hasTag(NONE)) { + if (at.getAnnotations().size() == 1) { + log.error(at.underlyingType.pos(), "cant.type.annotate.scoping.1", at.getAnnotations().head.attribute); + } else { + ListBuffer comps = new ListBuffer(); + for (JCAnnotation an : at.getAnnotations()) { + comps.add(an.attribute); + } + log.error(at.underlyingType.pos(), "cant.type.annotate.scoping", comps.toList()); + } + repeat = false; + } + enclTr = at.underlyingType; + // enclTy doesn't need to be changed + } else if (enclTr.hasTag(IDENT)) { + repeat = false; + } else if (enclTr.hasTag(JCTree.Tag.WILDCARD)) { + JCWildcard wc = (JCWildcard) enclTr; + if (wc.getKind() == JCTree.Kind.EXTENDS_WILDCARD) { + validateAnnotatedType(wc.getBound(), ((WildcardType)enclTy.unannotatedType()).getExtendsBound()); + } else if (wc.getKind() == JCTree.Kind.SUPER_WILDCARD) { + validateAnnotatedType(wc.getBound(), ((WildcardType)enclTy.unannotatedType()).getSuperBound()); + } else { + // Nothing to do for UNBOUND + } + repeat = false; + } else if (enclTr.hasTag(TYPEARRAY)) { + JCArrayTypeTree art = (JCArrayTypeTree) enclTr; + validateAnnotatedType(art.getType(), ((ArrayType)enclTy.unannotatedType()).getComponentType()); + repeat = false; + } else if (enclTr.hasTag(TYPEUNION)) { + JCTypeUnion ut = (JCTypeUnion) enclTr; + for (JCTree t : ut.getTypeAlternatives()) { + validateAnnotatedType(t, t.type); + } + repeat = false; + } else if (enclTr.hasTag(TYPEINTERSECTION)) { + JCTypeIntersection it = (JCTypeIntersection) enclTr; + for (JCTree t : it.getBounds()) { + validateAnnotatedType(t, t.type); + } + repeat = false; + } else if (enclTr.getKind() == JCTree.Kind.PRIMITIVE_TYPE) { + // This happens in test TargetTypeTest52.java + // Is there anything to do? + repeat = false; + } else { + Assert.error("Unexpected tree: " + enclTr + " with kind: " + enclTr.getKind() + + " within: "+ errtree + " with kind: " + errtree.getKind()); + } } } };