6917067: refactor type annotations code from TransTypes into new TypeAnnotations class
Co-authored-by: Michael Ernst <mernst@cs.washington.edu> Reviewed-by: jjg, darcy
This commit is contained in:
parent
4874fa7e28
commit
a9131d080c
@ -0,0 +1,411 @@
|
||||
/*
|
||||
* 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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user