提交 37b74a0d 编写于 作者: L lana

Merge

......@@ -744,6 +744,7 @@ public class ClassWriter {
out.writeByte(p.type_index);
break;
case CLASS_LITERAL:
case CLASS_LITERAL_GENERIC_OR_ARRAY:
out.writeShort(p.offset);
break;
// method parameter: not specified
......
......@@ -123,11 +123,14 @@ public class ExtendedAnnotation {
// 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 @@ public class ExtendedAnnotation {
// 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 class ExtendedAnnotation {
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;
......
......@@ -113,6 +113,7 @@ public class Flags {
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
......
......@@ -657,6 +657,11 @@ public abstract class Symbol implements Element {
public List<Attribute.Compound> 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;
}
......
......@@ -49,18 +49,18 @@ public class TypeAnnotationPosition {
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 @@ public class TypeAnnotationPosition {
sb.append(type_index);
break;
case CLASS_LITERAL:
case CLASS_LITERAL_GENERIC_OR_ARRAY:
sb.append(", offset = ");
sb.append(offset);
break;
......
/*
* 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<TypeAnnotations> key
= new Context.Key<TypeAnnotations>();
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<JCTree> 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<JCTree> 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<JCTree> newPath = path.tail;
return resolveFrame(newPath.head, newPath.tail.head, newPath, p);
}
case ARRAY_TYPE: {
p.location = p.location.prepend(0);
List<JCTree> 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<JCTree> 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<JCTree> 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<JCTypeAnnotation> 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<JCTypeAnnotation> 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<JCTree> path, JCTree param) {
List<JCTree> 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<Attribute.TypeCompound> 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<Attribute.TypeCompound> 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<Attribute.TypeCompound> 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<Attribute.TypeCompound> 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);
}
}
}
......@@ -2047,7 +2047,7 @@ public class Check {
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);
......
......@@ -100,6 +100,7 @@ public class Enter extends JCTree.Visitor {
MemberEnter memberEnter;
Types types;
Lint lint;
Names names;
JavaFileManager fileManager;
private final Todo todo;
......@@ -123,6 +124,7 @@ public class Enter extends JCTree.Visitor {
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 @@ public class Enter extends JCTree.Visitor {
}
}
}
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) {
......
......@@ -1994,19 +1994,14 @@ public class Lower extends TreeTranslator {
tree.packageAnnotations),
name, List.<JCTypeParameter>nil(),
null, List.<JCExpression>nil(), List.<JCTree>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);
}
}
......
......@@ -1065,11 +1065,6 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
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);
......
......@@ -61,8 +61,6 @@ public class TransTypes extends TreeTranslator {
return instance;
}
private boolean debugJSR308;
private Names names;
private Log log;
private Symtab syms;
......@@ -71,6 +69,7 @@ public class TransTypes extends TreeTranslator {
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 @@ public class TransTypes extends TreeTranslator {
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 class TransTypes extends TreeTranslator {
}
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 @@ public class TransTypes extends TreeTranslator {
pt = null;
return translate(cdef, null);
}
private class TypeAnnotationPositions extends TreeScanner {
private ListBuffer<JCTree> 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<JCTree> 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<JCTree> newPath = path.tail;
return resolveFrame(newPath.head, newPath.tail.head, newPath, p);
}
case ARRAY_TYPE: {
p.location = p.location.prepend(0);
List<JCTree> 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<JCTree> 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<JCTree> 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<JCTypeAnnotation> 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<JCTypeAnnotation> 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<JCTree> path, JCTree param) {
List<JCTree> 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<Attribute.TypeCompound> 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<Attribute.TypeCompound> 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<Attribute.TypeCompound> 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<Attribute.TypeCompound> 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);
}
}
}
......@@ -1425,11 +1425,11 @@ public class ClassReader implements Completer {
// 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:
......
......@@ -965,11 +965,11 @@ public class ClassWriter extends ClassFile {
// 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:
......
......@@ -1926,9 +1926,9 @@ public class Code {
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;
}
......
......@@ -1714,7 +1714,7 @@ public class Gen extends JCTree.Visitor {
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 @@ public class Gen extends JCTree.Visitor {
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 @@ public class Gen extends JCTree.Visitor {
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 @@ public class Gen extends JCTree.Visitor {
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);
......
......@@ -761,23 +761,28 @@ public class JavacParser implements Parser {
JCExpression[] odStack = newOdStack();
List<Token[]> savedOp = opStackSupply.elems;
Token[] opStack = newOpStack();
List<int[]> 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 @@ public class JavacParser implements Parser {
odStackSupply.elems = savedOd; // optimization
opStackSupply.elems = savedOp; // optimization
posStackSupply.elems = savedPos; // optimization
return t;
}
//where
......@@ -845,6 +851,7 @@ public class JavacParser implements Parser {
*/
ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
ListBuffer<int[]> posStackSupply = new ListBuffer<int[]>();
private JCExpression[] newOdStack() {
if (odStackSupply.elems == odStackSupply.last)
......@@ -862,6 +869,14 @@ public class JavacParser implements Parser {
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 @@ public class JavacParser implements Parser {
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 @@ public class JavacParser implements Parser {
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 @@ public class JavacParser implements Parser {
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 @@ public class JavacParser implements Parser {
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 @@ public class JavacParser implements Parser {
JCIdent id = toP(F.at(S.pos()).Ident(ident()));
result = F.at(pos).Erroneous(List.<JCTree>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 @@ public class JavacParser implements Parser {
return modifiersOpt(null);
}
JCModifiers modifiersOpt(JCModifiers partial) {
long flags = (partial == null) ? 0 : partial.flags;
long flags;
ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
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<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
if (partial != null) annotations.appendList(partial.annotations);
int pos = S.pos();
int lastPos = Position.NOPOS;
loop:
while (true) {
......@@ -2150,12 +2176,12 @@ public class JavacParser implements Parser {
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 @@ public class JavacParser implements Parser {
/* 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 @@ public class JavacParser implements Parser {
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 @@ public class JavacParser implements Parser {
}
List<JCTree> 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.<JCTypeParameter>nil(),
ClassDef(mods, name, List.<JCTypeParameter>nil(),
null, implementing, defs));
attach(result, dc);
return result;
......@@ -2695,16 +2721,8 @@ public class JavacParser implements Parser {
} else {
pos = S.pos();
List<JCTypeParameter> 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<JCAnnotation> annosAfterParams = annotationsOpt(AnnotationKind.DEFAULT_ANNO);
Token token = S.token();
Name name = S.name();
pos = S.pos();
JCExpression type;
......@@ -2715,7 +2733,11 @@ public class JavacParser implements Parser {
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 @@ public class JavacParser implements Parser {
}
}
}
JCMethodDecl result =
toP(F.at(pos).MethodDef(mods, name, type, typarams,
params, receiverAnnotations, thrown,
......
......@@ -67,6 +67,7 @@ import com.sun.tools.javac.tree.*;
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 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
errorStatus = true;
break runAround;
} else {
ListBuffer<ClassSymbol> classes = enterNewClassFiles(currentContext);
List<ClassSymbol> newClasses = enterNewClassFiles(currentContext);
compiler.enterTrees(roots);
// annotationsPresentInSource =
// collector.findAnnotations(parsedFiles);
classes.appendList(getTopLevelClasses(parsedFiles));
topLevelClasses = classes.toList();
packageInfoFiles = getPackageInfoFiles(parsedFiles);
ListBuffer<ClassSymbol> tlc = new ListBuffer<ClassSymbol>();
tlc.appendList(getTopLevelClasses(parsedFiles));
tlc.appendList(getTopLevelClassesFromClasses(newClasses));
topLevelClasses = tlc.toList();
ListBuffer<PackageSymbol> pif = new ListBuffer<PackageSymbol>();
pif.appendList(getPackageInfoFiles(parsedFiles));
pif.appendList(getPackageInfoFilesFromClasses(newClasses));
packageInfoFiles = pif.toList();
annotationsPresent = new LinkedHashSet<TypeElement>();
for (ClassSymbol classSym : topLevelClasses)
......@@ -1026,20 +1033,30 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
}
}
private ListBuffer<ClassSymbol> enterNewClassFiles(Context currentContext) {
private List<ClassSymbol> enterNewClassFiles(Context currentContext) {
ClassReader reader = ClassReader.instance(currentContext);
Names names = Names.instance(currentContext);
ListBuffer<ClassSymbol> list = new ListBuffer<ClassSymbol>();
List<ClassSymbol> list = List.nil();
for (Map.Entry<String,JavaFileObject> 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 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
return classes.reverse();
}
private List<ClassSymbol> getTopLevelClassesFromClasses(List<? extends ClassSymbol> syms) {
List<ClassSymbol> classes = List.nil();
for (ClassSymbol sym : syms) {
if (!isPkgInfo(sym)) {
classes = classes.prepend(sym);
}
}
return classes.reverse();
}
private List<PackageSymbol> getPackageInfoFiles(List<? extends JCCompilationUnit> units) {
List<PackageSymbol> 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<PackageSymbol> getPackageInfoFilesFromClasses(List<? extends ClassSymbol> syms) {
List<PackageSymbol> 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 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
node.sym = null;
super.visitIdent(node);
}
public void visitApply(JCMethodInvocation node) {
scan(node.typeargs);
super.visitApply(node);
}
};
......
......@@ -307,8 +307,18 @@ public class TreeInfo {
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 @@ public class TreeInfo {
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())
......
......@@ -480,7 +480,7 @@ public class TreeMaker implements JCTree.Factory {
public JCModifiers Modifiers(long flags, List<JCAnnotation> 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;
}
......
......@@ -193,6 +193,7 @@ public class TreeScanner extends Visitor {
}
public void visitApply(JCMethodInvocation tree) {
scan(tree.typeargs);
scan(tree.meth);
scan(tree.args);
}
......@@ -200,6 +201,7 @@ public class TreeScanner extends Visitor {
public void visitNewClass(JCNewClass tree) {
scan(tree.encl);
scan(tree.clazz);
scan(tree.typeargs);
scan(tree.args);
scan(tree.def);
}
......
......@@ -162,6 +162,7 @@ public class AnnotationWriter extends BasicWriter {
print(pos.type_index);
break;
case CLASS_LITERAL:
case CLASS_LITERAL_GENERIC_OR_ARRAY:
if (showOffsets) {
print(", offset=");
print(pos.offset);
......
/*
* 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;
}
}
}
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<X>, Neg01<java.lang.String>)
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<java.lang.Number>
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<X>, Neg01<? super java.lang.String>)
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<X>, Neg01<java.lang.String>)
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<java.lang.Number>
Neg01.java:25:38: compiler.err.cant.resolve.location.args: kindname.constructor, Neg01, , , kindname.class, Neg01<java.lang.Number>
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<X>, Neg01<? super java.lang.String>)
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<X>, Neg01<java.lang.String>)
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<java.lang.Number>
Neg01.java:31:9: compiler.err.cant.resolve.location: kindname.class, Foo, , , kindname.class, Neg01<X>
Neg01.java:31:35: compiler.err.cant.resolve.location.args: kindname.constructor, Neg01, , java.lang.String,java.lang.String, kindname.class, Neg01<java.lang.Number>
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<X>, Neg01<java.lang.String>)
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<java.lang.Number>
Neg01.java:35:43: compiler.err.cant.resolve.location.args: kindname.constructor, Neg01, , , kindname.class, Neg01<java.lang.Number>
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<X>, Neg01<? super java.lang.String>)
30 errors
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<X>, Neg02.Foo<java.lang.String>)
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<java.lang.Number>
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<X>, Neg02.Foo<? super java.lang.String>)
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<X>, Neg02.Foo<java.lang.String>)
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<java.lang.Number>
Neg02.java:26:34: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg02.Foo<java.lang.Number>
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<X>, Neg02.Foo<? super java.lang.String>)
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<X>, Neg02.Foo<java.lang.String>)
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<java.lang.Number>
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<X>, Neg02.Foo<? super java.lang.String>)
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<X>, Neg02.Foo<java.lang.String>)
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<java.lang.Number>
Neg02.java:36:39: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg02.Foo<java.lang.Number>
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<X>, Neg02.Foo<? super java.lang.String>)
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<X>, Neg02.Foo<java.lang.String>)
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<java.lang.Number>
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<X>, Neg02.Foo<? super java.lang.String>)
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<X>, Neg02.Foo<java.lang.String>)
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<java.lang.Number>
Neg02.java:48:40: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg02.Foo<java.lang.Number>
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<X>, Neg02.Foo<? super java.lang.String>)
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<X>, Neg02.Foo<java.lang.String>)
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<java.lang.Number>
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<X>, Neg02.Foo<? super java.lang.String>)
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<X>, Neg02.Foo<java.lang.String>)
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<java.lang.Number>
Neg02.java:58:45: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg02.Foo<java.lang.Number>
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<X>, Neg02.Foo<? super java.lang.String>)
60 errors
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<U>.Foo<V>, Neg03<U>.Foo<java.lang.String>)
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<U>.Foo<java.lang.Number>
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<U>.Foo<V>, Neg03<U>.Foo<? super java.lang.String>)
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<U>.Foo<V>, Neg03<U>.Foo<java.lang.String>)
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<U>.Foo<java.lang.Number>
Neg03.java:26:34: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03<U>.Foo<java.lang.Number>
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<U>.Foo<V>, Neg03<U>.Foo<? super java.lang.String>)
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<U>.Foo<V>, Neg03<U>.Foo<java.lang.String>)
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<U>.Foo<java.lang.Number>
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<U>.Foo<V>, Neg03<U>.Foo<? super java.lang.String>)
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<U>.Foo<V>, Neg03<U>.Foo<java.lang.String>)
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<U>.Foo<java.lang.Number>
Neg03.java:36:39: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03<U>.Foo<java.lang.Number>
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<U>.Foo<V>, Neg03<U>.Foo<? super java.lang.String>)
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<U>.Foo<V>, Neg03<U>.Foo<java.lang.String>)
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<U>.Foo<java.lang.Number>
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<U>.Foo<V>, Neg03<U>.Foo<? super java.lang.String>)
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<U>.Foo<V>, Neg03<U>.Foo<java.lang.String>)
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<U>.Foo<java.lang.Number>
Neg03.java:48:43: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03<U>.Foo<java.lang.Number>
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<U>.Foo<V>, Neg03<U>.Foo<? super java.lang.String>)
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<U>.Foo<V>, Neg03<U>.Foo<java.lang.String>)
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<U>.Foo<java.lang.Number>
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<U>.Foo<V>, Neg03<U>.Foo<? super java.lang.String>)
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<U>.Foo<V>, Neg03<U>.Foo<java.lang.String>)
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<U>.Foo<java.lang.Number>
Neg03.java:58:48: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03<U>.Foo<java.lang.Number>
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<U>.Foo<V>, Neg03<U>.Foo<? super java.lang.String>)
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<U>.Foo<V>, Neg03<U>.Foo<java.lang.String>)
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<U>.Foo<java.lang.Number>
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<U>.Foo<V>, Neg03<U>.Foo<? super java.lang.String>)
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<U>.Foo<V>, Neg03<U>.Foo<java.lang.String>)
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<U>.Foo<java.lang.Number>
Neg03.java:70:36: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03<U>.Foo<java.lang.Number>
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<U>.Foo<V>, Neg03<U>.Foo<? super java.lang.String>)
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<U>.Foo<V>, Neg03<U>.Foo<java.lang.String>)
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<U>.Foo<java.lang.Number>
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<U>.Foo<V>, Neg03<U>.Foo<? super java.lang.String>)
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<U>.Foo<V>, Neg03<U>.Foo<java.lang.String>)
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<U>.Foo<java.lang.Number>
Neg03.java:80:41: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03<U>.Foo<java.lang.Number>
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<U>.Foo<V>, Neg03<U>.Foo<? super java.lang.String>)
90 errors
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<V>, Foo<java.lang.String>)
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<java.lang.Number>
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<V>, Foo<? super java.lang.String>)
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<V>, Foo<java.lang.String>)
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<java.lang.Number>
Neg04.java:25:34: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Foo<java.lang.Number>
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<V>, Foo<? super java.lang.String>)
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<V>, Foo<java.lang.String>)
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<java.lang.Number>
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<V>, Foo<? super java.lang.String>)
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<V>, Foo<java.lang.String>)
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<java.lang.Number>
Neg04.java:35:39: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Foo<java.lang.Number>
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<V>, Foo<? super java.lang.String>)
30 errors
/*
* 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<? extends TypeElement> 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);
}
}
/*
* 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 {}
/*
* 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<String> opts = new ArrayList<String>();
List<File> files = new ArrayList<File>();
// 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<String> opts2 = new ArrayList<String>();
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<String> opts, List<File> files) throws Exception {
System.err.println("javac: " + opts + " " + files);
List<String> args = new ArrayList<String>();
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<Integer> tests = new HashSet<Integer>();
/* 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<? extends TypeElement> 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<? extends AnnotationMirror> 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;
}
}
/*
* 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 <Integer>C(); // exercises TreeScanner.visitNewClass
Object o = c.<Float>m(); // exercises TreeScanner.visitApply
}
static class C {
<T> C() { }
<T> T m() { return null; }
}
}
/*
* 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.
*
* <p>
* 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<File> files = new ArrayList<File>();
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<? extends JavaFileObject> files = fm.getJavaFileObjects(file);
JavacTask task = tool.getTask(pw, fm, r, Collections.<String>emptyList(), null, files);
Iterable<? extends CompilationUnitTree> trees = task.parse();
pw.flush();
if (r.errors > 0)
throw new ParseException(sw.toString());
Iterator<? extends CompilationUnitTree> 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<JCTree>();
scan(tree);
expect = new HashSet<JCTree>();
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<JCTree> missing = new HashSet<JCTree>();
missing.addAll(expect);
missing.removeAll(found);
for (JCTree t: missing)
error(tree.sourcefile, t, "missing");
Set<JCTree> excess = new HashSet<JCTree>();
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<JCTree> found;
Set<JCTree> 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<JavaFileObject> {
Reporter(PrintWriter out) {
this.out = out;
}
public void report(Diagnostic<? extends JavaFileObject> 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<Field> getFields(JCTree tree) {
Set<Field> fields = map.get(tree.getTag());
if (fields == null) {
fields = new HashSet<Field>();
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<Integer, Set<Field>> map = new HashMap<Integer,Set<Field>>();
/** 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;
}
}
}
/*
* 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)
}
/*
* 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();
}
/*
* 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();
}
/*
* 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();
}
/*
* 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<? extends TypeElement> 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> T getValue(AnnotationMirror m, Class<T> type) {
for (Map.Entry<? extends ExecutableElement,? extends AnnotationValue> 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<? extends JCAnnotation> annos, String name, JCTree tree) {
for (List<? extends JCAnnotation> 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 <i>name</i>=<i>value</i>.
*/
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<? extends JCTree> list) {
return print(list, ", ");
}
String print(List<? extends JCTree> list, String sep) {
StringBuilder sb = new StringBuilder();
if (list.nonEmpty()) {
sb.append(print(list.head));
for (List<? extends JCTree> 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;
}
}
此差异已折叠。
/*
* 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<? extends @A Object> o = null;
o.toString();
@A String m;
if (false) {
@A String a;
@A String b = "m";
b.toString();
List<? extends @A Object> c = null;
c.toString();
}
}
}
}
/*
* @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
......
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
/*
* @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
......
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
/*
* @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
......
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
/*
* @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
......
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
/*
* @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
......
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
/*
* @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
......
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
/*
* @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
......
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
/*
* @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
......
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
/*
* @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
......
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
/*
* 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;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册