8033004: Make base TypeAnnotationPosition data immutable, create better methods for creating base TypeAnnotationPositions

First of a series of major fixes to type annotations; cleans up interface with TypeAnnotationPosition

Reviewed-by: jjg
This commit is contained in:
Eric McCorkle 2014-02-03 17:19:15 -05:00
parent 4724c454cd
commit 3bd9bdd993
6 changed files with 1311 additions and 296 deletions

View File

@ -425,11 +425,15 @@ public class SymbolMetadata {
private final List<T> placeholderFor; private final List<T> placeholderFor;
private final Symbol on; private final Symbol on;
public Placeholder(Annotate.AnnotateRepeatedContext<T> ctx, List<T> placeholderFor, Symbol on) { public Placeholder(Annotate.AnnotateRepeatedContext<T> ctx,
List<T> placeholderFor, Symbol on) {
super(on.type, List.<Pair<Symbol.MethodSymbol, Attribute>>nil(), super(on.type, List.<Pair<Symbol.MethodSymbol, Attribute>>nil(),
ctx.isTypeCompound ? ctx.isTypeCompound ?
((Attribute.TypeCompound)placeholderFor.head).position : ((Attribute.TypeCompound)placeholderFor.head).position :
new TypeAnnotationPosition()); // TODO: Eventually, we will need to get rid of this
// use of unknown, either by using null, or by
// throwing an assertion failure here.
TypeAnnotationPosition.unknown);
this.ctx = ctx; this.ctx = ctx;
this.placeholderFor = placeholderFor; this.placeholderFor = placeholderFor;
this.on = on; this.on = on;

View File

@ -119,13 +119,20 @@ public class TypeAnnotationPosition {
} }
} }
public TargetType type = TargetType.UNKNOWN; public static final List<TypePathEntry> emptyPath = List.nil();
// NOTE: All of these will be converted to final fields eventually.
public final TargetType type;
// For generic/array types. // For generic/array types.
public List<TypePathEntry> location = List.nil();
// This field is in the process of being made final. Do not
// introduce new mutations.
public List<TypePathEntry> location;
// Tree position. // Tree position.
public int pos = -1; public final int pos;
// For type casts, type tests, new, locals (as start_pc), // For type casts, type tests, new, locals (as start_pc),
// and method and constructor reference type arguments. // and method and constructor reference type arguments.
@ -138,13 +145,17 @@ public class TypeAnnotationPosition {
public int[] lvarIndex = null; public int[] lvarIndex = null;
// For type parameter bound // For type parameter bound
public int bound_index = Integer.MIN_VALUE; public final int bound_index;
// For type parameter and method parameter // For type parameter and method parameter
public int parameter_index = Integer.MIN_VALUE; public final int parameter_index;
// For class extends, implements, and throws clauses // For class extends, implements, and throws clauses
public int type_index = Integer.MIN_VALUE;
// This field is effectively final. However, it needs to be
// modified by Gen for the time being. Do not introduce new
// mutations.
public int type_index;
// For exception parameters, index into exception table. // For exception parameters, index into exception table.
// In com.sun.tools.javac.jvm.Gen.genCatch we first set the type_index // In com.sun.tools.javac.jvm.Gen.genCatch we first set the type_index
@ -156,9 +167,10 @@ public class TypeAnnotationPosition {
// If this type annotation is within a lambda expression, // If this type annotation is within a lambda expression,
// store a pointer to the lambda expression tree in order // store a pointer to the lambda expression tree in order
// to allow a later translation to the right method. // to allow a later translation to the right method.
public JCLambda onLambda = null; public final JCLambda onLambda;
public TypeAnnotationPosition() {} // NOTE: This constructor will eventually go away, and be replaced
// by static builder methods.
@Override @Override
public String toString() { public String toString() {
@ -323,4 +335,847 @@ public class TypeAnnotationPosition {
} }
return loc.toList(); return loc.toList();
} }
// These methods are the new preferred way to create
// TypeAnnotationPositions
// Never make this a public constructor without creating a builder.
private TypeAnnotationPosition(final TargetType ttype,
final int pos,
final int parameter_index,
final JCLambda onLambda,
final int type_index,
final int bound_index,
final List<TypePathEntry> location) {
Assert.checkNonNull(location);
this.type = ttype;
this.pos = pos;
this.parameter_index = parameter_index;
this.onLambda = onLambda;
this.type_index = type_index;
this.bound_index = bound_index;
this.location = location;
}
/**
* Create a {@code TypeAnnotationPosition} for a method return.
*
* @param location The type path.
* @param onLambda The lambda for this parameter.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
methodReturn(final List<TypePathEntry> location,
final JCLambda onLambda,
final int pos) {
return new TypeAnnotationPosition(TargetType.METHOD_RETURN, pos,
Integer.MIN_VALUE, onLambda,
Integer.MIN_VALUE, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a method return.
*
* @param location The type path.
*/
public static TypeAnnotationPosition
methodReturn(final List<TypePathEntry> location) {
return methodReturn(location, null, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a method return.
*
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition methodReturn(final int pos) {
return methodReturn(emptyPath, null, pos);
}
/**
* Create a {@code TypeAnnotationPosition} for a method receiver.
*
* @param location The type path.
* @param onLambda The lambda for this parameter.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
methodReceiver(final List<TypePathEntry> location,
final JCLambda onLambda,
final int pos) {
return new TypeAnnotationPosition(TargetType.METHOD_RECEIVER, pos,
Integer.MIN_VALUE, onLambda,
Integer.MIN_VALUE, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a method receiver.
*
* @param location The type path.
*/
public static TypeAnnotationPosition
methodReceiver(final List<TypePathEntry> location) {
return methodReceiver(location, null, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a method receiver.
*
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition methodReceiver(final int pos) {
return methodReceiver(emptyPath, null, pos);
}
/**
* Create a {@code TypeAnnotationPosition} for a method formal parameter.
*
* @param location The type path.
* @param onLambda The lambda for this parameter.
* @param index The index of the parameter.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
methodParameter(final List<TypePathEntry> location,
final JCLambda onLambda,
final int parameter_index,
final int pos) {
return new TypeAnnotationPosition(TargetType.METHOD_FORMAL_PARAMETER,
pos, parameter_index, onLambda,
Integer.MIN_VALUE, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a method formal parameter.
*
* @param onLambda The lambda for this parameter.
* @param index The index of the parameter.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
methodParameter(final JCLambda onLambda,
final int parameter_index,
final int pos) {
return methodParameter(emptyPath, onLambda,
parameter_index, pos);
}
/**
* Create a {@code TypeAnnotationPosition} for a method formal parameter.
*
* @param index The index of the parameter.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
methodParameter(final int parameter_index,
final int pos) {
return methodParameter(null, parameter_index, pos);
}
/**
* Create a {@code TypeAnnotationPosition} for a method formal parameter.
*
* @param location The type path.
* @param index The index of the parameter.
*/
public static TypeAnnotationPosition
methodParameter(final List<TypePathEntry> location,
final int parameter_index) {
return methodParameter(location, null, parameter_index, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a method reference.
*
* @param location The type path.
* @param onLambda The lambda for this method reference.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
methodRef(final List<TypePathEntry> location,
final JCLambda onLambda,
final int pos) {
return new TypeAnnotationPosition(TargetType.METHOD_REFERENCE, pos,
Integer.MIN_VALUE, onLambda,
Integer.MIN_VALUE, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a method reference.
*
* @param location The type path.
* @param onLambda The lambda for this method reference.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
methodRef(final List<TypePathEntry> location) {
return methodRef(location, null, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a constructor reference.
*
* @param location The type path.
* @param onLambda The lambda for this constructor reference.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
constructorRef(final List<TypePathEntry> location,
final JCLambda onLambda,
final int pos) {
return new TypeAnnotationPosition(TargetType.CONSTRUCTOR_REFERENCE, pos,
Integer.MIN_VALUE, onLambda,
Integer.MIN_VALUE, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a constructor reference.
*
* @param location The type path.
* @param onLambda The lambda for this constructor reference.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
constructorRef(final List<TypePathEntry> location) {
return constructorRef(location, null, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a field.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
field(final List<TypePathEntry> location,
final JCLambda onLambda,
final int pos) {
return new TypeAnnotationPosition(TargetType.FIELD, pos,
Integer.MIN_VALUE, onLambda,
Integer.MIN_VALUE, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a field.
*
* @param location The type path.
*/
public static TypeAnnotationPosition
field(final List<TypePathEntry> location) {
return field(location, null, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a field.
*
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition field(final int pos) {
return field(emptyPath, null, pos);
}
/**
* Create a {@code TypeAnnotationPosition} for a local variable.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
localVariable(final List<TypePathEntry> location,
final JCLambda onLambda,
final int pos) {
return new TypeAnnotationPosition(TargetType.LOCAL_VARIABLE, pos,
Integer.MIN_VALUE, onLambda,
Integer.MIN_VALUE, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a local variable.
*
* @param onLambda The lambda for this variable.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
localVariable(final JCLambda onLambda,
final int pos) {
return localVariable(emptyPath, onLambda, pos);
}
/**
* Create a {@code TypeAnnotationPosition} for a local variable.
*
* @param location The type path.
*/
public static TypeAnnotationPosition
localVariable(final List<TypePathEntry> location) {
return localVariable(location, null, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for an exception parameter.
*
* @param location The type path.
* @param onLambda The lambda for this parameter.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
exceptionParameter(final List<TypePathEntry> location,
final JCLambda onLambda,
final int pos) {
return new TypeAnnotationPosition(TargetType.EXCEPTION_PARAMETER, pos,
Integer.MIN_VALUE, onLambda,
Integer.MIN_VALUE, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for an exception parameter.
*
* @param onLambda The lambda for this parameter.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
exceptionParameter(final JCLambda onLambda,
final int pos) {
return exceptionParameter(emptyPath, onLambda, pos);
}
/**
* Create a {@code TypeAnnotationPosition} for an exception parameter.
*
* @param location The type path.
*/
public static TypeAnnotationPosition
exceptionParameter(final List<TypePathEntry> location) {
return exceptionParameter(location, null, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a resource variable.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
resourceVariable(final List<TypePathEntry> location,
final JCLambda onLambda,
final int pos) {
return new TypeAnnotationPosition(TargetType.RESOURCE_VARIABLE, pos,
Integer.MIN_VALUE, onLambda,
Integer.MIN_VALUE, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a resource variable.
*
* @param onLambda The lambda for this variable.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
resourceVariable(final JCLambda onLambda,
final int pos) {
return resourceVariable(emptyPath, onLambda, pos);
}
/**
* Create a {@code TypeAnnotationPosition} for a resource variable.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
resourceVariable(final List<TypePathEntry> location) {
return resourceVariable(location, null, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a new.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
newObj(final List<TypePathEntry> location,
final JCLambda onLambda,
final int pos) {
return new TypeAnnotationPosition(TargetType.NEW, pos,
Integer.MIN_VALUE, onLambda,
Integer.MIN_VALUE, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a new.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition newObj(final int pos) {
return newObj(emptyPath, null, pos);
}
/**
* Create a {@code TypeAnnotationPosition} for a new.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
newObj(final List<TypePathEntry> location) {
return newObj(location, null, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a class extension.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param type_index The index of the interface.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
classExtends(final List<TypePathEntry> location,
final JCLambda onLambda,
final int type_index,
final int pos) {
return new TypeAnnotationPosition(TargetType.CLASS_EXTENDS, pos,
Integer.MIN_VALUE, onLambda,
type_index, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a class extension.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param type_index The index of the interface.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
classExtends(final List<TypePathEntry> location,
final JCLambda onLambda,
final int pos) {
return classExtends(location, onLambda, -1, pos);
}
/**
* Create a {@code TypeAnnotationPosition} for a class extension.
*
* @param location The type path.
* @param type_index The index of the interface.
*/
public static TypeAnnotationPosition
classExtends(final List<TypePathEntry> location,
final int type_index) {
return classExtends(location, null, type_index, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a class extension.
*
* @param type_index The index of the interface.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition classExtends(final int type_index,
final int pos) {
return classExtends(emptyPath, null, type_index, pos);
}
/**
* Create a {@code TypeAnnotationPosition} for a class extension.
*
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition classExtends(final int pos) {
return classExtends(-1, pos);
}
/**
* Create a {@code TypeAnnotationPosition} for an instanceof.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
instanceOf(final List<TypePathEntry> location,
final JCLambda onLambda,
final int pos) {
return new TypeAnnotationPosition(TargetType.INSTANCEOF, pos,
Integer.MIN_VALUE, onLambda,
Integer.MIN_VALUE, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for an instanceof.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
instanceOf(final List<TypePathEntry> location) {
return instanceOf(location, null, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a type cast.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param type_index The index into an intersection type.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
typeCast(final List<TypePathEntry> location,
final JCLambda onLambda,
final int type_index,
final int pos) {
return new TypeAnnotationPosition(TargetType.CAST, pos,
Integer.MIN_VALUE, onLambda,
type_index, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a type cast.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param type_index The index into an intersection type.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
typeCast(final List<TypePathEntry> location,
final int type_index) {
return typeCast(location, null, type_index, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a method
* invocation type argument.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param type_index The index of the type argument.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
methodInvocationTypeArg(final List<TypePathEntry> location,
final JCLambda onLambda,
final int type_index,
final int pos) {
return new TypeAnnotationPosition(TargetType.METHOD_INVOCATION_TYPE_ARGUMENT,
pos, Integer.MIN_VALUE, onLambda,
type_index, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a method
* invocation type argument.
*
* @param location The type path.
* @param type_index The index of the type argument.
*/
public static TypeAnnotationPosition
methodInvocationTypeArg(final List<TypePathEntry> location,
final int type_index) {
return methodInvocationTypeArg(location, null, type_index, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a constructor
* invocation type argument.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param type_index The index of the type argument.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
constructorInvocationTypeArg(final List<TypePathEntry> location,
final JCLambda onLambda,
final int type_index,
final int pos) {
return new TypeAnnotationPosition(TargetType.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT,
pos, Integer.MIN_VALUE, onLambda,
type_index, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a constructor
* invocation type argument.
*
* @param location The type path.
* @param type_index The index of the type argument.
*/
public static TypeAnnotationPosition
constructorInvocationTypeArg(final List<TypePathEntry> location,
final int type_index) {
return constructorInvocationTypeArg(location, null, type_index, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a type parameter.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param parameter_index The index of the type parameter.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
typeParameter(final List<TypePathEntry> location,
final JCLambda onLambda,
final int parameter_index,
final int pos) {
return new TypeAnnotationPosition(TargetType.CLASS_TYPE_PARAMETER, pos,
parameter_index, onLambda,
Integer.MIN_VALUE, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a type parameter.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param parameter_index The index of the type parameter.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
typeParameter(final List<TypePathEntry> location,
final int parameter_index) {
return typeParameter(location, null, parameter_index, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a method type parameter.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param parameter_index The index of the type parameter.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
methodTypeParameter(final List<TypePathEntry> location,
final JCLambda onLambda,
final int parameter_index,
final int pos) {
return new TypeAnnotationPosition(TargetType.METHOD_TYPE_PARAMETER,
pos, parameter_index, onLambda,
Integer.MIN_VALUE, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a method type parameter.
*
* @param location The type path.
* @param parameter_index The index of the type parameter.
*/
public static TypeAnnotationPosition
methodTypeParameter(final List<TypePathEntry> location,
final int parameter_index) {
return methodTypeParameter(location, null, parameter_index, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a throws clause.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param type_index The index of the exception.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
methodThrows(final List<TypePathEntry> location,
final JCLambda onLambda,
final int type_index,
final int pos) {
return new TypeAnnotationPosition(TargetType.THROWS, pos,
Integer.MIN_VALUE, onLambda,
type_index, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a throws clause.
*
* @param location The type path.
* @param type_index The index of the exception.
*/
public static TypeAnnotationPosition
methodThrows(final List<TypePathEntry> location,
final int type_index) {
return methodThrows(location, null, type_index, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a method reference
* type argument.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param parameter_index The index of the type argument.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
methodRefTypeArg(final List<TypePathEntry> location,
final JCLambda onLambda,
final int type_index,
final int pos) {
return new TypeAnnotationPosition(TargetType.METHOD_REFERENCE_TYPE_ARGUMENT,
pos, Integer.MIN_VALUE, onLambda,
type_index, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a method reference
* type argument.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param parameter_index The index of the type argument.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
methodRefTypeArg(final List<TypePathEntry> location,
final int type_index) {
return methodRefTypeArg(location, null, type_index, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a constructor reference
* type argument.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param parameter_index The index of the type argument.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
constructorRefTypeArg(final List<TypePathEntry> location,
final JCLambda onLambda,
final int type_index,
final int pos) {
return new TypeAnnotationPosition(TargetType.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT,
pos, Integer.MIN_VALUE, onLambda,
type_index, Integer.MIN_VALUE,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a constructor reference
* type argument.
*
* @param location The type path.
* @param parameter_index The index of the type argument.
*/
public static TypeAnnotationPosition
constructorRefTypeArg(final List<TypePathEntry> location,
final int type_index) {
return constructorRefTypeArg(location, null, type_index, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a type parameter bound.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param parameter_index The index of the type parameter.
* @param bound_index The index of the type parameter bound.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
typeParameterBound(final List<TypePathEntry> location,
final JCLambda onLambda,
final int parameter_index,
final int bound_index,
final int pos) {
return new TypeAnnotationPosition(TargetType.CLASS_TYPE_PARAMETER_BOUND,
pos, parameter_index, onLambda,
Integer.MIN_VALUE, bound_index,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a type parameter bound.
*
* @param location The type path.
* @param parameter_index The index of the type parameter.
* @param bound_index The index of the type parameter bound.
*/
public static TypeAnnotationPosition
typeParameterBound(final List<TypePathEntry> location,
final int parameter_index,
final int bound_index) {
return typeParameterBound(location, null, parameter_index,
bound_index, -1);
}
/**
* Create a {@code TypeAnnotationPosition} for a method type
* parameter bound.
*
* @param location The type path.
* @param onLambda The lambda for this variable.
* @param parameter_index The index of the type parameter.
* @param bound_index The index of the type parameter bound.
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition
methodTypeParameterBound(final List<TypePathEntry> location,
final JCLambda onLambda,
final int parameter_index,
final int bound_index,
final int pos) {
return new TypeAnnotationPosition(TargetType.METHOD_TYPE_PARAMETER_BOUND,
pos, parameter_index, onLambda,
Integer.MIN_VALUE, bound_index,
location);
}
/**
* Create a {@code TypeAnnotationPosition} for a method type
* parameter bound.
*
* @param location The type path.
* @param parameter_index The index of the type parameter.
* @param bound_index The index of the type parameter bound.
*/
public static TypeAnnotationPosition
methodTypeParameterBound(final List<TypePathEntry> location,
final int parameter_index,
final int bound_index) {
return methodTypeParameterBound(location, null, parameter_index,
bound_index, -1);
}
// Consider this deprecated on arrival. We eventually want to get
// rid of this value altogether. Do not use it for anything new.
public static final TypeAnnotationPosition unknown =
new TypeAnnotationPosition(TargetType.UNKNOWN, -1,
Integer.MIN_VALUE, null,
Integer.MIN_VALUE, Integer.MIN_VALUE,
emptyPath);
} }

View File

@ -663,8 +663,15 @@ public class TypeAnnotations {
* type annotations: determine the type annotation positions. * type annotations: determine the type annotation positions.
*/ */
private void resolveFrame(JCTree tree, JCTree frame, // This method is considered deprecated, and will be removed
List<JCTree> path, TypeAnnotationPosition p) { // in the near future. Don't use it for anything new.
private TypeAnnotationPosition
resolveFrame(JCTree tree,
JCTree frame,
List<JCTree> path,
JCLambda currentLambda,
int outer_type_index,
ListBuffer<TypePathEntry> location) {
/* /*
System.out.println("Resolving tree: " + tree + " kind: " + tree.getKind()); System.out.println("Resolving tree: " + tree + " kind: " + tree.getKind());
System.out.println(" Framing tree: " + frame + " kind: " + frame.getKind()); System.out.println(" Framing tree: " + frame + " kind: " + frame.getKind());
@ -675,87 +682,101 @@ public class TypeAnnotations {
switch (frame.getKind()) { switch (frame.getKind()) {
case TYPE_CAST: case TYPE_CAST:
JCTypeCast frameTC = (JCTypeCast) frame; return TypeAnnotationPosition.typeCast(location.toList(),
p.type = TargetType.CAST; currentLambda,
if (frameTC.clazz.hasTag(Tag.TYPEINTERSECTION)) { outer_type_index,
// This case was already handled by INTERSECTION_TYPE frame.pos);
} else {
p.type_index = 0;
}
p.pos = frame.pos;
return;
case INSTANCE_OF: case INSTANCE_OF:
p.type = TargetType.INSTANCEOF; return TypeAnnotationPosition.instanceOf(location.toList(),
p.pos = frame.pos; currentLambda,
return; frame.pos);
case NEW_CLASS: case NEW_CLASS:
JCNewClass frameNewClass = (JCNewClass) frame; final JCNewClass frameNewClass = (JCNewClass) frame;
if (frameNewClass.def != null) { if (frameNewClass.def != null) {
// Special handling for anonymous class instantiations // Special handling for anonymous class instantiations
JCClassDecl frameClassDecl = frameNewClass.def; final JCClassDecl frameClassDecl = frameNewClass.def;
if (frameClassDecl.extending == tree) { if (frameClassDecl.extending == tree) {
p.type = TargetType.CLASS_EXTENDS; return TypeAnnotationPosition
p.type_index = -1; .classExtends(location.toList(), currentLambda,
frame.pos);
} else if (frameClassDecl.implementing.contains(tree)) { } else if (frameClassDecl.implementing.contains(tree)) {
p.type = TargetType.CLASS_EXTENDS; final int type_index =
p.type_index = frameClassDecl.implementing.indexOf(tree); frameClassDecl.implementing.indexOf(tree);
return TypeAnnotationPosition
.classExtends(location.toList(), currentLambda,
type_index, frame.pos);
} else { } else {
// In contrast to CLASS below, typarams cannot occur here. // In contrast to CLASS below, typarams cannot occur here.
Assert.error("Could not determine position of tree " + tree + throw new AssertionError("Could not determine position of tree " + tree +
" within frame " + frame); " within frame " + frame);
} }
} else if (frameNewClass.typeargs.contains(tree)) { } else if (frameNewClass.typeargs.contains(tree)) {
p.type = TargetType.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT; final int type_index =
p.type_index = frameNewClass.typeargs.indexOf(tree); frameNewClass.typeargs.indexOf(tree);
return TypeAnnotationPosition
.constructorInvocationTypeArg(location.toList(),
currentLambda,
type_index,
frame.pos);
} else { } else {
p.type = TargetType.NEW; return TypeAnnotationPosition
.newObj(location.toList(), currentLambda,
frame.pos);
} }
p.pos = frame.pos;
return;
case NEW_ARRAY: case NEW_ARRAY:
p.type = TargetType.NEW; return TypeAnnotationPosition
p.pos = frame.pos; .newObj(location.toList(), currentLambda, frame.pos);
return;
case ANNOTATION_TYPE: case ANNOTATION_TYPE:
case CLASS: case CLASS:
case ENUM: case ENUM:
case INTERFACE: case INTERFACE:
p.pos = frame.pos;
if (((JCClassDecl)frame).extending == tree) { if (((JCClassDecl)frame).extending == tree) {
p.type = TargetType.CLASS_EXTENDS; return TypeAnnotationPosition
p.type_index = -1; .classExtends(location.toList(), currentLambda,
frame.pos);
} else if (((JCClassDecl)frame).implementing.contains(tree)) { } else if (((JCClassDecl)frame).implementing.contains(tree)) {
p.type = TargetType.CLASS_EXTENDS; final int type_index =
p.type_index = ((JCClassDecl)frame).implementing.indexOf(tree); ((JCClassDecl)frame).implementing.indexOf(tree);
return TypeAnnotationPosition
.classExtends(location.toList(), currentLambda,
type_index, frame.pos);
} else if (((JCClassDecl)frame).typarams.contains(tree)) { } else if (((JCClassDecl)frame).typarams.contains(tree)) {
p.type = TargetType.CLASS_TYPE_PARAMETER; final int parameter_index =
p.parameter_index = ((JCClassDecl)frame).typarams.indexOf(tree); ((JCClassDecl)frame).typarams.indexOf(tree);
return TypeAnnotationPosition
.typeParameter(location.toList(), currentLambda,
parameter_index, frame.pos);
} else { } else {
Assert.error("Could not determine position of tree " + tree + throw new AssertionError("Could not determine position of tree " +
" within frame " + frame); tree + " within frame " + frame);
} }
return;
case METHOD: { case METHOD: {
JCMethodDecl frameMethod = (JCMethodDecl) frame; final JCMethodDecl frameMethod = (JCMethodDecl) frame;
p.pos = frame.pos;
if (frameMethod.thrown.contains(tree)) { if (frameMethod.thrown.contains(tree)) {
p.type = TargetType.THROWS; final int type_index = frameMethod.thrown.indexOf(tree);
p.type_index = frameMethod.thrown.indexOf(tree); return TypeAnnotationPosition
.methodThrows(location.toList(), currentLambda,
type_index, frame.pos);
} else if (frameMethod.restype == tree) { } else if (frameMethod.restype == tree) {
p.type = TargetType.METHOD_RETURN; return TypeAnnotationPosition
.methodReturn(location.toList(), currentLambda,
frame.pos);
} else if (frameMethod.typarams.contains(tree)) { } else if (frameMethod.typarams.contains(tree)) {
p.type = TargetType.METHOD_TYPE_PARAMETER; final int parameter_index =
p.parameter_index = frameMethod.typarams.indexOf(tree); frameMethod.typarams.indexOf(tree);
return TypeAnnotationPosition
.methodTypeParameter(location.toList(),
currentLambda,
parameter_index, frame.pos);
} else { } else {
Assert.error("Could not determine position of tree " + tree + throw new AssertionError("Could not determine position of tree " + tree +
" within frame " + frame); " within frame " + frame);
} }
return;
} }
case PARAMETERIZED_TYPE: { case PARAMETERIZED_TYPE: {
@ -766,25 +787,30 @@ public class TypeAnnotations {
} else if (((JCTypeApply)frame).arguments.contains(tree)) { } else if (((JCTypeApply)frame).arguments.contains(tree)) {
JCTypeApply taframe = (JCTypeApply) frame; JCTypeApply taframe = (JCTypeApply) frame;
int arg = taframe.arguments.indexOf(tree); int arg = taframe.arguments.indexOf(tree);
p.location = p.location.prepend(new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg)); location = location.prepend(
new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT,
arg));
Type typeToUse; Type typeToUse;
if (newPath.tail != null && newPath.tail.head.hasTag(Tag.NEWCLASS)) { if (newPath.tail != null &&
// If we are within an anonymous class instantiation, use its type, newPath.tail.head.hasTag(Tag.NEWCLASS)) {
// because it contains a correctly nested type. // If we are within an anonymous class
// instantiation, use its type, because it
// contains a correctly nested type.
typeToUse = newPath.tail.head.type; typeToUse = newPath.tail.head.type;
} else { } else {
typeToUse = taframe.type; typeToUse = taframe.type;
} }
locateNestedTypes(typeToUse, p); location = locateNestedTypes(typeToUse, location);
} else { } else {
Assert.error("Could not determine type argument position of tree " + tree + throw new AssertionError("Could not determine type argument position of tree " + tree +
" within frame " + frame); " within frame " + frame);
} }
resolveFrame(newPath.head, newPath.tail.head, newPath, p); return resolveFrame(newPath.head, newPath.tail.head,
return; newPath, currentLambda,
outer_type_index, location);
} }
case MEMBER_REFERENCE: { case MEMBER_REFERENCE: {
@ -793,117 +819,140 @@ public class TypeAnnotations {
if (mrframe.expr == tree) { if (mrframe.expr == tree) {
switch (mrframe.mode) { switch (mrframe.mode) {
case INVOKE: case INVOKE:
p.type = TargetType.METHOD_REFERENCE; return TypeAnnotationPosition
break; .methodRef(location.toList(), currentLambda,
frame.pos);
case NEW: case NEW:
p.type = TargetType.CONSTRUCTOR_REFERENCE; return TypeAnnotationPosition
break; .constructorRef(location.toList(),
currentLambda,
frame.pos);
default: default:
Assert.error("Unknown method reference mode " + mrframe.mode + throw new AssertionError("Unknown method reference mode " + mrframe.mode +
" for tree " + tree + " within frame " + frame); " for tree " + tree + " within frame " + frame);
} }
p.pos = frame.pos;
} else if (mrframe.typeargs != null && } else if (mrframe.typeargs != null &&
mrframe.typeargs.contains(tree)) { mrframe.typeargs.contains(tree)) {
int arg = mrframe.typeargs.indexOf(tree); final int type_index = mrframe.typeargs.indexOf(tree);
p.type_index = arg;
switch (mrframe.mode) { switch (mrframe.mode) {
case INVOKE: case INVOKE:
p.type = TargetType.METHOD_REFERENCE_TYPE_ARGUMENT; return TypeAnnotationPosition
break; .methodRefTypeArg(location.toList(),
currentLambda,
type_index, frame.pos);
case NEW: case NEW:
p.type = TargetType.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT; return TypeAnnotationPosition
break; .constructorRefTypeArg(location.toList(),
currentLambda,
type_index, frame.pos);
default: default:
Assert.error("Unknown method reference mode " + mrframe.mode + throw new AssertionError("Unknown method reference mode " + mrframe.mode +
" for tree " + tree + " within frame " + frame); " for tree " + tree + " within frame " + frame);
} }
p.pos = frame.pos;
} else { } else {
Assert.error("Could not determine type argument position of tree " + tree + throw new AssertionError("Could not determine type argument position of tree " + tree +
" within frame " + frame); " within frame " + frame);
} }
return;
} }
case ARRAY_TYPE: { case ARRAY_TYPE: {
ListBuffer<TypePathEntry> index = new ListBuffer<>(); location = location.prepend(TypePathEntry.ARRAY);
index = index.append(TypePathEntry.ARRAY);
List<JCTree> newPath = path.tail; List<JCTree> newPath = path.tail;
while (true) { while (true) {
JCTree npHead = newPath.tail.head; JCTree npHead = newPath.tail.head;
if (npHead.hasTag(JCTree.Tag.TYPEARRAY)) { if (npHead.hasTag(JCTree.Tag.TYPEARRAY)) {
newPath = newPath.tail; newPath = newPath.tail;
index = index.append(TypePathEntry.ARRAY); location = location.prepend(TypePathEntry.ARRAY);
} else if (npHead.hasTag(JCTree.Tag.ANNOTATED_TYPE)) { } else if (npHead.hasTag(JCTree.Tag.ANNOTATED_TYPE)) {
newPath = newPath.tail; newPath = newPath.tail;
} else { } else {
break; break;
} }
} }
p.location = p.location.prependList(index.toList()); return resolveFrame(newPath.head, newPath.tail.head,
resolveFrame(newPath.head, newPath.tail.head, newPath, p); newPath, currentLambda,
return; outer_type_index, location);
} }
case TYPE_PARAMETER: case TYPE_PARAMETER:
if (path.tail.tail.head.hasTag(JCTree.Tag.CLASSDEF)) { if (path.tail.tail.head.hasTag(JCTree.Tag.CLASSDEF)) {
JCClassDecl clazz = (JCClassDecl)path.tail.tail.head; final JCClassDecl clazz =
p.type = TargetType.CLASS_TYPE_PARAMETER_BOUND; (JCClassDecl)path.tail.tail.head;
p.parameter_index = clazz.typarams.indexOf(path.tail.head); final int parameter_index =
p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree); clazz.typarams.indexOf(path.tail.head);
if (((JCTypeParameter)frame).bounds.get(0).type.isInterface()) { final int bound_index =
// Account for an implicit Object as bound 0 ((JCTypeParameter)frame).bounds.get(0)
p.bound_index += 1; .type.isInterface() ?
} ((JCTypeParameter)frame).bounds.indexOf(tree) + 1:
((JCTypeParameter)frame).bounds.indexOf(tree);
return TypeAnnotationPosition
.typeParameterBound(location.toList(),
currentLambda,
parameter_index, bound_index,
frame.pos);
} else if (path.tail.tail.head.hasTag(JCTree.Tag.METHODDEF)) { } else if (path.tail.tail.head.hasTag(JCTree.Tag.METHODDEF)) {
JCMethodDecl method = (JCMethodDecl)path.tail.tail.head; final JCMethodDecl method =
p.type = TargetType.METHOD_TYPE_PARAMETER_BOUND; (JCMethodDecl)path.tail.tail.head;
p.parameter_index = method.typarams.indexOf(path.tail.head); final int parameter_index =
p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree); method.typarams.indexOf(path.tail.head);
if (((JCTypeParameter)frame).bounds.get(0).type.isInterface()) { final int bound_index =
// Account for an implicit Object as bound 0 ((JCTypeParameter)frame).bounds.get(0)
p.bound_index += 1; .type.isInterface() ?
} ((JCTypeParameter)frame).bounds.indexOf(tree) + 1:
((JCTypeParameter)frame).bounds.indexOf(tree);
return TypeAnnotationPosition
.methodTypeParameterBound(location.toList(),
currentLambda,
parameter_index,
bound_index,
frame.pos);
} else { } else {
Assert.error("Could not determine position of tree " + tree + throw new AssertionError("Could not determine position of tree " + tree +
" within frame " + frame); " within frame " + frame);
} }
p.pos = frame.pos;
return;
case VARIABLE: case VARIABLE:
VarSymbol v = ((JCVariableDecl)frame).sym; 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;
break;
case PARAMETER:
if (v.getQualifiedName().equals(names._this)) {
// TODO: Intro a separate ElementKind?
p.type = TargetType.METHOD_RECEIVER;
} else {
p.type = TargetType.METHOD_FORMAL_PARAMETER;
p.parameter_index = methodParamIndex(path, frame);
}
break;
case EXCEPTION_PARAMETER:
p.type = TargetType.EXCEPTION_PARAMETER;
break;
case RESOURCE_VARIABLE:
p.type = TargetType.RESOURCE_VARIABLE;
break;
default:
Assert.error("Found unexpected type annotation for variable: " + v + " with kind: " + v.getKind());
}
if (v.getKind() != ElementKind.FIELD) { if (v.getKind() != ElementKind.FIELD) {
v.owner.appendUniqueTypeAttributes(v.getRawTypeAttributes()); v.owner.appendUniqueTypeAttributes(v.getRawTypeAttributes());
} }
return; switch (v.getKind()) {
case LOCAL_VARIABLE:
return TypeAnnotationPosition
.localVariable(location.toList(), currentLambda,
frame.pos);
case FIELD:
return TypeAnnotationPosition.field(location.toList(),
currentLambda,
frame.pos);
case PARAMETER:
if (v.getQualifiedName().equals(names._this)) {
return TypeAnnotationPosition
.methodReceiver(location.toList(),
currentLambda,
frame.pos);
} else {
final int parameter_index =
methodParamIndex(path, frame);
return TypeAnnotationPosition
.methodParameter(location.toList(),
currentLambda,
parameter_index,
frame.pos);
}
case EXCEPTION_PARAMETER:
return TypeAnnotationPosition
.exceptionParameter(location.toList(),
currentLambda,
frame.pos);
case RESOURCE_VARIABLE:
return TypeAnnotationPosition
.resourceVariable(location.toList(),
currentLambda,
frame.pos);
default:
throw new AssertionError("Found unexpected type annotation for variable: " + v + " with kind: " + v.getKind());
}
case ANNOTATED_TYPE: { case ANNOTATED_TYPE: {
if (frame == tree) { if (frame == tree) {
@ -921,83 +970,89 @@ public class TypeAnnotations {
// class/method as enclosing elements. // class/method as enclosing elements.
// There is actually nothing to do for them. // There is actually nothing to do for them.
} else { } else {
locateNestedTypes(utype, p); location = locateNestedTypes(utype, location);
} }
} }
List<JCTree> newPath = path.tail; List<JCTree> newPath = path.tail;
resolveFrame(newPath.head, newPath.tail.head, newPath, p); return resolveFrame(newPath.head, newPath.tail.head,
return; newPath, currentLambda,
outer_type_index, location);
} }
case UNION_TYPE: { case UNION_TYPE: {
List<JCTree> newPath = path.tail; List<JCTree> newPath = path.tail;
resolveFrame(newPath.head, newPath.tail.head, newPath, p); return resolveFrame(newPath.head, newPath.tail.head,
return; newPath, currentLambda,
outer_type_index, location);
} }
case INTERSECTION_TYPE: { case INTERSECTION_TYPE: {
JCTypeIntersection isect = (JCTypeIntersection)frame; JCTypeIntersection isect = (JCTypeIntersection)frame;
p.type_index = isect.bounds.indexOf(tree); final List<JCTree> newPath = path.tail;
List<JCTree> newPath = path.tail; return resolveFrame(newPath.head, newPath.tail.head,
resolveFrame(newPath.head, newPath.tail.head, newPath, p); newPath, currentLambda,
return; isect.bounds.indexOf(tree), location);
} }
case METHOD_INVOCATION: { case METHOD_INVOCATION: {
JCMethodInvocation invocation = (JCMethodInvocation)frame; JCMethodInvocation invocation = (JCMethodInvocation)frame;
if (!invocation.typeargs.contains(tree)) { if (!invocation.typeargs.contains(tree)) {
Assert.error("{" + tree + "} is not an argument in the invocation: " + invocation); throw new AssertionError("{" + tree + "} is not an argument in the invocation: " + invocation);
} }
MethodSymbol exsym = (MethodSymbol) TreeInfo.symbol(invocation.getMethodSelect()); MethodSymbol exsym = (MethodSymbol) TreeInfo.symbol(invocation.getMethodSelect());
final int type_index = invocation.typeargs.indexOf(tree);
if (exsym == null) { if (exsym == null) {
Assert.error("could not determine symbol for {" + invocation + "}"); throw new AssertionError("could not determine symbol for {" + invocation + "}");
} else if (exsym.isConstructor()) { } else if (exsym.isConstructor()) {
p.type = TargetType.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT; return TypeAnnotationPosition
.constructorInvocationTypeArg(location.toList(),
currentLambda,
type_index,
invocation.pos);
} else { } else {
p.type = TargetType.METHOD_INVOCATION_TYPE_ARGUMENT; return TypeAnnotationPosition
.methodInvocationTypeArg(location.toList(),
currentLambda,
type_index,
invocation.pos);
} }
p.pos = invocation.pos;
p.type_index = invocation.typeargs.indexOf(tree);
return;
} }
case EXTENDS_WILDCARD: case EXTENDS_WILDCARD:
case SUPER_WILDCARD: { case SUPER_WILDCARD: {
// Annotations in wildcard bounds // Annotations in wildcard bounds
p.location = p.location.prepend(TypePathEntry.WILDCARD); final List<JCTree> newPath = path.tail;
List<JCTree> newPath = path.tail; return resolveFrame(newPath.head, newPath.tail.head,
resolveFrame(newPath.head, newPath.tail.head, newPath, p); newPath, currentLambda,
return; outer_type_index,
location.prepend(TypePathEntry.WILDCARD));
} }
case MEMBER_SELECT: { case MEMBER_SELECT: {
List<JCTree> newPath = path.tail; final List<JCTree> newPath = path.tail;
resolveFrame(newPath.head, newPath.tail.head, newPath, p); return resolveFrame(newPath.head, newPath.tail.head,
return; newPath, currentLambda,
outer_type_index, location);
} }
default: default:
Assert.error("Unresolved frame: " + frame + " of kind: " + frame.getKind() + throw new AssertionError("Unresolved frame: " + frame +
"\n Looking for tree: " + tree); " of kind: " + frame.getKind() +
return; "\n Looking for tree: " + tree);
} }
} }
private void locateNestedTypes(Type type, TypeAnnotationPosition p) { private ListBuffer<TypePathEntry>
// The number of "steps" to get from the full type to the locateNestedTypes(Type type,
// left-most outer type. ListBuffer<TypePathEntry> depth) {
ListBuffer<TypePathEntry> depth = new ListBuffer<>();
Type encl = type.getEnclosingType(); Type encl = type.getEnclosingType();
while (encl != null && while (encl != null &&
encl.getKind() != TypeKind.NONE && encl.getKind() != TypeKind.NONE &&
encl.getKind() != TypeKind.ERROR) { encl.getKind() != TypeKind.ERROR) {
depth = depth.append(TypePathEntry.INNER_TYPE); depth = depth.prepend(TypePathEntry.INNER_TYPE);
encl = encl.getEnclosingType(); encl = encl.getEnclosingType();
} }
if (depth.nonEmpty()) { return depth;
p.location = p.location.prependList(depth.toList());
}
} }
private int methodParamIndex(List<JCTree> path, JCTree param) { private int methodParamIndex(List<JCTree> path, JCTree param) {
@ -1048,18 +1103,18 @@ public class TypeAnnotations {
} }
if (sigOnly) { if (sigOnly) {
if (!tree.mods.annotations.isEmpty()) { if (!tree.mods.annotations.isEmpty()) {
// Nothing to do for separateAnnotationsKinds if
// there are no annotations of either kind.
TypeAnnotationPosition pos = new TypeAnnotationPosition();
pos.type = TargetType.METHOD_RETURN;
if (tree.sym.isConstructor()) { if (tree.sym.isConstructor()) {
pos.pos = tree.pos; final TypeAnnotationPosition pos =
// Use null to mark that the annotations go with the symbol. TypeAnnotationPosition.methodReturn(tree.pos);
// Use null to mark that the annotations go
// with the symbol.
separateAnnotationsKinds(tree, null, tree.sym, pos); separateAnnotationsKinds(tree, null, tree.sym, pos);
} else { } else {
pos.pos = tree.restype.pos; final TypeAnnotationPosition pos =
separateAnnotationsKinds(tree.restype, tree.sym.type.getReturnType(), TypeAnnotationPosition.methodReturn(tree.restype.pos);
tree.sym, pos); separateAnnotationsKinds(tree.restype,
tree.sym.type.getReturnType(),
tree.sym, pos);
} }
} }
if (tree.recvparam != null && tree.recvparam.sym != null && if (tree.recvparam != null && tree.recvparam.sym != null &&
@ -1067,22 +1122,22 @@ public class TypeAnnotations {
// Nothing to do for separateAnnotationsKinds if // Nothing to do for separateAnnotationsKinds if
// there are no annotations of either kind. // there are no annotations of either kind.
// TODO: make sure there are no declaration annotations. // TODO: make sure there are no declaration annotations.
TypeAnnotationPosition pos = new TypeAnnotationPosition(); final TypeAnnotationPosition pos =
pos.type = TargetType.METHOD_RECEIVER; TypeAnnotationPosition.methodReceiver(tree.recvparam.vartype.pos);
pos.pos = tree.recvparam.vartype.pos; separateAnnotationsKinds(tree.recvparam.vartype,
separateAnnotationsKinds(tree.recvparam.vartype, tree.recvparam.sym.type, tree.recvparam.sym.type,
tree.recvparam.sym, pos); tree.recvparam.sym, pos);
} }
int i = 0; int i = 0;
for (JCVariableDecl param : tree.params) { for (JCVariableDecl param : tree.params) {
if (!param.mods.annotations.isEmpty()) { if (!param.mods.annotations.isEmpty()) {
// Nothing to do for separateAnnotationsKinds if // Nothing to do for separateAnnotationsKinds if
// there are no annotations of either kind. // there are no annotations of either kind.
TypeAnnotationPosition pos = new TypeAnnotationPosition(); final TypeAnnotationPosition pos =
pos.type = TargetType.METHOD_FORMAL_PARAMETER; TypeAnnotationPosition.methodParameter(i, param.vartype.pos);
pos.parameter_index = i; separateAnnotationsKinds(param.vartype,
pos.pos = param.vartype.pos; param.sym.type,
separateAnnotationsKinds(param.vartype, param.sym.type, param.sym, pos); param.sym, pos);
} }
++i; ++i;
} }
@ -1119,11 +1174,9 @@ public class TypeAnnotations {
if (!param.mods.annotations.isEmpty()) { if (!param.mods.annotations.isEmpty()) {
// Nothing to do for separateAnnotationsKinds if // Nothing to do for separateAnnotationsKinds if
// there are no annotations of either kind. // there are no annotations of either kind.
TypeAnnotationPosition pos = new TypeAnnotationPosition(); final TypeAnnotationPosition pos =
pos.type = TargetType.METHOD_FORMAL_PARAMETER; TypeAnnotationPosition.methodParameter(tree, i,
pos.parameter_index = i; param.vartype.pos);
pos.pos = param.vartype.pos;
pos.onLambda = tree;
separateAnnotationsKinds(param.vartype, param.sym.type, param.sym, pos); separateAnnotationsKinds(param.vartype, param.sym.type, param.sym, pos);
} }
++i; ++i;
@ -1153,28 +1206,24 @@ public class TypeAnnotations {
// Parameters are handled in visitMethodDef or visitLambda. // Parameters are handled in visitMethodDef or visitLambda.
} else if (tree.sym.getKind() == ElementKind.FIELD) { } else if (tree.sym.getKind() == ElementKind.FIELD) {
if (sigOnly) { if (sigOnly) {
TypeAnnotationPosition pos = new TypeAnnotationPosition(); TypeAnnotationPosition pos =
pos.type = TargetType.FIELD; TypeAnnotationPosition.field(tree.pos);
pos.pos = tree.pos;
separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos); separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
} }
} else if (tree.sym.getKind() == ElementKind.LOCAL_VARIABLE) { } else if (tree.sym.getKind() == ElementKind.LOCAL_VARIABLE) {
TypeAnnotationPosition pos = new TypeAnnotationPosition(); final TypeAnnotationPosition pos =
pos.type = TargetType.LOCAL_VARIABLE; TypeAnnotationPosition.localVariable(currentLambda,
pos.pos = tree.pos; tree.pos);
pos.onLambda = currentLambda;
separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos); separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
} else if (tree.sym.getKind() == ElementKind.EXCEPTION_PARAMETER) { } else if (tree.sym.getKind() == ElementKind.EXCEPTION_PARAMETER) {
TypeAnnotationPosition pos = new TypeAnnotationPosition(); final TypeAnnotationPosition pos =
pos.type = TargetType.EXCEPTION_PARAMETER; TypeAnnotationPosition.exceptionParameter(currentLambda,
pos.pos = tree.pos; tree.pos);
pos.onLambda = currentLambda;
separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos); separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
} else if (tree.sym.getKind() == ElementKind.RESOURCE_VARIABLE) { } else if (tree.sym.getKind() == ElementKind.RESOURCE_VARIABLE) {
TypeAnnotationPosition pos = new TypeAnnotationPosition(); final TypeAnnotationPosition pos =
pos.type = TargetType.RESOURCE_VARIABLE; TypeAnnotationPosition.resourceVariable(currentLambda,
pos.pos = tree.pos; tree.pos);
pos.onLambda = currentLambda;
separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos); separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
} else if (tree.sym.getKind() == ElementKind.ENUM_CONSTANT) { } else if (tree.sym.getKind() == ElementKind.ENUM_CONSTANT) {
// No type annotations can occur here. // No type annotations can occur here.
@ -1218,7 +1267,8 @@ public class TypeAnnotations {
private void copyNewClassAnnotationsToOwner(JCNewClass tree) { private void copyNewClassAnnotationsToOwner(JCNewClass tree) {
Symbol sym = tree.def.sym; Symbol sym = tree.def.sym;
TypeAnnotationPosition pos = new TypeAnnotationPosition(); final TypeAnnotationPosition pos =
TypeAnnotationPosition.newObj(tree.pos);
ListBuffer<Attribute.TypeCompound> newattrs = new ListBuffer<>(); ListBuffer<Attribute.TypeCompound> newattrs = new ListBuffer<>();
for (Attribute.TypeCompound old : sym.getRawTypeAttributes()) { for (Attribute.TypeCompound old : sym.getRawTypeAttributes()) {
@ -1226,8 +1276,6 @@ public class TypeAnnotations {
pos)); pos));
} }
pos.type = TargetType.NEW;
pos.pos = tree.pos;
sym.owner.appendUniqueTypeAttributes(newattrs.toList()); sym.owner.appendUniqueTypeAttributes(newattrs.toList());
} }
@ -1236,16 +1284,16 @@ public class TypeAnnotations {
if (tree.def != null && if (tree.def != null &&
!tree.def.mods.annotations.isEmpty()) { !tree.def.mods.annotations.isEmpty()) {
JCClassDecl classdecl = tree.def; JCClassDecl classdecl = tree.def;
TypeAnnotationPosition pos = new TypeAnnotationPosition(); TypeAnnotationPosition pos;
pos.type = TargetType.CLASS_EXTENDS;
pos.pos = tree.pos;
if (classdecl.extending == tree.clazz) { if (classdecl.extending == tree.clazz) {
pos.type_index = -1; pos = TypeAnnotationPosition.classExtends(tree.pos);
} else if (classdecl.implementing.contains(tree.clazz)) { } else if (classdecl.implementing.contains(tree.clazz)) {
pos.type_index = classdecl.implementing.indexOf(tree.clazz); final int index = classdecl.implementing.indexOf(tree.clazz);
pos = TypeAnnotationPosition.classExtends(index, tree.pos);
} else { } else {
// In contrast to CLASS elsewhere, typarams cannot occur here. // In contrast to CLASS elsewhere, typarams cannot occur here.
Assert.error("Could not determine position of tree " + tree); throw new AssertionError("Could not determine position of tree " + tree);
} }
Type before = classdecl.sym.type; Type before = classdecl.sym.type;
separateAnnotationsKinds(classdecl, tree.clazz.type, classdecl.sym, pos); separateAnnotationsKinds(classdecl, tree.clazz.type, classdecl.sym, pos);
@ -1273,14 +1321,16 @@ public class TypeAnnotations {
// handle annotations associated with dimensions // handle annotations associated with dimensions
for (int i = 0; i < dimAnnosCount; ++i) { for (int i = 0; i < dimAnnosCount; ++i) {
TypeAnnotationPosition p = new TypeAnnotationPosition(); ListBuffer<TypePathEntry> location =
p.pos = tree.pos; new ListBuffer<TypePathEntry>();
p.onLambda = currentLambda;
p.type = TargetType.NEW;
if (i != 0) { if (i != 0) {
depth = depth.append(TypePathEntry.ARRAY); depth = depth.append(TypePathEntry.ARRAY);
p.location = p.location.appendList(depth.toList()); location = location.appendList(depth.toList());
} }
final TypeAnnotationPosition p =
TypeAnnotationPosition.newObj(location.toList(),
currentLambda,
tree.pos);
setTypeAnnotationPos(tree.dimAnnotations.get(i), p); setTypeAnnotationPos(tree.dimAnnotations.get(i), p);
} }
@ -1293,12 +1343,14 @@ public class TypeAnnotations {
while (elemType != null) { while (elemType != null) {
if (elemType.hasTag(JCTree.Tag.ANNOTATED_TYPE)) { if (elemType.hasTag(JCTree.Tag.ANNOTATED_TYPE)) {
JCAnnotatedType at = (JCAnnotatedType)elemType; JCAnnotatedType at = (JCAnnotatedType)elemType;
TypeAnnotationPosition p = new TypeAnnotationPosition(); final ListBuffer<TypePathEntry> locationbuf =
p.type = TargetType.NEW; locateNestedTypes(elemType.type,
p.pos = tree.pos; new ListBuffer<TypePathEntry>());
p.onLambda = currentLambda; final List<TypePathEntry> location =
locateNestedTypes(elemType.type, p); locationbuf.toList().prependList(depth.toList());
p.location = p.location.prependList(depth.toList()); final TypeAnnotationPosition p =
TypeAnnotationPosition.newObj(location, currentLambda,
tree.pos);
setTypeAnnotationPos(at.annotations, p); setTypeAnnotationPos(at.annotations, p);
elemType = at.underlyingType; elemType = at.underlyingType;
} else if (elemType.hasTag(JCTree.Tag.TYPEARRAY)) { } else if (elemType.hasTag(JCTree.Tag.TYPEARRAY)) {
@ -1320,9 +1372,9 @@ public class TypeAnnotations {
System.err.println(" tree: " + tree + " kind: " + tree.getKind()); System.err.println(" tree: " + tree + " kind: " + tree.getKind());
System.err.println(" frame: " + frame + " kind: " + frame.getKind()); System.err.println(" frame: " + frame + " kind: " + frame.getKind());
*/ */
TypeAnnotationPosition p = new TypeAnnotationPosition(); final TypeAnnotationPosition p =
p.onLambda = currentLambda; resolveFrame(tree, frame, frames.toList(), currentLambda, 0,
resolveFrame(tree, frame, frames.toList(), p); new ListBuffer<TypePathEntry>());
setTypeAnnotationPos(annotations, p); setTypeAnnotationPos(annotations, p);
} }
} }

View File

@ -299,7 +299,13 @@ public class Annotate {
if (typeAnnotation) { if (typeAnnotation) {
if (a.attribute == null || !(a.attribute instanceof Attribute.TypeCompound)) { if (a.attribute == null || !(a.attribute instanceof Attribute.TypeCompound)) {
// Create a new TypeCompound // Create a new TypeCompound
Attribute.TypeCompound tc = new Attribute.TypeCompound(a.type, buf.toList(), new TypeAnnotationPosition());
Attribute.TypeCompound tc =
new Attribute.TypeCompound(a.type, buf.toList(),
// TODO: Eventually, we will get rid of this use of
// unknown, because we'll get a position from
// MemberEnter (task 8027262).
TypeAnnotationPosition.unknown);
a.attribute = tc; a.attribute = tc;
return tc; return tc;
} else { } else {

View File

@ -1469,26 +1469,46 @@ public class ClassReader {
if (!TargetType.isValidTargetTypeValue(tag)) if (!TargetType.isValidTargetTypeValue(tag))
throw this.badClassFile("bad.type.annotation.value", String.format("0x%02X", tag)); throw this.badClassFile("bad.type.annotation.value", String.format("0x%02X", tag));
TypeAnnotationPosition position = new TypeAnnotationPosition();
TargetType type = TargetType.fromTargetTypeValue(tag); TargetType type = TargetType.fromTargetTypeValue(tag);
position.type = type;
switch (type) { switch (type) {
// instanceof // instanceof
case INSTANCEOF: case INSTANCEOF: {
final int offset = nextChar();
final TypeAnnotationPosition position =
TypeAnnotationPosition.instanceOf(readTypePath());
position.offset = offset;
return position;
}
// new expression // new expression
case NEW: case NEW: {
final int offset = nextChar();
final TypeAnnotationPosition position =
TypeAnnotationPosition.newObj(readTypePath());
position.offset = offset;
return position;
}
// constructor/method reference receiver // constructor/method reference receiver
case CONSTRUCTOR_REFERENCE: case CONSTRUCTOR_REFERENCE: {
case METHOD_REFERENCE: final int offset = nextChar();
position.offset = nextChar(); final TypeAnnotationPosition position =
break; TypeAnnotationPosition.constructorRef(readTypePath());
position.offset = offset;
return position;
}
case METHOD_REFERENCE: {
final int offset = nextChar();
final TypeAnnotationPosition position =
TypeAnnotationPosition.methodRef(readTypePath());
position.offset = offset;
return position;
}
// local variable // local variable
case LOCAL_VARIABLE: case LOCAL_VARIABLE: {
// resource variable final int table_length = nextChar();
case RESOURCE_VARIABLE: final TypeAnnotationPosition position =
int table_length = nextChar(); TypeAnnotationPosition.localVariable(readTypePath());
position.lvarOffset = new int[table_length]; position.lvarOffset = new int[table_length];
position.lvarLength = new int[table_length]; position.lvarLength = new int[table_length];
position.lvarIndex = new int[table_length]; position.lvarIndex = new int[table_length];
@ -1498,67 +1518,142 @@ public class ClassReader {
position.lvarLength[i] = nextChar(); position.lvarLength[i] = nextChar();
position.lvarIndex[i] = nextChar(); position.lvarIndex[i] = nextChar();
} }
break; return position;
}
// resource variable
case RESOURCE_VARIABLE: {
final int table_length = nextChar();
final TypeAnnotationPosition position =
TypeAnnotationPosition.resourceVariable(readTypePath());
position.lvarOffset = new int[table_length];
position.lvarLength = new int[table_length];
position.lvarIndex = new int[table_length];
for (int i = 0; i < table_length; ++i) {
position.lvarOffset[i] = nextChar();
position.lvarLength[i] = nextChar();
position.lvarIndex[i] = nextChar();
}
return position;
}
// exception parameter // exception parameter
case EXCEPTION_PARAMETER: case EXCEPTION_PARAMETER: {
position.exception_index = nextChar(); final int exception_index = nextChar();
break; final TypeAnnotationPosition position =
TypeAnnotationPosition.exceptionParameter(readTypePath());
position.exception_index = exception_index;
return position;
}
// method receiver // method receiver
case METHOD_RECEIVER: case METHOD_RECEIVER:
// Do nothing return TypeAnnotationPosition.methodReceiver(readTypePath());
break;
// type parameter // type parameter
case CLASS_TYPE_PARAMETER: case CLASS_TYPE_PARAMETER: {
case METHOD_TYPE_PARAMETER: final int parameter_index = nextByte();
position.parameter_index = nextByte(); return TypeAnnotationPosition
break; .typeParameter(readTypePath(), parameter_index);
}
case METHOD_TYPE_PARAMETER: {
final int parameter_index = nextByte();
return TypeAnnotationPosition
.methodTypeParameter(readTypePath(), parameter_index);
}
// type parameter bound // type parameter bound
case CLASS_TYPE_PARAMETER_BOUND: case CLASS_TYPE_PARAMETER_BOUND: {
case METHOD_TYPE_PARAMETER_BOUND: final int parameter_index = nextByte();
position.parameter_index = nextByte(); final int bound_index = nextByte();
position.bound_index = nextByte(); return TypeAnnotationPosition
break; .typeParameterBound(readTypePath(), parameter_index,
bound_index);
}
case METHOD_TYPE_PARAMETER_BOUND: {
final int parameter_index = nextByte();
final int bound_index = nextByte();
return TypeAnnotationPosition
.methodTypeParameterBound(readTypePath(), parameter_index,
bound_index);
}
// class extends or implements clause // class extends or implements clause
case CLASS_EXTENDS: case CLASS_EXTENDS: {
position.type_index = nextChar(); final int type_index = nextChar();
break; return TypeAnnotationPosition.classExtends(readTypePath(),
type_index);
}
// throws // throws
case THROWS: case THROWS: {
position.type_index = nextChar(); final int type_index = nextChar();
break; return TypeAnnotationPosition.methodThrows(readTypePath(),
type_index);
}
// method parameter // method parameter
case METHOD_FORMAL_PARAMETER: case METHOD_FORMAL_PARAMETER: {
position.parameter_index = nextByte(); final int parameter_index = nextByte();
break; return TypeAnnotationPosition.methodParameter(readTypePath(),
parameter_index);
}
// type cast // type cast
case CAST: case CAST: {
final int offset = nextChar();
final int type_index = nextByte();
final TypeAnnotationPosition position =
TypeAnnotationPosition.typeCast(readTypePath(), type_index);
position.offset = offset;
return position;
}
// method/constructor/reference type argument // method/constructor/reference type argument
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: {
case METHOD_INVOCATION_TYPE_ARGUMENT: final int offset = nextChar();
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: final int type_index = nextByte();
case METHOD_REFERENCE_TYPE_ARGUMENT: final TypeAnnotationPosition position = TypeAnnotationPosition
position.offset = nextChar(); .constructorInvocationTypeArg(readTypePath(), type_index);
position.type_index = nextByte(); position.offset = offset;
break; return position;
}
case METHOD_INVOCATION_TYPE_ARGUMENT: {
final int offset = nextChar();
final int type_index = nextByte();
final TypeAnnotationPosition position = TypeAnnotationPosition
.methodInvocationTypeArg(readTypePath(), type_index);
position.offset = offset;
return position;
}
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: {
final int offset = nextChar();
final int type_index = nextByte();
final TypeAnnotationPosition position = TypeAnnotationPosition
.constructorRefTypeArg(readTypePath(), type_index);
position.offset = offset;
return position;
}
case METHOD_REFERENCE_TYPE_ARGUMENT: {
final int offset = nextChar();
final int type_index = nextByte();
final TypeAnnotationPosition position = TypeAnnotationPosition
.methodRefTypeArg(readTypePath(), type_index);
position.offset = offset;
return position;
}
// We don't need to worry about these // We don't need to worry about these
case METHOD_RETURN: case METHOD_RETURN:
return TypeAnnotationPosition.methodReturn(readTypePath());
case FIELD: case FIELD:
break; return TypeAnnotationPosition.field(readTypePath());
case UNKNOWN: case UNKNOWN:
throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!"); throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!");
default: default:
throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + position); throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + type);
} }
}
{ // See whether there is location info and read it List<TypeAnnotationPosition.TypePathEntry> readTypePath() {
int len = nextByte(); int len = nextByte();
ListBuffer<Integer> loc = new ListBuffer<>(); ListBuffer<Integer> loc = new ListBuffer<>();
for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i) for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i)
loc = loc.append(nextByte()); loc = loc.append(nextByte());
position.location = TypeAnnotationPosition.getTypePathFromBinary(loc.toList());
} return TypeAnnotationPosition.getTypePathFromBinary(loc.toList());
return position;
} }
Attribute readAttributeValue() { Attribute readAttributeValue() {

View File

@ -2299,6 +2299,9 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
// Attribute.Compound if tag is ANNOTATION // Attribute.Compound if tag is ANNOTATION
// Attribute.TypeCompound if tag is TYPE_ANNOTATION // Attribute.TypeCompound if tag is TYPE_ANNOTATION
//
// NOTE: This field is slated for removal in the future. Do
// not use it for anything new.
public Attribute.Compound attribute; public Attribute.Compound attribute;
protected JCAnnotation(Tag tag, JCTree annotationType, List<JCExpression> args) { protected JCAnnotation(Tag tag, JCTree annotationType, List<JCExpression> args) {