This commit is contained in:
Michael Fang 2013-09-25 14:02:16 -07:00
commit 33c36e737b
3 changed files with 49 additions and 36 deletions

View file

@ -31,10 +31,7 @@ import javax.lang.model.type.TypeKind;
import javax.tools.JavaFileObject; import javax.tools.JavaFileObject;
import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.Attribute.TypeCompound; import com.sun.tools.javac.code.Attribute.TypeCompound;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Kinds;
import com.sun.tools.javac.code.Type.AnnotatedType; import com.sun.tools.javac.code.Type.AnnotatedType;
import com.sun.tools.javac.code.Type.ArrayType; import com.sun.tools.javac.code.Type.ArrayType;
import com.sun.tools.javac.code.Type.CapturedType; import com.sun.tools.javac.code.Type.CapturedType;
@ -49,7 +46,6 @@ import com.sun.tools.javac.code.Type.Visitor;
import com.sun.tools.javac.code.Type.WildcardType; import com.sun.tools.javac.code.Type.WildcardType;
import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntry; import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntry;
import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntryKind; import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntryKind;
import com.sun.tools.javac.code.TypeTag;
import com.sun.tools.javac.code.Symbol.VarSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.comp.Annotate; import com.sun.tools.javac.comp.Annotate;
@ -70,6 +66,7 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.TreeScanner; import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.Assert; import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.Log;
@ -83,8 +80,28 @@ import com.sun.tools.javac.util.Names;
* and determine the TypeAnnotationPositions for all type annotations. * and determine the TypeAnnotationPositions for all type annotations.
*/ */
public class TypeAnnotations { public class TypeAnnotations {
// Class cannot be instantiated. protected static final Context.Key<TypeAnnotations> typeAnnosKey =
private TypeAnnotations() {} new Context.Key<TypeAnnotations>();
public static TypeAnnotations instance(Context context) {
TypeAnnotations instance = context.get(typeAnnosKey);
if (instance == null)
instance = new TypeAnnotations(context);
return instance;
}
final Log log;
final Names names;
final Symtab syms;
final Annotate annotate;
protected TypeAnnotations(Context context) {
context.put(typeAnnosKey, this);
names = Names.instance(context);
log = Log.instance(context);
syms = Symtab.instance(context);
annotate = Annotate.instance(context);
}
/** /**
* Separate type annotations from declaration annotations and * Separate type annotations from declaration annotations and
@ -95,15 +112,14 @@ public class TypeAnnotations {
* adds an Annotator to the correct Annotate queue for * adds an Annotator to the correct Annotate queue for
* later processing. * later processing.
*/ */
public static void organizeTypeAnnotationsSignatures(final Symtab syms, final Names names, public void organizeTypeAnnotationsSignatures(final Env<AttrContext> env, final JCClassDecl tree) {
final Log log, final Env<AttrContext> env, final JCClassDecl tree, final Annotate annotate) {
annotate.afterRepeated( new Annotator() { annotate.afterRepeated( new Annotator() {
@Override @Override
public void enterAnnotation() { public void enterAnnotation() {
JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile); JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile);
try { try {
new TypeAnnotationPositions(syms, names, log, true).scan(tree); new TypeAnnotationPositions(true).scan(tree);
} finally { } finally {
log.useSource(oldSource); log.useSource(oldSource);
} }
@ -115,8 +131,8 @@ public class TypeAnnotations {
* This version only visits types in bodies, that is, field initializers, * This version only visits types in bodies, that is, field initializers,
* top-level blocks, and method bodies, and should be called from Attr. * top-level blocks, and method bodies, and should be called from Attr.
*/ */
public static void organizeTypeAnnotationsBodies(Symtab syms, Names names, Log log, JCClassDecl tree) { public void organizeTypeAnnotationsBodies(JCClassDecl tree) {
new TypeAnnotationPositions(syms, names, log, false).scan(tree); new TypeAnnotationPositions(false).scan(tree);
} }
public enum AnnotationType { DECLARATION, TYPE, BOTH }; public enum AnnotationType { DECLARATION, TYPE, BOTH };
@ -125,8 +141,7 @@ public class TypeAnnotations {
* Determine whether an annotation is a declaration annotation, * Determine whether an annotation is a declaration annotation,
* a type annotation, or both. * a type annotation, or both.
*/ */
public static AnnotationType annotationType(Symtab syms, Names names, public AnnotationType annotationType(Attribute.Compound a, Symbol s) {
Attribute.Compound a, Symbol s) {
Attribute.Compound atTarget = Attribute.Compound atTarget =
a.type.tsym.attribute(syms.annotationTargetType.tsym); a.type.tsym.attribute(syms.annotationTargetType.tsym);
if (atTarget == null) { if (atTarget == null) {
@ -215,17 +230,11 @@ public class TypeAnnotations {
} }
private static class TypeAnnotationPositions extends TreeScanner { private class TypeAnnotationPositions extends TreeScanner {
private final Symtab syms;
private final Names names;
private final Log log;
private final boolean sigOnly; private final boolean sigOnly;
private TypeAnnotationPositions(Symtab syms, Names names, Log log, boolean sigOnly) { TypeAnnotationPositions(boolean sigOnly) {
this.syms = syms;
this.names = names;
this.log = log;
this.sigOnly = sigOnly; this.sigOnly = sigOnly;
} }
@ -265,7 +274,7 @@ public class TypeAnnotations {
ListBuffer<Attribute.TypeCompound> typeAnnos = new ListBuffer<Attribute.TypeCompound>(); ListBuffer<Attribute.TypeCompound> typeAnnos = new ListBuffer<Attribute.TypeCompound>();
for (Attribute.Compound a : annotations) { for (Attribute.Compound a : annotations) {
switch (annotationType(syms, names, a, sym)) { switch (annotationType(a, sym)) {
case DECLARATION: case DECLARATION:
declAnnos.append(a); declAnnos.append(a);
break; break;
@ -301,7 +310,7 @@ public class TypeAnnotations {
} }
// type is non-null and annotations are added to that type // type is non-null and annotations are added to that type
type = typeWithAnnotations(typetree, type, typeAnnotations, log); type = typeWithAnnotations(typetree, type, typeAnnotations);
if (sym.getKind() == ElementKind.METHOD) { if (sym.getKind() == ElementKind.METHOD) {
sym.type.asMethodType().restype = type; sym.type.asMethodType().restype = type;
@ -352,8 +361,8 @@ public class TypeAnnotations {
// //
// As a side effect the method sets the type annotation position of "annotations". // As a side effect the method sets the type annotation position of "annotations".
// Note that it is assumed that all annotations share the same position. // Note that it is assumed that all annotations share the same position.
private static Type typeWithAnnotations(final JCTree typetree, final Type type, private Type typeWithAnnotations(final JCTree typetree, final Type type,
final List<Attribute.TypeCompound> annotations, Log log) { final List<Attribute.TypeCompound> annotations) {
// System.out.printf("typeWithAnnotations(typetree: %s, type: %s, annotations: %s)%n", // System.out.printf("typeWithAnnotations(typetree: %s, type: %s, annotations: %s)%n",
// typetree, type, annotations); // typetree, type, annotations);
if (annotations.isEmpty()) { if (annotations.isEmpty()) {
@ -400,7 +409,7 @@ public class TypeAnnotations {
arTree = arrayTypeTree(arTree.elemtype); arTree = arrayTypeTree(arTree.elemtype);
depth = depth.append(TypePathEntry.ARRAY); depth = depth.append(TypePathEntry.ARRAY);
} }
Type arelemType = typeWithAnnotations(arTree.elemtype, arType.elemtype, annotations, log); Type arelemType = typeWithAnnotations(arTree.elemtype, arType.elemtype, annotations);
tomodify.elemtype = arelemType; tomodify.elemtype = arelemType;
{ {
// All annotations share the same position; modify the first one. // All annotations share the same position; modify the first one.
@ -417,7 +426,7 @@ public class TypeAnnotations {
// There is a TypeKind, but no TypeTag. // There is a TypeKind, but no TypeTag.
JCTypeUnion tutree = (JCTypeUnion) typetree; JCTypeUnion tutree = (JCTypeUnion) typetree;
JCExpression fst = tutree.alternatives.get(0); JCExpression fst = tutree.alternatives.get(0);
Type res = typeWithAnnotations(fst, fst.type, annotations, log); Type res = typeWithAnnotations(fst, fst.type, annotations);
fst.type = res; fst.type = res;
// TODO: do we want to set res as first element in uct.alternatives? // TODO: do we want to set res as first element in uct.alternatives?
// UnionClassType uct = (com.sun.tools.javac.code.Type.UnionClassType)type; // UnionClassType uct = (com.sun.tools.javac.code.Type.UnionClassType)type;
@ -505,7 +514,7 @@ public class TypeAnnotations {
} }
} }
private static JCArrayTypeTree arrayTypeTree(JCTree typetree) { private JCArrayTypeTree arrayTypeTree(JCTree typetree) {
if (typetree.getKind() == JCTree.Kind.ARRAY_TYPE) { if (typetree.getKind() == JCTree.Kind.ARRAY_TYPE) {
return (JCArrayTypeTree) typetree; return (JCArrayTypeTree) typetree;
} else if (typetree.getKind() == JCTree.Kind.ANNOTATED_TYPE) { } else if (typetree.getKind() == JCTree.Kind.ANNOTATED_TYPE) {
@ -532,7 +541,7 @@ public class TypeAnnotations {
* @param annotations The annotations to insert. * @param annotations The annotations to insert.
* @return A copy of type that contains the annotations. * @return A copy of type that contains the annotations.
*/ */
private static Type typeWithAnnotations(final Type type, private Type typeWithAnnotations(final Type type,
final Type stopAt, final Type stopAt,
final List<Attribute.TypeCompound> annotations) { final List<Attribute.TypeCompound> annotations) {
Visitor<Type, List<TypeCompound>> visitor = Visitor<Type, List<TypeCompound>> visitor =
@ -619,7 +628,7 @@ public class TypeAnnotations {
return type.accept(visitor, annotations); return type.accept(visitor, annotations);
} }
private static Attribute.TypeCompound toTypeCompound(Attribute.Compound a, TypeAnnotationPosition p) { private Attribute.TypeCompound toTypeCompound(Attribute.Compound a, TypeAnnotationPosition p) {
// It is safe to alias the position. // It is safe to alias the position.
return new Attribute.TypeCompound(a, p); return new Attribute.TypeCompound(a, p);
} }
@ -953,7 +962,7 @@ public class TypeAnnotations {
} }
} }
private static void locateNestedTypes(Type type, TypeAnnotationPosition p) { private void locateNestedTypes(Type type, TypeAnnotationPosition p) {
// The number of "steps" to get from the full type to the // The number of "steps" to get from the full type to the
// left-most outer type. // left-most outer type.
ListBuffer<TypePathEntry> depth = new ListBuffer<>(); ListBuffer<TypePathEntry> depth = new ListBuffer<>();
@ -970,7 +979,7 @@ public class TypeAnnotations {
} }
} }
private static int methodParamIndex(List<JCTree> path, JCTree param) { private int methodParamIndex(List<JCTree> path, JCTree param) {
List<JCTree> curr = path; List<JCTree> curr = path;
while (curr.head.getTag() != Tag.METHODDEF && while (curr.head.getTag() != Tag.METHODDEF &&
curr.head.getTag() != Tag.LAMBDA) { curr.head.getTag() != Tag.LAMBDA) {
@ -1284,7 +1293,7 @@ public class TypeAnnotations {
} }
} }
private static void setTypeAnnotationPos(List<JCAnnotation> annotations, private void setTypeAnnotationPos(List<JCAnnotation> annotations,
TypeAnnotationPosition position) { TypeAnnotationPosition position) {
for (JCAnnotation anno : annotations) { for (JCAnnotation anno : annotations) {
// attribute might be null during DeferredAttr; // attribute might be null during DeferredAttr;

View file

@ -93,6 +93,7 @@ public class Attr extends JCTree.Visitor {
final Types types; final Types types;
final JCDiagnostic.Factory diags; final JCDiagnostic.Factory diags;
final Annotate annotate; final Annotate annotate;
final TypeAnnotations typeAnnotations;
final DeferredLintHandler deferredLintHandler; final DeferredLintHandler deferredLintHandler;
public static Attr instance(Context context) { public static Attr instance(Context context) {
@ -121,6 +122,7 @@ public class Attr extends JCTree.Visitor {
types = Types.instance(context); types = Types.instance(context);
diags = JCDiagnostic.Factory.instance(context); diags = JCDiagnostic.Factory.instance(context);
annotate = Annotate.instance(context); annotate = Annotate.instance(context);
typeAnnotations = TypeAnnotations.instance(context);
deferredLintHandler = DeferredLintHandler.instance(context); deferredLintHandler = DeferredLintHandler.instance(context);
Options options = Options.instance(context); Options options = Options.instance(context);
@ -2228,7 +2230,7 @@ public class Attr extends JCTree.Visitor {
// empty annotations, if only declaration annotations were given. // empty annotations, if only declaration annotations were given.
// This method will raise an error for such a type. // This method will raise an error for such a type.
for (JCAnnotation ai : annotations) { for (JCAnnotation ai : annotations) {
if (TypeAnnotations.annotationType(syms, names, ai.attribute, sym) == TypeAnnotations.AnnotationType.DECLARATION) { if (typeAnnotations.annotationType(ai.attribute, sym) == TypeAnnotations.AnnotationType.DECLARATION) {
log.error(ai.pos(), "annotation.type.not.applicable"); log.error(ai.pos(), "annotation.type.not.applicable");
} }
} }
@ -4339,7 +4341,7 @@ public class Attr extends JCTree.Visitor {
} }
if (allowTypeAnnos) { if (allowTypeAnnos) {
// Correctly organize the postions of the type annotations // Correctly organize the postions of the type annotations
TypeAnnotations.organizeTypeAnnotationsBodies(this.syms, this.names, this.log, tree); typeAnnotations.organizeTypeAnnotationsBodies(tree);
// Check type annotations applicability rules // Check type annotations applicability rules
validateTypeAnnotations(tree); validateTypeAnnotations(tree);

View file

@ -79,6 +79,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
private final ClassReader reader; private final ClassReader reader;
private final Todo todo; private final Todo todo;
private final Annotate annotate; private final Annotate annotate;
private final TypeAnnotations typeAnnotations;
private final Types types; private final Types types;
private final JCDiagnostic.Factory diags; private final JCDiagnostic.Factory diags;
private final Source source; private final Source source;
@ -105,6 +106,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
reader = ClassReader.instance(context); reader = ClassReader.instance(context);
todo = Todo.instance(context); todo = Todo.instance(context);
annotate = Annotate.instance(context); annotate = Annotate.instance(context);
typeAnnotations = TypeAnnotations.instance(context);
types = Types.instance(context); types = Types.instance(context);
diags = JCDiagnostic.Factory.instance(context); diags = JCDiagnostic.Factory.instance(context);
source = Source.instance(context); source = Source.instance(context);
@ -1164,7 +1166,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
} }
} }
if (allowTypeAnnos) { if (allowTypeAnnos) {
TypeAnnotations.organizeTypeAnnotationsSignatures(syms, names, log, env, tree, annotate); typeAnnotations.organizeTypeAnnotationsSignatures(env, tree);
} }
} }