# HG changeset patch # User lana # Date 1266219580 28800 # Node ID d9cd5b8286e44f3baf90da290cd295433e21c05a # Parent 2edcb5dc642d928810512f7c979252752588d59f# Parent 56a46d079264b2aa03780b544b4811c1c10cdc63 Merge diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/classfile/ClassWriter.java --- a/src/share/classes/com/sun/tools/classfile/ClassWriter.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/classfile/ClassWriter.java Sun Feb 14 23:39:40 2010 -0800 @@ -744,6 +744,7 @@ out.writeByte(p.type_index); break; case CLASS_LITERAL: + case CLASS_LITERAL_GENERIC_OR_ARRAY: out.writeShort(p.offset); break; // method parameter: not specified diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/classfile/ExtendedAnnotation.java --- a/src/share/classes/com/sun/tools/classfile/ExtendedAnnotation.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/classfile/ExtendedAnnotation.java Sun Feb 14 23:39:40 2010 -0800 @@ -123,11 +123,14 @@ // Class extends and implements clauses case CLASS_EXTENDS: case CLASS_EXTENDS_GENERIC_OR_ARRAY: - position.type_index = cr.readUnsignedByte(); + int in = cr.readUnsignedShort(); + if (in == 0xFFFF) + in = -1; + position.type_index = in; break; // throws case THROWS: - position.type_index = cr.readUnsignedByte(); + position.type_index = cr.readUnsignedShort(); break; case CLASS_LITERAL: case CLASS_LITERAL_GENERIC_OR_ARRAY: @@ -213,11 +216,11 @@ // Class extends and implements clauses case CLASS_EXTENDS: case CLASS_EXTENDS_GENERIC_OR_ARRAY: - n += 1; // type_index + n += 2; // type_index break; // throws case THROWS: - n += 1; // type_index + n += 2; // type_index break; case CLASS_LITERAL: case CLASS_LITERAL_GENERIC_OR_ARRAY: @@ -264,18 +267,18 @@ public int offset = -1; // For locals. - public int[] lvarOffset = new int[] { -1 }; - public int[] lvarLength = new int[] { -1 }; - public int[] lvarIndex = new int[] { -1 }; + public int[] lvarOffset = null; + public int[] lvarLength = null; + public int[] lvarIndex = null; // For type parameter bound - public int bound_index = -1; + public int bound_index = Integer.MIN_VALUE; // For type parameter and method parameter - public int parameter_index = -1; + public int parameter_index = Integer.MIN_VALUE; // For class extends, implements, and throws classes - public int type_index = -2; + public int type_index = Integer.MIN_VALUE; // For wildcards public Position wildcard_position = null; diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/code/Flags.java --- a/src/share/classes/com/sun/tools/javac/code/Flags.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/code/Flags.java Sun Feb 14 23:39:40 2010 -0800 @@ -113,6 +113,7 @@ public static final int ENUM = 1<<14; public static final int StandardFlags = 0x0fff; + public static final int ModifierFlags = StandardFlags & ~INTERFACE; // Because the following access flags are overloaded with other // bit positions, we translate them when reading and writing class diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/code/Symbol.java --- a/src/share/classes/com/sun/tools/javac/code/Symbol.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java Sun Feb 14 23:39:40 2010 -0800 @@ -657,6 +657,11 @@ public List getAnnotationMirrors() { if (completer != null) complete(); + if (package_info != null && package_info.completer != null) { + package_info.complete(); + if (attributes_field.isEmpty()) + attributes_field = package_info.attributes_field; + } assert attributes_field != null; return attributes_field; } diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java --- a/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java Sun Feb 14 23:39:40 2010 -0800 @@ -49,18 +49,18 @@ public int offset = -1; // For locals. arrays same length - public int[] lvarOffset = new int[] { -1 }; - public int[] lvarLength = new int[] { -1 }; - public int[] lvarIndex = new int[] { -1 }; + public int[] lvarOffset = null; + public int[] lvarLength = null; + public int[] lvarIndex = null; // For type parameter bound - public int bound_index = -1; + public int bound_index = Integer.MIN_VALUE; // For type parameter and method parameter - public int parameter_index = -1; + public int parameter_index = Integer.MIN_VALUE; // For class extends, implements, and throws classes - public int type_index = -2; + public int type_index = Integer.MIN_VALUE; // For wildcards public TypeAnnotationPosition wildcard_position = null; @@ -139,6 +139,7 @@ sb.append(type_index); break; case CLASS_LITERAL: + case CLASS_LITERAL_GENERIC_OR_ARRAY: sb.append(", offset = "); sb.append(offset); break; diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java Sun Feb 14 23:39:40 2010 -0800 @@ -0,0 +1,400 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tools.javac.code; + +import javax.lang.model.element.ElementKind; + +import com.sun.tools.javac.code.Symbol.VarSymbol; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.tree.JCTree.*; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.List; +import com.sun.tools.javac.util.ListBuffer; + +/** + * Contains operations specific to processing type annotations + */ +public class TypeAnnotations { + private static final Context.Key key + = new Context.Key(); + + public static TypeAnnotations instance(Context context) { + TypeAnnotations instance = context.get(key); + if (instance == null) + instance = new TypeAnnotations(context); + return instance; + } + + protected TypeAnnotations(Context context) { + context.put(key, this); + } + + public void taFillAndLift(JCClassDecl tree, boolean visitBodies) { + new TypeAnnotationPositions().scan(tree); + new TypeAnnotationLift().scan(tree); + } + + private static class TypeAnnotationPositions extends TreeScanner { + + private ListBuffer frames = ListBuffer.lb(); + private void push(JCTree t) { frames = frames.prepend(t); } + private JCTree pop() { return frames.next(); } + private JCTree peek2() { return frames.toList().tail.head; } + + @Override + public void scan(JCTree tree) { + push(tree); + super.scan(tree); + pop(); + } + + private boolean inClass = false; + + @Override + public void visitClassDef(JCClassDecl tree) { + if (!inClass) { + // Do not recurse into nested and inner classes since + // TransTypes.visitClassDef makes an invocation for each class + // separately. + inClass = true; + try { + super.visitClassDef(tree); + } finally { + inClass = false; + } + } + } + + private TypeAnnotationPosition resolveFrame(JCTree tree, JCTree frame, + List path, TypeAnnotationPosition p) { + switch (frame.getKind()) { + case TYPE_CAST: + p.type = TargetType.TYPECAST; + p.pos = frame.pos; + return p; + + case INSTANCE_OF: + p.type = TargetType.INSTANCEOF; + p.pos = frame.pos; + return p; + + case NEW_CLASS: + p.type = TargetType.NEW; + p.pos = frame.pos; + return p; + + case NEW_ARRAY: + p.type = TargetType.NEW; + p.pos = frame.pos; + return p; + + case CLASS: + p.pos = frame.pos; + if (((JCClassDecl)frame).extending == tree) { + p.type = TargetType.CLASS_EXTENDS; + p.type_index = -1; + } else if (((JCClassDecl)frame).implementing.contains(tree)) { + p.type = TargetType.CLASS_EXTENDS; + p.type_index = ((JCClassDecl)frame).implementing.indexOf(tree); + } else if (((JCClassDecl)frame).typarams.contains(tree)) { + p.type = TargetType.CLASS_TYPE_PARAMETER; + p.parameter_index = ((JCClassDecl)frame).typarams.indexOf(tree); + } else + throw new AssertionError(); + return p; + + case METHOD: { + JCMethodDecl frameMethod = (JCMethodDecl)frame; + p.pos = frame.pos; + if (frameMethod.receiverAnnotations.contains(tree)) + p.type = TargetType.METHOD_RECEIVER; + else if (frameMethod.thrown.contains(tree)) { + p.type = TargetType.THROWS; + p.type_index = frameMethod.thrown.indexOf(tree); + } else if (((JCMethodDecl)frame).restype == tree) { + p.type = TargetType.METHOD_RETURN_GENERIC_OR_ARRAY; + } else if (frameMethod.typarams.contains(tree)) { + p.type = TargetType.METHOD_TYPE_PARAMETER; + p.parameter_index = frameMethod.typarams.indexOf(tree); + } else + throw new AssertionError(); + return p; + } + case MEMBER_SELECT: { + JCFieldAccess fieldFrame = (JCFieldAccess)frame; + if ("class".contentEquals(fieldFrame.name)) { + p.type = TargetType.CLASS_LITERAL; + p.pos = TreeInfo.innermostType(fieldFrame.selected).pos; + } else + throw new AssertionError(); + return p; + } + case PARAMETERIZED_TYPE: { + TypeAnnotationPosition nextP; + if (((JCTypeApply)frame).clazz == tree) + nextP = p; // generic: RAW; noop + else if (((JCTypeApply)frame).arguments.contains(tree)) + p.location = p.location.prepend( + ((JCTypeApply)frame).arguments.indexOf(tree)); + else + throw new AssertionError(); + + List newPath = path.tail; + return resolveFrame(newPath.head, newPath.tail.head, newPath, p); + } + + case ARRAY_TYPE: { + p.location = p.location.prepend(0); + List newPath = path.tail; + return resolveFrame(newPath.head, newPath.tail.head, newPath, p); + } + + case TYPE_PARAMETER: + if (path.tail.tail.head.getTag() == JCTree.CLASSDEF) { + JCClassDecl clazz = (JCClassDecl)path.tail.tail.head; + p.type = TargetType.CLASS_TYPE_PARAMETER_BOUND; + p.parameter_index = clazz.typarams.indexOf(path.tail.head); + p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree); + } else if (path.tail.tail.head.getTag() == JCTree.METHODDEF) { + JCMethodDecl method = (JCMethodDecl)path.tail.tail.head; + p.type = TargetType.METHOD_TYPE_PARAMETER_BOUND; + p.parameter_index = method.typarams.indexOf(path.tail.head); + p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree); + } else + throw new AssertionError(); + p.pos = frame.pos; + return p; + + case VARIABLE: + VarSymbol v = ((JCVariableDecl)frame).sym; + p.pos = frame.pos; + switch (v.getKind()) { + case LOCAL_VARIABLE: + p.type = TargetType.LOCAL_VARIABLE; break; + case FIELD: + p.type = TargetType.FIELD_GENERIC_OR_ARRAY; break; + case PARAMETER: + p.type = TargetType.METHOD_PARAMETER_GENERIC_OR_ARRAY; + p.parameter_index = methodParamIndex(path, frame); + break; + default: throw new AssertionError(); + } + return p; + + case ANNOTATED_TYPE: { + List newPath = path.tail; + return resolveFrame(newPath.head, newPath.tail.head, + newPath, p); + } + + case METHOD_INVOCATION: { + JCMethodInvocation invocation = (JCMethodInvocation)frame; + if (!invocation.typeargs.contains(tree)) + throw new AssertionError("{" + tree + "} is not an argument in the invocation: " + invocation); + p.type = TargetType.METHOD_TYPE_ARGUMENT; + p.pos = invocation.pos; + p.type_index = invocation.typeargs.indexOf(tree); + return p; + } + + case EXTENDS_WILDCARD: + case SUPER_WILDCARD: { + p.type = TargetType.WILDCARD_BOUND; + List newPath = path.tail; + + TypeAnnotationPosition wildcard = + resolveFrame(newPath.head, newPath.tail.head, newPath, + new TypeAnnotationPosition()); + if (!wildcard.location.isEmpty()) + wildcard.type = wildcard.type.getGenericComplement(); + p.wildcard_position = wildcard; + p.pos = frame.pos; + return p; + } + } + return p; + } + + private void setTypeAnnotationPos(List annotations, TypeAnnotationPosition position) { + for (JCTypeAnnotation anno : annotations) { + anno.annotation_position = position; + anno.attribute_field.position = position; + } + } + + @Override + public void visitNewArray(JCNewArray tree) { + findPosition(tree, tree, tree.annotations); + int dimAnnosCount = tree.dimAnnotations.size(); + + // handle annotations associated with dimentions + for (int i = 0; i < dimAnnosCount; ++i) { + TypeAnnotationPosition p = new TypeAnnotationPosition(); + p.type = TargetType.NEW_GENERIC_OR_ARRAY; + p.pos = tree.pos; + p.location = p.location.append(i); + setTypeAnnotationPos(tree.dimAnnotations.get(i), p); + } + + // handle "free" annotations + int i = dimAnnosCount == 0 ? 0 : dimAnnosCount - 1; + JCExpression elemType = tree.elemtype; + while (elemType != null) { + if (elemType.getTag() == JCTree.ANNOTATED_TYPE) { + JCAnnotatedType at = (JCAnnotatedType)elemType; + TypeAnnotationPosition p = new TypeAnnotationPosition(); + p.type = TargetType.NEW_GENERIC_OR_ARRAY; + p.pos = tree.pos; + p.location = p.location.append(i); + setTypeAnnotationPos(at.annotations, p); + elemType = at.underlyingType; + } else if (elemType.getTag() == JCTree.TYPEARRAY) { + ++i; + elemType = ((JCArrayTypeTree)elemType).elemtype; + } else + break; + } + + // find annotations locations of initializer elements + scan(tree.elems); + } + + @Override + public void visitAnnotatedType(JCAnnotatedType tree) { + findPosition(tree, peek2(), tree.annotations); + super.visitAnnotatedType(tree); + } + + @Override + public void visitMethodDef(JCMethodDecl tree) { + TypeAnnotationPosition p = new TypeAnnotationPosition(); + p.type = TargetType.METHOD_RECEIVER; + setTypeAnnotationPos(tree.receiverAnnotations, p); + super.visitMethodDef(tree); + } + @Override + public void visitTypeParameter(JCTypeParameter tree) { + findPosition(tree, peek2(), tree.annotations); + super.visitTypeParameter(tree); + } + + void findPosition(JCTree tree, JCTree frame, List annotations) { + if (!annotations.isEmpty()) { + TypeAnnotationPosition p = + resolveFrame(tree, frame, frames.toList(), + new TypeAnnotationPosition()); + if (!p.location.isEmpty()) + p.type = p.type.getGenericComplement(); + setTypeAnnotationPos(annotations, p); + } + } + + private int methodParamIndex(List path, JCTree param) { + List curr = path; + if (curr.head != param) + curr = path.tail; + JCMethodDecl method = (JCMethodDecl)curr.tail.head; + return method.params.indexOf(param); + } + } + + private static class TypeAnnotationLift extends TreeScanner { + List recordedTypeAnnotations = List.nil(); + + boolean isInner = false; + @Override + public void visitClassDef(JCClassDecl tree) { + if (isInner) { + // tree is an inner class tree. stop now. + // TransTypes.visitClassDef makes an invocation for each class + // separately. + return; + } + isInner = true; + List prevTAs = recordedTypeAnnotations; + recordedTypeAnnotations = List.nil(); + try { + super.visitClassDef(tree); + } finally { + tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations); + recordedTypeAnnotations = prevTAs; + } + } + + @Override + public void visitMethodDef(JCMethodDecl tree) { + List prevTAs = recordedTypeAnnotations; + recordedTypeAnnotations = List.nil(); + try { + super.visitMethodDef(tree); + } finally { + tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations); + recordedTypeAnnotations = prevTAs; + } + } + + @Override + public void visitVarDef(JCVariableDecl tree) { + List prevTAs = recordedTypeAnnotations; + recordedTypeAnnotations = List.nil(); + ElementKind kind = tree.sym.getKind(); + if (kind == ElementKind.LOCAL_VARIABLE && tree.mods.annotations.nonEmpty()) { + // need to lift the annotations + TypeAnnotationPosition position = new TypeAnnotationPosition(); + position.pos = tree.pos; + position.type = TargetType.LOCAL_VARIABLE; + for (Attribute.Compound attribute : tree.sym.attributes_field) { + Attribute.TypeCompound tc = + new Attribute.TypeCompound(attribute.type, attribute.values, position); + recordedTypeAnnotations = recordedTypeAnnotations.append(tc); + } + } + try { + super.visitVarDef(tree); + } finally { + if (kind.isField() || kind == ElementKind.LOCAL_VARIABLE) + tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations); + recordedTypeAnnotations = kind.isField() ? prevTAs : prevTAs.appendList(recordedTypeAnnotations); + } + } + + @Override + public void visitApply(JCMethodInvocation tree) { + scan(tree.meth); + scan(tree.typeargs); + scan(tree.args); + } + + public void visitAnnotation(JCAnnotation tree) { + if (tree instanceof JCTypeAnnotation) + recordedTypeAnnotations = recordedTypeAnnotations.append(((JCTypeAnnotation)tree).attribute_field); + super.visitAnnotation(tree); + } + } + +} diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/comp/Check.java --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Sun Feb 14 23:39:40 2010 -0800 @@ -2047,7 +2047,7 @@ Symbol m = TreeInfo.symbol(assign.lhs); if (m == null || m.type.isErroneous()) continue; if (!members.remove(m)) - log.error(arg.pos(), "duplicate.annotation.member.value", + log.error(assign.lhs.pos(), "duplicate.annotation.member.value", m.name, a.type); if (assign.rhs.getTag() == ANNOTATION) validateAnnotation((JCAnnotation)assign.rhs); diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/comp/Enter.java --- a/src/share/classes/com/sun/tools/javac/comp/Enter.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/comp/Enter.java Sun Feb 14 23:39:40 2010 -0800 @@ -100,6 +100,7 @@ MemberEnter memberEnter; Types types; Lint lint; + Names names; JavaFileManager fileManager; private final Todo todo; @@ -123,6 +124,7 @@ types = Types.instance(context); annotate = Annotate.instance(context); lint = Lint.instance(context); + names = Names.instance(context); predefClassDef = make.ClassDef( make.Modifiers(PUBLIC), @@ -308,6 +310,17 @@ } } } + + for (Symbol q = tree.packge; q != null && q.kind == PCK; q = q.owner) + q.flags_field |= EXISTS; + + Name name = names.package_info; + ClassSymbol c = reader.enterClass(name, tree.packge); + c.flatname = names.fromString(tree.packge + "." + name); + c.sourcefile = tree.sourcefile; + c.completer = null; + c.members_field = new Scope(c); + tree.packge.package_info = c; } classEnter(tree.defs, env); if (addEnv) { diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/comp/Lower.java --- a/src/share/classes/com/sun/tools/javac/comp/Lower.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java Sun Feb 14 23:39:40 2010 -0800 @@ -1994,19 +1994,14 @@ tree.packageAnnotations), name, List.nil(), null, List.nil(), List.nil()); - ClassSymbol c = reader.enterClass(name, tree.packge); - c.flatname = names.fromString(tree.packge + "." + name); - c.sourcefile = tree.sourcefile; - c.completer = null; - c.members_field = new Scope(c); - c.flags_field = flags; + ClassSymbol c = tree.packge.package_info; + c.flags_field |= flags; c.attributes_field = tree.packge.attributes_field; ClassType ctype = (ClassType) c.type; ctype.supertype_field = syms.objectType; ctype.interfaces_field = List.nil(); packageAnnotationsClass.sym = c; - translated.append(packageAnnotationsClass); } } diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/comp/MemberEnter.java --- a/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Sun Feb 14 23:39:40 2010 -0800 @@ -1065,11 +1065,6 @@ super.visitNewArray(tree); } @Override - public void visitApply(JCMethodInvocation tree) { - super.visitApply(tree); - scan(tree.typeargs); - } - @Override public void visitMethodDef(JCMethodDecl tree) { annotate(tree, tree.receiverAnnotations); super.visitMethodDef(tree); diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/comp/TransTypes.java --- a/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Sun Feb 14 23:39:40 2010 -0800 @@ -61,8 +61,6 @@ return instance; } - private boolean debugJSR308; - private Names names; private Log log; private Symtab syms; @@ -71,6 +69,7 @@ private boolean allowEnums; private Types types; private final Resolve resolve; + private final TypeAnnotations typeAnnotations; /** * Flag to indicate whether or not to generate bridge methods. @@ -92,7 +91,7 @@ types = Types.instance(context); make = TreeMaker.instance(context); resolve = Resolve.instance(context); - debugJSR308 = Options.instance(context).get("TA:trans") != null; + typeAnnotations = TypeAnnotations.instance(context); } /** A hashtable mapping bridge methods to the methods they override after @@ -440,8 +439,7 @@ } public void visitClassDef(JCClassDecl tree) { - new TypeAnnotationPositions().scan(tree); - new TypeAnnotationLift().scan(tree); + typeAnnotations.taFillAndLift(tree, true); translateClass(tree.sym); result = tree; } @@ -801,359 +799,4 @@ pt = null; return translate(cdef, null); } - - private class TypeAnnotationPositions extends TreeScanner { - - private ListBuffer frames = ListBuffer.lb(); - private void push(JCTree t) { frames = frames.prepend(t); } - private JCTree pop() { return frames.next(); } - private JCTree peek() { return frames.first(); } - private JCTree peek2() { return frames.toList().tail.head; } - - @Override - public void scan(JCTree tree) { - push(tree); - super.scan(tree); - pop(); - } - - private boolean inClass = false; - - @Override - public void visitClassDef(JCClassDecl tree) { - if (!inClass) { - // Do not recurse into nested and inner classes since - // TransTypes.visitClassDef makes an invocation for each class - // separately. - inClass = true; - try { - super.visitClassDef(tree); - } finally { - inClass = false; - } - } - } - - private TypeAnnotationPosition resolveFrame(JCTree tree, JCTree frame, - List path, TypeAnnotationPosition p) { - switch (frame.getKind()) { - case TYPE_CAST: - p.type = TargetType.TYPECAST; - p.pos = frame.pos; - return p; - - case INSTANCE_OF: - p.type = TargetType.INSTANCEOF; - p.pos = frame.pos; - return p; - - case NEW_CLASS: - p.type = TargetType.NEW; - p.pos = frame.pos; - return p; - - case NEW_ARRAY: - p.type = TargetType.NEW; - p.pos = frame.pos; - return p; - - case CLASS: - p.pos = frame.pos; - if (((JCClassDecl)frame).extending == tree) { - p.type = TargetType.CLASS_EXTENDS; - p.type_index = -1; - } else if (((JCClassDecl)frame).implementing.contains(tree)) { - p.type = TargetType.CLASS_EXTENDS; - p.type_index = ((JCClassDecl)frame).implementing.indexOf(tree); - } else if (((JCClassDecl)frame).typarams.contains(tree)) { - p.type = TargetType.CLASS_TYPE_PARAMETER; - p.parameter_index = ((JCClassDecl)frame).typarams.indexOf(tree); - } else - throw new AssertionError(); - return p; - - case METHOD: { - JCMethodDecl frameMethod = (JCMethodDecl)frame; - p.pos = frame.pos; - if (frameMethod.receiverAnnotations.contains(tree)) - p.type = TargetType.METHOD_RECEIVER; - else if (frameMethod.thrown.contains(tree)) { - p.type = TargetType.THROWS; - p.type_index = frameMethod.thrown.indexOf(tree); - } else if (((JCMethodDecl)frame).restype == tree) { - p.type = TargetType.METHOD_RETURN_GENERIC_OR_ARRAY; - } else if (frameMethod.typarams.contains(tree)) { - p.type = TargetType.METHOD_TYPE_PARAMETER; - p.parameter_index = frameMethod.typarams.indexOf(tree); - } else - throw new AssertionError(); - return p; - } - case MEMBER_SELECT: { - JCFieldAccess fieldFrame = (JCFieldAccess)frame; - if (fieldFrame.name == names._class) { - p.type = TargetType.CLASS_LITERAL; - if (fieldFrame.selected instanceof JCAnnotatedType) { - p.pos = TreeInfo.typeIn(fieldFrame).pos; - } else if (fieldFrame.selected instanceof JCArrayTypeTree) { - p.pos = fieldFrame.selected.pos; - } - } else - throw new AssertionError(); - return p; - } - case PARAMETERIZED_TYPE: { - TypeAnnotationPosition nextP; - if (((JCTypeApply)frame).clazz == tree) - nextP = p; // generic: RAW; noop - else if (((JCTypeApply)frame).arguments.contains(tree)) - p.location = p.location.prepend( - ((JCTypeApply)frame).arguments.indexOf(tree)); - else - throw new AssertionError(); - - List newPath = path.tail; - return resolveFrame(newPath.head, newPath.tail.head, newPath, p); - } - - case ARRAY_TYPE: { - p.location = p.location.prepend(0); - List newPath = path.tail; - return resolveFrame(newPath.head, newPath.tail.head, newPath, p); - } - - case TYPE_PARAMETER: - if (path.tail.tail.head.getTag() == JCTree.CLASSDEF) { - JCClassDecl clazz = (JCClassDecl)path.tail.tail.head; - p.type = TargetType.CLASS_TYPE_PARAMETER_BOUND; - p.parameter_index = clazz.typarams.indexOf(path.tail.head); - p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree); - } else if (path.tail.tail.head.getTag() == JCTree.METHODDEF) { - JCMethodDecl method = (JCMethodDecl)path.tail.tail.head; - p.type = TargetType.METHOD_TYPE_PARAMETER_BOUND; - p.parameter_index = method.typarams.indexOf(path.tail.head); - p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree); - } else - throw new AssertionError(); - p.pos = frame.pos; - return p; - - case VARIABLE: - VarSymbol v = ((JCVariableDecl)frame).sym; - p.pos = frame.pos; - switch (v.getKind()) { - case LOCAL_VARIABLE: - p.type = TargetType.LOCAL_VARIABLE; break; - case FIELD: - p.type = TargetType.FIELD_GENERIC_OR_ARRAY; break; - case PARAMETER: - p.type = TargetType.METHOD_PARAMETER_GENERIC_OR_ARRAY; - p.parameter_index = methodParamIndex(path, frame); - break; - default: throw new AssertionError(); - } - return p; - - case ANNOTATED_TYPE: { - List newPath = path.tail; - return resolveFrame(newPath.head, newPath.tail.head, - newPath, p); - } - - case METHOD_INVOCATION: { - JCMethodInvocation invocation = (JCMethodInvocation)frame; - if (!invocation.typeargs.contains(tree)) - throw new AssertionError("{" + tree + "} is not an argument in the invocation: " + invocation); - p.type = TargetType.METHOD_TYPE_ARGUMENT; - p.pos = invocation.pos; - p.type_index = invocation.typeargs.indexOf(tree); - return p; - } - - case EXTENDS_WILDCARD: - case SUPER_WILDCARD: { - p.type = TargetType.WILDCARD_BOUND; - List newPath = path.tail; - - TypeAnnotationPosition wildcard = - resolveFrame(newPath.head, newPath.tail.head, newPath, - new TypeAnnotationPosition()); - if (!wildcard.location.isEmpty()) - wildcard.type = wildcard.type.getGenericComplement(); - p.wildcard_position = wildcard; - p.pos = frame.pos; - return p; - } - } - return p; - } - - @Override - public void visitApply(JCMethodInvocation tree) { - scan(tree.meth); - scan(tree.typeargs); - scan(tree.args); - } - - private void setTypeAnnotationPos(List annotations, TypeAnnotationPosition position) { - for (JCTypeAnnotation anno : annotations) { - anno.annotation_position = position; - anno.attribute_field.position = position; - } - } - - @Override - public void visitNewArray(JCNewArray tree) { - findPosition(tree, tree, tree.annotations); - int dimAnnosCount = tree.dimAnnotations.size(); - - // handle annotations associated with dimentions - for (int i = 0; i < dimAnnosCount; ++i) { - TypeAnnotationPosition p = new TypeAnnotationPosition(); - p.type = TargetType.NEW_GENERIC_OR_ARRAY; - p.pos = tree.pos; - p.location = p.location.append(i); - setTypeAnnotationPos(tree.dimAnnotations.get(i), p); - } - - // handle "free" annotations - int i = dimAnnosCount == 0 ? 0 : dimAnnosCount - 1; - JCExpression elemType = tree.elemtype; - while (elemType != null) { - if (elemType.getTag() == JCTree.ANNOTATED_TYPE) { - JCAnnotatedType at = (JCAnnotatedType)elemType; - TypeAnnotationPosition p = new TypeAnnotationPosition(); - p.type = TargetType.NEW_GENERIC_OR_ARRAY; - p.pos = tree.pos; - p.location = p.location.append(i); - setTypeAnnotationPos(at.annotations, p); - elemType = at.underlyingType; - } else if (elemType.getTag() == JCTree.TYPEARRAY) { - ++i; - elemType = ((JCArrayTypeTree)elemType).elemtype; - } else - break; - } - - // find annotations locations of initializer elements - scan(tree.elems); - } - - @Override - public void visitAnnotatedType(JCAnnotatedType tree) { - findPosition(tree, peek2(), tree.annotations); - super.visitAnnotatedType(tree); - } - - @Override - public void visitMethodDef(JCMethodDecl tree) { - TypeAnnotationPosition p = new TypeAnnotationPosition(); - p.type = TargetType.METHOD_RECEIVER; - setTypeAnnotationPos(tree.receiverAnnotations, p); - super.visitMethodDef(tree); - } - @Override - public void visitTypeParameter(JCTypeParameter tree) { - findPosition(tree, peek2(), tree.annotations); - super.visitTypeParameter(tree); - } - - void findPosition(JCTree tree, JCTree frame, List annotations) { - if (!annotations.isEmpty()) { - TypeAnnotationPosition p = - resolveFrame(tree, frame, frames.toList(), - new TypeAnnotationPosition()); - if (!p.location.isEmpty()) - p.type = p.type.getGenericComplement(); - setTypeAnnotationPos(annotations, p); - if (debugJSR308) { - System.out.println("trans: " + tree); - System.out.println(" target: " + p); - } - } - } - - private int methodParamIndex(List path, JCTree param) { - List curr = path; - if (curr.head != param) - curr = path.tail; - JCMethodDecl method = (JCMethodDecl)curr.tail.head; - return method.params.indexOf(param); - } - } - - private class TypeAnnotationLift extends TreeScanner { - List recordedTypeAnnotations = List.nil(); - - boolean isInner = false; - @Override - public void visitClassDef(JCClassDecl tree) { - if (isInner) { - // tree is an inner class tree. stop now. - // TransTypes.visitClassDef makes an invocation for each class - // seperately. - return; - } - isInner = true; - List prevTAs = recordedTypeAnnotations; - recordedTypeAnnotations = List.nil(); - try { - super.visitClassDef(tree); - } finally { - tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations); - recordedTypeAnnotations = prevTAs; - } - } - - @Override - public void visitMethodDef(JCMethodDecl tree) { - List prevTAs = recordedTypeAnnotations; - recordedTypeAnnotations = List.nil(); - try { - super.visitMethodDef(tree); - } finally { - tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations); - recordedTypeAnnotations = prevTAs; - } - } - - @Override - public void visitVarDef(JCVariableDecl tree) { - List prevTAs = recordedTypeAnnotations; - recordedTypeAnnotations = List.nil(); - ElementKind kind = tree.sym.getKind(); - if (kind == ElementKind.LOCAL_VARIABLE && tree.mods.annotations.nonEmpty()) { - // need to lift the annotations - TypeAnnotationPosition position = new TypeAnnotationPosition(); - position.pos = tree.pos; - position.type = TargetType.LOCAL_VARIABLE; - for (Attribute.Compound attribute : tree.sym.attributes_field) { - Attribute.TypeCompound tc = - new Attribute.TypeCompound(attribute.type, attribute.values, position); - recordedTypeAnnotations = recordedTypeAnnotations.append(tc); - } - } - try { - super.visitVarDef(tree); - } finally { - if (kind.isField() || kind == ElementKind.LOCAL_VARIABLE) - tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations); - recordedTypeAnnotations = kind.isField() ? prevTAs : prevTAs.appendList(recordedTypeAnnotations); - } - } - - @Override - public void visitApply(JCMethodInvocation tree) { - scan(tree.meth); - scan(tree.typeargs); - scan(tree.args); - } - - public void visitAnnotation(JCAnnotation tree) { - if (tree instanceof JCTypeAnnotation) - recordedTypeAnnotations = recordedTypeAnnotations.append(((JCTypeAnnotation)tree).attribute_field); - super.visitAnnotation(tree); - } - } - } diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/jvm/ClassReader.java --- a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Sun Feb 14 23:39:40 2010 -0800 @@ -1425,11 +1425,11 @@ // Class extends and implements clauses case CLASS_EXTENDS: case CLASS_EXTENDS_GENERIC_OR_ARRAY: - position.type_index = nextByte(); + position.type_index = nextChar(); break; // throws case THROWS: - position.type_index = nextByte(); + position.type_index = nextChar(); break; case CLASS_LITERAL: case CLASS_LITERAL_GENERIC_OR_ARRAY: diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java --- a/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Sun Feb 14 23:39:40 2010 -0800 @@ -965,11 +965,11 @@ // Class extends and implements clauses case CLASS_EXTENDS: case CLASS_EXTENDS_GENERIC_OR_ARRAY: - databuf.appendByte(p.type_index); + databuf.appendChar(p.type_index); break; // throws case THROWS: - databuf.appendByte(p.type_index); + databuf.appendChar(p.type_index); break; case CLASS_LITERAL: case CLASS_LITERAL_GENERIC_OR_ARRAY: diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/jvm/Code.java --- a/src/share/classes/com/sun/tools/javac/jvm/Code.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/jvm/Code.java Sun Feb 14 23:39:40 2010 -0800 @@ -1926,9 +1926,9 @@ for (Attribute.TypeCompound ta : lv.sym.typeAnnotations) { TypeAnnotationPosition p = ta.position; while (p != null) { - p.lvarOffset[0] = (int)lv.start_pc; - p.lvarLength[0] = (int)lv.length; - p.lvarIndex[0] = (int)lv.reg; + p.lvarOffset = new int[] { (int)lv.start_pc }; + p.lvarLength = new int[] { (int)lv.length }; + p.lvarIndex = new int[] { (int)lv.reg }; p.isValidOffset = true; p = p.wildcard_position; } diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/jvm/Gen.java --- a/src/share/classes/com/sun/tools/javac/jvm/Gen.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/jvm/Gen.java Sun Feb 14 23:39:40 2010 -0800 @@ -1714,7 +1714,7 @@ for (Attribute.TypeCompound ta : meth.typeAnnotations) { if (ta.position.pos == treePos) { ta.position.offset = code.cp; - ta.position.lvarOffset[0] = code.cp; + ta.position.lvarOffset = new int[] { code.cp }; ta.position.isValidOffset = true; } } @@ -1726,7 +1726,7 @@ for (Attribute.TypeCompound ta : meth.owner.typeAnnotations) { if (ta.position.pos == treePos) { ta.position.offset = code.cp; - ta.position.lvarOffset[0] = code.cp; + ta.position.lvarOffset = new int[] { code.cp }; ta.position.isValidOffset = true; } } @@ -1738,7 +1738,7 @@ for (Attribute.TypeCompound ta : s.typeAnnotations) { if (ta.position.pos == treePos) { ta.position.offset = code.cp; - ta.position.lvarOffset[0] = code.cp; + ta.position.lvarOffset = new int[] { code.cp }; ta.position.isValidOffset = true; } } @@ -2158,6 +2158,11 @@ code.emitop2(ldc2, makeRef(tree.pos(), tree.selected.type)); result = items.makeStackItem(pt); return; + } else if (tree.name == names.TYPE) { + // Set the annotation positions for primitive class literals + // (e.g. int.class) which have been converted to TYPE field + // access on the corresponding boxed type (e.g. Integer.TYPE). + setTypeAnnotationPositions(tree.pos); } Symbol ssym = TreeInfo.symbol(tree.selected); diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/parser/JavacParser.java --- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Sun Feb 14 23:39:40 2010 -0800 @@ -761,23 +761,28 @@ JCExpression[] odStack = newOdStack(); List savedOp = opStackSupply.elems; Token[] opStack = newOpStack(); + List savedPos = posStackSupply.elems; + int[] posStack = newPosStack(); // optimization, was odStack = new Tree[...]; opStack = new Tree[...]; int top = 0; odStack[0] = t; int startPos = S.pos(); Token topOp = ERROR; + int topOpPos = Position.NOPOS; while (prec(S.token()) >= minprec) { + posStack[top] = topOpPos; opStack[top] = topOp; top++; topOp = S.token(); - int pos = S.pos(); + topOpPos = S.pos(); S.nextToken(); - odStack[top] = topOp == INSTANCEOF ? parseType() : term3(); + odStack[top] = (topOp == INSTANCEOF) ? parseType() : term3(); while (top > 0 && prec(topOp) >= prec(S.token())) { - odStack[top-1] = makeOp(pos, topOp, odStack[top-1], + odStack[top-1] = makeOp(topOpPos, topOp, odStack[top-1], odStack[top]); top--; topOp = opStack[top]; + topOpPos = posStack[top]; } } assert top == 0; @@ -792,6 +797,7 @@ odStackSupply.elems = savedOd; // optimization opStackSupply.elems = savedOp; // optimization + posStackSupply.elems = savedPos; // optimization return t; } //where @@ -845,6 +851,7 @@ */ ListBuffer odStackSupply = new ListBuffer(); ListBuffer opStackSupply = new ListBuffer(); + ListBuffer posStackSupply = new ListBuffer(); private JCExpression[] newOdStack() { if (odStackSupply.elems == odStackSupply.last) @@ -862,6 +869,14 @@ return opStack; } + private int[] newPosStack() { + if (posStackSupply.elems == posStackSupply.last) + posStackSupply.append(new int[infixPrecedenceLevels + 1]); + int[] posStack = posStackSupply.elems.head; + posStackSupply.elems = posStackSupply.elems.tail; + return posStack; + } + /** Expression3 = PrefixOp Expression3 * | "(" Expr | TypeNoParams ")" Expression3 * | Primary {Selector} {PostfixOp} @@ -939,7 +954,7 @@ args.append(typeArgument()); } accept(GT); - t = F.at(pos1).TypeApply(t, args.toList()); + t = toP(F.at(pos1).TypeApply(t, args.toList())); checkGenerics(); while (S.token() == DOT) { S.nextToken(); @@ -950,7 +965,8 @@ t = bracketsOpt(toP(t)); } else if ((mode & EXPR) != 0) { mode = EXPR; - t = F.at(pos1).Binary(op, t, term2Rest(t1, TreeInfo.shiftPrec)); + JCExpression e = term2Rest(t1, TreeInfo.shiftPrec); + t = F.at(pos1).Binary(op, t, e); t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); } else { accept(GT); @@ -998,7 +1014,8 @@ case SUPER: if ((mode & EXPR) != 0) { mode = EXPR; - t = to(superSuffix(typeArgs, F.at(pos).Ident(names._super))); + t = to(F.at(pos).Ident(names._super)); + t = superSuffix(typeArgs, t); typeArgs = null; } else return illegal(); break; @@ -1380,13 +1397,15 @@ S.nextToken(); JCExpression result; if (S.token() == EXTENDS) { - TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.EXTENDS)); + TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS)); S.nextToken(); - result = F.at(pos).Wildcard(t, parseType()); + JCExpression bound = parseType(); + result = F.at(pos).Wildcard(t, bound); } else if (S.token() == SUPER) { - TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.SUPER)); + TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER)); S.nextToken(); - result = F.at(pos).Wildcard(t, parseType()); + JCExpression bound = parseType(); + result = F.at(pos).Wildcard(t, bound); } else if (S.token() == IDENTIFIER) { //error recovery reportSyntaxError(S.prevEndPos(), "expected3", @@ -1396,7 +1415,7 @@ JCIdent id = toP(F.at(S.pos()).Ident(ident())); result = F.at(pos).Erroneous(List.of(wc, id)); } else { - TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); + TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND)); result = toP(F.at(pos).Wildcard(t, null)); } if (!annotations.isEmpty()) @@ -2117,14 +2136,21 @@ return modifiersOpt(null); } JCModifiers modifiersOpt(JCModifiers partial) { - long flags = (partial == null) ? 0 : partial.flags; + long flags; + ListBuffer annotations = new ListBuffer(); + int pos; + if (partial == null) { + flags = 0; + pos = S.pos(); + } else { + flags = partial.flags; + annotations.appendList(partial.annotations); + pos = partial.pos; + } if (S.deprecatedFlag()) { flags |= Flags.DEPRECATED; S.resetDeprecatedFlag(); } - ListBuffer annotations = new ListBuffer(); - if (partial != null) annotations.appendList(partial.annotations); - int pos = S.pos(); int lastPos = Position.NOPOS; loop: while (true) { @@ -2150,12 +2176,12 @@ if (flag == Flags.ANNOTATION) { checkAnnotations(); if (S.token() != INTERFACE) { - JCAnnotation ann = annotation(lastPos, AnnotationKind.DEFAULT_ANNO); - // if first modifier is an annotation, set pos to annotation's. - if (flags == 0 && annotations.isEmpty()) - pos = ann.pos; - annotations.append(ann); - lastPos = ann.pos; + JCAnnotation ann = annotation(lastPos, AnnotationKind.DEFAULT_ANNO); + // if first modifier is an annotation, set pos to annotation's. + if (flags == 0 && annotations.isEmpty()) + pos = ann.pos; + annotations.append(ann); + lastPos = ann.pos; flag = 0; } } @@ -2169,7 +2195,7 @@ /* A modifiers tree with no modifier tokens or annotations * has no text position. */ - if (flags == 0 && annotations.isEmpty()) + if ((flags & Flags.ModifierFlags) == 0 && annotations.isEmpty()) pos = Position.NOPOS; JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList()); @@ -2226,7 +2252,8 @@ if (t1.getTag() == JCTree.IDENT && S.token() == EQ) { int pos = S.pos(); accept(EQ); - return toP(F.at(pos).Assign(t1, annotationValue())); + JCExpression v = annotationValue(); + return toP(F.at(pos).Assign(t1, v)); } else { return t1; } @@ -2543,10 +2570,9 @@ } List defs = enumBody(name); - JCModifiers newMods = - F.at(mods.pos).Modifiers(mods.flags|Flags.ENUM, mods.annotations); + mods.flags |= Flags.ENUM; JCClassDecl result = toP(F.at(pos). - ClassDef(newMods, name, List.nil(), + ClassDef(mods, name, List.nil(), null, implementing, defs)); attach(result, dc); return result; @@ -2695,16 +2721,8 @@ } else { pos = S.pos(); List typarams = typeParametersOpt(); - // Hack alert: if there are type arguments but no Modifiers, the start - // position will be lost unless we set the Modifiers position. There - // should be an AST node for type parameters (BugId 5005090). - if (typarams.length() > 0 && mods.pos == Position.NOPOS) { - mods.pos = pos; - } - List annosAfterParams = annotationsOpt(AnnotationKind.DEFAULT_ANNO); - Token token = S.token(); Name name = S.name(); pos = S.pos(); JCExpression type; @@ -2715,7 +2733,11 @@ type = to(F.at(pos).TypeIdent(TypeTags.VOID)); S.nextToken(); } else { - mods.annotations = mods.annotations.appendList(annosAfterParams); + if (annosAfterParams.nonEmpty()) { + mods.annotations = mods.annotations.appendList(annosAfterParams); + if (mods.pos == Position.NOPOS) + mods.pos = mods.annotations.head.pos; + } // method returns types are un-annotated types type = unannotatedType(); } @@ -2813,6 +2835,7 @@ } } } + JCMethodDecl result = toP(F.at(pos).MethodDef(mods, name, type, typarams, params, receiverAnnotations, thrown, diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java --- a/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Sun Feb 14 23:39:40 2010 -0800 @@ -67,6 +67,7 @@ import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.Abort; import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Convert; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Log; @@ -893,14 +894,20 @@ errorStatus = true; break runAround; } else { - ListBuffer classes = enterNewClassFiles(currentContext); + List newClasses = enterNewClassFiles(currentContext); compiler.enterTrees(roots); // annotationsPresentInSource = // collector.findAnnotations(parsedFiles); - classes.appendList(getTopLevelClasses(parsedFiles)); - topLevelClasses = classes.toList(); - packageInfoFiles = getPackageInfoFiles(parsedFiles); + ListBuffer tlc = new ListBuffer(); + tlc.appendList(getTopLevelClasses(parsedFiles)); + tlc.appendList(getTopLevelClassesFromClasses(newClasses)); + topLevelClasses = tlc.toList(); + + ListBuffer pif = new ListBuffer(); + pif.appendList(getPackageInfoFiles(parsedFiles)); + pif.appendList(getPackageInfoFilesFromClasses(newClasses)); + packageInfoFiles = pif.toList(); annotationsPresent = new LinkedHashSet(); for (ClassSymbol classSym : topLevelClasses) @@ -1026,20 +1033,30 @@ } } - private ListBuffer enterNewClassFiles(Context currentContext) { + private List enterNewClassFiles(Context currentContext) { ClassReader reader = ClassReader.instance(currentContext); Names names = Names.instance(currentContext); - ListBuffer list = new ListBuffer(); + List list = List.nil(); for (Map.Entry entry : filer.getGeneratedClasses().entrySet()) { Name name = names.fromString(entry.getKey()); JavaFileObject file = entry.getValue(); if (file.getKind() != JavaFileObject.Kind.CLASS) throw new AssertionError(file); - ClassSymbol cs = reader.enterClass(name, file); - list.append(cs); + ClassSymbol cs; + if (isPkgInfo(file, JavaFileObject.Kind.CLASS)) { + Name packageName = Convert.packagePart(name); + PackageSymbol p = reader.enterPackage(packageName); + if (p.package_info == null) + p.package_info = reader.enterClass(Convert.shortName(name), p); + cs = p.package_info; + if (cs.classfile == null) + cs.classfile = file; + } else + cs = reader.enterClass(name, file); + list = list.prepend(cs); } - return list; + return list.reverse(); } /** @@ -1066,18 +1083,44 @@ return classes.reverse(); } + private List getTopLevelClassesFromClasses(List syms) { + List classes = List.nil(); + for (ClassSymbol sym : syms) { + if (!isPkgInfo(sym)) { + classes = classes.prepend(sym); + } + } + return classes.reverse(); + } + private List getPackageInfoFiles(List units) { List packages = List.nil(); for (JCCompilationUnit unit : units) { - boolean isPkgInfo = unit.sourcefile.isNameCompatible("package-info", - JavaFileObject.Kind.SOURCE); - if (isPkgInfo) { + if (isPkgInfo(unit.sourcefile, JavaFileObject.Kind.SOURCE)) { packages = packages.prepend(unit.packge); } } return packages.reverse(); } + private List getPackageInfoFilesFromClasses(List syms) { + List packages = List.nil(); + for (ClassSymbol sym : syms) { + if (isPkgInfo(sym)) { + packages = packages.prepend((PackageSymbol) sym.owner); + } + } + return packages.reverse(); + } + + private boolean isPkgInfo(JavaFileObject fo, JavaFileObject.Kind kind) { + return fo.isNameCompatible("package-info", kind); + } + + private boolean isPkgInfo(ClassSymbol sym) { + return isPkgInfo(sym.classfile, JavaFileObject.Kind.CLASS) && (sym.packge().package_info == sym); + } + private Context contextForNextRound(Context context, boolean shareNames) throws IOException { @@ -1252,10 +1295,6 @@ node.sym = null; super.visitIdent(node); } - public void visitApply(JCMethodInvocation node) { - scan(node.typeargs); - super.visitApply(node); - } }; diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/tree/TreeInfo.java --- a/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Sun Feb 14 23:39:40 2010 -0800 @@ -307,8 +307,18 @@ case(JCTree.POSTINC): case(JCTree.POSTDEC): return getStartPos(((JCUnary) tree).arg); - case(JCTree.ANNOTATED_TYPE): - return getStartPos(((JCAnnotatedType) tree).underlyingType); + case(JCTree.ANNOTATED_TYPE): { + JCAnnotatedType node = (JCAnnotatedType) tree; + if (node.annotations.nonEmpty()) + return getStartPos(node.annotations.head); + return getStartPos(node.underlyingType); + } + case(JCTree.NEWCLASS): { + JCNewClass node = (JCNewClass)tree; + if (node.encl != null) + return getStartPos(node.encl); + break; + } case(JCTree.VARDEF): { JCVariableDecl node = (JCVariableDecl)tree; if (node.mods.pos != Position.NOPOS) { @@ -406,6 +416,8 @@ return getEndPos(((JCUnary) tree).arg, endPositions); case(JCTree.WHILELOOP): return getEndPos(((JCWhileLoop) tree).body, endPositions); + case(JCTree.ANNOTATED_TYPE): + return getEndPos(((JCAnnotatedType) tree).underlyingType, endPositions); case(JCTree.ERRONEOUS): { JCErroneous node = (JCErroneous)tree; if (node.errs != null && node.errs.nonEmpty()) diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/tree/TreeMaker.java --- a/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java Sun Feb 14 23:39:40 2010 -0800 @@ -480,7 +480,7 @@ public JCModifiers Modifiers(long flags, List annotations) { JCModifiers tree = new JCModifiers(flags, annotations); - boolean noFlags = (flags & Flags.StandardFlags) == 0; + boolean noFlags = (flags & Flags.ModifierFlags) == 0; tree.pos = (noFlags && annotations.isEmpty()) ? Position.NOPOS : pos; return tree; } diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javac/tree/TreeScanner.java --- a/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java Sun Feb 14 23:39:40 2010 -0800 @@ -193,6 +193,7 @@ } public void visitApply(JCMethodInvocation tree) { + scan(tree.typeargs); scan(tree.meth); scan(tree.args); } @@ -200,6 +201,7 @@ public void visitNewClass(JCNewClass tree) { scan(tree.encl); scan(tree.clazz); + scan(tree.typeargs); scan(tree.args); scan(tree.def); } diff -r 2edcb5dc642d -r d9cd5b8286e4 src/share/classes/com/sun/tools/javap/AnnotationWriter.java --- a/src/share/classes/com/sun/tools/javap/AnnotationWriter.java Fri Feb 12 13:25:27 2010 -0800 +++ b/src/share/classes/com/sun/tools/javap/AnnotationWriter.java Sun Feb 14 23:39:40 2010 -0800 @@ -162,6 +162,7 @@ print(pos.type_index); break; case CLASS_LITERAL: + case CLASS_LITERAL_GENERIC_OR_ARRAY: if (showOffsets) { print(", offset="); print(pos.offset); diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/T6654037.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/T6654037.java Sun Feb 14 23:39:40 2010 -0800 @@ -0,0 +1,76 @@ +/* + * Copyright 2008-2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6654037 + * @summary JCTree.pos may be incorrect for BinaryTrees + */ + +import com.sun.source.tree.BinaryTree; +import com.sun.source.tree.ClassTree; +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.MethodTree; +import com.sun.source.tree.VariableTree; +import com.sun.tools.javac.api.JavacTaskImpl; +import com.sun.tools.javac.tree.JCTree; +import java.net.URI; +import java.util.Arrays; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.ToolProvider; + +public class T6654037 { + + public static void main(String[] args) throws Exception { + final String bootPath = System.getProperty("sun.boot.class.path"); //NOI18N + final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); + assert tool != null; + + String code = "package test; public class Test {private void test() {Object o = null; boolean b = o != null && o instanceof String;} private Test() {}}"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, Arrays.asList("-bootclasspath", bootPath, "-Xjcov"), null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + MethodTree method = (MethodTree) clazz.getMembers().get(0); + VariableTree condSt = (VariableTree) method.getBody().getStatements().get(1); + BinaryTree cond = (BinaryTree) condSt.getInitializer(); + JCTree condJC = (JCTree) cond; + + if (condJC.pos != 93) + throw new IllegalStateException("Unexpected position=" + condJC.pos); + } + + static class MyFileObject extends SimpleJavaFileObject { + private String text; + public MyFileObject(String text) { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + this.text = text; + } + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return text; + } + } +} diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/generics/diamond/neg/Neg01.out --- a/test/tools/javac/generics/diamond/neg/Neg01.out Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/generics/diamond/neg/Neg01.out Sun Feb 14 23:39:40 2010 -0800 @@ -1,31 +1,31 @@ Neg01.java:18:15: compiler.err.not.within.bounds: java.lang.String Neg01.java:18:37: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg01, Neg01) -Neg01.java:19:25: compiler.err.not.within.bounds: ? extends java.lang.String +Neg01.java:19:15: compiler.err.not.within.bounds: ? extends java.lang.String Neg01.java:19:47: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg01.java:20:23: compiler.err.cant.resolve.location.args: kindname.constructor, Neg01, , java.lang.String, kindname.class, Neg01 -Neg01.java:21:23: compiler.err.not.within.bounds: ? super java.lang.String +Neg01.java:21:15: compiler.err.not.within.bounds: ? super java.lang.String Neg01.java:21:45: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg01, Neg01) Neg01.java:23:15: compiler.err.not.within.bounds: java.lang.String Neg01.java:23:37: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg01, Neg01) -Neg01.java:24:25: compiler.err.not.within.bounds: ? extends java.lang.String +Neg01.java:24:15: compiler.err.not.within.bounds: ? extends java.lang.String Neg01.java:24:47: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg01.java:25:23: compiler.err.cant.resolve.location.args: kindname.constructor, Neg01, , java.lang.String, kindname.class, Neg01 Neg01.java:25:38: compiler.err.cant.resolve.location.args: kindname.constructor, Neg01, , , kindname.class, Neg01 -Neg01.java:26:23: compiler.err.not.within.bounds: ? super java.lang.String +Neg01.java:26:15: compiler.err.not.within.bounds: ? super java.lang.String Neg01.java:26:45: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg01, Neg01) Neg01.java:28:15: compiler.err.not.within.bounds: java.lang.String Neg01.java:28:37: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg01, Neg01) -Neg01.java:29:25: compiler.err.not.within.bounds: ? extends java.lang.String +Neg01.java:29:15: compiler.err.not.within.bounds: ? extends java.lang.String Neg01.java:29:48: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg01.java:30:24: compiler.err.cant.resolve.location.args: kindname.constructor, Neg01, , java.lang.String,java.lang.String, kindname.class, Neg01 Neg01.java:31:9: compiler.err.cant.resolve.location: kindname.class, Foo, , , kindname.class, Neg01 Neg01.java:31:35: compiler.err.cant.resolve.location.args: kindname.constructor, Neg01, , java.lang.String,java.lang.String, kindname.class, Neg01 Neg01.java:33:15: compiler.err.not.within.bounds: java.lang.String Neg01.java:33:38: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg01, Neg01) -Neg01.java:34:25: compiler.err.not.within.bounds: ? extends java.lang.String +Neg01.java:34:15: compiler.err.not.within.bounds: ? extends java.lang.String Neg01.java:34:48: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg01.java:35:24: compiler.err.cant.resolve.location.args: kindname.constructor, Neg01, , java.lang.String,java.lang.String, kindname.class, Neg01 Neg01.java:35:43: compiler.err.cant.resolve.location.args: kindname.constructor, Neg01, , , kindname.class, Neg01 -Neg01.java:36:23: compiler.err.not.within.bounds: ? super java.lang.String +Neg01.java:36:15: compiler.err.not.within.bounds: ? super java.lang.String Neg01.java:36:46: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg01, Neg01) 30 errors diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/generics/diamond/neg/Neg02.out --- a/test/tools/javac/generics/diamond/neg/Neg02.out Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/generics/diamond/neg/Neg02.out Sun Feb 14 23:39:40 2010 -0800 @@ -1,61 +1,61 @@ Neg02.java:19:13: compiler.err.not.within.bounds: java.lang.String Neg02.java:19:33: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) -Neg02.java:20:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg02.java:20:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg02.java:20:43: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg02.java:21:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg02.Foo -Neg02.java:22:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg02.java:22:13: compiler.err.not.within.bounds: ? super java.lang.String Neg02.java:22:41: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) Neg02.java:24:13: compiler.err.not.within.bounds: java.lang.String Neg02.java:24:33: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) -Neg02.java:25:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg02.java:25:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg02.java:25:43: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg02.java:26:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg02.Foo Neg02.java:26:34: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg02.Foo -Neg02.java:27:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg02.java:27:13: compiler.err.not.within.bounds: ? super java.lang.String Neg02.java:27:41: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) Neg02.java:29:13: compiler.err.not.within.bounds: java.lang.String Neg02.java:29:33: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) -Neg02.java:30:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg02.java:30:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg02.java:30:44: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg02.java:31:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg02.Foo -Neg02.java:32:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg02.java:32:13: compiler.err.not.within.bounds: ? super java.lang.String Neg02.java:32:42: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) Neg02.java:34:13: compiler.err.not.within.bounds: java.lang.String Neg02.java:34:34: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) -Neg02.java:35:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg02.java:35:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg02.java:35:44: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg02.java:36:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg02.Foo Neg02.java:36:39: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg02.Foo -Neg02.java:37:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg02.java:37:13: compiler.err.not.within.bounds: ? super java.lang.String Neg02.java:37:42: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) Neg02.java:41:13: compiler.err.not.within.bounds: java.lang.String Neg02.java:41:39: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) -Neg02.java:42:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg02.java:42:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg02.java:42:49: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg02.java:43:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg02.Foo -Neg02.java:44:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg02.java:44:13: compiler.err.not.within.bounds: ? super java.lang.String Neg02.java:44:47: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) Neg02.java:46:13: compiler.err.not.within.bounds: java.lang.String Neg02.java:46:39: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) -Neg02.java:47:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg02.java:47:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg02.java:47:49: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg02.java:48:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg02.Foo Neg02.java:48:40: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg02.Foo -Neg02.java:49:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg02.java:49:13: compiler.err.not.within.bounds: ? super java.lang.String Neg02.java:49:47: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) Neg02.java:51:13: compiler.err.not.within.bounds: java.lang.String Neg02.java:51:39: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) -Neg02.java:52:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg02.java:52:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg02.java:52:50: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg02.java:53:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg02.Foo -Neg02.java:54:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg02.java:54:13: compiler.err.not.within.bounds: ? super java.lang.String Neg02.java:54:48: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) Neg02.java:56:13: compiler.err.not.within.bounds: java.lang.String Neg02.java:56:40: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) -Neg02.java:57:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg02.java:57:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg02.java:57:50: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg02.java:58:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg02.Foo Neg02.java:58:45: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg02.Foo -Neg02.java:59:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg02.java:59:13: compiler.err.not.within.bounds: ? super java.lang.String Neg02.java:59:48: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) 60 errors diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/generics/diamond/neg/Neg03.out --- a/test/tools/javac/generics/diamond/neg/Neg03.out Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/generics/diamond/neg/Neg03.out Sun Feb 14 23:39:40 2010 -0800 @@ -1,91 +1,91 @@ Neg03.java:19:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:19:33: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:20:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:20:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:20:43: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:21:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg03.Foo -Neg03.java:22:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:22:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:22:41: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:24:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:24:33: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:25:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:25:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:25:43: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:26:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg03.Foo Neg03.java:26:34: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03.Foo -Neg03.java:27:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:27:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:27:41: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:29:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:29:33: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:30:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:30:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:30:44: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:31:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg03.Foo -Neg03.java:32:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:32:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:32:42: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:34:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:34:34: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:35:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:35:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:35:44: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:36:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg03.Foo Neg03.java:36:39: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03.Foo -Neg03.java:37:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:37:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:37:42: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:41:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:41:42: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:42:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:42:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:42:52: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:43:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg03.Foo -Neg03.java:44:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:44:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:44:50: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:46:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:46:42: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:47:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:47:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:47:52: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:48:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg03.Foo Neg03.java:48:43: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03.Foo -Neg03.java:49:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:49:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:49:50: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:51:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:51:42: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:52:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:52:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:52:53: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:53:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg03.Foo -Neg03.java:54:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:54:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:54:51: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:56:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:56:43: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:57:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:57:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:57:53: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:58:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg03.Foo Neg03.java:58:48: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03.Foo -Neg03.java:59:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:59:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:59:51: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:63:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:63:28: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:64:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:64:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:64:38: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:65:23: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg03.Foo -Neg03.java:66:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:66:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:66:36: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:68:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:68:28: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:69:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:69:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:69:38: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:70:23: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg03.Foo Neg03.java:70:36: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03.Foo -Neg03.java:71:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:71:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:71:36: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:73:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:73:28: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:74:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:74:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:74:39: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:75:24: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg03.Foo -Neg03.java:76:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:76:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:76:37: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:78:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:78:29: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:79:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:79:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:79:39: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:80:24: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg03.Foo Neg03.java:80:41: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03.Foo -Neg03.java:81:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:81:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:81:37: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) 90 errors diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/generics/diamond/neg/Neg04.out --- a/test/tools/javac/generics/diamond/neg/Neg04.out Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/generics/diamond/neg/Neg04.out Sun Feb 14 23:39:40 2010 -0800 @@ -1,31 +1,31 @@ Neg04.java:18:13: compiler.err.not.within.bounds: java.lang.String Neg04.java:18:33: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Foo, Foo) -Neg04.java:19:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg04.java:19:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg04.java:19:43: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg04.java:20:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Foo -Neg04.java:21:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg04.java:21:13: compiler.err.not.within.bounds: ? super java.lang.String Neg04.java:21:41: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Foo, Foo) Neg04.java:23:13: compiler.err.not.within.bounds: java.lang.String Neg04.java:23:33: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Foo, Foo) -Neg04.java:24:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg04.java:24:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg04.java:24:43: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg04.java:25:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Foo Neg04.java:25:34: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Foo -Neg04.java:26:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg04.java:26:13: compiler.err.not.within.bounds: ? super java.lang.String Neg04.java:26:41: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Foo, Foo) Neg04.java:28:13: compiler.err.not.within.bounds: java.lang.String Neg04.java:28:33: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Foo, Foo) -Neg04.java:29:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg04.java:29:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg04.java:29:44: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg04.java:30:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Foo -Neg04.java:31:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg04.java:31:13: compiler.err.not.within.bounds: ? super java.lang.String Neg04.java:31:42: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Foo, Foo) Neg04.java:33:13: compiler.err.not.within.bounds: java.lang.String Neg04.java:33:34: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Foo, Foo) -Neg04.java:34:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg04.java:34:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg04.java:34:44: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg04.java:35:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Foo Neg04.java:35:39: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Foo -Neg04.java:36:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg04.java:36:13: compiler.err.not.within.bounds: ? super java.lang.String Neg04.java:36:42: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Foo, Foo) 30 errors diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/processing/6499119/ClassProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/processing/6499119/ClassProcessor.java Sun Feb 14 23:39:40 2010 -0800 @@ -0,0 +1,132 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.io.*; +import java.util.*; +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.lang.model.SourceVersion; +import javax.tools.Diagnostic.Kind; + +/* + * @test + * @bug 6499119 + * @summary Created package-info class file modeled improperly + * @compile ClassProcessor.java package-info.java + * @compile/process -cp . -processor ClassProcessor -Akind=java java.lang.Object + * @compile/process -cp . -processor ClassProcessor -Akind=class java.lang.Object + */ + +@SupportedOptions({ "gen", "expect" }) +@SupportedAnnotationTypes({"*"}) +public class ClassProcessor extends AbstractProcessor { + int round = 1; + + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (round == 1) { + System.out.println("-- Round 1 --"); + createPackageFile(); + } else if (round == 2) { + boolean found_foo_A = false; + System.out.println("-- Round 2 --"); + for(Element e: roundEnv.getRootElements()) { + System.out.println("ElementKind: " + e.getKind()); + System.out.println("Modifiers: " + e.getModifiers()); + System.out.println("Annotations: " + e.getAnnotationMirrors()); + if (e.getAnnotationMirrors().toString().equals("@foo.A")) { + found_foo_A = true; + checkEqual("ElementKind", e.getKind().toString(), "PACKAGE"); + checkEqual("Modifiers", e.getModifiers().toString(), "[]"); + } + } + if (!found_foo_A) + error("did not find @foo.A"); + } + round++; + return true; + } + + private void createPackageFile() { + Filer filer = processingEnv.getFiler(); + + String kind = processingEnv.getOptions().get("kind"); + + File pkgInfo; + if (kind.equals("java")) + pkgInfo = new File(System.getProperty("test.src"), "package-info.java"); + else + pkgInfo = new File(System.getProperty("test.classes"), "foo/package-info.class"); + + byte[] bytes = new byte[(int) pkgInfo.length()]; + DataInputStream in = null; + try { + in = new DataInputStream(new FileInputStream(pkgInfo)); + in.readFully(bytes); + } catch (IOException ioe) { + error("Couldn't read package info file: " + ioe); + } finally { + if(in != null) { + try { + in.close(); + } catch (IOException e) { + error("InputStream closing failed: " + e); + } + } + } + + OutputStream out = null; + try { + if (kind.equals("java")) + out = filer.createSourceFile("foo.package-info").openOutputStream(); + else + out = filer.createClassFile("foo.package-info").openOutputStream(); + out.write(bytes, 0, bytes.length); + } catch (IOException ioe) { + error("Couldn't create package info file: " + ioe); + } finally { + if(out != null) { + try { + out.close(); + } catch (IOException e) { + error("OutputStream closing failed: " + e); + } + } + } + } + + private void checkEqual(String label, String actual, String expect) { + if (!actual.equals(expect)) { + error("Unexpected value for " + label + "; actual=" + actual + ", expected=" + expect); + } + } + + private void error(String msg) { + Messager messager = processingEnv.getMessager(); + messager.printMessage(Kind.ERROR, msg); + } +} + diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/processing/6499119/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/processing/6499119/package-info.java Sun Feb 14 23:39:40 2010 -0800 @@ -0,0 +1,27 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +@A package foo; + +@interface A {} + diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/processing/T6920317.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/processing/T6920317.java Sun Feb 14 23:39:40 2010 -0800 @@ -0,0 +1,462 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6920317 + * @summary package-info.java file has to be specified on the javac cmdline, else it will not be avail + */ + +import java.io.*; +import java.util.*; +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; +import javax.lang.model.util.*; +import javax.tools.*; + +/** + * The test exercises different ways of providing annotations for a package. + * Each way provides an annotation with a unique argument. For each test + * case, the test verifies that the annotation with the correct argument is + * found by the compiler. + */ +public class T6920317 { + public static void main(String... args) throws Exception { + new T6920317().run(args); + } + + // Used to describe properties of files to be put on command line, source path, class path + enum Kind { + /** File is not used. */ + NONE, + /** File is used. */ + OLD, + /** Only applies to files on classpath/sourcepath, when there is another file on the + * other path of type OLD, in which case, this file must be newer than the other one. */ + NEW, + /** Only applies to files on classpath/sourcepath, when there is no file in any other + * location, in which case, this file will be generated by the annotation processor. */ + GEN + } + + void run(String... args) throws Exception { + // if no args given, all test cases are run + // if args given, they indicate the test cases to be run + for (int i = 0; i < args.length; i++) { + tests.add(Integer.valueOf(args[i])); + } + + setup(); + + // Run tests for all combinations of files on command line, source path and class path. + // Invalid combinations are skipped in the test method + for (Kind cmdLine: EnumSet.of(Kind.NONE, Kind.OLD)) { + for (Kind srcPath: Kind.values()) { + for (Kind clsPath: Kind.values()) { + try { + test(cmdLine, srcPath, clsPath); + } catch (Exception e) { + e.printStackTrace(); + error("Exception " + e); + // uncomment to stop on first failed test case + // throw e; + } + } + } + } + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + /** One time setup for files and directories to be used in the various test cases. */ + void setup() throws Exception { + // Annotation used in test cases to annotate package. This file is + // given on the command line in test cases. + test_java = writeFile("Test.java", "package p; @interface Test { String value(); }"); + // Compile the annotation for use later in setup + File tmpClasses = new File("tmp.classes"); + compile(tmpClasses, new String[] { }, test_java); + + // package-info file to use on the command line when requied + cl_pkgInfo_java = writeFile("cl/p/package-info.java", "@Test(\"CL\") package p;"); + + // source path containing package-info + sp_old = new File("src.old"); + writeFile("src.old/p/package-info.java", "@Test(\"SP_OLD\") package p;"); + + // class path containing package-info + cp_old = new File("classes.old"); + compile(cp_old, new String[] { "-classpath", tmpClasses.getPath() }, + writeFile("tmp.old/p/package-info.java", "@Test(\"CP_OLD\") package p;")); + + // source path containing package-info which is newer than the one in cp-old + sp_new = new File("src.new"); + File old_class = new File(cp_old, "p/package-info.class"); + writeFile("src.new/p/package-info.java", "@Test(\"SP_NEW\") package p;", old_class); + + // class path containing package-info which is newer than the one in sp-old + cp_new = new File("classes.new"); + File old_java = new File(sp_old, "p/package-info.java"); + compile(cp_new, new String[] { "-classpath", tmpClasses.getPath() }, + writeFile("tmp.new/p/package-info.java", "@Test(\"CP_NEW\") package p;", old_java)); + + // directory containing package-info.java to be "generated" later by annotation processor + sp_gen = new File("src.gen"); + writeFile("src.gen/p/package-info.java", "@Test(\"SP_GEN\") package p;"); + + // directory containing package-info.class to be "generated" later by annotation processor + cp_gen = new File("classes.gen"); + compile(cp_gen, new String[] { "-classpath", tmpClasses.getPath() }, + writeFile("tmp.gen/p/package-info.java", "@Test(\"CP_GEN\") package p;")); + } + + void test(Kind cl, Kind sp, Kind cp) throws Exception { + if (skip(cl, sp, cp)) + return; + + ++count; + // if test cases specified, skip this test case if not selected + if (tests.size() > 0 && !tests.contains(count)) + return; + + System.err.println("Test " + count + " cl:" + cl + " sp:" + sp + " cp:" + cp); + + // test specific tmp directory + File test_tmp = new File("tmp.test" + count); + test_tmp.mkdirs(); + + // build up list of options and files to be compiled + List opts = new ArrayList(); + List files = new ArrayList(); + + // expected value for annotation + String expect = null; + + opts.add("-processorpath"); + opts.add(System.getProperty("test.classes")); + opts.add("-processor"); + opts.add(Processor.class.getName()); + opts.add("-proc:only"); + opts.add("-d"); + opts.add(test_tmp.getPath()); + //opts.add("-verbose"); + files.add(test_java); + + /* + * Analyze each of cl, cp, sp, building up the options and files to + * be compiled, and determining the expected outcome fo the test case. + */ + + // command line file: either omitted or given + if (cl == Kind.OLD) { + files.add(cl_pkgInfo_java); + // command line files always supercede files on paths + expect = "CL"; + } + + // source path: + switch (sp) { + case NONE: + break; + + case OLD: + opts.add("-sourcepath"); + opts.add(sp_old.getPath()); + if (expect == null && cp == Kind.NONE) { + assert cl == Kind.NONE && cp == Kind.NONE; + expect = "SP_OLD"; + } + break; + + case NEW: + opts.add("-sourcepath"); + opts.add(sp_new.getPath()); + if (expect == null) { + assert cl == Kind.NONE && cp == Kind.OLD; + expect = "SP_NEW"; + } + break; + + case GEN: + opts.add("-Agen=" + new File(sp_gen, "p/package-info.java")); + assert cl == Kind.NONE && cp == Kind.NONE; + expect = "SP_GEN"; + break; + } + + // class path: + switch (cp) { + case NONE: + break; + + case OLD: + opts.add("-classpath"); + opts.add(cp_old.getPath()); + if (expect == null && sp == Kind.NONE) { + assert cl == Kind.NONE && sp == Kind.NONE; + expect = "CP_OLD"; + } + break; + + case NEW: + opts.add("-classpath"); + opts.add(cp_new.getPath()); + if (expect == null) { + assert cl == Kind.NONE && sp == Kind.OLD; + expect = "CP_NEW"; + } + break; + + case GEN: + opts.add("-Agen=" + new File(cp_gen, "p/package-info.class")); + assert cl == Kind.NONE && sp == Kind.NONE; + expect = "CP_GEN"; + break; + } + + // pass expected value to annotation processor + assert expect != null; + opts.add("-Aexpect=" + expect); + + // compile the files with the options that have been built up + compile(opts, files); + } + + /** + * Return true if this combination of parameters does not identify a useful test case. + */ + boolean skip(Kind cl, Kind sp, Kind cp) { + // skip if no package files required + if (cl == Kind.NONE && sp == Kind.NONE && cp == Kind.NONE) + return true; + + // skip if both sp and sp are OLD, since results may be indeterminate + if (sp == Kind.OLD && cp == Kind.OLD) + return true; + + // skip if sp or cp is NEW but the other is not OLD + if ((sp == Kind.NEW && cp != Kind.OLD) || (cp == Kind.NEW && sp != Kind.OLD)) + return true; + + // only use GEN if no other package-info files present + if (sp == Kind.GEN && !(cl == Kind.NONE && cp == Kind.NONE) || + cp == Kind.GEN && !(cl == Kind.NONE && sp == Kind.NONE)) { + return true; + } + + // remaining combinations are valid + return false; + } + + /** Write a file with a given body. */ + File writeFile(String path, String body) throws Exception { + File f = new File(path); + if (f.getParentFile() != null) + f.getParentFile().mkdirs(); + Writer out = new FileWriter(path); + try { + out.write(body); + } finally { + out.close(); + } + return f; + } + + /** Write a file with a given body, ensuring that the file is newer than a reference file. */ + File writeFile(String path, String body, File ref) throws Exception { + for (int i = 0; i < 5; i++) { + File f = writeFile(path, body); + if (f.lastModified() > ref.lastModified()) + return f; + Thread.sleep(2000); + } + throw new Exception("cannot create file " + path + " newer than " + ref); + } + + /** Compile a file to a given directory, with options provided. */ + void compile(File dir, String[] opts, File src) throws Exception { + dir.mkdirs(); + List opts2 = new ArrayList(); + opts2.addAll(Arrays.asList("-d", dir.getPath())); + opts2.addAll(Arrays.asList(opts)); + compile(opts2, Collections.singletonList(src)); + } + + /** Compile files with options provided. */ + void compile(List opts, List files) throws Exception { + System.err.println("javac: " + opts + " " + files); + List args = new ArrayList(); + args.addAll(opts); + for (File f: files) + args.add(f.getPath()); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]), pw); + pw.flush(); + if (sw.getBuffer().length() > 0) + System.err.println(sw.toString()); + if (rc != 0) + throw new Exception("compilation failed: rc=" + rc); + } + + /** Report an error. */ + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + /** Test case counter. */ + int count; + + /** Number of errors found. */ + int errors; + + /** Optional set of test cases to be run; empty implies all test cases. */ + Set tests = new HashSet(); + + /* Files created by setup. */ + File test_java; + File sp_old; + File sp_new; + File sp_gen; + File cp_old; + File cp_new; + File cp_gen; + File cl_pkgInfo_java; + + /** Annotation processor used to verify the expected value for the + package annotations found by javac. */ + @SupportedOptions({ "gen", "expect" }) + @SupportedAnnotationTypes({"*"}) + public static class Processor extends AbstractProcessor { + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + public boolean process(Set annots, RoundEnvironment renv) { + round++; + System.err.println("Round " + round + " annots:" + annots + " rootElems:" + renv.getRootElements()); + + // if this is the first round and the gen option is given, use the filer to create + // a copy of the file specified by the gen option. + String gen = getOption("gen"); + if (round == 1 && gen != null) { + try { + Filer filer = processingEnv.getFiler(); + JavaFileObject f; + if (gen.endsWith(".java")) + f = filer.createSourceFile("p.package-info"); + else + f = filer.createClassFile("p.package-info"); + System.err.println("copy " + gen + " to " + f.getName()); + write(f, read(new File(gen))); + } catch (IOException e) { + error("Cannot create package-info file: " + e); + } + } + + // if annotation processing is complete, verify the package annotation + // found by the compiler. + if (renv.processingOver()) { + System.err.println("final round"); + Elements eu = processingEnv.getElementUtils(); + TypeElement te = eu.getTypeElement("p.Test"); + PackageElement pe = eu.getPackageOf(te); + System.err.println("final: te:" + te + " pe:" + pe); + List annos = pe.getAnnotationMirrors(); + System.err.println("final: annos:" + annos); + if (annos.size() == 1) { + String expect = "@" + te + "(\"" + getOption("expect") + "\")"; + String actual = annos.get(0).toString(); + checkEqual("package annotations", actual, expect); + } else { + error("Wrong number of annotations found: (" + annos.size() + ") " + annos); + } + } + + return true; + } + + /** Get an option given to the annotation processor. */ + String getOption(String name) { + return processingEnv.getOptions().get(name); + } + + /** Read a file. */ + byte[] read(File file) { + byte[] bytes = new byte[(int) file.length()]; + DataInputStream in = null; + try { + in = new DataInputStream(new FileInputStream(file)); + in.readFully(bytes); + } catch (IOException e) { + error("Error reading file: " + e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + error("Error closing file: " + e); + } + } + } + return bytes; + } + + /** Write a file. */ + void write(JavaFileObject file, byte[] bytes) { + OutputStream out = null; + try { + out = file.openOutputStream(); + out.write(bytes, 0, bytes.length); + } catch (IOException e) { + error("Error writing file: " + e); + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException e) { + error("Error closing file: " + e); + } + } + } + } + + /** Check two strings are equal, and report an error if they are not. */ + private void checkEqual(String label, String actual, String expect) { + if (!actual.equals(expect)) { + error("Unexpected value for " + label + "; actual=" + actual + ", expected=" + expect); + } + } + + /** Report an error to the annotation processing system. */ + void error(String msg) { + Messager messager = processingEnv.getMessager(); + messager.printMessage(Diagnostic.Kind.ERROR, msg); + } + + int round; + } +} diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/tree/T6923080.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/tree/T6923080.java Sun Feb 14 23:39:40 2010 -0800 @@ -0,0 +1,40 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is not a regular test, but is processed by ./TreeScannerTest.java, + * which verifies the operation of the javac TreeScanner. + * @bug 6923080 + * @summary TreeScanner.visitNewClass should scan tree.typeargs + */ +class T6923080 { + void test() { + C c = new C(); // exercises TreeScanner.visitNewClass + Object o = c.m(); // exercises TreeScanner.visitApply + } + + static class C { + C() { } + T m() { return null; } + } +} diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/tree/TreeScannerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/tree/TreeScannerTest.java Sun Feb 14 23:39:40 2010 -0800 @@ -0,0 +1,387 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + + +/** + * Utility and test program to check javac's internal TreeScanner class. + * The program can be run standalone, or as a jtreg test. For info on + * command line args, run program with no args. + * + *

+ * jtreg: Note that by using the -r switch in the test description below, this test + * will process all java files in the langtools/test directory, thus implicitly + * covering any new language features that may be tested in this test suite. + */ + +/* + * @test + * @bug 6923080 + * @summary TreeScanner.visitNewClass should scan tree.typeargs + * @run main TreeScannerTest -q -r . + */ + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; +import javax.tools.*; + +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.tree.*; +import com.sun.tools.javac.tree.JCTree.*; +import com.sun.tools.javac.util.List; + +public class TreeScannerTest { + /** + * Main entry point. + * If test.src is set, program runs in jtreg mode, and will throw an Error + * if any errors arise, otherwise System.exit will be used. In jtreg mode, + * the default base directory for file args is the value of ${test.src}. + * In jtreg mode, the -r option can be given to change the default base + * directory to the root test directory. + */ + public static void main(String... args) { + String testSrc = System.getProperty("test.src"); + File baseDir = (testSrc == null) ? null : new File(testSrc); + boolean ok = new TreeScannerTest().run(baseDir, args); + if (!ok) { + if (testSrc != null) // jtreg mode + throw new Error("failed"); + else + System.exit(1); + } + } + + /** + * Run the program. A base directory can be provided for file arguments. + * In jtreg mode, the -r option can be given to change the default base + * directory to the test root directory. For other options, see usage(). + * @param baseDir base directory for any file arguments. + * @param args command line args + * @return true if successful or in gui mode + */ + boolean run(File baseDir, String... args) { + if (args.length == 0) { + usage(System.out); + return true; + } + + ArrayList files = new ArrayList(); + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + if (arg.equals("-q")) + quiet = true; + else if (arg.equals("-v")) + verbose = true; + else if (arg.equals("-r")) { + File d = baseDir; + while (!new File(d, "TEST.ROOT").exists()) { + d = d.getParentFile(); + if (d == null) + throw new Error("cannot find TEST.ROOT"); + } + baseDir = d; + } + else if (arg.startsWith("-")) + throw new Error("unknown option: " + arg); + else { + while (i < args.length) + files.add(new File(baseDir, args[i++])); + } + } + + for (File file: files) { + if (file.exists()) + test(file); + else + error("File not found: " + file); + } + + if (fileCount != 1) + System.err.println(fileCount + " files read"); + if (errors > 0) + System.err.println(errors + " errors"); + + return (errors == 0); + } + + /** + * Print command line help. + * @param out output stream + */ + void usage(PrintStream out) { + out.println("Usage:"); + out.println(" java TreeScannerTest options... files..."); + out.println(""); + out.println("where options include:"); + out.println("-q Quiet: don't report on inapplicable files"); + out.println("-v Verbose: report on files as they are being read"); + out.println(""); + out.println("files may be directories or files"); + out.println("directories will be scanned recursively"); + out.println("non java files, or java files which cannot be parsed, will be ignored"); + out.println(""); + } + + /** + * Test a file. If the file is a directory, it will be recursively scanned + * for java files. + * @param file the file or directory to test + */ + void test(File file) { + if (file.isDirectory()) { + for (File f: file.listFiles()) { + test(f); + } + return; + } + + if (file.isFile() && file.getName().endsWith(".java")) { + try { + if (verbose) + System.err.println(file); + fileCount++; + ScanTester t = new ScanTester(); + t.test(read(file)); + } catch (ParseException e) { + if (!quiet) { + error("Error parsing " + file + "\n" + e.getMessage()); + } + } catch (IOException e) { + error("Error reading " + file + ": " + e); + } + return; + } + + if (!quiet) + error("File " + file + " ignored"); + } + + /** + * Read a file. + * @param file the file to be read + * @return the tree for the content of the file + * @throws IOException if any IO errors occur + * @throws TreePosTest.ParseException if any errors occur while parsing the file + */ + JCCompilationUnit read(File file) throws IOException, ParseException { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + Reporter r = new Reporter(pw); + JavacTool tool = JavacTool.create(); + StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null); + Iterable files = fm.getJavaFileObjects(file); + JavacTask task = tool.getTask(pw, fm, r, Collections.emptyList(), null, files); + Iterable trees = task.parse(); + pw.flush(); + if (r.errors > 0) + throw new ParseException(sw.toString()); + Iterator iter = trees.iterator(); + if (!iter.hasNext()) + throw new Error("no trees found"); + JCCompilationUnit t = (JCCompilationUnit) iter.next(); + if (iter.hasNext()) + throw new Error("too many trees found"); + return t; + } + + /** + * Report an error. When the program is complete, the program will either + * exit or throw an Error if any errors have been reported. + * @param msg the error message + */ + void error(String msg) { + System.err.println(msg); + errors++; + } + + /** + * Report an error for a specific tree node. + * @param file the source file for the tree + * @param t the tree node + * @param label an indication of the error + */ + void error(JavaFileObject file, JCTree t, String msg) { + error(file.getName() + ":" + getLine(file, t) + ": " + msg + " " + trim(t, 64)); + } + + /** + * Get a trimmed string for a tree node, with normalized white space and limited length. + */ + String trim(JCTree t, int len) { + String s = t.toString().replaceAll("[\r\n]+", " ").replaceAll(" +", " "); + return (s.length() < len) ? s : s.substring(0, len); + } + + /** Number of files that have been analyzed. */ + int fileCount; + /** Number of errors reported. */ + int errors; + /** Flag: don't report irrelevant files. */ + boolean quiet; + /** Flag: report files as they are processed. */ + boolean verbose; + + /** + * Main class for testing operation of tree scanner. + * The set of nodes found by the scanner are compared + * against the set of nodes found by reflection. + */ + private class ScanTester extends TreeScanner { + /** Main entry method for the class. */ + void test(JCCompilationUnit tree) { + sourcefile = tree.sourcefile; + found = new HashSet(); + scan(tree); + expect = new HashSet(); + reflectiveScan(tree); + if (found.equals(expect)) + return; + + error("Differences found for " + tree.sourcefile.getName()); + + if (found.size() != expect.size()) + error("Size mismatch; found: " + found.size() + ", expected: " + expect.size()); + + Set missing = new HashSet(); + missing.addAll(expect); + missing.removeAll(found); + for (JCTree t: missing) + error(tree.sourcefile, t, "missing"); + + Set excess = new HashSet(); + excess.addAll(found); + excess.removeAll(expect); + for (JCTree t: excess) + error(tree.sourcefile, t, "unexpected"); + } + + /** Record all tree nodes found by scanner. */ + @Override + public void scan(JCTree tree) { + if (tree == null) + return; + System.err.println("FOUND: " + tree.getTag() + " " + trim(tree, 64)); + found.add(tree); + super.scan(tree); + } + + /** record all tree nodes found by reflection. */ + public void reflectiveScan(Object o) { + if (o == null) + return; + if (o instanceof JCTree) { + JCTree tree = (JCTree) o; + System.err.println("EXPECT: " + tree.getTag() + " " + trim(tree, 64)); + expect.add(tree); + for (Field f: getFields(tree)) { + try { + //System.err.println("FIELD: " + f.getName()); + reflectiveScan(f.get(tree)); + } catch (IllegalAccessException e) { + error(e.toString()); + } + } + } else if (o instanceof List) { + List list = (List) o; + for (Object item: list) + reflectiveScan(item); + } else + error("unexpected item: " + o); + } + + JavaFileObject sourcefile; + Set found; + Set expect; + } + + /** + * Thrown when errors are found parsing a java file. + */ + private static class ParseException extends Exception { + ParseException(String msg) { + super(msg); + } + } + + /** + * DiagnosticListener to report diagnostics and count any errors that occur. + */ + private static class Reporter implements DiagnosticListener { + Reporter(PrintWriter out) { + this.out = out; + } + + public void report(Diagnostic diagnostic) { + out.println(diagnostic); + switch (diagnostic.getKind()) { + case ERROR: + errors++; + } + } + int errors; + PrintWriter out; + } + + /** + * Get the set of fields for a tree node that may contain child tree nodes. + * These are the fields that are subtypes of JCTree or List. + * The results are cached, based on the tree's tag. + */ + Set getFields(JCTree tree) { + Set fields = map.get(tree.getTag()); + if (fields == null) { + fields = new HashSet(); + for (Field f: tree.getClass().getFields()) { + Class fc = f.getType(); + if (JCTree.class.isAssignableFrom(fc) || List.class.isAssignableFrom(fc)) + fields.add(f); + } + map.put(tree.getTag(), fields); + } + return fields; + } + // where + Map> map = new HashMap>(); + + /** Get the line number for the primary position for a tree. + * The code is intended to be simple, although not necessarily efficient. + * However, note that a file manager such as JavacFileManager is likely + * to cache the results of file.getCharContent, avoiding the need to read + * the bits from disk each time this method is called. + */ + int getLine(JavaFileObject file, JCTree tree) { + try { + CharSequence cs = file.getCharContent(true); + int line = 1; + for (int i = 0; i < tree.pos; i++) { + if (cs.charAt(i) == '\n') // jtreg tests always use Unix line endings + line++; + } + return line; + } catch (IOException e) { + return -1; + } + } +} diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/treeannotests/AnnoTreeTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/treeannotests/AnnoTreeTests.java Sun Feb 14 23:39:40 2010 -0800 @@ -0,0 +1,44 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @build DA TA Test TestProcessor + * @compile -proc:only -processor TestProcessor AnnoTreeTests.java + */ + +@Test(6) +class AnnoTreeTests { + // primitive types + @DA("int") int i1; + int i2 = (@TA("int") int) 0; + + // simple array types + @DA("int[]") int[] a1; + int @TA("int") [] a2; + int[] a3 = (@TA("int[]") int[]) a1; + int[] a4 = (int @TA("int") []) a1; + + // multi-dimensional array types + // (still to come) +} diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/treeannotests/DA.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/treeannotests/DA.java Sun Feb 14 23:39:40 2010 -0800 @@ -0,0 +1,37 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.lang.annotation.*; +import static java.lang.annotation.ElementType.*; + +/** + * Annotation used by TestProcessor to indicate the expected type + * of the declaration to which the annotation is attached. + * These annotations are expected to be found in the modifiers + * field on ClassDef, MethodDef and VarDef nodes. + */ +@Target({FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE}) +@interface DA { + String value(); +} + diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/treeannotests/TA.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/treeannotests/TA.java Sun Feb 14 23:39:40 2010 -0800 @@ -0,0 +1,36 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.lang.annotation.*; +import static java.lang.annotation.ElementType.*; + +/** + * Annotation used by TestProcessor to indicate the expected type + * to which the annotation is attached. + * These annotations are expected to be found in AnnotatedType nodes. + */ +@Target({TYPE_USE, TYPE_PARAMETER}) +@interface TA { + String value(); +} + diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/treeannotests/Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/treeannotests/Test.java Sun Feb 14 23:39:40 2010 -0800 @@ -0,0 +1,32 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * Annotation used by TestProcessor to indicate the expected number of + * @DA and @TA annotations in the source tree to which the Test annotation + * is attached. + */ +@interface Test { + int value(); +} + diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/treeannotests/TestProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/treeannotests/TestProcessor.java Sun Feb 14 23:39:40 2010 -0800 @@ -0,0 +1,302 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.io.*; +import java.util.*; +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; +import javax.lang.model.util.*; +import javax.tools.*; + +import com.sun.source.util.*; +import com.sun.tools.javac.code.BoundKind; +import com.sun.tools.javac.tree.JCTree.*; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.tree.*; +import com.sun.tools.javac.util.List; + +/** + * Test processor used to check test programs using the @Test, @DA, and @TA + * annotations. + * + * The processor looks for elements annotated with @Test, and analyzes the + * syntax trees for those elements. Within such trees, the processor looks + * for the DA annotations on decls and TA annotations on types. + * The value of these annotations should be a simple string rendition of + * the tree node to which it is attached. + * The expected number of annotations is given by the parameter to the + * @Test annotation itself. + */ +@SupportedAnnotationTypes({"Test"}) +public class TestProcessor extends AbstractProcessor { + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + /** Process trees for elements annotated with the @Test(n) annotation. */ + public boolean process(Set annos, RoundEnvironment renv) { + if (renv.processingOver()) + return true; + + Elements elements = processingEnv.getElementUtils(); + Trees trees = Trees.instance(processingEnv); + + TypeElement testAnno = elements.getTypeElement("Test"); + for (Element elem: renv.getElementsAnnotatedWith(testAnno)) { + System.err.println("ELEM: " + elem); + int count = getValue(getAnnoMirror(elem, testAnno), Integer.class); + System.err.println("count: " + count); + TreePath p = trees.getPath(elem); + JavaFileObject file = p.getCompilationUnit().getSourceFile(); + JCTree tree = (JCTree) p.getLeaf(); + System.err.println("tree: " + tree); + new TestScanner(file).check(tree, count); + } + return true; + } + + /** Get the AnnotationMirror on an element for a given annotation. */ + AnnotationMirror getAnnoMirror(Element e, TypeElement anno) { + Types types = processingEnv.getTypeUtils(); + for (AnnotationMirror m: e.getAnnotationMirrors()) { + if (types.isSameType(m.getAnnotationType(), anno.asType())) + return m; + } + return null; + } + + /** Get the value of the value element of an annotation mirror. */ + T getValue(AnnotationMirror m, Class type) { + for (Map.Entry e: m.getElementValues().entrySet()) { + ExecutableElement ee = e.getKey(); + if (ee.getSimpleName().contentEquals("value")) { + AnnotationValue av = e.getValue(); + return type.cast(av.getValue()); + } + } + return null; + } + + /** Report an error to the annotation processing system. */ + void error(String msg) { + Messager messager = processingEnv.getMessager(); + messager.printMessage(Diagnostic.Kind.ERROR, msg); + } + + /** Report an error to the annotation processing system. */ + void error(JavaFileObject file, JCTree tree, String msg) { + // need better API for reporting tree position errors to the messager + Messager messager = processingEnv.getMessager(); + String text = file.getName() + ":" + getLine(file, tree) + ": " + msg; + messager.printMessage(Diagnostic.Kind.ERROR, text); + } + + /** Get the line number for the primary position for a tree. + * The code is intended to be simple, although not necessarily efficient. + * However, note that a file manager such as JavacFileManager is likely + * to cache the results of file.getCharContent, avoiding the need to read + * the bits from disk each time this method is called. + */ + int getLine(JavaFileObject file, JCTree tree) { + try { + CharSequence cs = file.getCharContent(true); + int line = 1; + for (int i = 0; i < tree.pos; i++) { + if (cs.charAt(i) == '\n') // jtreg tests always use Unix line endings + line++; + } + return line; + } catch (IOException e) { + return -1; + } + } + + /** Scan a tree, looking for @DA and @TA annotations, and verifying that such + * annotations are attached to the expected tree node matching the string + * parameter of the annotation. + */ + class TestScanner extends TreeScanner { + /** Create a scanner for a given file. */ + TestScanner(JavaFileObject file) { + this.file = file; + } + + /** Check the annotations in a given tree. */ + void check(JCTree tree, int expectCount) { + foundCount = 0; + scan(tree); + if (foundCount != expectCount) + error(file, tree, "Wrong number of annotations found: " + foundCount + ", expected: " + expectCount); + } + + /** Check @DA annotations on a class declaration. */ + @Override + public void visitClassDef(JCClassDecl tree) { + super.visitClassDef(tree); + check(tree.mods.annotations, "DA", tree); + } + + /** Check @DA annotations on a method declaration. */ + @Override + public void visitMethodDef(JCMethodDecl tree) { + super.visitMethodDef(tree); + check(tree.mods.annotations, "DA", tree); + } + + /** Check @DA annotations on a field, parameter or local variable declaration. */ + @Override + public void visitVarDef(JCVariableDecl tree) { + super.visitVarDef(tree); + check(tree.mods.annotations, "DA", tree); + } + + /** Check @TA annotations on a type. */ + public void visitAnnotatedType(JCAnnotatedType tree) { + super.visitAnnotatedType(tree); + check(tree.annotations, "TA", tree); + } + + /** Check to see if a list of annotations contains a named annotation, and + * if so, verify the annotation is expected by comparing the value of the + * annotation's argument against the string rendition of the reference tree + * node. + * @param annos the list of annotations to be checked + * @param name the name of the annotation to be checked + * @param tree the tree against which to compare the annotations's argument + */ + void check(List annos, String name, JCTree tree) { + for (List l = annos; l.nonEmpty(); l = l.tail) { + JCAnnotation anno = l.head; + if (anno.annotationType.toString().equals(name) && (anno.args.size() == 1)) { + String expect = getStringValue(anno.args.head); + foundCount++; + System.err.println("found: " + name + " " + expect); + String found = new TypePrinter().print(tree); + if (!found.equals(expect)) + error(file, anno, "Unexpected result: expected: \"" + expect + "\", found: \"" + found + "\""); + } + } + } + + /** Get the string value of an annotation argument, which is given by the + * expression name=value. + */ + String getStringValue(JCExpression e) { + if (e.getTag() == JCTree.ASSIGN) { + JCAssign a = (JCAssign) e; + JCExpression rhs = a.rhs; + if (rhs.getTag() == JCTree.LITERAL) { + JCLiteral l = (JCLiteral) rhs; + return (String) l.value; + } + } + throw new IllegalArgumentException(e.toString()); + } + + /** The file for the tree. Used to locate errors. */ + JavaFileObject file; + /** The number of annotations that have been found. @see #check */ + int foundCount; + } + + /** Convert a type or decl tree to a reference string used by the @DA and @TA annotations. */ + class TypePrinter extends Visitor { + /** Convert a type or decl tree to a string. */ + String print(JCTree tree) { + if (tree == null) + return null; + tree.accept(this); + return result; + } + + String print(List list) { + return print(list, ", "); + } + + String print(List list, String sep) { + StringBuilder sb = new StringBuilder(); + if (list.nonEmpty()) { + sb.append(print(list.head)); + for (List l = list.tail; l.nonEmpty(); l = l.tail) { + sb.append(sep); + sb.append(print(l.head)); + } + } + return sb.toString(); + } + + @Override + public void visitClassDef(JCClassDecl tree) { + result = tree.name.toString(); + } + + @Override + public void visitMethodDef(JCMethodDecl tree) { + result = tree.name.toString(); + } + + @Override + public void visitVarDef(JCVariableDecl tree) { + tree.vartype.accept(this); + } + + @Override + public void visitAnnotatedType(JCAnnotatedType tree) { + tree.underlyingType.accept(this); + } + + @Override + public void visitTypeIdent(JCPrimitiveTypeTree tree) { + result = tree.toString(); + } + + @Override + public void visitTypeArray(JCArrayTypeTree tree) { + result = print(tree.elemtype) + "[]"; + } + + @Override + public void visitTypeApply(JCTypeApply tree) { + result = print(tree.clazz) + "<" + print(tree.arguments) + ">"; + } + + @Override + public void visitTypeParameter(JCTypeParameter tree) { + if (tree.bounds.isEmpty()) + result = tree.name.toString(); + else + result = tree.name + " extends " + print(tree.bounds, "&"); + } + + @Override + public void visitWildcard(JCWildcard tree) { + if (tree.kind.kind == BoundKind.UNBOUND) + result = tree.kind.toString(); + else + result = tree.kind + " " + print(tree.inner); + } + + private String result; + } +} diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/treepostests/TreePosTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/treepostests/TreePosTest.java Sun Feb 14 23:39:40 2010 -0800 @@ -0,0 +1,752 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultHighlighter; +import javax.swing.text.Highlighter; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticListener; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; + +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; +import com.sun.tools.javac.tree.JCTree.JCNewClass; +import com.sun.tools.javac.tree.JCTree.JCVariableDecl; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeScanner; + +import static com.sun.tools.javac.util.Position.NOPOS; + +/** + * Utility and test program to check validity of tree positions for tree nodes. + * The program can be run standalone, or as a jtreg test. In standalone mode, + * errors can be displayed in a gui viewer. For info on command line args, + * run program with no args. + * + *

+ * jtreg: Note that by using the -r switch in the test description below, this test + * will process all java files in the langtools/test directory, thus implicitly + * covering any new language features that may be tested in this test suite. + */ + +/* + * @test + * @bug 6919889 + * @summary assorted position errors in compiler syntax trees + * @run main TreePosTest -q -r -ef ./tools/javac/typeAnnotations -ef ./tools/javap/typeAnnotations . + */ +public class TreePosTest { + /** + * Main entry point. + * If test.src is set, program runs in jtreg mode, and will throw an Error + * if any errors arise, otherwise System.exit will be used, unless the gui + * viewer is being used. In jtreg mode, the default base directory for file + * args is the value of ${test.src}. In jtreg mode, the -r option can be + * given to change the default base directory to the root test directory. + */ + public static void main(String... args) { + String testSrc = System.getProperty("test.src"); + File baseDir = (testSrc == null) ? null : new File(testSrc); + boolean ok = new TreePosTest().run(baseDir, args); + if (!ok) { + if (testSrc != null) // jtreg mode + throw new Error("failed"); + else + System.exit(1); + } + } + + /** + * Run the program. A base directory can be provided for file arguments. + * In jtreg mode, the -r option can be given to change the default base + * directory to the test root directory. For other options, see usage(). + * @param baseDir base directory for any file arguments. + * @param args command line args + * @return true if successful or in gui mode + */ + boolean run(File baseDir, String... args) { + if (args.length == 0) { + usage(System.out); + return true; + } + + List files = new ArrayList(); + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + if (arg.equals("-encoding") && i + 1 < args.length) + encoding = args[++i]; + else if (arg.equals("-gui")) + gui = true; + else if (arg.equals("-q")) + quiet = true; + else if (arg.equals("-v")) + verbose = true; + else if (arg.equals("-t") && i + 1 < args.length) + tags.add(args[++i]); + else if (arg.equals("-ef") && i + 1 < args.length) + excludeFiles.add(new File(baseDir, args[++i])); + else if (arg.equals("-r")) { + if (excludeFiles.size() > 0) + throw new Error("-r must be used before -ef"); + File d = baseDir; + while (!new File(d, "TEST.ROOT").exists()) { + d = d.getParentFile(); + if (d == null) + throw new Error("cannot find TEST.ROOT"); + } + baseDir = d; + } + else if (arg.startsWith("-")) + throw new Error("unknown option: " + arg); + else { + while (i < args.length) + files.add(new File(baseDir, args[i++])); + } + } + + for (File file: files) { + if (file.exists()) + test(file); + else + error("File not found: " + file); + } + + if (fileCount != 1) + System.err.println(fileCount + " files read"); + if (errors > 0) + System.err.println(errors + " errors"); + + return (gui || errors == 0); + } + + /** + * Print command line help. + * @param out output stream + */ + void usage(PrintStream out) { + out.println("Usage:"); + out.println(" java TreePosTest options... files..."); + out.println(""); + out.println("where options include:"); + out.println("-gui Display returns in a GUI viewer"); + out.println("-q Quiet: don't report on inapplicable files"); + out.println("-v Verbose: report on files as they are being read"); + out.println("-t tag Limit checks to tree nodes with this tag"); + out.println(" Can be repeated if desired"); + out.println("-ef file Exclude file or directory"); + out.println(""); + out.println("files may be directories or files"); + out.println("directories will be scanned recursively"); + out.println("non java files, or java files which cannot be parsed, will be ignored"); + out.println(""); + } + + /** + * Test a file. If the file is a directory, it will be recursively scanned + * for java files. + * @param file the file or directory to test + */ + void test(File file) { + if (excludeFiles.contains(file)) { + if (!quiet) + error("File " + file + " excluded"); + return; + } + + if (file.isDirectory()) { + for (File f: file.listFiles()) { + test(f); + } + return; + } + + if (file.isFile() && file.getName().endsWith(".java")) { + try { + if (verbose) + System.err.println(file); + fileCount++; + PosTester p = new PosTester(); + p.test(read(file)); + } catch (ParseException e) { + if (!quiet) { + error("Error parsing " + file + "\n" + e.getMessage()); + } + } catch (IOException e) { + error("Error reading " + file + ": " + e); + } + return; + } + + if (!quiet) + error("File " + file + " ignored"); + } + + /** + * Read a file. + * @param file the file to be read + * @return the tree for the content of the file + * @throws IOException if any IO errors occur + * @throws TreePosTest.ParseException if any errors occur while parsing the file + */ + JCCompilationUnit read(File file) throws IOException, ParseException { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + Reporter r = new Reporter(pw); + JavacTool tool = JavacTool.create(); + Charset cs = (encoding == null ? null : Charset.forName(encoding)); + StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null); + Iterable files = fm.getJavaFileObjects(file); + JavacTask task = tool.getTask(pw, fm, r, Collections.emptyList(), null, files); + Iterable trees = task.parse(); + pw.flush(); + if (r.errors > 0) + throw new ParseException(sw.toString()); + Iterator iter = trees.iterator(); + if (!iter.hasNext()) + throw new Error("no trees found"); + JCCompilationUnit t = (JCCompilationUnit) iter.next(); + if (iter.hasNext()) + throw new Error("too many trees found"); + return t; + } + + /** + * Report an error. When the program is complete, the program will either + * exit or throw an Error if any errors have been reported. + * @param msg the error message + */ + void error(String msg) { + System.err.println(msg); + errors++; + } + + /** Number of files that have been analyzed. */ + int fileCount; + /** Number of errors reported. */ + int errors; + /** Flag: don't report irrelevant files. */ + boolean quiet; + /** Flag: report files as they are processed. */ + boolean verbose; + /** Flag: show errors in GUI viewer. */ + boolean gui; + /** Option: encoding for test files. */ + String encoding; + /** The GUI viewer for errors. */ + Viewer viewer; + /** The set of tags for tree nodes to be analyzed; if empty, all tree nodes + * are analyzed. */ + Set tags = new HashSet(); + /** Set of files and directories to be excluded from analysis. */ + Set excludeFiles = new HashSet(); + /** Table of printable names for tree tag values. */ + TagNames tagNames = new TagNames(); + + /** + * Main class for testing assertions concerning tree positions for tree nodes. + */ + private class PosTester extends TreeScanner { + void test(JCCompilationUnit tree) { + sourcefile = tree.sourcefile; + endPosTable = tree.endPositions; + encl = new Info(); + tree.accept(this); + } + + @Override + public void scan(JCTree tree) { + if (tree == null) + return; + + Info self = new Info(tree, endPosTable); + if (check(self)) { + // Modifiers nodes are present throughout the tree even where + // there is no corresponding source text. + // Redundant semicolons in a class definition can cause empty + // initializer blocks with no positions. + if ((self.tag == JCTree.MODIFIERS || self.tag == JCTree.BLOCK) + && self.pos == NOPOS) { + // If pos is NOPOS, so should be the start and end positions + check("start == NOPOS", encl, self, self.start == NOPOS); + check("end == NOPOS", encl, self, self.end == NOPOS); + } else { + // For this node, start , pos, and endpos should be all defined + check("start != NOPOS", encl, self, self.start != NOPOS); + check("pos != NOPOS", encl, self, self.pos != NOPOS); + check("end != NOPOS", encl, self, self.end != NOPOS); + // The following should normally be ordered + // encl.start <= start <= pos <= end <= encl.end + // In addition, the position of the enclosing node should be + // within this node. + // The primary exceptions are for array type nodes, because of the + // need to support legacy syntax: + // e.g. int a[]; int[] b[]; int f()[] { return null; } + // and because of inconsistent nesting of left and right of + // array declarations: + // e.g. int[][] a = new int[2][]; + check("encl.start <= start", encl, self, encl.start <= self.start); + check("start <= pos", encl, self, self.start <= self.pos); + if (!(self.tag == JCTree.TYPEARRAY + && (encl.tag == JCTree.VARDEF || encl.tag == JCTree.TYPEARRAY))) { + check("encl.pos <= start || end <= encl.pos", + encl, self, encl.pos <= self.start || self.end <= encl.pos); + } + check("pos <= end", encl, self, self.pos <= self.end); + if (!(self.tag == JCTree.TYPEARRAY && encl.tag == JCTree.TYPEARRAY)) { + check("end <= encl.end", encl, self, self.end <= encl.end); + } + } + } + + Info prevEncl = encl; + encl = self; + tree.accept(this); + encl = prevEncl; + } + + @Override + public void visitVarDef(JCVariableDecl tree) { + // enum member declarations are desugared in the parser and have + // ill-defined semantics for tree positions, so for now, we + // skip the synthesized bits and just check parts which came from + // the original source text + if ((tree.mods.flags & Flags.ENUM) != 0) { + scan(tree.mods); + if (tree.init != null) { + if (tree.init.getTag() == JCTree.NEWCLASS) { + JCNewClass init = (JCNewClass) tree.init; + if (init.args != null && init.args.nonEmpty()) { + scan(init.args); + } + if (init.def != null && init.def.defs != null) { + scan(init.def.defs); + } + } + } + } else + super.visitVarDef(tree); + } + + boolean check(Info x) { + return tags.size() == 0 || tags.contains(tagNames.get(x.tag)); + } + + void check(String label, Info encl, Info self, boolean ok) { + if (!ok) { + if (gui) { + if (viewer == null) + viewer = new Viewer(); + viewer.addEntry(sourcefile, label, encl, self); + } + + String s = self.tree.toString(); + String msg = sourcefile.getName() + ": " + label + ": " + + "encl:" + encl + " this:" + self + "\n" + + s.substring(0, Math.min(80, s.length())).replaceAll("[\r\n]+", " "); + error(msg); + } + } + + JavaFileObject sourcefile; + Map endPosTable; + Info encl; + + } + + /** + * Utility class providing easy access to position and other info for a tree node. + */ + private class Info { + Info() { + tree = null; + tag = JCTree.ERRONEOUS; + start = 0; + pos = 0; + end = Integer.MAX_VALUE; + } + + Info(JCTree tree, Map endPosTable) { + this.tree = tree; + tag = tree.getTag(); + start = TreeInfo.getStartPos(tree); + pos = tree.pos; + end = TreeInfo.getEndPos(tree, endPosTable); + } + + @Override + public String toString() { + return tagNames.get(tree.getTag()) + "[start:" + start + ",pos:" + pos + ",end:" + end + "]"; + } + + final JCTree tree; + final int tag; + final int start; + final int pos; + final int end; + } + + /** + * Names for tree tags. + * javac does not provide an API to convert tag values to strings, so this class uses + * reflection to determine names of public static final int values in JCTree. + */ + private static class TagNames { + String get(int tag) { + if (map == null) { + map = new HashMap(); + Class c = JCTree.class; + for (Field f : c.getDeclaredFields()) { + if (f.getType().equals(int.class)) { + int mods = f.getModifiers(); + if (Modifier.isPublic(mods) && Modifier.isStatic(mods) && Modifier.isFinal(mods)) { + try { + map.put(f.getInt(null), f.getName()); + } catch (IllegalAccessException e) { + } + } + } + } + } + String name = map.get(tag); + return (name == null) ? "??" : name; + } + + private Map map; + } + + /** + * Thrown when errors are found parsing a java file. + */ + private static class ParseException extends Exception { + ParseException(String msg) { + super(msg); + } + } + + /** + * DiagnosticListener to report diagnostics and count any errors that occur. + */ + private static class Reporter implements DiagnosticListener { + Reporter(PrintWriter out) { + this.out = out; + } + + public void report(Diagnostic diagnostic) { + out.println(diagnostic); + switch (diagnostic.getKind()) { + case ERROR: + errors++; + } + } + int errors; + PrintWriter out; + } + + /** + * GUI viewer for issues found by TreePosTester. The viewer provides a drop + * down list for selecting error conditions, a header area providing details + * about an error, and a text area with the ranges of text highlighted as + * appropriate. + */ + private class Viewer extends JFrame { + /** + * Create a viewer. + */ + Viewer() { + initGUI(); + } + + /** + * Add another entry to the list of errors. + * @param file The file containing the error + * @param check The condition that was being tested, and which failed + * @param encl the enclosing tree node + * @param self the tree node containing the error + */ + void addEntry(JavaFileObject file, String check, Info encl, Info self) { + Entry e = new Entry(file, check, encl, self); + DefaultComboBoxModel m = (DefaultComboBoxModel) entries.getModel(); + m.addElement(e); + if (m.getSize() == 1) + entries.setSelectedItem(e); + } + + /** + * Initialize the GUI window. + */ + private void initGUI() { + JPanel head = new JPanel(new GridBagLayout()); + GridBagConstraints lc = new GridBagConstraints(); + GridBagConstraints fc = new GridBagConstraints(); + fc.anchor = GridBagConstraints.WEST; + fc.fill = GridBagConstraints.HORIZONTAL; + fc.gridwidth = GridBagConstraints.REMAINDER; + + entries = new JComboBox(); + entries.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + showEntry((Entry) entries.getSelectedItem()); + } + }); + fc.insets.bottom = 10; + head.add(entries, fc); + fc.insets.bottom = 0; + head.add(new JLabel("check:"), lc); + head.add(checkField = createTextField(80), fc); + fc.fill = GridBagConstraints.NONE; + head.add(setBackground(new JLabel("encl:"), enclColor), lc); + head.add(enclPanel = new InfoPanel(), fc); + head.add(setBackground(new JLabel("self:"), selfColor), lc); + head.add(selfPanel = new InfoPanel(), fc); + add(head, BorderLayout.NORTH); + + body = new JTextArea(); + body.setFont(Font.decode(Font.MONOSPACED)); + body.addCaretListener(new CaretListener() { + public void caretUpdate(CaretEvent e) { + int dot = e.getDot(); + int mark = e.getMark(); + if (dot == mark) + statusText.setText("dot: " + dot); + else + statusText.setText("dot: " + dot + ", mark:" + mark); + } + }); + JScrollPane p = new JScrollPane(body, + JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, + JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + p.setPreferredSize(new Dimension(640, 480)); + add(p, BorderLayout.CENTER); + + statusText = createTextField(80); + add(statusText, BorderLayout.SOUTH); + + pack(); + setLocationRelativeTo(null); // centered on screen + setVisible(true); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + } + + /** Show an entry that has been selected. */ + private void showEntry(Entry e) { + try { + // update simple fields + setTitle(e.file.getName()); + checkField.setText(e.check); + enclPanel.setInfo(e.encl); + selfPanel.setInfo(e.self); + // show file text with highlights + body.setText(e.file.getCharContent(true).toString()); + Highlighter highlighter = body.getHighlighter(); + highlighter.removeAllHighlights(); + addHighlight(highlighter, e.encl, enclColor); + addHighlight(highlighter, e.self, selfColor); + scroll(body, getMinPos(enclPanel.info, selfPanel.info)); + } catch (IOException ex) { + body.setText("Cannot read " + e.file.getName() + ": " + e); + } + } + + /** Create a test field. */ + private JTextField createTextField(int width) { + JTextField f = new JTextField(width); + f.setEditable(false); + f.setBorder(null); + return f; + } + + /** Add a highlighted region based on the positions in an Info object. */ + private void addHighlight(Highlighter h, Info info, Color c) { + int start = info.start; + int end = info.end; + if (start == -1 && end == -1) + return; + if (start == -1) + start = end; + if (end == -1) + end = start; + try { + h.addHighlight(info.start, info.end, + new DefaultHighlighter.DefaultHighlightPainter(c)); + if (info.pos != -1) { + Color c2 = new Color(c.getRed(), c.getGreen(), c.getBlue(), (int)(.4f * 255)); // 40% + h.addHighlight(info.pos, info.pos + 1, + new DefaultHighlighter.DefaultHighlightPainter(c2)); + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + /** Get the minimum valid position in a set of info objects. */ + private int getMinPos(Info... values) { + int i = Integer.MAX_VALUE; + for (Info info: values) { + if (info.start >= 0) i = Math.min(i, info.start); + if (info.pos >= 0) i = Math.min(i, info.pos); + if (info.end >= 0) i = Math.min(i, info.end); + } + return (i == Integer.MAX_VALUE) ? 0 : i; + } + + /** Set the background on a component. */ + private JComponent setBackground(JComponent comp, Color c) { + comp.setOpaque(true); + comp.setBackground(c); + return comp; + } + + /** Scroll a text area to display a given position near the middle of the visible area. */ + private void scroll(final JTextArea t, final int pos) { + // Using invokeLater appears to give text a chance to sort itself out + // before the scroll happens; otherwise scrollRectToVisible doesn't work. + // Maybe there's a better way to sync with the text... + EventQueue.invokeLater(new Runnable() { + public void run() { + try { + Rectangle r = t.modelToView(pos); + JScrollPane p = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, t); + r.y = Math.max(0, r.y - p.getHeight() * 2 / 5); + r.height += p.getHeight() * 4 / 5; + t.scrollRectToVisible(r); + } catch (BadLocationException ignore) { + } + } + }); + } + + private JComboBox entries; + private JTextField checkField; + private InfoPanel enclPanel; + private InfoPanel selfPanel; + private JTextArea body; + private JTextField statusText; + + private Color selfColor = new Color(0.f, 1.f, 0.f, 0.2f); // 20% green + private Color enclColor = new Color(1.f, 0.f, 0.f, 0.2f); // 20% red + + /** Panel to display an Info object. */ + private class InfoPanel extends JPanel { + InfoPanel() { + add(tagName = createTextField(20)); + add(new JLabel("start:")); + add(addListener(start = createTextField(6))); + add(new JLabel("pos:")); + add(addListener(pos = createTextField(6))); + add(new JLabel("end:")); + add(addListener(end = createTextField(6))); + } + + void setInfo(Info info) { + this.info = info; + tagName.setText(tagNames.get(info.tag)); + start.setText(String.valueOf(info.start)); + pos.setText(String.valueOf(info.pos)); + end.setText(String.valueOf(info.end)); + } + + JTextField addListener(final JTextField f) { + f.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + body.setCaretPosition(Integer.valueOf(f.getText())); + body.getCaret().setVisible(true); + } + }); + return f; + } + + Info info; + JTextField tagName; + JTextField start; + JTextField pos; + JTextField end; + } + + /** Object to record information about an error to be displayed. */ + private class Entry { + Entry(JavaFileObject file, String check, Info encl, Info self) { + this.file = file; + this.check = check; + this.encl = encl; + this.self= self; + } + + @Override + public String toString() { + return file.getName() + " " + check + " " + getMinPos(encl, self); + } + + final JavaFileObject file; + final String check; + final Info encl; + final Info self; + } + } +} + diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/classfile/DeadCode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/typeAnnotations/classfile/DeadCode.java Sun Feb 14 23:39:40 2010 -0800 @@ -0,0 +1,181 @@ +/* + * Copyright 2009-2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.io.*; +import java.net.URL; +import java.util.List; + +import com.sun.tools.classfile.*; + +/* + * @test + * @bug 6917130 + * @summary test that optimized away annotations are not emited to classfile + */ + +public class DeadCode { + public static void main(String[] args) throws Exception { + new DeadCode().run(); + } + + public void run() throws Exception { + ClassFile cf = getClassFile("DeadCode$Test.class"); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + ClassFile getClassFile(String name) throws IOException, ConstantPoolException { + URL url = getClass().getResource(name); + InputStream in = url.openStream(); + try { + return ClassFile.read(in); + } finally { + in.close(); + } + } + + /************ Helper annotations counting methods ******************/ + void test(ClassFile cf) { + test(cf, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Method m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Field m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, String name, boolean visible) { + int index = cf.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = cf.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Field m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + void countAnnotations() { + int expected_all = expected_visibles + expected_invisibles; + + if (expected_all != all) { + errors++; + System.err.println("expected " + expected_all + + " annotations but found " + all); + } + + if (expected_visibles != visibles) { + errors++; + System.err.println("expected " + expected_visibles + + " visibles annotations but found " + visibles); + } + + if (expected_invisibles != invisibles) { + errors++; + System.err.println("expected " + expected_invisibles + + " invisibles annotations but found " + invisibles); + } + + } + + int errors; + int all; + int visibles; + int invisibles; + + /*********************** Test class *************************/ + static int expected_invisibles = 1; + static int expected_visibles = 0; + static class Test { + @interface A {} + + void test() { + List o = null; + o.toString(); + + @A String m; + if (false) { + @A String a; + @A String b = "m"; + b.toString(); + List c = null; + c.toString(); + } + } + } + +} diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/arrayclass/DuplicateAnnotationValue.java --- a/test/tools/javac/typeAnnotations/failures/common/arrayclass/DuplicateAnnotationValue.java Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/arrayclass/DuplicateAnnotationValue.java Sun Feb 14 23:39:40 2010 -0800 @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 6843077 + * @bug 6843077 6919944 * @summary check for duplicate annotation values * @author Mahmood Ali * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/arrayclass/DuplicateAnnotationValue.out --- a/test/tools/javac/typeAnnotations/failures/common/arrayclass/DuplicateAnnotationValue.out Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/arrayclass/DuplicateAnnotationValue.out Sun Feb 14 23:39:40 2010 -0800 @@ -1,2 +1,2 @@ -DuplicateAnnotationValue.java:10:45: compiler.err.duplicate.annotation.member.value: value, A +DuplicateAnnotationValue.java:10:37: compiler.err.duplicate.annotation.member.value: value, A 1 error diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.java --- a/test/tools/javac/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.java Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.java Sun Feb 14 23:39:40 2010 -0800 @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 6843077 + * @bug 6843077 6919944 * @summary check for duplicate annotation values * @author Mahmood Ali * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.out --- a/test/tools/javac/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.out Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.out Sun Feb 14 23:39:40 2010 -0800 @@ -1,2 +1,2 @@ -DuplicateAnnotationValue.java:10:34: compiler.err.duplicate.annotation.member.value: value, A +DuplicateAnnotationValue.java:10:26: compiler.err.duplicate.annotation.member.value: value, A 1 error diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.java --- a/test/tools/javac/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.java Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.java Sun Feb 14 23:39:40 2010 -0800 @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 6843077 + * @bug 6843077 6919944 * @summary check for duplicate annotation values for type parameter * @author Mahmood Ali * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.out --- a/test/tools/javac/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.out Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.out Sun Feb 14 23:39:40 2010 -0800 @@ -1,2 +1,2 @@ -DuplicateAnnotationValue.java:10:39: compiler.err.duplicate.annotation.member.value: value, A +DuplicateAnnotationValue.java:10:31: compiler.err.duplicate.annotation.member.value: value, A 1 error diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.java --- a/test/tools/javac/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.java Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.java Sun Feb 14 23:39:40 2010 -0800 @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 6843077 + * @bug 6843077 6919944 * @summary check for duplicate annotation values * @author Mahmood Ali * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.out --- a/test/tools/javac/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.out Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.out Sun Feb 14 23:39:40 2010 -0800 @@ -1,2 +1,2 @@ -DuplicateAnnotationValue.java:10:51: compiler.err.duplicate.annotation.member.value: value, A +DuplicateAnnotationValue.java:10:43: compiler.err.duplicate.annotation.member.value: value, A 1 error diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.java --- a/test/tools/javac/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.java Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.java Sun Feb 14 23:39:40 2010 -0800 @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 6843077 + * @bug 6843077 6919944 * @summary check for duplicate annotation values for type parameter * @author Mahmood Ali * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.out --- a/test/tools/javac/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.out Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.out Sun Feb 14 23:39:40 2010 -0800 @@ -1,2 +1,2 @@ -DuplicateAnnotationValue.java:8:64: compiler.err.duplicate.annotation.member.value: value, A +DuplicateAnnotationValue.java:8:56: compiler.err.duplicate.annotation.member.value: value, A 1 error diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.java --- a/test/tools/javac/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.java Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.java Sun Feb 14 23:39:40 2010 -0800 @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 6843077 + * @bug 6843077 6919944 * @summary check for duplicate annotation values in receiver * @author Mahmood Ali * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.out --- a/test/tools/javac/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.out Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.out Sun Feb 14 23:39:40 2010 -0800 @@ -1,2 +1,2 @@ -DuplicateAnnotationValue.java:9:37: compiler.err.duplicate.annotation.member.value: value, A +DuplicateAnnotationValue.java:9:29: compiler.err.duplicate.annotation.member.value: value, A 1 error diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.java --- a/test/tools/javac/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.java Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.java Sun Feb 14 23:39:40 2010 -0800 @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 6843077 + * @bug 6843077 6919944 * @summary check for duplicate annotation values for type parameter * @author Mahmood Ali * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.out --- a/test/tools/javac/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.out Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.out Sun Feb 14 23:39:40 2010 -0800 @@ -1,2 +1,2 @@ -DuplicateAnnotationValue.java:9:50: compiler.err.duplicate.annotation.member.value: value, A +DuplicateAnnotationValue.java:9:42: compiler.err.duplicate.annotation.member.value: value, A 1 error diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.java --- a/test/tools/javac/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.java Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.java Sun Feb 14 23:39:40 2010 -0800 @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 6843077 + * @bug 6843077 6919944 * @summary check for duplicate annotation values for type parameter * @author Mahmood Ali * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.out --- a/test/tools/javac/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.out Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.out Sun Feb 14 23:39:40 2010 -0800 @@ -1,2 +1,2 @@ -DuplicateAnnotationValue.java:8:54: compiler.err.duplicate.annotation.member.value: value, A +DuplicateAnnotationValue.java:8:46: compiler.err.duplicate.annotation.member.value: value, A 1 error diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.java --- a/test/tools/javac/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.java Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.java Sun Feb 14 23:39:40 2010 -0800 @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 6843077 + * @bug 6843077 6919944 * @summary check for duplicate annotation values for type parameter * @author Mahmood Ali * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javac/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.out --- a/test/tools/javac/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.out Fri Feb 12 13:25:27 2010 -0800 +++ b/test/tools/javac/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.out Sun Feb 14 23:39:40 2010 -0800 @@ -1,2 +1,2 @@ -DuplicateAnnotationValue.java:9:50: compiler.err.duplicate.annotation.member.value: value, A +DuplicateAnnotationValue.java:9:42: compiler.err.duplicate.annotation.member.value: value, A 1 error diff -r 2edcb5dc642d -r d9cd5b8286e4 test/tools/javap/typeAnnotations/ArrayClassLiterals2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javap/typeAnnotations/ArrayClassLiterals2.java Sun Feb 14 23:39:40 2010 -0800 @@ -0,0 +1,82 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6918625 + * @summary javap dumps type information of array class literals + */ + +import java.io.*; + +public class ArrayClassLiterals2 { + public static void main(String[] args) throws Exception { + new ArrayClassLiterals2().run(); + } + + public void run() throws IOException { + File classFile = new File(System.getProperty("test.classes"), "ArrayClassLiterals2$Test.class"); + + verify(classFile, + "RuntimeInvisibleTypeAnnotations:", + "CLASS_LITERAL_GENERIC_OR_ARRAY" + ); + + if (errors > 0) + throw new Error(errors + " found."); + } + + String javap(File f) { + StringWriter sw = new StringWriter(); + PrintWriter out = new PrintWriter(sw); + int rc = com.sun.tools.javap.Main.run(new String[] { "-v", f.getPath() }, out); + if (rc != 0) + throw new Error("javap failed. rc=" + rc); + out.close(); + return sw.toString(); + } + + void verify(File classFile, String... expects) { + String output = javap(classFile); + for (String expect: expects) { + if (output.indexOf(expect)< 0) + error(expect + " not found"); + } + } + + void error(String msg) { + System.err.println(msg); + errors++; + } + + int errors; + + + /*********************** Test class *************************/ + static class Test { + @interface A { } + void test() { + Object a = @A String @A [] @A [].class; + } + } +}