1 /*
2  * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package com.sun.tools.javac.code;
27 
28 import javax.lang.model.element.Element;
29 import javax.lang.model.element.ElementKind;
30 import javax.lang.model.type.TypeKind;
31 
32 import javax.tools.JavaFileObject;
33 
34 import com.sun.tools.javac.code.Attribute.TypeCompound;
35 import com.sun.tools.javac.code.Type.AnnotatedType;
36 import com.sun.tools.javac.code.Type.ArrayType;
37 import com.sun.tools.javac.code.Type.CapturedType;
38 import com.sun.tools.javac.code.Type.ClassType;
39 import com.sun.tools.javac.code.Type.ErrorType;
40 import com.sun.tools.javac.code.Type.ForAll;
41 import com.sun.tools.javac.code.Type.MethodType;
42 import com.sun.tools.javac.code.Type.PackageType;
43 import com.sun.tools.javac.code.Type.TypeVar;
44 import com.sun.tools.javac.code.Type.UndetVar;
45 import com.sun.tools.javac.code.Type.Visitor;
46 import com.sun.tools.javac.code.Type.WildcardType;
47 import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntry;
48 import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntryKind;
49 import com.sun.tools.javac.code.Symbol.VarSymbol;
50 import com.sun.tools.javac.code.Symbol.MethodSymbol;
51 import com.sun.tools.javac.comp.Annotate;
52 import com.sun.tools.javac.comp.Annotate.Worker;
53 import com.sun.tools.javac.comp.Attr;
54 import com.sun.tools.javac.comp.AttrContext;
55 import com.sun.tools.javac.comp.Env;
56 import com.sun.tools.javac.tree.JCTree;
57 import com.sun.tools.javac.tree.TreeInfo;
58 import com.sun.tools.javac.tree.JCTree.JCBlock;
59 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
60 import com.sun.tools.javac.tree.JCTree.JCExpression;
61 import com.sun.tools.javac.tree.JCTree.JCLambda;
62 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
63 import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
64 import com.sun.tools.javac.tree.JCTree.JCNewClass;
65 import com.sun.tools.javac.tree.JCTree.JCTypeApply;
66 import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
67 import com.sun.tools.javac.tree.TreeScanner;
68 import com.sun.tools.javac.tree.JCTree.*;
69 import com.sun.tools.javac.util.Assert;
70 import com.sun.tools.javac.util.Context;
71 import com.sun.tools.javac.util.List;
72 import com.sun.tools.javac.util.ListBuffer;
73 import com.sun.tools.javac.util.Log;
74 import com.sun.tools.javac.util.Names;
75 import com.sun.tools.javac.util.Options;
76 
77 /**
78  * Contains operations specific to processing type annotations.
79  * This class has two functions:
80  * separate declaration from type annotations and insert the type
81  * annotations to their types;
82  * and determine the TypeAnnotationPositions for all type annotations.
83  */
84 public class TypeAnnotations {
85     protected static final Context.Key<TypeAnnotations> typeAnnosKey =
86         new Context.Key<TypeAnnotations>();
87 
instance(Context context)88     public static TypeAnnotations instance(Context context) {
89         TypeAnnotations instance = context.get(typeAnnosKey);
90         if (instance == null)
91             instance = new TypeAnnotations(context);
92         return instance;
93     }
94 
95     final Log log;
96     final Names names;
97     final Symtab syms;
98     final Annotate annotate;
99     final Attr attr;
100 
TypeAnnotations(Context context)101     protected TypeAnnotations(Context context) {
102         context.put(typeAnnosKey, this);
103         names = Names.instance(context);
104         log = Log.instance(context);
105         syms = Symtab.instance(context);
106         annotate = Annotate.instance(context);
107         attr = Attr.instance(context);
108         Options options = Options.instance(context);
109     }
110 
111     /**
112      * Separate type annotations from declaration annotations and
113      * determine the correct positions for type annotations.
114      * This version only visits types in signatures and should be
115      * called from MemberEnter.
116      * The method takes the Annotate object as parameter and
117      * adds an Annotate.Worker to the correct Annotate queue for
118      * later processing.
119      */
organizeTypeAnnotationsSignatures(final Env<AttrContext> env, final JCClassDecl tree)120     public void organizeTypeAnnotationsSignatures(final Env<AttrContext> env, final JCClassDecl tree) {
121         annotate.afterRepeated( new Worker() {
122             @Override
123             public void run() {
124                 JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile);
125 
126                 try {
127                     new TypeAnnotationPositions(true).scan(tree);
128                 } finally {
129                     log.useSource(oldSource);
130                 }
131             }
132         } );
133     }
134 
validateTypeAnnotationsSignatures(final Env<AttrContext> env, final JCClassDecl tree)135     public void validateTypeAnnotationsSignatures(final Env<AttrContext> env, final JCClassDecl tree) {
136         annotate.validate(new Worker() { //validate annotations
137             @Override
138             public void run() {
139                 JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile);
140 
141                 try {
142                     attr.validateTypeAnnotations(tree, true);
143                 } finally {
144                     log.useSource(oldSource);
145                 }
146             }
147         } );
148     }
149 
150     /**
151      * This version only visits types in bodies, that is, field initializers,
152      * top-level blocks, and method bodies, and should be called from Attr.
153      */
organizeTypeAnnotationsBodies(JCClassDecl tree)154     public void organizeTypeAnnotationsBodies(JCClassDecl tree) {
155         new TypeAnnotationPositions(false).scan(tree);
156     }
157 
158     public enum AnnotationType { DECLARATION, TYPE, BOTH };
159 
160     /**
161      * Determine whether an annotation is a declaration annotation,
162      * a type annotation, or both.
163      */
annotationType(Attribute.Compound a, Symbol s)164     public AnnotationType annotationType(Attribute.Compound a, Symbol s) {
165         Attribute.Compound atTarget =
166             a.type.tsym.attribute(syms.annotationTargetType.tsym);
167         if (atTarget == null) {
168             return inferTargetMetaInfo(a, s);
169         }
170         Attribute atValue = atTarget.member(names.value);
171         if (!(atValue instanceof Attribute.Array)) {
172             Assert.error("annotationType(): bad @Target argument " + atValue +
173                     " (" + atValue.getClass() + ")");
174             return AnnotationType.DECLARATION; // error recovery
175         }
176         Attribute.Array arr = (Attribute.Array) atValue;
177         boolean isDecl = false, isType = false;
178         for (Attribute app : arr.values) {
179             if (!(app instanceof Attribute.Enum)) {
180                 Assert.error("annotationType(): unrecognized Attribute kind " + app +
181                         " (" + app.getClass() + ")");
182                 isDecl = true;
183                 continue;
184             }
185             Attribute.Enum e = (Attribute.Enum) app;
186             if (e.value.name == names.TYPE) {
187                 if (s.kind == Kinds.TYP)
188                     isDecl = true;
189             } else if (e.value.name == names.FIELD) {
190                 if (s.kind == Kinds.VAR &&
191                         s.owner.kind != Kinds.MTH)
192                     isDecl = true;
193             } else if (e.value.name == names.METHOD) {
194                 if (s.kind == Kinds.MTH &&
195                         !s.isConstructor())
196                     isDecl = true;
197             } else if (e.value.name == names.PARAMETER) {
198                 if (s.kind == Kinds.VAR &&
199                         s.owner.kind == Kinds.MTH &&
200                         (s.flags() & Flags.PARAMETER) != 0)
201                     isDecl = true;
202             } else if (e.value.name == names.CONSTRUCTOR) {
203                 if (s.kind == Kinds.MTH &&
204                         s.isConstructor())
205                     isDecl = true;
206             } else if (e.value.name == names.LOCAL_VARIABLE) {
207                 if (s.kind == Kinds.VAR &&
208                         s.owner.kind == Kinds.MTH &&
209                         (s.flags() & Flags.PARAMETER) == 0)
210                     isDecl = true;
211             } else if (e.value.name == names.ANNOTATION_TYPE) {
212                 if (s.kind == Kinds.TYP &&
213                         (s.flags() & Flags.ANNOTATION) != 0)
214                     isDecl = true;
215             } else if (e.value.name == names.PACKAGE) {
216                 if (s.kind == Kinds.PCK)
217                     isDecl = true;
218             } else if (e.value.name == names.TYPE_USE) {
219                 if (s.kind == Kinds.TYP ||
220                         s.kind == Kinds.VAR ||
221                         (s.kind == Kinds.MTH && !s.isConstructor() &&
222                         !s.type.getReturnType().hasTag(TypeTag.VOID)) ||
223                         (s.kind == Kinds.MTH && s.isConstructor()))
224                     isType = true;
225             } else if (e.value.name == names.TYPE_PARAMETER) {
226                 /* Irrelevant in this case */
227                 // TYPE_PARAMETER doesn't aid in distinguishing between
228                 // Type annotations and declaration annotations on an
229                 // Element
230             } else {
231                 Assert.error("annotationType(): unrecognized Attribute name " + e.value.name +
232                         " (" + e.value.name.getClass() + ")");
233                 isDecl = true;
234             }
235         }
236         if (isDecl && isType) {
237             return AnnotationType.BOTH;
238         } else if (isType) {
239             return AnnotationType.TYPE;
240         } else {
241             return AnnotationType.DECLARATION;
242         }
243     }
244 
245     /** Infer the target annotation kind, if none is give.
246      * We only infer declaration annotations.
247      */
inferTargetMetaInfo(Attribute.Compound a, Symbol s)248     private static AnnotationType inferTargetMetaInfo(Attribute.Compound a, Symbol s) {
249         return AnnotationType.DECLARATION;
250     }
251 
252 
253     private class TypeAnnotationPositions extends TreeScanner {
254 
255         private final boolean sigOnly;
256 
TypeAnnotationPositions(boolean sigOnly)257         TypeAnnotationPositions(boolean sigOnly) {
258             this.sigOnly = sigOnly;
259         }
260 
261         /*
262          * When traversing the AST we keep the "frames" of visited
263          * trees in order to determine the position of annotations.
264          */
265         private ListBuffer<JCTree> frames = new ListBuffer<>();
266 
push(JCTree t)267         protected void push(JCTree t) { frames = frames.prepend(t); }
pop()268         protected JCTree pop() { return frames.next(); }
269         // could this be frames.elems.tail.head?
peek2()270         private JCTree peek2() { return frames.toList().tail.head; }
271 
272         @Override
scan(JCTree tree)273         public void scan(JCTree tree) {
274             push(tree);
275             super.scan(tree);
276             pop();
277         }
278 
279         /**
280          * Separates type annotations from declaration annotations.
281          * This step is needed because in certain locations (where declaration
282          * and type annotations can be mixed, e.g. the type of a field)
283          * we never build an JCAnnotatedType. This step finds these
284          * annotations and marks them as if they were part of the type.
285          */
separateAnnotationsKinds(JCTree typetree, Type type, Symbol sym, TypeAnnotationPosition pos)286         private void separateAnnotationsKinds(JCTree typetree, Type type, Symbol sym,
287                 TypeAnnotationPosition pos) {
288             List<Attribute.Compound> annotations = sym.getRawAttributes();
289             ListBuffer<Attribute.Compound> declAnnos = new ListBuffer<Attribute.Compound>();
290             ListBuffer<Attribute.TypeCompound> typeAnnos = new ListBuffer<Attribute.TypeCompound>();
291             ListBuffer<Attribute.TypeCompound> onlyTypeAnnos = new ListBuffer<Attribute.TypeCompound>();
292 
293             for (Attribute.Compound a : annotations) {
294                 switch (annotationType(a, sym)) {
295                 case DECLARATION:
296                     declAnnos.append(a);
297                     break;
298                 case BOTH: {
299                     declAnnos.append(a);
300                     Attribute.TypeCompound ta = toTypeCompound(a, pos);
301                     typeAnnos.append(ta);
302                     break;
303                 }
304                 case TYPE: {
305                     Attribute.TypeCompound ta = toTypeCompound(a, pos);
306                     typeAnnos.append(ta);
307                     // Also keep track which annotations are only type annotations
308                     onlyTypeAnnos.append(ta);
309                     break;
310                 }
311                 }
312             }
313 
314             sym.resetAnnotations();
315             sym.setDeclarationAttributes(declAnnos.toList());
316 
317             if (typeAnnos.isEmpty()) {
318                 return;
319             }
320 
321             List<Attribute.TypeCompound> typeAnnotations = typeAnnos.toList();
322 
323             if (type == null) {
324                 // When type is null, put the type annotations to the symbol.
325                 // This is used for constructor return annotations, for which
326                 // we use the type of the enclosing class.
327                 type = sym.getEnclosingElement().asType();
328 
329                 // Declaration annotations are always allowed on constructor returns.
330                 // Therefore, use typeAnnotations instead of onlyTypeAnnos.
331                 type = typeWithAnnotations(typetree, type, typeAnnotations, typeAnnotations);
332                 // Note that we don't use the result, the call to
333                 // typeWithAnnotations side-effects the type annotation positions.
334                 // This is important for constructors of nested classes.
335 
336                 sym.appendUniqueTypeAttributes(typeAnnotations);
337                 return;
338             }
339 
340             // type is non-null and annotations are added to that type
341             type = typeWithAnnotations(typetree, type, typeAnnotations, onlyTypeAnnos.toList());
342 
343             if (sym.getKind() == ElementKind.METHOD) {
344                 sym.type.asMethodType().restype = type;
345             } else if (sym.getKind() == ElementKind.PARAMETER) {
346                 sym.type = type;
347                 if (sym.getQualifiedName().equals(names._this)) {
348                     sym.owner.type.asMethodType().recvtype = type;
349                     // note that the typeAnnotations will also be added to the owner below.
350                 } else {
351                     MethodType methType = sym.owner.type.asMethodType();
352                     List<VarSymbol> params = ((MethodSymbol)sym.owner).params;
353                     List<Type> oldArgs = methType.argtypes;
354                     ListBuffer<Type> newArgs = new ListBuffer<Type>();
355                     while (params.nonEmpty()) {
356                         if (params.head == sym) {
357                             newArgs.add(type);
358                         } else {
359                             newArgs.add(oldArgs.head);
360                         }
361                         oldArgs = oldArgs.tail;
362                         params = params.tail;
363                     }
364                     methType.argtypes = newArgs.toList();
365                 }
366             } else {
367                 sym.type = type;
368             }
369 
370             sym.appendUniqueTypeAttributes(typeAnnotations);
371 
372             if (sym.getKind() == ElementKind.PARAMETER ||
373                 sym.getKind() == ElementKind.LOCAL_VARIABLE ||
374                 sym.getKind() == ElementKind.RESOURCE_VARIABLE ||
375                 sym.getKind() == ElementKind.EXCEPTION_PARAMETER) {
376                 // Make sure all type annotations from the symbol are also
377                 // on the owner.
378                 sym.owner.appendUniqueTypeAttributes(sym.getRawTypeAttributes());
379             }
380         }
381 
382         // This method has a similar purpose as
383         // {@link com.sun.tools.javac.parser.JavacParser.insertAnnotationsToMostInner(JCExpression, List<JCTypeAnnotation>, boolean)}
384         // We found a type annotation in a declaration annotation position,
385         // for example, on the return type.
386         // Such an annotation is _not_ part of an JCAnnotatedType tree and we therefore
387         // need to set its position explicitly.
388         // The method returns a copy of type that contains these annotations.
389         //
390         // As a side effect the method sets the type annotation position of "annotations".
391         // Note that it is assumed that all annotations share the same position.
typeWithAnnotations(final JCTree typetree, final Type type, final List<Attribute.TypeCompound> annotations, final List<Attribute.TypeCompound> onlyTypeAnnotations)392         private Type typeWithAnnotations(final JCTree typetree, final Type type,
393                 final List<Attribute.TypeCompound> annotations,
394                 final List<Attribute.TypeCompound> onlyTypeAnnotations) {
395             // System.out.printf("typeWithAnnotations(typetree: %s, type: %s, annotations: %s, onlyTypeAnnotations: %s)%n",
396             //         typetree, type, annotations, onlyTypeAnnotations);
397             if (annotations.isEmpty()) {
398                 return type;
399             }
400             if (type.hasTag(TypeTag.ARRAY)) {
401                 Type.ArrayType arType = (Type.ArrayType) type.unannotatedType();
402                 Type.ArrayType tomodify = new Type.ArrayType(null, arType.tsym);
403                 Type toreturn;
404                 if (type.isAnnotated()) {
405                     toreturn = tomodify.annotatedType(type.getAnnotationMirrors());
406                 } else {
407                     toreturn = tomodify;
408                 }
409 
410                 JCArrayTypeTree arTree = arrayTypeTree(typetree);
411 
412                 ListBuffer<TypePathEntry> depth = new ListBuffer<>();
413                 depth = depth.append(TypePathEntry.ARRAY);
414                 while (arType.elemtype.hasTag(TypeTag.ARRAY)) {
415                     if (arType.elemtype.isAnnotated()) {
416                         Type aelemtype = arType.elemtype;
417                         arType = (Type.ArrayType) aelemtype.unannotatedType();
418                         ArrayType prevToMod = tomodify;
419                         tomodify = new Type.ArrayType(null, arType.tsym);
420                         prevToMod.elemtype = tomodify.annotatedType(arType.elemtype.getAnnotationMirrors());
421                     } else {
422                         arType = (Type.ArrayType) arType.elemtype;
423                         tomodify.elemtype = new Type.ArrayType(null, arType.tsym);
424                         tomodify = (Type.ArrayType) tomodify.elemtype;
425                     }
426                     arTree = arrayTypeTree(arTree.elemtype);
427                     depth = depth.append(TypePathEntry.ARRAY);
428                 }
429                 Type arelemType = typeWithAnnotations(arTree.elemtype, arType.elemtype, annotations, onlyTypeAnnotations);
430                 tomodify.elemtype = arelemType;
431                 {
432                     // All annotations share the same position; modify the first one.
433                     Attribute.TypeCompound a = annotations.get(0);
434                     TypeAnnotationPosition p = a.position;
435                     p.location = p.location.prependList(depth.toList());
436                 }
437                 typetree.type = toreturn;
438                 return toreturn;
439             } else if (type.hasTag(TypeTag.TYPEVAR)) {
440                 // Nothing to do for type variables.
441                 return type;
442             } else if (type.getKind() == TypeKind.UNION) {
443                 // There is a TypeKind, but no TypeTag.
444                 JCTypeUnion tutree = (JCTypeUnion) typetree;
445                 JCExpression fst = tutree.alternatives.get(0);
446                 Type res = typeWithAnnotations(fst, fst.type, annotations, onlyTypeAnnotations);
447                 fst.type = res;
448                 // TODO: do we want to set res as first element in uct.alternatives?
449                 // UnionClassType uct = (com.sun.tools.javac.code.Type.UnionClassType)type;
450                 // Return the un-annotated union-type.
451                 return type;
452             } else {
453                 Type enclTy = type;
454                 Element enclEl = type.asElement();
455                 JCTree enclTr = typetree;
456 
457                 while (enclEl != null &&
458                         enclEl.getKind() != ElementKind.PACKAGE &&
459                         enclTy != null &&
460                         enclTy.getKind() != TypeKind.NONE &&
461                         enclTy.getKind() != TypeKind.ERROR &&
462                         (enclTr.getKind() == JCTree.Kind.MEMBER_SELECT ||
463                          enclTr.getKind() == JCTree.Kind.PARAMETERIZED_TYPE ||
464                          enclTr.getKind() == JCTree.Kind.ANNOTATED_TYPE)) {
465                     // Iterate also over the type tree, not just the type: the type is already
466                     // completely resolved and we cannot distinguish where the annotation
467                     // belongs for a nested type.
468                     if (enclTr.getKind() == JCTree.Kind.MEMBER_SELECT) {
469                         // only change encl in this case.
470                         enclTy = enclTy.getEnclosingType();
471                         enclEl = enclEl.getEnclosingElement();
472                         enclTr = ((JCFieldAccess)enclTr).getExpression();
473                     } else if (enclTr.getKind() == JCTree.Kind.PARAMETERIZED_TYPE) {
474                         enclTr = ((JCTypeApply)enclTr).getType();
475                     } else {
476                         // only other option because of while condition
477                         enclTr = ((JCAnnotatedType)enclTr).getUnderlyingType();
478                     }
479                 }
480 
481                 /** We are trying to annotate some enclosing type,
482                  * but nothing more exists.
483                  */
484                 if (enclTy != null &&
485                         enclTy.hasTag(TypeTag.NONE)) {
486                     switch (onlyTypeAnnotations.size()) {
487                     case 0:
488                         // Don't issue an error if all type annotations are
489                         // also declaration annotations.
490                         // If the annotations are also declaration annotations, they are
491                         // illegal as type annotations but might be legal as declaration annotations.
492                         // The normal declaration annotation checks make sure that the use is valid.
493                         break;
494                     case 1:
495                         log.error(typetree.pos(), "cant.type.annotate.scoping.1",
496                                 onlyTypeAnnotations);
497                         break;
498                     default:
499                         log.error(typetree.pos(), "cant.type.annotate.scoping",
500                                 onlyTypeAnnotations);
501                     }
502                     return type;
503                 }
504 
505                 // At this point we have visited the part of the nested
506                 // type that is written in the source code.
507                 // Now count from here to the actual top-level class to determine
508                 // the correct nesting.
509 
510                 // The genericLocation for the annotation.
511                 ListBuffer<TypePathEntry> depth = new ListBuffer<>();
512 
513                 Type topTy = enclTy;
514                 while (enclEl != null &&
515                         enclEl.getKind() != ElementKind.PACKAGE &&
516                         topTy != null &&
517                         topTy.getKind() != TypeKind.NONE &&
518                         topTy.getKind() != TypeKind.ERROR) {
519                     topTy = topTy.getEnclosingType();
520                     enclEl = enclEl.getEnclosingElement();
521 
522                     if (topTy != null && topTy.getKind() != TypeKind.NONE) {
523                         // Only count enclosing types.
524                         depth = depth.append(TypePathEntry.INNER_TYPE);
525                     }
526                 }
527 
528                 if (depth.nonEmpty()) {
529                     // Only need to change the annotation positions
530                     // if they are on an enclosed type.
531                     // All annotations share the same position; modify the first one.
532                     Attribute.TypeCompound a = annotations.get(0);
533                     TypeAnnotationPosition p = a.position;
534                     p.location = p.location.appendList(depth.toList());
535                 }
536 
537                 Type ret = typeWithAnnotations(type, enclTy, annotations);
538                 typetree.type = ret;
539                 return ret;
540             }
541         }
542 
arrayTypeTree(JCTree typetree)543         private JCArrayTypeTree arrayTypeTree(JCTree typetree) {
544             if (typetree.getKind() == JCTree.Kind.ARRAY_TYPE) {
545                 return (JCArrayTypeTree) typetree;
546             } else if (typetree.getKind() == JCTree.Kind.ANNOTATED_TYPE) {
547                 return (JCArrayTypeTree) ((JCAnnotatedType)typetree).underlyingType;
548             } else {
549                 Assert.error("Could not determine array type from type tree: " + typetree);
550                 return null;
551             }
552         }
553 
554         /** Return a copy of the first type that only differs by
555          * inserting the annotations to the left-most/inner-most type
556          * or the type given by stopAt.
557          *
558          * We need the stopAt parameter to know where on a type to
559          * put the annotations.
560          * If we have nested classes Outer > Middle > Inner, and we
561          * have the source type "@A Middle.Inner", we will invoke
562          * this method with type = Outer.Middle.Inner,
563          * stopAt = Middle.Inner, and annotations = @A.
564          *
565          * @param type The type to copy.
566          * @param stopAt The type to stop at.
567          * @param annotations The annotations to insert.
568          * @return A copy of type that contains the annotations.
569          */
typeWithAnnotations(final Type type, final Type stopAt, final List<Attribute.TypeCompound> annotations)570         private Type typeWithAnnotations(final Type type,
571                 final Type stopAt,
572                 final List<Attribute.TypeCompound> annotations) {
573             Visitor<Type, List<TypeCompound>> visitor =
574                     new Type.Visitor<Type, List<Attribute.TypeCompound>>() {
575                 @Override
576                 public Type visitClassType(ClassType t, List<TypeCompound> s) {
577                     // assert that t.constValue() == null?
578                     if (t == stopAt ||
579                         t.getEnclosingType() == Type.noType) {
580                         return t.annotatedType(s);
581                     } else {
582                         ClassType ret = new ClassType(t.getEnclosingType().accept(this, s),
583                                 t.typarams_field, t.tsym);
584                         ret.all_interfaces_field = t.all_interfaces_field;
585                         ret.allparams_field = t.allparams_field;
586                         ret.interfaces_field = t.interfaces_field;
587                         ret.rank_field = t.rank_field;
588                         ret.supertype_field = t.supertype_field;
589                         return ret;
590                     }
591                 }
592 
593                 @Override
594                 public Type visitAnnotatedType(AnnotatedType t, List<TypeCompound> s) {
595                     return t.unannotatedType().accept(this, s).annotatedType(t.getAnnotationMirrors());
596                 }
597 
598                 @Override
599                 public Type visitWildcardType(WildcardType t, List<TypeCompound> s) {
600                     return t.annotatedType(s);
601                 }
602 
603                 @Override
604                 public Type visitArrayType(ArrayType t, List<TypeCompound> s) {
605                     ArrayType ret = new ArrayType(t.elemtype.accept(this, s), t.tsym);
606                     return ret;
607                 }
608 
609                 @Override
610                 public Type visitMethodType(MethodType t, List<TypeCompound> s) {
611                     // Impossible?
612                     return t;
613                 }
614 
615                 @Override
616                 public Type visitPackageType(PackageType t, List<TypeCompound> s) {
617                     // Impossible?
618                     return t;
619                 }
620 
621                 @Override
622                 public Type visitTypeVar(TypeVar t, List<TypeCompound> s) {
623                     return t.annotatedType(s);
624                 }
625 
626                 @Override
627                 public Type visitCapturedType(CapturedType t, List<TypeCompound> s) {
628                     return t.annotatedType(s);
629                 }
630 
631                 @Override
632                 public Type visitForAll(ForAll t, List<TypeCompound> s) {
633                     // Impossible?
634                     return t;
635                 }
636 
637                 @Override
638                 public Type visitUndetVar(UndetVar t, List<TypeCompound> s) {
639                     // Impossible?
640                     return t;
641                 }
642 
643                 @Override
644                 public Type visitErrorType(ErrorType t, List<TypeCompound> s) {
645                     return t.annotatedType(s);
646                 }
647 
648                 @Override
649                 public Type visitType(Type t, List<TypeCompound> s) {
650                     return t.annotatedType(s);
651                 }
652             };
653 
654             return type.accept(visitor, annotations);
655         }
656 
toTypeCompound(Attribute.Compound a, TypeAnnotationPosition p)657         private Attribute.TypeCompound toTypeCompound(Attribute.Compound a, TypeAnnotationPosition p) {
658             // It is safe to alias the position.
659             return new Attribute.TypeCompound(a, p);
660         }
661 
662 
663         /* This is the beginning of the second part of organizing
664          * type annotations: determine the type annotation positions.
665          */
666 
resolveFrame(JCTree tree, JCTree frame, List<JCTree> path, TypeAnnotationPosition p)667         private void resolveFrame(JCTree tree, JCTree frame,
668                 List<JCTree> path, TypeAnnotationPosition p) {
669             /*
670             System.out.println("Resolving tree: " + tree + " kind: " + tree.getKind());
671             System.out.println("    Framing tree: " + frame + " kind: " + frame.getKind());
672             */
673 
674             // Note that p.offset is set in
675             // com.sun.tools.javac.jvm.Gen.setTypeAnnotationPositions(int)
676 
677             switch (frame.getKind()) {
678                 case TYPE_CAST:
679                     JCTypeCast frameTC = (JCTypeCast) frame;
680                     p.type = TargetType.CAST;
681                     if (frameTC.clazz.hasTag(Tag.TYPEINTERSECTION)) {
682                         // This case was already handled by INTERSECTION_TYPE
683                     } else {
684                         p.type_index = 0;
685                     }
686                     p.pos = frame.pos;
687                     return;
688 
689                 case INSTANCE_OF:
690                     p.type = TargetType.INSTANCEOF;
691                     p.pos = frame.pos;
692                     return;
693 
694                 case NEW_CLASS:
695                     JCNewClass frameNewClass = (JCNewClass) frame;
696                     if (frameNewClass.def != null) {
697                         // Special handling for anonymous class instantiations
698                         JCClassDecl frameClassDecl = frameNewClass.def;
699                         if (frameClassDecl.extending == tree) {
700                             p.type = TargetType.CLASS_EXTENDS;
701                             p.type_index = -1;
702                         } else if (frameClassDecl.implementing.contains(tree)) {
703                             p.type = TargetType.CLASS_EXTENDS;
704                             p.type_index = frameClassDecl.implementing.indexOf(tree);
705                         } else {
706                             // In contrast to CLASS below, typarams cannot occur here.
707                             Assert.error("Could not determine position of tree " + tree +
708                                     " within frame " + frame);
709                         }
710                     } else if (frameNewClass.typeargs.contains(tree)) {
711                         p.type = TargetType.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT;
712                         p.type_index = frameNewClass.typeargs.indexOf(tree);
713                     } else {
714                         p.type = TargetType.NEW;
715                     }
716                     p.pos = frame.pos;
717                     return;
718 
719                 case NEW_ARRAY:
720                     p.type = TargetType.NEW;
721                     p.pos = frame.pos;
722                     return;
723 
724                 case ANNOTATION_TYPE:
725                 case CLASS:
726                 case ENUM:
727                 case INTERFACE:
728                     p.pos = frame.pos;
729                     if (((JCClassDecl)frame).extending == tree) {
730                         p.type = TargetType.CLASS_EXTENDS;
731                         p.type_index = -1;
732                     } else if (((JCClassDecl)frame).implementing.contains(tree)) {
733                         p.type = TargetType.CLASS_EXTENDS;
734                         p.type_index = ((JCClassDecl)frame).implementing.indexOf(tree);
735                     } else if (((JCClassDecl)frame).typarams.contains(tree)) {
736                         p.type = TargetType.CLASS_TYPE_PARAMETER;
737                         p.parameter_index = ((JCClassDecl)frame).typarams.indexOf(tree);
738                     } else {
739                         Assert.error("Could not determine position of tree " + tree +
740                                 " within frame " + frame);
741                     }
742                     return;
743 
744                 case METHOD: {
745                     JCMethodDecl frameMethod = (JCMethodDecl) frame;
746                     p.pos = frame.pos;
747                     if (frameMethod.thrown.contains(tree)) {
748                         p.type = TargetType.THROWS;
749                         p.type_index = frameMethod.thrown.indexOf(tree);
750                     } else if (frameMethod.restype == tree) {
751                         p.type = TargetType.METHOD_RETURN;
752                     } else if (frameMethod.typarams.contains(tree)) {
753                         p.type = TargetType.METHOD_TYPE_PARAMETER;
754                         p.parameter_index = frameMethod.typarams.indexOf(tree);
755                     } else {
756                         Assert.error("Could not determine position of tree " + tree +
757                                 " within frame " + frame);
758                     }
759                     return;
760                 }
761 
762                 case PARAMETERIZED_TYPE: {
763                     List<JCTree> newPath = path.tail;
764 
765                     if (((JCTypeApply)frame).clazz == tree) {
766                         // generic: RAW; noop
767                     } else if (((JCTypeApply)frame).arguments.contains(tree)) {
768                         JCTypeApply taframe = (JCTypeApply) frame;
769                         int arg = taframe.arguments.indexOf(tree);
770                         p.location = p.location.prepend(new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg));
771 
772                         Type typeToUse;
773                         if (newPath.tail != null && newPath.tail.head.hasTag(Tag.NEWCLASS)) {
774                             // If we are within an anonymous class instantiation, use its type,
775                             // because it contains a correctly nested type.
776                             typeToUse = newPath.tail.head.type;
777                         } else {
778                             typeToUse = taframe.type;
779                         }
780 
781                         locateNestedTypes(typeToUse, p);
782                     } else {
783                         Assert.error("Could not determine type argument position of tree " + tree +
784                                 " within frame " + frame);
785                     }
786 
787                     resolveFrame(newPath.head, newPath.tail.head, newPath, p);
788                     return;
789                 }
790 
791                 case MEMBER_REFERENCE: {
792                     JCMemberReference mrframe = (JCMemberReference) frame;
793 
794                     if (mrframe.expr == tree) {
795                         switch (mrframe.mode) {
796                         case INVOKE:
797                             p.type = TargetType.METHOD_REFERENCE;
798                             break;
799                         case NEW:
800                             p.type = TargetType.CONSTRUCTOR_REFERENCE;
801                             break;
802                         default:
803                             Assert.error("Unknown method reference mode " + mrframe.mode +
804                                     " for tree " + tree + " within frame " + frame);
805                         }
806                         p.pos = frame.pos;
807                     } else if (mrframe.typeargs != null &&
808                             mrframe.typeargs.contains(tree)) {
809                         int arg = mrframe.typeargs.indexOf(tree);
810                         p.type_index = arg;
811                         switch (mrframe.mode) {
812                         case INVOKE:
813                             p.type = TargetType.METHOD_REFERENCE_TYPE_ARGUMENT;
814                             break;
815                         case NEW:
816                             p.type = TargetType.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT;
817                             break;
818                         default:
819                             Assert.error("Unknown method reference mode " + mrframe.mode +
820                                     " for tree " + tree + " within frame " + frame);
821                         }
822                         p.pos = frame.pos;
823                     } else {
824                         Assert.error("Could not determine type argument position of tree " + tree +
825                                 " within frame " + frame);
826                     }
827                     return;
828                 }
829 
830                 case ARRAY_TYPE: {
831                     ListBuffer<TypePathEntry> index = new ListBuffer<>();
832                     index = index.append(TypePathEntry.ARRAY);
833                     List<JCTree> newPath = path.tail;
834                     while (true) {
835                         JCTree npHead = newPath.tail.head;
836                         if (npHead.hasTag(JCTree.Tag.TYPEARRAY)) {
837                             newPath = newPath.tail;
838                             index = index.append(TypePathEntry.ARRAY);
839                         } else if (npHead.hasTag(JCTree.Tag.ANNOTATED_TYPE)) {
840                             newPath = newPath.tail;
841                         } else {
842                             break;
843                         }
844                     }
845                     p.location = p.location.prependList(index.toList());
846                     resolveFrame(newPath.head, newPath.tail.head, newPath, p);
847                     return;
848                 }
849 
850                 case TYPE_PARAMETER:
851                     if (path.tail.tail.head.hasTag(JCTree.Tag.CLASSDEF)) {
852                         JCClassDecl clazz = (JCClassDecl)path.tail.tail.head;
853                         p.type = TargetType.CLASS_TYPE_PARAMETER_BOUND;
854                         p.parameter_index = clazz.typarams.indexOf(path.tail.head);
855                         p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree);
856                         if (((JCTypeParameter)frame).bounds.get(0).type.isInterface()) {
857                             // Account for an implicit Object as bound 0
858                             p.bound_index += 1;
859                         }
860                     } else if (path.tail.tail.head.hasTag(JCTree.Tag.METHODDEF)) {
861                         JCMethodDecl method = (JCMethodDecl)path.tail.tail.head;
862                         p.type = TargetType.METHOD_TYPE_PARAMETER_BOUND;
863                         p.parameter_index = method.typarams.indexOf(path.tail.head);
864                         p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree);
865                         if (((JCTypeParameter)frame).bounds.get(0).type.isInterface()) {
866                             // Account for an implicit Object as bound 0
867                             p.bound_index += 1;
868                         }
869                     } else {
870                         Assert.error("Could not determine position of tree " + tree +
871                                 " within frame " + frame);
872                     }
873                     p.pos = frame.pos;
874                     return;
875 
876                 case VARIABLE:
877                     VarSymbol v = ((JCVariableDecl)frame).sym;
878                     p.pos = frame.pos;
879                     switch (v.getKind()) {
880                         case LOCAL_VARIABLE:
881                             p.type = TargetType.LOCAL_VARIABLE;
882                             break;
883                         case FIELD:
884                             p.type = TargetType.FIELD;
885                             break;
886                         case PARAMETER:
887                             if (v.getQualifiedName().equals(names._this)) {
888                                 // TODO: Intro a separate ElementKind?
889                                 p.type = TargetType.METHOD_RECEIVER;
890                             } else {
891                                 p.type = TargetType.METHOD_FORMAL_PARAMETER;
892                                 p.parameter_index = methodParamIndex(path, frame);
893                             }
894                             break;
895                         case EXCEPTION_PARAMETER:
896                             p.type = TargetType.EXCEPTION_PARAMETER;
897                             break;
898                         case RESOURCE_VARIABLE:
899                             p.type = TargetType.RESOURCE_VARIABLE;
900                             break;
901                         default:
902                             Assert.error("Found unexpected type annotation for variable: " + v + " with kind: " + v.getKind());
903                     }
904                     if (v.getKind() != ElementKind.FIELD) {
905                         v.owner.appendUniqueTypeAttributes(v.getRawTypeAttributes());
906                     }
907                     return;
908 
909                 case ANNOTATED_TYPE: {
910                     if (frame == tree) {
911                         // This is only true for the first annotated type we see.
912                         // For any other annotated types along the path, we do
913                         // not care about inner types.
914                         JCAnnotatedType atypetree = (JCAnnotatedType) frame;
915                         final Type utype = atypetree.underlyingType.type;
916                         if (utype == null) {
917                             // This might happen during DeferredAttr;
918                             // we will be back later.
919                             return;
920                         }
921                         Symbol tsym = utype.tsym;
922                         if (tsym.getKind().equals(ElementKind.TYPE_PARAMETER) ||
923                                 utype.getKind().equals(TypeKind.WILDCARD) ||
924                                 utype.getKind().equals(TypeKind.ARRAY)) {
925                             // Type parameters, wildcards, and arrays have the declaring
926                             // class/method as enclosing elements.
927                             // There is actually nothing to do for them.
928                         } else {
929                             locateNestedTypes(utype, p);
930                         }
931                     }
932                     List<JCTree> newPath = path.tail;
933                     resolveFrame(newPath.head, newPath.tail.head, newPath, p);
934                     return;
935                 }
936 
937                 case UNION_TYPE: {
938                     List<JCTree> newPath = path.tail;
939                     resolveFrame(newPath.head, newPath.tail.head, newPath, p);
940                     return;
941                 }
942 
943                 case INTERSECTION_TYPE: {
944                     JCTypeIntersection isect = (JCTypeIntersection)frame;
945                     p.type_index = isect.bounds.indexOf(tree);
946                     List<JCTree> newPath = path.tail;
947                     resolveFrame(newPath.head, newPath.tail.head, newPath, p);
948                     return;
949                 }
950 
951                 case METHOD_INVOCATION: {
952                     JCMethodInvocation invocation = (JCMethodInvocation)frame;
953                     if (!invocation.typeargs.contains(tree)) {
954                         Assert.error("{" + tree + "} is not an argument in the invocation: " + invocation);
955                     }
956                     MethodSymbol exsym = (MethodSymbol) TreeInfo.symbol(invocation.getMethodSelect());
957                     if (exsym == null) {
958                         Assert.error("could not determine symbol for {" + invocation + "}");
959                     } else if (exsym.isConstructor()) {
960                         p.type = TargetType.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT;
961                     } else {
962                         p.type = TargetType.METHOD_INVOCATION_TYPE_ARGUMENT;
963                     }
964                     p.pos = invocation.pos;
965                     p.type_index = invocation.typeargs.indexOf(tree);
966                     return;
967                 }
968 
969                 case EXTENDS_WILDCARD:
970                 case SUPER_WILDCARD: {
971                     // Annotations in wildcard bounds
972                     p.location = p.location.prepend(TypePathEntry.WILDCARD);
973                     List<JCTree> newPath = path.tail;
974                     resolveFrame(newPath.head, newPath.tail.head, newPath, p);
975                     return;
976                 }
977 
978                 case MEMBER_SELECT: {
979                     List<JCTree> newPath = path.tail;
980                     resolveFrame(newPath.head, newPath.tail.head, newPath, p);
981                     return;
982                 }
983 
984                 default:
985                     Assert.error("Unresolved frame: " + frame + " of kind: " + frame.getKind() +
986                             "\n    Looking for tree: " + tree);
987                     return;
988             }
989         }
990 
locateNestedTypes(Type type, TypeAnnotationPosition p)991         private void locateNestedTypes(Type type, TypeAnnotationPosition p) {
992             // The number of "steps" to get from the full type to the
993             // left-most outer type.
994             ListBuffer<TypePathEntry> depth = new ListBuffer<>();
995 
996             Type encl = type.getEnclosingType();
997             while (encl != null &&
998                     encl.getKind() != TypeKind.NONE &&
999                     encl.getKind() != TypeKind.ERROR) {
1000                 depth = depth.append(TypePathEntry.INNER_TYPE);
1001                 encl = encl.getEnclosingType();
1002             }
1003             if (depth.nonEmpty()) {
1004                 p.location = p.location.prependList(depth.toList());
1005             }
1006         }
1007 
methodParamIndex(List<JCTree> path, JCTree param)1008         private int methodParamIndex(List<JCTree> path, JCTree param) {
1009             List<JCTree> curr = path;
1010             while (curr.head.getTag() != Tag.METHODDEF &&
1011                     curr.head.getTag() != Tag.LAMBDA) {
1012                 curr = curr.tail;
1013             }
1014             if (curr.head.getTag() == Tag.METHODDEF) {
1015                 JCMethodDecl method = (JCMethodDecl)curr.head;
1016                 return method.params.indexOf(param);
1017             } else if (curr.head.getTag() == Tag.LAMBDA) {
1018                 JCLambda lambda = (JCLambda)curr.head;
1019                 return lambda.params.indexOf(param);
1020             } else {
1021                 Assert.error("methodParamIndex expected to find method or lambda for param: " + param);
1022                 return -1;
1023             }
1024         }
1025 
1026         // Each class (including enclosed inner classes) is visited separately.
1027         // This flag is used to prevent from visiting inner classes.
1028         private boolean isInClass = false;
1029 
1030         @Override
visitClassDef(JCClassDecl tree)1031         public void visitClassDef(JCClassDecl tree) {
1032             if (isInClass)
1033                 return;
1034             isInClass = true;
1035 
1036             if (sigOnly) {
1037                 scan(tree.mods);
1038                 scan(tree.typarams);
1039                 scan(tree.extending);
1040                 scan(tree.implementing);
1041             }
1042             scan(tree.defs);
1043         }
1044 
1045         /**
1046          * Resolve declaration vs. type annotations in methods and
1047          * then determine the positions.
1048          */
1049         @Override
visitMethodDef(final JCMethodDecl tree)1050         public void visitMethodDef(final JCMethodDecl tree) {
1051             if (tree.sym == null) {
1052                 Assert.error("Visiting tree node before memberEnter");
1053             }
1054             if (sigOnly) {
1055                 if (!tree.mods.annotations.isEmpty()) {
1056                     // Nothing to do for separateAnnotationsKinds if
1057                     // there are no annotations of either kind.
1058                     TypeAnnotationPosition pos = new TypeAnnotationPosition();
1059                     pos.type = TargetType.METHOD_RETURN;
1060                     if (tree.sym.isConstructor()) {
1061                         pos.pos = tree.pos;
1062                         // Use null to mark that the annotations go with the symbol.
1063                         separateAnnotationsKinds(tree, null, tree.sym, pos);
1064                     } else {
1065                         pos.pos = tree.restype.pos;
1066                         separateAnnotationsKinds(tree.restype, tree.sym.type.getReturnType(),
1067                                 tree.sym, pos);
1068                     }
1069                 }
1070                 if (tree.recvparam != null && tree.recvparam.sym != null &&
1071                         !tree.recvparam.mods.annotations.isEmpty()) {
1072                     // Nothing to do for separateAnnotationsKinds if
1073                     // there are no annotations of either kind.
1074                     // TODO: make sure there are no declaration annotations.
1075                     TypeAnnotationPosition pos = new TypeAnnotationPosition();
1076                     pos.type = TargetType.METHOD_RECEIVER;
1077                     pos.pos = tree.recvparam.vartype.pos;
1078                     separateAnnotationsKinds(tree.recvparam.vartype, tree.recvparam.sym.type,
1079                             tree.recvparam.sym, pos);
1080                 }
1081                 int i = 0;
1082                 for (JCVariableDecl param : tree.params) {
1083                     if (!param.mods.annotations.isEmpty()) {
1084                         // Nothing to do for separateAnnotationsKinds if
1085                         // there are no annotations of either kind.
1086                         TypeAnnotationPosition pos = new TypeAnnotationPosition();
1087                         pos.type = TargetType.METHOD_FORMAL_PARAMETER;
1088                         pos.parameter_index = i;
1089                         pos.pos = param.vartype.pos;
1090                         separateAnnotationsKinds(param.vartype, param.sym.type, param.sym, pos);
1091                     }
1092                     ++i;
1093                 }
1094             }
1095 
1096             push(tree);
1097             // super.visitMethodDef(tree);
1098             if (sigOnly) {
1099                 scan(tree.mods);
1100                 scan(tree.restype);
1101                 scan(tree.typarams);
1102                 scan(tree.recvparam);
1103                 scan(tree.params);
1104                 scan(tree.thrown);
1105             } else {
1106                 scan(tree.defaultValue);
1107                 scan(tree.body);
1108             }
1109             pop();
1110         }
1111 
1112         /* Store a reference to the current lambda expression, to
1113          * be used by all type annotations within this expression.
1114          */
1115         private JCLambda currentLambda = null;
1116 
visitLambda(JCLambda tree)1117         public void visitLambda(JCLambda tree) {
1118             JCLambda prevLambda = currentLambda;
1119             try {
1120                 currentLambda = tree;
1121 
1122                 int i = 0;
1123                 for (JCVariableDecl param : tree.params) {
1124                     if (!param.mods.annotations.isEmpty()) {
1125                         // Nothing to do for separateAnnotationsKinds if
1126                         // there are no annotations of either kind.
1127                         TypeAnnotationPosition pos = new TypeAnnotationPosition();
1128                         pos.type = TargetType.METHOD_FORMAL_PARAMETER;
1129                         pos.parameter_index = i;
1130                         pos.pos = param.vartype.pos;
1131                         pos.onLambda = tree;
1132                         separateAnnotationsKinds(param.vartype, param.sym.type, param.sym, pos);
1133                     }
1134                     ++i;
1135                 }
1136 
1137                 push(tree);
1138                 scan(tree.body);
1139                 scan(tree.params);
1140                 pop();
1141             } finally {
1142                 currentLambda = prevLambda;
1143             }
1144         }
1145 
1146         /**
1147          * Resolve declaration vs. type annotations in variable declarations and
1148          * then determine the positions.
1149          */
1150         @Override
visitVarDef(final JCVariableDecl tree)1151         public void visitVarDef(final JCVariableDecl tree) {
1152             if (tree.mods.annotations.isEmpty()) {
1153                 // Nothing to do for separateAnnotationsKinds if
1154                 // there are no annotations of either kind.
1155             } else if (tree.sym == null) {
1156                 Assert.error("Visiting tree node before memberEnter");
1157             } else if (tree.sym.getKind() == ElementKind.PARAMETER) {
1158                 // Parameters are handled in visitMethodDef or visitLambda.
1159             } else if (tree.sym.getKind() == ElementKind.FIELD) {
1160                 if (sigOnly) {
1161                     TypeAnnotationPosition pos = new TypeAnnotationPosition();
1162                     pos.type = TargetType.FIELD;
1163                     pos.pos = tree.pos;
1164                     separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
1165                 }
1166             } else if (tree.sym.getKind() == ElementKind.LOCAL_VARIABLE) {
1167                 TypeAnnotationPosition pos = new TypeAnnotationPosition();
1168                 pos.type = TargetType.LOCAL_VARIABLE;
1169                 pos.pos = tree.pos;
1170                 pos.onLambda = currentLambda;
1171                 separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
1172             } else if (tree.sym.getKind() == ElementKind.EXCEPTION_PARAMETER) {
1173                 TypeAnnotationPosition pos = new TypeAnnotationPosition();
1174                 pos.type = TargetType.EXCEPTION_PARAMETER;
1175                 pos.pos = tree.pos;
1176                 pos.onLambda = currentLambda;
1177                 separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
1178             } else if (tree.sym.getKind() == ElementKind.RESOURCE_VARIABLE) {
1179                 TypeAnnotationPosition pos = new TypeAnnotationPosition();
1180                 pos.type = TargetType.RESOURCE_VARIABLE;
1181                 pos.pos = tree.pos;
1182                 pos.onLambda = currentLambda;
1183                 separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
1184             } else if (tree.sym.getKind() == ElementKind.ENUM_CONSTANT) {
1185                 // No type annotations can occur here.
1186             } else {
1187                 // There is nothing else in a variable declaration that needs separation.
1188                 Assert.error("Unhandled variable kind: " + tree + " of kind: " + tree.sym.getKind());
1189             }
1190 
1191             push(tree);
1192             // super.visitVarDef(tree);
1193             scan(tree.mods);
1194             scan(tree.vartype);
1195             if (!sigOnly) {
1196                 scan(tree.init);
1197             }
1198             pop();
1199         }
1200 
1201         @Override
visitBlock(JCBlock tree)1202         public void visitBlock(JCBlock tree) {
1203             // Do not descend into top-level blocks when only interested
1204             // in the signature.
1205             if (!sigOnly) {
1206                 scan(tree.stats);
1207             }
1208         }
1209 
1210         @Override
visitAnnotatedType(JCAnnotatedType tree)1211         public void visitAnnotatedType(JCAnnotatedType tree) {
1212             push(tree);
1213             findPosition(tree, tree, tree.annotations);
1214             pop();
1215             super.visitAnnotatedType(tree);
1216         }
1217 
1218         @Override
visitTypeParameter(JCTypeParameter tree)1219         public void visitTypeParameter(JCTypeParameter tree) {
1220             findPosition(tree, peek2(), tree.annotations);
1221             super.visitTypeParameter(tree);
1222         }
1223 
copyNewClassAnnotationsToOwner(JCNewClass tree)1224         private void copyNewClassAnnotationsToOwner(JCNewClass tree) {
1225             Symbol sym = tree.def.sym;
1226             TypeAnnotationPosition pos = new TypeAnnotationPosition();
1227             ListBuffer<Attribute.TypeCompound> newattrs =
1228                 new ListBuffer<Attribute.TypeCompound>();
1229 
1230             for (Attribute.TypeCompound old : sym.getRawTypeAttributes()) {
1231                 newattrs.append(new Attribute.TypeCompound(old.type, old.values,
1232                                                            pos));
1233             }
1234 
1235             pos.type = TargetType.NEW;
1236             pos.pos = tree.pos;
1237             sym.owner.appendUniqueTypeAttributes(newattrs.toList());
1238         }
1239 
1240         @Override
visitNewClass(JCNewClass tree)1241         public void visitNewClass(JCNewClass tree) {
1242             if (tree.def != null &&
1243                     !tree.def.mods.annotations.isEmpty()) {
1244                 JCClassDecl classdecl = tree.def;
1245                 TypeAnnotationPosition pos = new TypeAnnotationPosition();
1246                 pos.type = TargetType.CLASS_EXTENDS;
1247                 pos.pos = tree.pos;
1248                 if (classdecl.extending == tree.clazz) {
1249                     pos.type_index = -1;
1250                 } else if (classdecl.implementing.contains(tree.clazz)) {
1251                     pos.type_index = classdecl.implementing.indexOf(tree.clazz);
1252                 } else {
1253                     // In contrast to CLASS elsewhere, typarams cannot occur here.
1254                     Assert.error("Could not determine position of tree " + tree);
1255                 }
1256                 Type before = classdecl.sym.type;
1257                 separateAnnotationsKinds(classdecl, tree.clazz.type, classdecl.sym, pos);
1258                 copyNewClassAnnotationsToOwner(tree);
1259                 // classdecl.sym.type now contains an annotated type, which
1260                 // is not what we want there.
1261                 // TODO: should we put this type somewhere in the superclass/interface?
1262                 classdecl.sym.type = before;
1263             }
1264 
1265             scan(tree.encl);
1266             scan(tree.typeargs);
1267             scan(tree.clazz);
1268             scan(tree.args);
1269 
1270             // The class body will already be scanned.
1271             // scan(tree.def);
1272         }
1273 
1274         @Override
visitNewArray(JCNewArray tree)1275         public void visitNewArray(JCNewArray tree) {
1276             findPosition(tree, tree, tree.annotations);
1277             int dimAnnosCount = tree.dimAnnotations.size();
1278             ListBuffer<TypePathEntry> depth = new ListBuffer<>();
1279 
1280             // handle annotations associated with dimensions
1281             for (int i = 0; i < dimAnnosCount; ++i) {
1282                 TypeAnnotationPosition p = new TypeAnnotationPosition();
1283                 p.pos = tree.pos;
1284                 p.onLambda = currentLambda;
1285                 p.type = TargetType.NEW;
1286                 if (i != 0) {
1287                     depth = depth.append(TypePathEntry.ARRAY);
1288                     p.location = p.location.appendList(depth.toList());
1289                 }
1290 
1291                 setTypeAnnotationPos(tree.dimAnnotations.get(i), p);
1292             }
1293 
1294             // handle "free" annotations
1295             // int i = dimAnnosCount == 0 ? 0 : dimAnnosCount - 1;
1296             // TODO: is depth.size == i here?
1297             JCExpression elemType = tree.elemtype;
1298             depth = depth.append(TypePathEntry.ARRAY);
1299             while (elemType != null) {
1300                 if (elemType.hasTag(JCTree.Tag.ANNOTATED_TYPE)) {
1301                     JCAnnotatedType at = (JCAnnotatedType)elemType;
1302                     TypeAnnotationPosition p = new TypeAnnotationPosition();
1303                     p.type = TargetType.NEW;
1304                     p.pos = tree.pos;
1305                     p.onLambda = currentLambda;
1306                     locateNestedTypes(elemType.type, p);
1307                     p.location = p.location.prependList(depth.toList());
1308                     setTypeAnnotationPos(at.annotations, p);
1309                     elemType = at.underlyingType;
1310                 } else if (elemType.hasTag(JCTree.Tag.TYPEARRAY)) {
1311                     depth = depth.append(TypePathEntry.ARRAY);
1312                     elemType = ((JCArrayTypeTree)elemType).elemtype;
1313                 } else if (elemType.hasTag(JCTree.Tag.SELECT)) {
1314                     elemType = ((JCFieldAccess)elemType).selected;
1315                 } else {
1316                     break;
1317                 }
1318             }
1319             scan(tree.elems);
1320         }
1321 
findPosition(JCTree tree, JCTree frame, List<JCAnnotation> annotations)1322         private void findPosition(JCTree tree, JCTree frame, List<JCAnnotation> annotations) {
1323             if (!annotations.isEmpty()) {
1324                 /*
1325                 System.err.println("Finding pos for: " + annotations);
1326                 System.err.println("    tree: " + tree + " kind: " + tree.getKind());
1327                 System.err.println("    frame: " + frame + " kind: " + frame.getKind());
1328                 */
1329                 TypeAnnotationPosition p = new TypeAnnotationPosition();
1330                 p.onLambda = currentLambda;
1331                 resolveFrame(tree, frame, frames.toList(), p);
1332                 setTypeAnnotationPos(annotations, p);
1333             }
1334         }
1335 
setTypeAnnotationPos(List<JCAnnotation> annotations, TypeAnnotationPosition position)1336         private void setTypeAnnotationPos(List<JCAnnotation> annotations,
1337                 TypeAnnotationPosition position) {
1338             for (JCAnnotation anno : annotations) {
1339                 // attribute might be null during DeferredAttr;
1340                 // we will be back later.
1341                 if (anno.attribute != null) {
1342                     ((Attribute.TypeCompound) anno.attribute).position = position;
1343                 }
1344             }
1345         }
1346 
1347         @Override
toString()1348         public String toString() {
1349             return super.toString() + ": sigOnly: " + sigOnly;
1350         }
1351     }
1352 }
1353