Sun, 17 Feb 2013 16:44:55 -0500
Merge
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 */
26 package com.sun.tools.javac.code;
28 import javax.lang.model.element.Element;
29 import javax.lang.model.element.ElementKind;
30 import javax.lang.model.type.TypeKind;
32 import com.sun.tools.javac.code.Attribute;
33 import com.sun.tools.javac.code.Attribute.TypeCompound;
34 import com.sun.tools.javac.code.Flags;
35 import com.sun.tools.javac.code.Kinds;
36 import com.sun.tools.javac.code.Type.AnnotatedType;
37 import com.sun.tools.javac.code.Type.ArrayType;
38 import com.sun.tools.javac.code.Type.CapturedType;
39 import com.sun.tools.javac.code.Type.ClassType;
40 import com.sun.tools.javac.code.Type.ErrorType;
41 import com.sun.tools.javac.code.Type.ForAll;
42 import com.sun.tools.javac.code.Type.MethodType;
43 import com.sun.tools.javac.code.Type.PackageType;
44 import com.sun.tools.javac.code.Type.TypeVar;
45 import com.sun.tools.javac.code.Type.UndetVar;
46 import com.sun.tools.javac.code.Type.Visitor;
47 import com.sun.tools.javac.code.Type.WildcardType;
48 import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntry;
49 import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntryKind;
50 import com.sun.tools.javac.code.TypeTag;
51 import com.sun.tools.javac.code.Symbol.VarSymbol;
52 import com.sun.tools.javac.comp.Annotate.Annotator;
53 import com.sun.tools.javac.tree.JCTree;
54 import com.sun.tools.javac.tree.JCTree.JCBlock;
55 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
56 import com.sun.tools.javac.tree.JCTree.JCExpression;
57 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
58 import com.sun.tools.javac.tree.JCTree.JCTypeApply;
59 import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
60 import com.sun.tools.javac.tree.TreeScanner;
61 import com.sun.tools.javac.tree.JCTree.*;
62 import com.sun.tools.javac.util.Assert;
63 import com.sun.tools.javac.util.List;
64 import com.sun.tools.javac.util.ListBuffer;
65 import com.sun.tools.javac.util.Log;
66 import com.sun.tools.javac.util.Names;
68 /**
69 * Contains operations specific to processing type annotations.
70 * This class has two functions:
71 * separate declaration from type annotations and insert the type
72 * annotations to their types;
73 * and determine the TypeAnnotationPositions for all type annotations.
74 */
75 public class TypeAnnotations {
76 // Class cannot be instantiated.
77 private TypeAnnotations() {}
79 /**
80 * Separate type annotations from declaration annotations and
81 * determine the correct positions for type annotations.
82 * This version only visits types in signatures and should be
83 * called from MemberEnter.
84 * The method returns the Annotator object that should be added
85 * to the correct Annotate queue for later processing.
86 */
87 public static Annotator organizeTypeAnnotationsSignatures(final Symtab syms, final Names names,
88 final Log log, final JCClassDecl tree) {
89 return new Annotator() {
90 @Override
91 public void enterAnnotation() {
92 new TypeAnnotationPositions(syms, names, log, true).scan(tree);
93 }
94 };
95 }
97 /**
98 * This version only visits types in bodies, that is, field initializers,
99 * top-level blocks, and method bodies, and should be called from Attr.
100 */
101 public static void organizeTypeAnnotationsBodies(Symtab syms, Names names, Log log, JCClassDecl tree) {
102 new TypeAnnotationPositions(syms, names, log, false).scan(tree);
103 }
105 private static class TypeAnnotationPositions extends TreeScanner {
107 private enum AnnotationType { DECLARATION, TYPE, BOTH };
109 private final Symtab syms;
110 private final Names names;
111 private final Log log;
112 private final boolean sigOnly;
114 private TypeAnnotationPositions(Symtab syms, Names names, Log log, boolean sigOnly) {
115 this.syms = syms;
116 this.names = names;
117 this.log = log;
118 this.sigOnly = sigOnly;
119 }
121 /*
122 * When traversing the AST we keep the "frames" of visited
123 * trees in order to determine the position of annotations.
124 */
125 private ListBuffer<JCTree> frames = ListBuffer.lb();
127 protected void push(JCTree t) { frames = frames.prepend(t); }
128 protected JCTree pop() { return frames.next(); }
129 // could this be frames.elems.tail.head?
130 private JCTree peek2() { return frames.toList().tail.head; }
132 @Override
133 public void scan(JCTree tree) {
134 push(tree);
135 super.scan(tree);
136 pop();
137 }
139 /**
140 * Separates type annotations from declaration annotations.
141 * This step is needed because in certain locations (where declaration
142 * and type annotations can be mixed, e.g. the type of a field)
143 * we never build an JCAnnotatedType. This step finds these
144 * annotations and marks them as if they were part of the type.
145 */
146 private void separateAnnotationsKinds(JCTree typetree, Type type, Symbol sym,
147 TypeAnnotationPosition pos) {
148 /*
149 System.out.printf("separateAnnotationsKinds(typetree: %s, type: %s, symbol: %s, pos: %s%n",
150 typetree, type, sym, pos);
151 */
152 List<Attribute.Compound> annotations = sym.getRawAttributes();
153 ListBuffer<Attribute.Compound> declAnnos = new ListBuffer<Attribute.Compound>();
154 ListBuffer<Attribute.TypeCompound> typeAnnos = new ListBuffer<Attribute.TypeCompound>();
156 for (Attribute.Compound a : annotations) {
157 switch (annotationType(a, sym)) {
158 case DECLARATION:
159 declAnnos.append(a);
160 break;
161 case BOTH: {
162 declAnnos.append(a);
163 Attribute.TypeCompound ta = toTypeCompound(a, pos);
164 typeAnnos.append(ta);
165 break;
166 }
167 case TYPE: {
168 Attribute.TypeCompound ta = toTypeCompound(a, pos);
169 typeAnnos.append(ta);
170 break;
171 }
172 }
173 }
175 sym.annotations.reset();
176 sym.annotations.setDeclarationAttributes(declAnnos.toList());
178 List<Attribute.TypeCompound> typeAnnotations = typeAnnos.toList();
180 if (type == null) {
181 // When type is null, put the type annotations to the symbol.
182 // This is used for constructor return annotations, for which
183 // no appropriate type exists.
184 sym.annotations.appendUniqueTypes(typeAnnotations);
185 return;
186 }
188 // type is non-null and annotations are added to that type
189 type = typeWithAnnotations(typetree, type, typeAnnotations, log);
191 if (sym.getKind() == ElementKind.METHOD) {
192 sym.type.asMethodType().restype = type;
193 } else {
194 sym.type = type;
195 }
197 sym.annotations.appendUniqueTypes(typeAnnotations);
198 if (sym.getKind() == ElementKind.PARAMETER &&
199 sym.getQualifiedName().equals(names._this)) {
200 sym.owner.type.asMethodType().recvtype = type;
201 // note that the typeAnnotations will also be added to the owner below.
202 }
203 if (sym.getKind() == ElementKind.PARAMETER ||
204 sym.getKind() == ElementKind.LOCAL_VARIABLE ||
205 sym.getKind() == ElementKind.RESOURCE_VARIABLE ||
206 sym.getKind() == ElementKind.EXCEPTION_PARAMETER) {
207 // Make sure all type annotations from the symbol are also
208 // on the owner.
209 sym.owner.annotations.appendUniqueTypes(sym.getTypeAnnotationMirrors());
210 }
211 }
213 // This method has a similar purpose as
214 // {@link com.sun.tools.javac.parser.JavacParser.insertAnnotationsToMostInner(JCExpression, List<JCTypeAnnotation>, boolean)}
215 // We found a type annotation in a declaration annotation position,
216 // for example, on the return type.
217 // Such an annotation is _not_ part of an JCAnnotatedType tree and we therefore
218 // need to set its position explicitly.
219 // The method returns a copy of type that contains these annotations.
220 //
221 // As a side effect the method sets the type annotation position of "annotations".
222 // Note that it is assumed that all annotations share the same position.
223 private static Type typeWithAnnotations(final JCTree typetree, final Type type,
224 final List<Attribute.TypeCompound> annotations, Log log) {
225 // System.out.printf("typeWithAnnotations(typetree: %s, type: %s, annotations: %s)%n",
226 // typetree, type, annotations);
227 if (annotations.isEmpty()) {
228 return type;
229 }
230 if (type.hasTag(TypeTag.ARRAY)) {
231 Type toreturn;
232 Type.ArrayType tomodify;
233 Type.ArrayType arType;
234 {
235 Type touse = type;
236 if (type.getKind() == TypeKind.ANNOTATED) {
237 Type.AnnotatedType atype = (Type.AnnotatedType)type;
238 toreturn = new Type.AnnotatedType(atype.underlyingType);
239 ((Type.AnnotatedType)toreturn).typeAnnotations = atype.typeAnnotations;
240 touse = atype.underlyingType;
241 arType = (Type.ArrayType) touse;
242 tomodify = new Type.ArrayType(null, arType.tsym);
243 ((Type.AnnotatedType)toreturn).underlyingType = tomodify;
244 } else {
245 arType = (Type.ArrayType) touse;
246 tomodify = new Type.ArrayType(null, arType.tsym);
247 toreturn = tomodify;
248 }
249 }
250 JCArrayTypeTree arTree = arrayTypeTree(typetree);
252 ListBuffer<TypePathEntry> depth = ListBuffer.lb();
253 depth = depth.append(TypePathEntry.ARRAY);
254 while (arType.elemtype.hasTag(TypeTag.ARRAY)) {
255 if (arType.elemtype.getKind() == TypeKind.ANNOTATED) {
256 Type.AnnotatedType aelemtype = (Type.AnnotatedType) arType.elemtype;
257 Type.AnnotatedType newAT = new Type.AnnotatedType(aelemtype.underlyingType);
258 tomodify.elemtype = newAT;
259 newAT.typeAnnotations = aelemtype.typeAnnotations;
260 arType = (Type.ArrayType) aelemtype.underlyingType;
261 tomodify = new Type.ArrayType(null, arType.tsym);
262 newAT.underlyingType = tomodify;
263 } else {
264 arType = (Type.ArrayType) arType.elemtype;
265 tomodify.elemtype = new Type.ArrayType(null, arType.tsym);
266 tomodify = (Type.ArrayType) tomodify.elemtype;
267 }
268 arTree = arrayTypeTree(arTree.elemtype);
269 depth = depth.append(TypePathEntry.ARRAY);
270 }
271 Type arelemType = typeWithAnnotations(arTree.elemtype, arType.elemtype, annotations, log);
272 tomodify.elemtype = arelemType;
273 {
274 // All annotations share the same position; modify the first one.
275 Attribute.TypeCompound a = annotations.get(0);
276 TypeAnnotationPosition p = a.position;
277 p.location = p.location.prependList(depth.toList());
278 }
279 return toreturn;
280 } else if (type.hasTag(TypeTag.TYPEVAR)) {
281 // Nothing to do for type variables.
282 return type;
283 } else {
284 Type enclTy = type;
285 Element enclEl = type.asElement();
286 JCTree enclTr = typetree;
288 while (enclEl != null &&
289 enclEl.getKind() != ElementKind.PACKAGE &&
290 enclTy != null &&
291 enclTy.getKind() != TypeKind.NONE &&
292 enclTy.getKind() != TypeKind.ERROR &&
293 (enclTr.getKind() == JCTree.Kind.MEMBER_SELECT ||
294 enclTr.getKind() == JCTree.Kind.PARAMETERIZED_TYPE ||
295 enclTr.getKind() == JCTree.Kind.ANNOTATED_TYPE)) {
296 // Iterate also over the type tree, not just the type: the type is already
297 // completely resolved and we cannot distinguish where the annotation
298 // belongs for a nested type.
299 if (enclTr.getKind() == JCTree.Kind.MEMBER_SELECT) {
300 // only change encl in this case.
301 enclTy = enclTy.getEnclosingType();
302 enclEl = enclEl.getEnclosingElement();
303 enclTr = ((JCFieldAccess)enclTr).getExpression();
304 } else if (enclTr.getKind() == JCTree.Kind.PARAMETERIZED_TYPE) {
305 enclTr = ((JCTypeApply)enclTr).getType();
306 } else {
307 // only other option because of while condition
308 enclTr = ((JCAnnotatedType)enclTr).getUnderlyingType();
309 }
310 }
312 /** We are trying to annotate some enclosing type,
313 * but nothing more exists.
314 */
315 if (enclTy != null &&
316 enclTy.getKind() == TypeKind.NONE &&
317 (enclTr.getKind() == JCTree.Kind.IDENTIFIER ||
318 enclTr.getKind() == JCTree.Kind.MEMBER_SELECT ||
319 enclTr.getKind() == JCTree.Kind.PARAMETERIZED_TYPE ||
320 enclTr.getKind() == JCTree.Kind.ANNOTATED_TYPE)) {
321 // TODO: also if it's "java. @A lang.Object", that is,
322 // if it's on a package?
323 log.error(enclTr.pos(), "cant.annotate.nested.type", enclTr.toString());
324 return type;
325 }
327 // At this point we have visited the part of the nested
328 // type that is written in the source code.
329 // Now count from here to the actual top-level class to determine
330 // the correct nesting.
332 // The genericLocation for the annotation.
333 ListBuffer<TypePathEntry> depth = ListBuffer.lb();
335 Type topTy = enclTy;
336 while (enclEl != null &&
337 enclEl.getKind() != ElementKind.PACKAGE &&
338 topTy != null &&
339 topTy.getKind() != TypeKind.NONE &&
340 topTy.getKind() != TypeKind.ERROR) {
341 topTy = topTy.getEnclosingType();
342 enclEl = enclEl.getEnclosingElement();
344 if (topTy != null && topTy.getKind() != TypeKind.NONE) {
345 // Only count enclosing types.
346 depth = depth.append(TypePathEntry.INNER_TYPE);
347 }
348 }
350 if (depth.nonEmpty()) {
351 // Only need to change the annotation positions
352 // if they are on an enclosed type.
353 // All annotations share the same position; modify the first one.
354 Attribute.TypeCompound a = annotations.get(0);
355 TypeAnnotationPosition p = a.position;
356 p.location = p.location.appendList(depth.toList());
357 }
359 Type ret = typeWithAnnotations(type, enclTy, annotations);
360 return ret;
361 }
362 }
364 private static JCArrayTypeTree arrayTypeTree(JCTree typetree) {
365 if (typetree.getKind() == JCTree.Kind.ARRAY_TYPE) {
366 return (JCArrayTypeTree) typetree;
367 } else if (typetree.getKind() == JCTree.Kind.ANNOTATED_TYPE) {
368 return (JCArrayTypeTree) ((JCAnnotatedType)typetree).underlyingType;
369 } else {
370 Assert.error("Could not determine array type from type tree: " + typetree);
371 return null;
372 }
373 }
375 /** Return a copy of the first type that only differs by
376 * inserting the annotations to the left-most/inner-most type
377 * or the type given by stopAt.
378 *
379 * We need the stopAt parameter to know where on a type to
380 * put the annotations.
381 * If we have nested classes Outer > Middle > Inner, and we
382 * have the source type "@A Middle.Inner", we will invoke
383 * this method with type = Outer.Middle.Inner,
384 * stopAt = Middle.Inner, and annotations = @A.
385 *
386 * @param type The type to copy.
387 * @param stopAt The type to stop at.
388 * @param annotations The annotations to insert.
389 * @return A copy of type that contains the annotations.
390 */
391 private static Type typeWithAnnotations(final Type type,
392 final Type stopAt,
393 final List<Attribute.TypeCompound> annotations) {
394 Visitor<Type, List<TypeCompound>> visitor =
395 new Type.Visitor<Type, List<Attribute.TypeCompound>>() {
396 @Override
397 public Type visitClassType(ClassType t, List<TypeCompound> s) {
398 // assert that t.constValue() == null?
399 if (t == stopAt ||
400 t.getEnclosingType() == Type.noType) {
401 return new AnnotatedType(s, t);
402 } else {
403 ClassType ret = new ClassType(t.getEnclosingType().accept(this, s),
404 t.typarams_field, t.tsym);
405 ret.all_interfaces_field = t.all_interfaces_field;
406 ret.allparams_field = t.allparams_field;
407 ret.interfaces_field = t.interfaces_field;
408 ret.rank_field = t.rank_field;
409 ret.supertype_field = t.supertype_field;
410 return ret;
411 }
412 }
414 @Override
415 public Type visitAnnotatedType(AnnotatedType t, List<TypeCompound> s) {
416 return new AnnotatedType(t.typeAnnotations, t.underlyingType.accept(this, s));
417 }
419 @Override
420 public Type visitWildcardType(WildcardType t, List<TypeCompound> s) {
421 return new AnnotatedType(s, t);
422 }
424 @Override
425 public Type visitArrayType(ArrayType t, List<TypeCompound> s) {
426 ArrayType ret = new ArrayType(t.elemtype.accept(this, s), t.tsym);
427 return ret;
428 }
430 @Override
431 public Type visitMethodType(MethodType t, List<TypeCompound> s) {
432 // Impossible?
433 return t;
434 }
436 @Override
437 public Type visitPackageType(PackageType t, List<TypeCompound> s) {
438 // Impossible?
439 return t;
440 }
442 @Override
443 public Type visitTypeVar(TypeVar t, List<TypeCompound> s) {
444 return new AnnotatedType(s, t);
445 }
447 @Override
448 public Type visitCapturedType(CapturedType t, List<TypeCompound> s) {
449 return new AnnotatedType(s, t);
450 }
452 @Override
453 public Type visitForAll(ForAll t, List<TypeCompound> s) {
454 // Impossible?
455 return t;
456 }
458 @Override
459 public Type visitUndetVar(UndetVar t, List<TypeCompound> s) {
460 // Impossible?
461 return t;
462 }
464 @Override
465 public Type visitErrorType(ErrorType t, List<TypeCompound> s) {
466 return new AnnotatedType(s, t);
467 }
469 @Override
470 public Type visitType(Type t, List<TypeCompound> s) {
471 return new AnnotatedType(s, t);
472 }
473 };
475 return type.accept(visitor, annotations);
476 }
478 private static Attribute.TypeCompound toTypeCompound(Attribute.Compound a, TypeAnnotationPosition p) {
479 // It is safe to alias the position.
480 return new Attribute.TypeCompound(a, p);
481 }
483 private AnnotationType annotationType(Attribute.Compound a, Symbol s) {
484 Attribute.Compound atTarget =
485 a.type.tsym.attribute(syms.annotationTargetType.tsym);
486 if (atTarget == null) {
487 return inferTargetMetaInfo(a, s);
488 }
489 Attribute atValue = atTarget.member(names.value);
490 if (!(atValue instanceof Attribute.Array)) {
491 Assert.error("annotationType(): bad @Target argument " + atValue +
492 " (" + atValue.getClass() + ")");
493 return AnnotationType.DECLARATION; // error recovery
494 }
495 Attribute.Array arr = (Attribute.Array) atValue;
496 boolean isDecl = false, isType = false;
497 for (Attribute app : arr.values) {
498 if (!(app instanceof Attribute.Enum)) {
499 Assert.error("annotationType(): unrecognized Attribute kind " + app +
500 " (" + app.getClass() + ")");
501 isDecl = true;
502 continue;
503 }
504 Attribute.Enum e = (Attribute.Enum) app;
505 if (e.value.name == names.TYPE) {
506 if (s.kind == Kinds.TYP)
507 isDecl = true;
508 } else if (e.value.name == names.FIELD) {
509 if (s.kind == Kinds.VAR &&
510 s.owner.kind != Kinds.MTH)
511 isDecl = true;
512 } else if (e.value.name == names.METHOD) {
513 if (s.kind == Kinds.MTH &&
514 !s.isConstructor())
515 isDecl = true;
516 } else if (e.value.name == names.PARAMETER) {
517 if (s.kind == Kinds.VAR &&
518 s.owner.kind == Kinds.MTH &&
519 (s.flags() & Flags.PARAMETER) != 0)
520 isDecl = true;
521 } else if (e.value.name == names.CONSTRUCTOR) {
522 if (s.kind == Kinds.MTH &&
523 s.isConstructor())
524 isDecl = true;
525 } else if (e.value.name == names.LOCAL_VARIABLE) {
526 if (s.kind == Kinds.VAR &&
527 s.owner.kind == Kinds.MTH &&
528 (s.flags() & Flags.PARAMETER) == 0)
529 isDecl = true;
530 } else if (e.value.name == names.ANNOTATION_TYPE) {
531 if (s.kind == Kinds.TYP &&
532 (s.flags() & Flags.ANNOTATION) != 0)
533 isDecl = true;
534 } else if (e.value.name == names.PACKAGE) {
535 if (s.kind == Kinds.PCK)
536 isDecl = true;
537 } else if (e.value.name == names.TYPE_USE) {
538 if (s.kind == Kinds.TYP ||
539 s.kind == Kinds.VAR ||
540 (s.kind == Kinds.MTH && !s.isConstructor() &&
541 !s.type.getReturnType().hasTag(TypeTag.VOID)) ||
542 (s.kind == Kinds.MTH && s.isConstructor()))
543 isType = true;
544 } else if (e.value.name == names.TYPE_PARAMETER) {
545 /* Irrelevant in this case */
546 // TYPE_PARAMETER doesn't aid in distinguishing between
547 // Type annotations and declaration annotations on an
548 // Element
549 } else {
550 Assert.error("annotationType(): unrecognized Attribute name " + e.value.name +
551 " (" + e.value.name.getClass() + ")");
552 isDecl = true;
553 }
554 }
555 if (isDecl && isType) {
556 return AnnotationType.BOTH;
557 } else if (isType) {
558 return AnnotationType.TYPE;
559 } else {
560 return AnnotationType.DECLARATION;
561 }
562 }
564 /** Infer the target annotation kind, if none is give.
565 * We only infer declaration annotations.
566 */
567 private static AnnotationType inferTargetMetaInfo(Attribute.Compound a, Symbol s) {
568 return AnnotationType.DECLARATION;
569 }
572 /* This is the beginning of the second part of organizing
573 * type annotations: determine the type annotation positions.
574 */
576 private void resolveFrame(JCTree tree, JCTree frame,
577 List<JCTree> path, TypeAnnotationPosition p) {
578 /*
579 System.out.println("Resolving tree: " + tree + " kind: " + tree.getKind());
580 System.out.println(" Framing tree: " + frame + " kind: " + frame.getKind());
581 */
583 // Note that p.offset is set in
584 // com.sun.tools.javac.jvm.Gen.setTypeAnnotationPositions(int)
586 switch (frame.getKind()) {
587 case TYPE_CAST:
588 p.type = TargetType.CAST;
589 p.pos = frame.pos;
590 return;
592 case INSTANCE_OF:
593 p.type = TargetType.INSTANCEOF;
594 p.pos = frame.pos;
595 return;
597 case NEW_CLASS:
598 JCNewClass frameNewClass = (JCNewClass)frame;
599 if (frameNewClass.typeargs.contains(tree)) {
600 p.type = TargetType.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT;
601 p.type_index = frameNewClass.typeargs.indexOf(tree);
602 } else {
603 p.type = TargetType.NEW;
604 }
605 p.pos = frame.pos;
606 return;
608 case NEW_ARRAY:
609 p.type = TargetType.NEW;
610 p.pos = frame.pos;
611 return;
613 case ANNOTATION_TYPE:
614 case CLASS:
615 case ENUM:
616 case INTERFACE:
617 p.pos = frame.pos;
618 if (((JCClassDecl)frame).extending == tree) {
619 p.type = TargetType.CLASS_EXTENDS;
620 p.type_index = -1;
621 } else if (((JCClassDecl)frame).implementing.contains(tree)) {
622 p.type = TargetType.CLASS_EXTENDS;
623 p.type_index = ((JCClassDecl)frame).implementing.indexOf(tree);
624 } else if (((JCClassDecl)frame).typarams.contains(tree)) {
625 p.type = TargetType.CLASS_TYPE_PARAMETER;
626 p.parameter_index = ((JCClassDecl)frame).typarams.indexOf(tree);
627 } else {
628 Assert.error("Could not determine position of tree " + tree +
629 " within frame " + frame);
630 }
631 return;
633 case METHOD: {
634 JCMethodDecl frameMethod = (JCMethodDecl) frame;
635 p.pos = frame.pos;
636 if (frameMethod.thrown.contains(tree)) {
637 p.type = TargetType.THROWS;
638 p.type_index = frameMethod.thrown.indexOf(tree);
639 } else if (frameMethod.restype == tree) {
640 p.type = TargetType.METHOD_RETURN;
641 } else if (frameMethod.typarams.contains(tree)) {
642 p.type = TargetType.METHOD_TYPE_PARAMETER;
643 p.parameter_index = frameMethod.typarams.indexOf(tree);
644 } else {
645 Assert.error("Could not determine position of tree " + tree +
646 " within frame " + frame);
647 }
648 return;
649 }
651 case PARAMETERIZED_TYPE: {
652 if (((JCTypeApply)frame).clazz == tree) {
653 // generic: RAW; noop
654 } else if (((JCTypeApply)frame).arguments.contains(tree)) {
655 JCTypeApply taframe = (JCTypeApply) frame;
656 int arg = taframe.arguments.indexOf(tree);
657 p.location = p.location.prepend(new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg));
659 locateNestedTypes(taframe.type, p);
660 } else {
661 Assert.error("Could not determine type argument position of tree " + tree +
662 " within frame " + frame);
663 }
665 List<JCTree> newPath = path.tail;
666 resolveFrame(newPath.head, newPath.tail.head, newPath, p);
667 return;
668 }
670 case MEMBER_REFERENCE: {
671 JCMemberReference mrframe = (JCMemberReference) frame;
673 if (mrframe.expr == tree) {
674 switch (mrframe.mode) {
675 case INVOKE:
676 p.type = TargetType.METHOD_REFERENCE;
677 break;
678 case NEW:
679 p.type = TargetType.CONSTRUCTOR_REFERENCE;
680 break;
681 default:
682 Assert.error("Unknown method reference mode " + mrframe.mode +
683 " for tree " + tree + " within frame " + frame);
684 }
685 p.pos = frame.pos;
686 } else if (mrframe.typeargs != null &&
687 mrframe.typeargs.contains(tree)) {
688 int arg = mrframe.typeargs.indexOf(tree);
689 p.type_index = arg;
690 switch (mrframe.mode) {
691 case INVOKE:
692 p.type = TargetType.METHOD_REFERENCE_TYPE_ARGUMENT;
693 break;
694 case NEW:
695 p.type = TargetType.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT;
696 break;
697 default:
698 Assert.error("Unknown method reference mode " + mrframe.mode +
699 " for tree " + tree + " within frame " + frame);
700 }
701 p.pos = frame.pos;
702 } else {
703 Assert.error("Could not determine type argument position of tree " + tree +
704 " within frame " + frame);
705 }
706 return;
707 }
709 case ARRAY_TYPE: {
710 ListBuffer<TypePathEntry> index = ListBuffer.lb();
711 index = index.append(TypePathEntry.ARRAY);
712 List<JCTree> newPath = path.tail;
713 while (true) {
714 JCTree npHead = newPath.tail.head;
715 if (npHead.hasTag(JCTree.Tag.TYPEARRAY)) {
716 newPath = newPath.tail;
717 index = index.append(TypePathEntry.ARRAY);
718 } else if (npHead.hasTag(JCTree.Tag.ANNOTATED_TYPE)) {
719 newPath = newPath.tail;
720 } else {
721 break;
722 }
723 }
724 p.location = p.location.prependList(index.toList());
725 resolveFrame(newPath.head, newPath.tail.head, newPath, p);
726 return;
727 }
729 case TYPE_PARAMETER:
730 if (path.tail.tail.head.hasTag(JCTree.Tag.CLASSDEF)) {
731 JCClassDecl clazz = (JCClassDecl)path.tail.tail.head;
732 p.type = TargetType.CLASS_TYPE_PARAMETER_BOUND;
733 p.parameter_index = clazz.typarams.indexOf(path.tail.head);
734 p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree);
735 if (((JCTypeParameter)frame).bounds.get(0).type.isInterface()) {
736 // Account for an implicit Object as bound 0
737 p.bound_index += 1;
738 }
739 } else if (path.tail.tail.head.hasTag(JCTree.Tag.METHODDEF)) {
740 JCMethodDecl method = (JCMethodDecl)path.tail.tail.head;
741 p.type = TargetType.METHOD_TYPE_PARAMETER_BOUND;
742 p.parameter_index = method.typarams.indexOf(path.tail.head);
743 p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree);
744 if (((JCTypeParameter)frame).bounds.get(0).type.isInterface()) {
745 // Account for an implicit Object as bound 0
746 p.bound_index += 1;
747 }
748 } else {
749 Assert.error("Could not determine position of tree " + tree +
750 " within frame " + frame);
751 }
752 p.pos = frame.pos;
753 return;
755 case VARIABLE:
756 VarSymbol v = ((JCVariableDecl)frame).sym;
757 p.pos = frame.pos;
758 switch (v.getKind()) {
759 case LOCAL_VARIABLE:
760 p.type = TargetType.LOCAL_VARIABLE;
761 break;
762 case FIELD:
763 p.type = TargetType.FIELD;
764 break;
765 case PARAMETER:
766 if (v.getQualifiedName().equals(names._this)) {
767 // TODO: Intro a separate ElementKind?
768 p.type = TargetType.METHOD_RECEIVER;
769 } else {
770 p.type = TargetType.METHOD_FORMAL_PARAMETER;
771 p.parameter_index = methodParamIndex(path, frame);
772 }
773 break;
774 case EXCEPTION_PARAMETER:
775 p.type = TargetType.EXCEPTION_PARAMETER;
776 break;
777 case RESOURCE_VARIABLE:
778 p.type = TargetType.RESOURCE_VARIABLE;
779 break;
780 default:
781 Assert.error("Found unexpected type annotation for variable: " + v + " with kind: " + v.getKind());
782 }
783 return;
785 case ANNOTATED_TYPE: {
786 if (frame == tree) {
787 // This is only true for the first annotated type we see.
788 // For any other annotated types along the path, we do
789 // not care about inner types.
790 JCAnnotatedType atypetree = (JCAnnotatedType) frame;
791 final Type utype = atypetree.underlyingType.type;
792 Symbol tsym = utype.tsym;
793 if (tsym.getKind().equals(ElementKind.TYPE_PARAMETER) ||
794 utype.getKind().equals(TypeKind.WILDCARD) ||
795 utype.getKind().equals(TypeKind.ARRAY)) {
796 // Type parameters, wildcards, and arrays have the declaring
797 // class/method as enclosing elements.
798 // There is actually nothing to do for them.
799 } else {
800 locateNestedTypes(utype, p);
801 }
802 }
803 List<JCTree> newPath = path.tail;
804 resolveFrame(newPath.head, newPath.tail.head, newPath, p);
805 return;
806 }
808 case UNION_TYPE: {
809 // TODO: can we store any information here to help in
810 // determining the final position?
811 List<JCTree> newPath = path.tail;
812 resolveFrame(newPath.head, newPath.tail.head, newPath, p);
813 return;
814 }
816 case INTERSECTION_TYPE: {
817 JCTypeIntersection isect = (JCTypeIntersection)frame;
818 p.type_index = isect.bounds.indexOf(tree);
819 List<JCTree> newPath = path.tail;
820 resolveFrame(newPath.head, newPath.tail.head, newPath, p);
821 return;
822 }
824 case METHOD_INVOCATION: {
825 JCMethodInvocation invocation = (JCMethodInvocation)frame;
826 if (!invocation.typeargs.contains(tree)) {
827 Assert.error("{" + tree + "} is not an argument in the invocation: " + invocation);
828 }
829 p.type = TargetType.METHOD_INVOCATION_TYPE_ARGUMENT;
830 p.pos = invocation.pos;
831 p.type_index = invocation.typeargs.indexOf(tree);
832 return;
833 }
835 case EXTENDS_WILDCARD:
836 case SUPER_WILDCARD: {
837 // Annotations in wildcard bounds
838 p.location = p.location.prepend(TypePathEntry.WILDCARD);
839 List<JCTree> newPath = path.tail;
840 resolveFrame(newPath.head, newPath.tail.head, newPath, p);
841 return;
842 }
844 case MEMBER_SELECT: {
845 List<JCTree> newPath = path.tail;
846 resolveFrame(newPath.head, newPath.tail.head, newPath, p);
847 return;
848 }
850 default:
851 Assert.error("Unresolved frame: " + frame + " of kind: " + frame.getKind() +
852 "\n Looking for tree: " + tree);
853 return;
854 }
855 }
857 private static void locateNestedTypes(Type type, TypeAnnotationPosition p) {
858 // The number of "steps" to get from the full type to the
859 // left-most outer type.
860 ListBuffer<TypePathEntry> depth = ListBuffer.lb();
862 Type encl = type.getEnclosingType();
863 while (encl != null &&
864 encl.getKind() != TypeKind.NONE &&
865 encl.getKind() != TypeKind.ERROR) {
866 depth = depth.append(TypePathEntry.INNER_TYPE);
867 encl = encl.getEnclosingType();
868 }
869 if (depth.nonEmpty()) {
870 p.location = p.location.prependList(depth.toList());
871 }
872 }
874 private static int methodParamIndex(List<JCTree> path, JCTree param) {
875 List<JCTree> curr = path;
876 while (curr.head.getTag() != Tag.METHODDEF) {
877 curr = curr.tail;
878 }
879 JCMethodDecl method = (JCMethodDecl)curr.head;
880 return method.params.indexOf(param);
881 }
883 // Each class (including enclosed inner classes) is visited separately.
884 // This flag is used to prevent from visiting inner classes.
885 private boolean isInClass = false;
887 @Override
888 public void visitClassDef(JCClassDecl tree) {
889 if (isInClass)
890 return;
891 isInClass = true;
892 if (sigOnly) {
893 scan(tree.mods);
894 scan(tree.typarams);
895 scan(tree.extending);
896 scan(tree.implementing);
897 }
898 scan(tree.defs);
899 }
901 /**
902 * Resolve declaration vs. type annotations in methods and
903 * then determine the positions.
904 */
905 @Override
906 public void visitMethodDef(final JCMethodDecl tree) {
907 if (tree.sym == null) {
908 // Something most be wrong, e.g. a class not found.
909 // Quietly ignore. (See test FailOver15.java)
910 return;
911 }
912 if (sigOnly) {
913 {
914 TypeAnnotationPosition pos = new TypeAnnotationPosition();
915 pos.type = TargetType.METHOD_RETURN;
916 if (tree.sym.isConstructor()) {
917 pos.pos = tree.pos;
918 // Use null to mark that the annotations go with the symbol.
919 separateAnnotationsKinds(tree, null, tree.sym, pos);
920 } else {
921 pos.pos = tree.restype.pos;
922 separateAnnotationsKinds(tree.restype, tree.sym.type.getReturnType(),
923 tree.sym, pos);
924 }
925 }
926 if (tree.recvparam != null && tree.recvparam.sym != null) {
927 // TODO: make sure there are no declaration annotations.
928 TypeAnnotationPosition pos = new TypeAnnotationPosition();
929 pos.type = TargetType.METHOD_RECEIVER;
930 pos.pos = tree.recvparam.vartype.pos;
931 separateAnnotationsKinds(tree.recvparam.vartype, tree.recvparam.sym.type,
932 tree.recvparam.sym, pos);
933 }
934 int i = 0;
935 for (JCVariableDecl param : tree.params) {
936 TypeAnnotationPosition pos = new TypeAnnotationPosition();
937 pos.type = TargetType.METHOD_FORMAL_PARAMETER;
938 pos.parameter_index = i;
939 pos.pos = param.vartype.pos;
940 separateAnnotationsKinds(param.vartype, param.sym.type, param.sym, pos);
941 ++i;
942 }
943 }
945 push(tree);
946 // super.visitMethodDef(tree);
947 if (sigOnly) {
948 scan(tree.mods);
949 scan(tree.restype);
950 scan(tree.typarams);
951 scan(tree.recvparam);
952 scan(tree.params);
953 scan(tree.thrown);
954 } else {
955 scan(tree.defaultValue);
956 scan(tree.body);
957 }
958 pop();
959 }
961 /**
962 * Resolve declaration vs. type annotations in variable declarations and
963 * then determine the positions.
964 */
965 @Override
966 public void visitVarDef(final JCVariableDecl tree) {
967 if (tree.sym == null) {
968 // Something is wrong already. Quietly ignore.
969 } else if (tree.sym.getKind() == ElementKind.PARAMETER) {
970 // Parameters are handled in visitMethodDef above.
971 } else if (tree.sym.getKind() == ElementKind.FIELD) {
972 if (sigOnly) {
973 TypeAnnotationPosition pos = new TypeAnnotationPosition();
974 pos.type = TargetType.FIELD;
975 pos.pos = tree.pos;
976 separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
977 }
978 } else if (tree.sym.getKind() == ElementKind.LOCAL_VARIABLE) {
979 TypeAnnotationPosition pos = new TypeAnnotationPosition();
980 pos.type = TargetType.LOCAL_VARIABLE;
981 pos.pos = tree.pos;
982 separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
983 } else if (tree.sym.getKind() == ElementKind.EXCEPTION_PARAMETER) {
984 TypeAnnotationPosition pos = new TypeAnnotationPosition();
985 pos.type = TargetType.EXCEPTION_PARAMETER;
986 pos.pos = tree.pos;
987 separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
988 } else if (tree.sym.getKind() == ElementKind.RESOURCE_VARIABLE) {
989 TypeAnnotationPosition pos = new TypeAnnotationPosition();
990 pos.type = TargetType.RESOURCE_VARIABLE;
991 pos.pos = tree.pos;
992 separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
993 } else if (tree.sym.getKind() == ElementKind.ENUM_CONSTANT) {
994 // No type annotations can occur here.
995 } else {
996 // There is nothing else in a variable declaration that needs separation.
997 Assert.error("Unhandled variable kind: " + tree + " of kind: " + tree.sym.getKind());
998 }
1000 push(tree);
1001 // super.visitVarDef(tree);
1002 scan(tree.mods);
1003 scan(tree.vartype);
1004 if (!sigOnly) {
1005 scan(tree.init);
1006 }
1007 pop();
1008 }
1010 @Override
1011 public void visitBlock(JCBlock tree) {
1012 // Do not descend into top-level blocks when only interested
1013 // in the signature.
1014 if (!sigOnly) {
1015 scan(tree.stats);
1016 }
1017 }
1019 @Override
1020 public void visitAnnotatedType(JCAnnotatedType tree) {
1021 push(tree);
1022 findPosition(tree, tree, tree.annotations);
1023 pop();
1024 super.visitAnnotatedType(tree);
1025 }
1027 @Override
1028 public void visitTypeParameter(JCTypeParameter tree) {
1029 findPosition(tree, peek2(), tree.annotations);
1030 super.visitTypeParameter(tree);
1031 }
1033 @Override
1034 public void visitNewArray(JCNewArray tree) {
1035 findPosition(tree, tree, tree.annotations);
1036 int dimAnnosCount = tree.dimAnnotations.size();
1037 ListBuffer<TypePathEntry> depth = ListBuffer.lb();
1039 // handle annotations associated with dimensions
1040 for (int i = 0; i < dimAnnosCount; ++i) {
1041 TypeAnnotationPosition p = new TypeAnnotationPosition();
1042 p.pos = tree.pos;
1043 p.type = TargetType.NEW;
1044 if (i != 0) {
1045 depth = depth.append(TypePathEntry.ARRAY);
1046 p.location = p.location.appendList(depth.toList());
1047 }
1049 setTypeAnnotationPos(tree.dimAnnotations.get(i), p);
1050 }
1052 // handle "free" annotations
1053 // int i = dimAnnosCount == 0 ? 0 : dimAnnosCount - 1;
1054 // TODO: is depth.size == i here?
1055 JCExpression elemType = tree.elemtype;
1056 while (elemType != null) {
1057 if (elemType.hasTag(JCTree.Tag.ANNOTATED_TYPE)) {
1058 JCAnnotatedType at = (JCAnnotatedType)elemType;
1059 TypeAnnotationPosition p = new TypeAnnotationPosition();
1060 p.type = TargetType.NEW;
1061 p.pos = tree.pos;
1062 p.location = p.location.appendList(depth.toList());
1063 setTypeAnnotationPos(at.annotations, p);
1064 elemType = at.underlyingType;
1065 } else if (elemType.hasTag(JCTree.Tag.TYPEARRAY)) {
1066 depth = depth.append(TypePathEntry.ARRAY);
1067 elemType = ((JCArrayTypeTree)elemType).elemtype;
1068 } else {
1069 break;
1070 }
1071 }
1072 scan(tree.elems);
1073 }
1075 private void findPosition(JCTree tree, JCTree frame, List<JCAnnotation> annotations) {
1076 if (!annotations.isEmpty()) {
1077 /*
1078 System.out.println("Finding pos for: " + annotations);
1079 System.out.println(" tree: " + tree);
1080 System.out.println(" frame: " + frame);
1081 */
1082 TypeAnnotationPosition p = new TypeAnnotationPosition();
1083 resolveFrame(tree, frame, frames.toList(), p);
1084 setTypeAnnotationPos(annotations, p);
1085 }
1086 }
1088 private static void setTypeAnnotationPos(List<JCAnnotation> annotations,
1089 TypeAnnotationPosition position) {
1090 for (JCAnnotation anno : annotations) {
1091 ((Attribute.TypeCompound) anno.attribute).position = position;
1092 }
1093 }
1094 }
1095 }