29 import javax.lang.model.element.ElementKind; |
29 import javax.lang.model.element.ElementKind; |
30 import javax.lang.model.type.TypeKind; |
30 import javax.lang.model.type.TypeKind; |
31 |
31 |
32 import javax.tools.JavaFileObject; |
32 import javax.tools.JavaFileObject; |
33 |
33 |
34 import com.sun.tools.javac.code.Attribute; |
|
35 import com.sun.tools.javac.code.Attribute.TypeCompound; |
34 import com.sun.tools.javac.code.Attribute.TypeCompound; |
36 import com.sun.tools.javac.code.Flags; |
|
37 import com.sun.tools.javac.code.Kinds; |
|
38 import com.sun.tools.javac.code.Type.AnnotatedType; |
35 import com.sun.tools.javac.code.Type.AnnotatedType; |
39 import com.sun.tools.javac.code.Type.ArrayType; |
36 import com.sun.tools.javac.code.Type.ArrayType; |
40 import com.sun.tools.javac.code.Type.CapturedType; |
37 import com.sun.tools.javac.code.Type.CapturedType; |
41 import com.sun.tools.javac.code.Type.ClassType; |
38 import com.sun.tools.javac.code.Type.ClassType; |
42 import com.sun.tools.javac.code.Type.ErrorType; |
39 import com.sun.tools.javac.code.Type.ErrorType; |
47 import com.sun.tools.javac.code.Type.UndetVar; |
44 import com.sun.tools.javac.code.Type.UndetVar; |
48 import com.sun.tools.javac.code.Type.Visitor; |
45 import com.sun.tools.javac.code.Type.Visitor; |
49 import com.sun.tools.javac.code.Type.WildcardType; |
46 import com.sun.tools.javac.code.Type.WildcardType; |
50 import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntry; |
47 import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntry; |
51 import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntryKind; |
48 import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntryKind; |
52 import com.sun.tools.javac.code.TypeTag; |
|
53 import com.sun.tools.javac.code.Symbol.VarSymbol; |
49 import com.sun.tools.javac.code.Symbol.VarSymbol; |
54 import com.sun.tools.javac.code.Symbol.MethodSymbol; |
50 import com.sun.tools.javac.code.Symbol.MethodSymbol; |
55 import com.sun.tools.javac.comp.Annotate; |
51 import com.sun.tools.javac.comp.Annotate; |
56 import com.sun.tools.javac.comp.Annotate.Annotator; |
52 import com.sun.tools.javac.comp.Annotate.Annotator; |
57 import com.sun.tools.javac.comp.AttrContext; |
53 import com.sun.tools.javac.comp.AttrContext; |
68 import com.sun.tools.javac.tree.JCTree.JCTypeApply; |
64 import com.sun.tools.javac.tree.JCTree.JCTypeApply; |
69 import com.sun.tools.javac.tree.JCTree.JCVariableDecl; |
65 import com.sun.tools.javac.tree.JCTree.JCVariableDecl; |
70 import com.sun.tools.javac.tree.TreeScanner; |
66 import com.sun.tools.javac.tree.TreeScanner; |
71 import com.sun.tools.javac.tree.JCTree.*; |
67 import com.sun.tools.javac.tree.JCTree.*; |
72 import com.sun.tools.javac.util.Assert; |
68 import com.sun.tools.javac.util.Assert; |
|
69 import com.sun.tools.javac.util.Context; |
73 import com.sun.tools.javac.util.List; |
70 import com.sun.tools.javac.util.List; |
74 import com.sun.tools.javac.util.ListBuffer; |
71 import com.sun.tools.javac.util.ListBuffer; |
75 import com.sun.tools.javac.util.Log; |
72 import com.sun.tools.javac.util.Log; |
76 import com.sun.tools.javac.util.Names; |
73 import com.sun.tools.javac.util.Names; |
77 |
74 |
81 * separate declaration from type annotations and insert the type |
78 * separate declaration from type annotations and insert the type |
82 * annotations to their types; |
79 * annotations to their types; |
83 * and determine the TypeAnnotationPositions for all type annotations. |
80 * and determine the TypeAnnotationPositions for all type annotations. |
84 */ |
81 */ |
85 public class TypeAnnotations { |
82 public class TypeAnnotations { |
86 // Class cannot be instantiated. |
83 protected static final Context.Key<TypeAnnotations> typeAnnosKey = |
87 private TypeAnnotations() {} |
84 new Context.Key<TypeAnnotations>(); |
|
85 |
|
86 public static TypeAnnotations instance(Context context) { |
|
87 TypeAnnotations instance = context.get(typeAnnosKey); |
|
88 if (instance == null) |
|
89 instance = new TypeAnnotations(context); |
|
90 return instance; |
|
91 } |
|
92 |
|
93 final Log log; |
|
94 final Names names; |
|
95 final Symtab syms; |
|
96 final Annotate annotate; |
|
97 |
|
98 protected TypeAnnotations(Context context) { |
|
99 context.put(typeAnnosKey, this); |
|
100 names = Names.instance(context); |
|
101 log = Log.instance(context); |
|
102 syms = Symtab.instance(context); |
|
103 annotate = Annotate.instance(context); |
|
104 } |
88 |
105 |
89 /** |
106 /** |
90 * Separate type annotations from declaration annotations and |
107 * Separate type annotations from declaration annotations and |
91 * determine the correct positions for type annotations. |
108 * determine the correct positions for type annotations. |
92 * This version only visits types in signatures and should be |
109 * This version only visits types in signatures and should be |
93 * called from MemberEnter. |
110 * called from MemberEnter. |
94 * The method takes the Annotate object as parameter and |
111 * The method takes the Annotate object as parameter and |
95 * adds an Annotator to the correct Annotate queue for |
112 * adds an Annotator to the correct Annotate queue for |
96 * later processing. |
113 * later processing. |
97 */ |
114 */ |
98 public static void organizeTypeAnnotationsSignatures(final Symtab syms, final Names names, |
115 public void organizeTypeAnnotationsSignatures(final Env<AttrContext> env, final JCClassDecl tree) { |
99 final Log log, final Env<AttrContext> env, final JCClassDecl tree, final Annotate annotate) { |
|
100 annotate.afterRepeated( new Annotator() { |
116 annotate.afterRepeated( new Annotator() { |
101 @Override |
117 @Override |
102 public void enterAnnotation() { |
118 public void enterAnnotation() { |
103 JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile); |
119 JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile); |
104 |
120 |
105 try { |
121 try { |
106 new TypeAnnotationPositions(syms, names, log, true).scan(tree); |
122 new TypeAnnotationPositions(true).scan(tree); |
107 } finally { |
123 } finally { |
108 log.useSource(oldSource); |
124 log.useSource(oldSource); |
109 } |
125 } |
110 } |
126 } |
111 } ); |
127 } ); |
113 |
129 |
114 /** |
130 /** |
115 * This version only visits types in bodies, that is, field initializers, |
131 * This version only visits types in bodies, that is, field initializers, |
116 * top-level blocks, and method bodies, and should be called from Attr. |
132 * top-level blocks, and method bodies, and should be called from Attr. |
117 */ |
133 */ |
118 public static void organizeTypeAnnotationsBodies(Symtab syms, Names names, Log log, JCClassDecl tree) { |
134 public void organizeTypeAnnotationsBodies(JCClassDecl tree) { |
119 new TypeAnnotationPositions(syms, names, log, false).scan(tree); |
135 new TypeAnnotationPositions(false).scan(tree); |
120 } |
136 } |
121 |
137 |
122 public enum AnnotationType { DECLARATION, TYPE, BOTH }; |
138 public enum AnnotationType { DECLARATION, TYPE, BOTH }; |
123 |
139 |
124 /** |
140 /** |
125 * Determine whether an annotation is a declaration annotation, |
141 * Determine whether an annotation is a declaration annotation, |
126 * a type annotation, or both. |
142 * a type annotation, or both. |
127 */ |
143 */ |
128 public static AnnotationType annotationType(Symtab syms, Names names, |
144 public AnnotationType annotationType(Attribute.Compound a, Symbol s) { |
129 Attribute.Compound a, Symbol s) { |
|
130 Attribute.Compound atTarget = |
145 Attribute.Compound atTarget = |
131 a.type.tsym.attribute(syms.annotationTargetType.tsym); |
146 a.type.tsym.attribute(syms.annotationTargetType.tsym); |
132 if (atTarget == null) { |
147 if (atTarget == null) { |
133 return inferTargetMetaInfo(a, s); |
148 return inferTargetMetaInfo(a, s); |
134 } |
149 } |
213 private static AnnotationType inferTargetMetaInfo(Attribute.Compound a, Symbol s) { |
228 private static AnnotationType inferTargetMetaInfo(Attribute.Compound a, Symbol s) { |
214 return AnnotationType.DECLARATION; |
229 return AnnotationType.DECLARATION; |
215 } |
230 } |
216 |
231 |
217 |
232 |
218 private static class TypeAnnotationPositions extends TreeScanner { |
233 private class TypeAnnotationPositions extends TreeScanner { |
219 |
234 |
220 private final Symtab syms; |
|
221 private final Names names; |
|
222 private final Log log; |
|
223 private final boolean sigOnly; |
235 private final boolean sigOnly; |
224 |
236 |
225 private TypeAnnotationPositions(Symtab syms, Names names, Log log, boolean sigOnly) { |
237 TypeAnnotationPositions(boolean sigOnly) { |
226 this.syms = syms; |
|
227 this.names = names; |
|
228 this.log = log; |
|
229 this.sigOnly = sigOnly; |
238 this.sigOnly = sigOnly; |
230 } |
239 } |
231 |
240 |
232 /* |
241 /* |
233 * When traversing the AST we keep the "frames" of visited |
242 * When traversing the AST we keep the "frames" of visited |
263 List<Attribute.Compound> annotations = sym.getRawAttributes(); |
272 List<Attribute.Compound> annotations = sym.getRawAttributes(); |
264 ListBuffer<Attribute.Compound> declAnnos = new ListBuffer<Attribute.Compound>(); |
273 ListBuffer<Attribute.Compound> declAnnos = new ListBuffer<Attribute.Compound>(); |
265 ListBuffer<Attribute.TypeCompound> typeAnnos = new ListBuffer<Attribute.TypeCompound>(); |
274 ListBuffer<Attribute.TypeCompound> typeAnnos = new ListBuffer<Attribute.TypeCompound>(); |
266 |
275 |
267 for (Attribute.Compound a : annotations) { |
276 for (Attribute.Compound a : annotations) { |
268 switch (annotationType(syms, names, a, sym)) { |
277 switch (annotationType(a, sym)) { |
269 case DECLARATION: |
278 case DECLARATION: |
270 declAnnos.append(a); |
279 declAnnos.append(a); |
271 break; |
280 break; |
272 case BOTH: { |
281 case BOTH: { |
273 declAnnos.append(a); |
282 declAnnos.append(a); |
299 sym.appendUniqueTypeAttributes(typeAnnotations); |
308 sym.appendUniqueTypeAttributes(typeAnnotations); |
300 return; |
309 return; |
301 } |
310 } |
302 |
311 |
303 // type is non-null and annotations are added to that type |
312 // type is non-null and annotations are added to that type |
304 type = typeWithAnnotations(typetree, type, typeAnnotations, log); |
313 type = typeWithAnnotations(typetree, type, typeAnnotations); |
305 |
314 |
306 if (sym.getKind() == ElementKind.METHOD) { |
315 if (sym.getKind() == ElementKind.METHOD) { |
307 sym.type.asMethodType().restype = type; |
316 sym.type.asMethodType().restype = type; |
308 } else if (sym.getKind() == ElementKind.PARAMETER) { |
317 } else if (sym.getKind() == ElementKind.PARAMETER) { |
309 sym.type = type; |
318 sym.type = type; |
350 // need to set its position explicitly. |
359 // need to set its position explicitly. |
351 // The method returns a copy of type that contains these annotations. |
360 // The method returns a copy of type that contains these annotations. |
352 // |
361 // |
353 // As a side effect the method sets the type annotation position of "annotations". |
362 // As a side effect the method sets the type annotation position of "annotations". |
354 // Note that it is assumed that all annotations share the same position. |
363 // Note that it is assumed that all annotations share the same position. |
355 private static Type typeWithAnnotations(final JCTree typetree, final Type type, |
364 private Type typeWithAnnotations(final JCTree typetree, final Type type, |
356 final List<Attribute.TypeCompound> annotations, Log log) { |
365 final List<Attribute.TypeCompound> annotations) { |
357 // System.out.printf("typeWithAnnotations(typetree: %s, type: %s, annotations: %s)%n", |
366 // System.out.printf("typeWithAnnotations(typetree: %s, type: %s, annotations: %s)%n", |
358 // typetree, type, annotations); |
367 // typetree, type, annotations); |
359 if (annotations.isEmpty()) { |
368 if (annotations.isEmpty()) { |
360 return type; |
369 return type; |
361 } |
370 } |
398 tomodify = (Type.ArrayType) tomodify.elemtype; |
407 tomodify = (Type.ArrayType) tomodify.elemtype; |
399 } |
408 } |
400 arTree = arrayTypeTree(arTree.elemtype); |
409 arTree = arrayTypeTree(arTree.elemtype); |
401 depth = depth.append(TypePathEntry.ARRAY); |
410 depth = depth.append(TypePathEntry.ARRAY); |
402 } |
411 } |
403 Type arelemType = typeWithAnnotations(arTree.elemtype, arType.elemtype, annotations, log); |
412 Type arelemType = typeWithAnnotations(arTree.elemtype, arType.elemtype, annotations); |
404 tomodify.elemtype = arelemType; |
413 tomodify.elemtype = arelemType; |
405 { |
414 { |
406 // All annotations share the same position; modify the first one. |
415 // All annotations share the same position; modify the first one. |
407 Attribute.TypeCompound a = annotations.get(0); |
416 Attribute.TypeCompound a = annotations.get(0); |
408 TypeAnnotationPosition p = a.position; |
417 TypeAnnotationPosition p = a.position; |
415 return type; |
424 return type; |
416 } else if (type.getKind() == TypeKind.UNION) { |
425 } else if (type.getKind() == TypeKind.UNION) { |
417 // There is a TypeKind, but no TypeTag. |
426 // There is a TypeKind, but no TypeTag. |
418 JCTypeUnion tutree = (JCTypeUnion) typetree; |
427 JCTypeUnion tutree = (JCTypeUnion) typetree; |
419 JCExpression fst = tutree.alternatives.get(0); |
428 JCExpression fst = tutree.alternatives.get(0); |
420 Type res = typeWithAnnotations(fst, fst.type, annotations, log); |
429 Type res = typeWithAnnotations(fst, fst.type, annotations); |
421 fst.type = res; |
430 fst.type = res; |
422 // TODO: do we want to set res as first element in uct.alternatives? |
431 // TODO: do we want to set res as first element in uct.alternatives? |
423 // UnionClassType uct = (com.sun.tools.javac.code.Type.UnionClassType)type; |
432 // UnionClassType uct = (com.sun.tools.javac.code.Type.UnionClassType)type; |
424 // Return the un-annotated union-type. |
433 // Return the un-annotated union-type. |
425 return type; |
434 return type; |
530 * @param type The type to copy. |
539 * @param type The type to copy. |
531 * @param stopAt The type to stop at. |
540 * @param stopAt The type to stop at. |
532 * @param annotations The annotations to insert. |
541 * @param annotations The annotations to insert. |
533 * @return A copy of type that contains the annotations. |
542 * @return A copy of type that contains the annotations. |
534 */ |
543 */ |
535 private static Type typeWithAnnotations(final Type type, |
544 private Type typeWithAnnotations(final Type type, |
536 final Type stopAt, |
545 final Type stopAt, |
537 final List<Attribute.TypeCompound> annotations) { |
546 final List<Attribute.TypeCompound> annotations) { |
538 Visitor<Type, List<TypeCompound>> visitor = |
547 Visitor<Type, List<TypeCompound>> visitor = |
539 new Type.Visitor<Type, List<Attribute.TypeCompound>>() { |
548 new Type.Visitor<Type, List<Attribute.TypeCompound>>() { |
540 @Override |
549 @Override |
951 "\n Looking for tree: " + tree); |
960 "\n Looking for tree: " + tree); |
952 return; |
961 return; |
953 } |
962 } |
954 } |
963 } |
955 |
964 |
956 private static void locateNestedTypes(Type type, TypeAnnotationPosition p) { |
965 private void locateNestedTypes(Type type, TypeAnnotationPosition p) { |
957 // The number of "steps" to get from the full type to the |
966 // The number of "steps" to get from the full type to the |
958 // left-most outer type. |
967 // left-most outer type. |
959 ListBuffer<TypePathEntry> depth = new ListBuffer<>(); |
968 ListBuffer<TypePathEntry> depth = new ListBuffer<>(); |
960 |
969 |
961 Type encl = type.getEnclosingType(); |
970 Type encl = type.getEnclosingType(); |
968 if (depth.nonEmpty()) { |
977 if (depth.nonEmpty()) { |
969 p.location = p.location.prependList(depth.toList()); |
978 p.location = p.location.prependList(depth.toList()); |
970 } |
979 } |
971 } |
980 } |
972 |
981 |
973 private static int methodParamIndex(List<JCTree> path, JCTree param) { |
982 private int methodParamIndex(List<JCTree> path, JCTree param) { |
974 List<JCTree> curr = path; |
983 List<JCTree> curr = path; |
975 while (curr.head.getTag() != Tag.METHODDEF && |
984 while (curr.head.getTag() != Tag.METHODDEF && |
976 curr.head.getTag() != Tag.LAMBDA) { |
985 curr.head.getTag() != Tag.LAMBDA) { |
977 curr = curr.tail; |
986 curr = curr.tail; |
978 } |
987 } |
1282 resolveFrame(tree, frame, frames.toList(), p); |
1291 resolveFrame(tree, frame, frames.toList(), p); |
1283 setTypeAnnotationPos(annotations, p); |
1292 setTypeAnnotationPos(annotations, p); |
1284 } |
1293 } |
1285 } |
1294 } |
1286 |
1295 |
1287 private static void setTypeAnnotationPos(List<JCAnnotation> annotations, |
1296 private void setTypeAnnotationPos(List<JCAnnotation> annotations, |
1288 TypeAnnotationPosition position) { |
1297 TypeAnnotationPosition position) { |
1289 for (JCAnnotation anno : annotations) { |
1298 for (JCAnnotation anno : annotations) { |
1290 // attribute might be null during DeferredAttr; |
1299 // attribute might be null during DeferredAttr; |
1291 // we will be back later. |
1300 // we will be back later. |
1292 if (anno.attribute != null) { |
1301 if (anno.attribute != null) { |