src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java

changeset 1570
f91144b7da75
parent 1521
71f35e4b93a5
child 1563
bc456436c613
equal deleted inserted replaced
1569:475eb15dfdad 1570:f91144b7da75
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 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;
67
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() {}
78
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 }
96
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 }
104
105 private static class TypeAnnotationPositions extends TreeScanner {
106
107 private enum AnnotationType { DECLARATION, TYPE, BOTH };
108
109 private final Symtab syms;
110 private final Names names;
111 private final Log log;
112 private final boolean sigOnly;
113
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 }
120
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();
126
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; }
131
132 @Override
133 public void scan(JCTree tree) {
134 push(tree);
135 super.scan(tree);
136 pop();
137 }
138
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>();
155
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 }
174
175 sym.annotations.reset();
176 sym.annotations.setDeclarationAttributes(declAnnos.toList());
177
178 List<Attribute.TypeCompound> typeAnnotations = typeAnnos.toList();
179
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 }
187
188 // type is non-null and annotations are added to that type
189 type = typeWithAnnotations(typetree, type, typeAnnotations, log);
190
191 if (sym.getKind() == ElementKind.METHOD) {
192 sym.type.asMethodType().restype = type;
193 } else {
194 sym.type = type;
195 }
196
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 }
212
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 private static Type typeWithAnnotations(final JCTree typetree, final Type type,
221 final List<Attribute.TypeCompound> annotations, Log log) {
222 // System.out.printf("typeWithAnnotations(typetree: %s, type: %s, annotations: %s)%n",
223 // typetree, type, annotations);
224 if (annotations.isEmpty()) {
225 return type;
226 }
227 if (type.hasTag(TypeTag.ARRAY)) {
228 Type toreturn;
229 Type.ArrayType tomodify;
230 Type.ArrayType arType;
231 {
232 Type touse = type;
233 if (type.getKind() == TypeKind.ANNOTATED) {
234 Type.AnnotatedType atype = (Type.AnnotatedType)type;
235 toreturn = new Type.AnnotatedType(atype.underlyingType);
236 ((Type.AnnotatedType)toreturn).typeAnnotations = atype.typeAnnotations;
237 touse = atype.underlyingType;
238 arType = (Type.ArrayType) touse;
239 tomodify = new Type.ArrayType(null, arType.tsym);
240 ((Type.AnnotatedType)toreturn).underlyingType = tomodify;
241 } else {
242 arType = (Type.ArrayType) touse;
243 tomodify = new Type.ArrayType(null, arType.tsym);
244 toreturn = tomodify;
245 }
246 }
247 JCArrayTypeTree arTree = arrayTypeTree(typetree);
248
249 ListBuffer<TypePathEntry> depth = ListBuffer.lb();
250 depth = depth.append(TypePathEntry.ARRAY);
251 while (arType.elemtype.hasTag(TypeTag.ARRAY)) {
252 if (arType.elemtype.getKind() == TypeKind.ANNOTATED) {
253 Type.AnnotatedType aelemtype = (Type.AnnotatedType) arType.elemtype;
254 Type.AnnotatedType newAT = new Type.AnnotatedType(aelemtype.underlyingType);
255 tomodify.elemtype = newAT;
256 newAT.typeAnnotations = aelemtype.typeAnnotations;
257 arType = (Type.ArrayType) aelemtype.underlyingType;
258 tomodify = new Type.ArrayType(null, arType.tsym);
259 newAT.underlyingType = tomodify;
260 } else {
261 arType = (Type.ArrayType) arType.elemtype;
262 tomodify.elemtype = new Type.ArrayType(null, arType.tsym);
263 tomodify = (Type.ArrayType) tomodify.elemtype;
264 }
265 arTree = arrayTypeTree(arTree.elemtype);
266 depth = depth.append(TypePathEntry.ARRAY);
267 }
268 Type arelemType = typeWithAnnotations(arTree.elemtype, arType.elemtype, annotations, log);
269 tomodify.elemtype = arelemType;
270 for (Attribute.TypeCompound a : annotations) {
271 TypeAnnotationPosition p = a.position;
272 p.location = p.location.prependList(depth.toList());
273 }
274 return toreturn;
275 } else if (type.hasTag(TypeTag.TYPEVAR)) {
276 // Nothing to do for type variables.
277 return type;
278 } else {
279 Type enclTy = type;
280 Element enclEl = type.asElement();
281 JCTree enclTr = typetree;
282
283 while (enclEl != null &&
284 enclEl.getKind() != ElementKind.PACKAGE &&
285 enclTy != null &&
286 enclTy.getKind() != TypeKind.NONE &&
287 enclTy.getKind() != TypeKind.ERROR &&
288 (enclTr.getKind() == JCTree.Kind.MEMBER_SELECT ||
289 enclTr.getKind() == JCTree.Kind.PARAMETERIZED_TYPE ||
290 enclTr.getKind() == JCTree.Kind.ANNOTATED_TYPE)) {
291 // Iterate also over the type tree, not just the type: the type is already
292 // completely resolved and we cannot distinguish where the annotation
293 // belongs for a nested type.
294 if (enclTr.getKind() == JCTree.Kind.MEMBER_SELECT) {
295 // only change encl in this case.
296 enclTy = enclTy.getEnclosingType();
297 enclEl = enclEl.getEnclosingElement();
298 enclTr = ((JCFieldAccess)enclTr).getExpression();
299 } else if (enclTr.getKind() == JCTree.Kind.PARAMETERIZED_TYPE) {
300 enclTr = ((JCTypeApply)enclTr).getType();
301 } else {
302 // only other option because of while condition
303 enclTr = ((JCAnnotatedType)enclTr).getUnderlyingType();
304 }
305 }
306
307 /** We are trying to annotate some enclosing type,
308 * but nothing more exists.
309 */
310 if (enclTy != null &&
311 enclTy.getKind() == TypeKind.NONE &&
312 (enclTr.getKind() == JCTree.Kind.IDENTIFIER ||
313 enclTr.getKind() == JCTree.Kind.MEMBER_SELECT ||
314 enclTr.getKind() == JCTree.Kind.PARAMETERIZED_TYPE ||
315 enclTr.getKind() == JCTree.Kind.ANNOTATED_TYPE)) {
316 // TODO: also if it's "java. @A lang.Object", that is,
317 // if it's on a package?
318 log.error(enclTr.pos(), "cant.annotate.nested.type", enclTr.toString());
319 return type;
320 }
321
322 // At this point we have visited the part of the nested
323 // type that is written in the source code.
324 // Now count from here to the actual top-level class to determine
325 // the correct nesting.
326
327 // The genericLocation for the annotation.
328 ListBuffer<TypePathEntry> depth = ListBuffer.lb();
329
330 Type topTy = enclTy;
331 while (enclEl != null &&
332 enclEl.getKind() != ElementKind.PACKAGE &&
333 topTy != null &&
334 topTy.getKind() != TypeKind.NONE &&
335 topTy.getKind() != TypeKind.ERROR) {
336 topTy = topTy.getEnclosingType();
337 enclEl = enclEl.getEnclosingElement();
338
339 if (topTy != null && topTy.getKind() != TypeKind.NONE) {
340 // Only count enclosing types.
341 depth = depth.append(TypePathEntry.INNER_TYPE);
342 }
343 }
344
345 if (depth.nonEmpty()) {
346 // Only need to change the annotation positions
347 // if they are on an enclosed type.
348 for (Attribute.TypeCompound a : annotations) {
349 TypeAnnotationPosition p = a.position;
350 p.location = p.location.appendList(depth.toList());
351 }
352 }
353
354 Type ret = typeWithAnnotations(type, enclTy, annotations);
355 return ret;
356 }
357 }
358
359 private static JCArrayTypeTree arrayTypeTree(JCTree typetree) {
360 if (typetree.getKind() == JCTree.Kind.ARRAY_TYPE) {
361 return (JCArrayTypeTree) typetree;
362 } else if (typetree.getKind() == JCTree.Kind.ANNOTATED_TYPE) {
363 return (JCArrayTypeTree) ((JCAnnotatedType)typetree).underlyingType;
364 } else {
365 Assert.error("Could not determine array type from type tree: " + typetree);
366 return null;
367 }
368 }
369
370 /** Return a copy of the first type that only differs by
371 * inserting the annotations to the left-most/inner-most type
372 * or the type given by stopAt.
373 *
374 * We need the stopAt parameter to know where on a type to
375 * put the annotations.
376 * If we have nested classes Outer > Middle > Inner, and we
377 * have the source type "@A Middle.Inner", we will invoke
378 * this method with type = Outer.Middle.Inner,
379 * stopAt = Middle.Inner, and annotations = @A.
380 *
381 * @param type The type to copy.
382 * @param stopAt The type to stop at.
383 * @param annotations The annotations to insert.
384 * @return A copy of type that contains the annotations.
385 */
386 private static Type typeWithAnnotations(final Type type,
387 final Type stopAt,
388 final List<Attribute.TypeCompound> annotations) {
389 Visitor<Type, List<TypeCompound>> visitor =
390 new Type.Visitor<Type, List<Attribute.TypeCompound>>() {
391 @Override
392 public Type visitClassType(ClassType t, List<TypeCompound> s) {
393 // assert that t.constValue() == null?
394 if (t == stopAt ||
395 t.getEnclosingType() == Type.noType) {
396 return new AnnotatedType(s, t);
397 } else {
398 ClassType ret = new ClassType(t.getEnclosingType().accept(this, s),
399 t.typarams_field, t.tsym);
400 ret.all_interfaces_field = t.all_interfaces_field;
401 ret.allparams_field = t.allparams_field;
402 ret.interfaces_field = t.interfaces_field;
403 ret.rank_field = t.rank_field;
404 ret.supertype_field = t.supertype_field;
405 return ret;
406 }
407 }
408
409 @Override
410 public Type visitAnnotatedType(AnnotatedType t, List<TypeCompound> s) {
411 return new AnnotatedType(t.typeAnnotations, t.underlyingType.accept(this, s));
412 }
413
414 @Override
415 public Type visitWildcardType(WildcardType t, List<TypeCompound> s) {
416 return new AnnotatedType(s, t);
417 }
418
419 @Override
420 public Type visitArrayType(ArrayType t, List<TypeCompound> s) {
421 ArrayType ret = new ArrayType(t.elemtype.accept(this, s), t.tsym);
422 return ret;
423 }
424
425 @Override
426 public Type visitMethodType(MethodType t, List<TypeCompound> s) {
427 // Impossible?
428 return t;
429 }
430
431 @Override
432 public Type visitPackageType(PackageType t, List<TypeCompound> s) {
433 // Impossible?
434 return t;
435 }
436
437 @Override
438 public Type visitTypeVar(TypeVar t, List<TypeCompound> s) {
439 return new AnnotatedType(s, t);
440 }
441
442 @Override
443 public Type visitCapturedType(CapturedType t, List<TypeCompound> s) {
444 return new AnnotatedType(s, t);
445 }
446
447 @Override
448 public Type visitForAll(ForAll t, List<TypeCompound> s) {
449 // Impossible?
450 return t;
451 }
452
453 @Override
454 public Type visitUndetVar(UndetVar t, List<TypeCompound> s) {
455 // Impossible?
456 return t;
457 }
458
459 @Override
460 public Type visitErrorType(ErrorType t, List<TypeCompound> s) {
461 return new AnnotatedType(s, t);
462 }
463
464 @Override
465 public Type visitType(Type t, List<TypeCompound> s) {
466 // Error?
467 return t;
468 }
469 };
470
471 return type.accept(visitor, annotations);
472 }
473
474 private static Attribute.TypeCompound toTypeCompound(Attribute.Compound a, TypeAnnotationPosition p) {
475 // It is safe to alias the position.
476 return new Attribute.TypeCompound(a, p);
477 }
478
479 private AnnotationType annotationType(Attribute.Compound a, Symbol s) {
480 Attribute.Compound atTarget =
481 a.type.tsym.attribute(syms.annotationTargetType.tsym);
482 if (atTarget == null) {
483 return inferTargetMetaInfo(a, s);
484 }
485 Attribute atValue = atTarget.member(names.value);
486 if (!(atValue instanceof Attribute.Array)) {
487 Assert.error("annotationType(): bad @Target argument " + atValue +
488 " (" + atValue.getClass() + ")");
489 return AnnotationType.DECLARATION; // error recovery
490 }
491 Attribute.Array arr = (Attribute.Array) atValue;
492 boolean isDecl = false, isType = false;
493 for (Attribute app : arr.values) {
494 if (!(app instanceof Attribute.Enum)) {
495 Assert.error("annotationType(): unrecognized Attribute kind " + app +
496 " (" + app.getClass() + ")");
497 isDecl = true;
498 continue;
499 }
500 Attribute.Enum e = (Attribute.Enum) app;
501 if (e.value.name == names.TYPE) {
502 if (s.kind == Kinds.TYP)
503 isDecl = true;
504 } else if (e.value.name == names.FIELD) {
505 if (s.kind == Kinds.VAR &&
506 s.owner.kind != Kinds.MTH)
507 isDecl = true;
508 } else if (e.value.name == names.METHOD) {
509 if (s.kind == Kinds.MTH &&
510 !s.isConstructor())
511 isDecl = true;
512 } else if (e.value.name == names.PARAMETER) {
513 if (s.kind == Kinds.VAR &&
514 s.owner.kind == Kinds.MTH &&
515 (s.flags() & Flags.PARAMETER) != 0)
516 isDecl = true;
517 } else if (e.value.name == names.CONSTRUCTOR) {
518 if (s.kind == Kinds.MTH &&
519 s.isConstructor())
520 isDecl = true;
521 } else if (e.value.name == names.LOCAL_VARIABLE) {
522 if (s.kind == Kinds.VAR &&
523 s.owner.kind == Kinds.MTH &&
524 (s.flags() & Flags.PARAMETER) == 0)
525 isDecl = true;
526 } else if (e.value.name == names.ANNOTATION_TYPE) {
527 if (s.kind == Kinds.TYP &&
528 (s.flags() & Flags.ANNOTATION) != 0)
529 isDecl = true;
530 } else if (e.value.name == names.PACKAGE) {
531 if (s.kind == Kinds.PCK)
532 isDecl = true;
533 } else if (e.value.name == names.TYPE_USE) {
534 if (s.kind == Kinds.TYP ||
535 s.kind == Kinds.VAR ||
536 (s.kind == Kinds.MTH && !s.isConstructor() &&
537 !s.type.getReturnType().hasTag(TypeTag.VOID)) ||
538 (s.kind == Kinds.MTH && s.isConstructor()))
539 isType = true;
540 } else if (e.value.name == names.TYPE_PARAMETER) {
541 /* Irrelevant in this case */
542 // TYPE_PARAMETER doesn't aid in distinguishing between
543 // Type annotations and declaration annotations on an
544 // Element
545 } else {
546 Assert.error("annotationType(): unrecognized Attribute name " + e.value.name +
547 " (" + e.value.name.getClass() + ")");
548 isDecl = true;
549 }
550 }
551 if (isDecl && isType) {
552 return AnnotationType.BOTH;
553 } else if (isType) {
554 return AnnotationType.TYPE;
555 } else {
556 return AnnotationType.DECLARATION;
557 }
558 }
559
560 /** Infer the target annotation kind, if none is give.
561 * We only infer declaration annotations.
562 */
563 private static AnnotationType inferTargetMetaInfo(Attribute.Compound a, Symbol s) {
564 return AnnotationType.DECLARATION;
565 }
566
567
568 /* This is the beginning of the second part of organizing
569 * type annotations: determine the type annotation positions.
570 */
571
572 private void resolveFrame(JCTree tree, JCTree frame,
573 List<JCTree> path, TypeAnnotationPosition p) {
574 /*
575 System.out.println("Resolving tree: " + tree + " kind: " + tree.getKind());
576 System.out.println(" Framing tree: " + frame + " kind: " + frame.getKind());
577 */
578 switch (frame.getKind()) {
579 case TYPE_CAST:
580 p.type = TargetType.CAST;
581 p.pos = frame.pos;
582 return;
583
584 case INSTANCE_OF:
585 p.type = TargetType.INSTANCEOF;
586 p.pos = frame.pos;
587 return;
588
589 case NEW_CLASS:
590 JCNewClass frameNewClass = (JCNewClass)frame;
591 if (frameNewClass.typeargs.contains(tree)) {
592 p.type = TargetType.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT;
593 p.type_index = frameNewClass.typeargs.indexOf(tree);
594 } else {
595 p.type = TargetType.NEW;
596 }
597 p.pos = frame.pos;
598 return;
599
600 case NEW_ARRAY:
601 p.type = TargetType.NEW;
602 p.pos = frame.pos;
603 return;
604
605 case ANNOTATION_TYPE:
606 case CLASS:
607 case ENUM:
608 case INTERFACE:
609 p.pos = frame.pos;
610 if (((JCClassDecl)frame).extending == tree) {
611 p.type = TargetType.CLASS_EXTENDS;
612 p.type_index = -1;
613 } else if (((JCClassDecl)frame).implementing.contains(tree)) {
614 p.type = TargetType.CLASS_EXTENDS;
615 p.type_index = ((JCClassDecl)frame).implementing.indexOf(tree);
616 } else if (((JCClassDecl)frame).typarams.contains(tree)) {
617 p.type = TargetType.CLASS_TYPE_PARAMETER;
618 p.parameter_index = ((JCClassDecl)frame).typarams.indexOf(tree);
619 } else {
620 Assert.error("Could not determine position of tree " + tree +
621 " within frame " + frame);
622 }
623 return;
624
625 case METHOD: {
626 JCMethodDecl frameMethod = (JCMethodDecl) frame;
627 p.pos = frame.pos;
628 if (frameMethod.thrown.contains(tree)) {
629 p.type = TargetType.THROWS;
630 p.type_index = frameMethod.thrown.indexOf(tree);
631 } else if (frameMethod.restype == tree) {
632 p.type = TargetType.METHOD_RETURN;
633 } else if (frameMethod.typarams.contains(tree)) {
634 p.type = TargetType.METHOD_TYPE_PARAMETER;
635 p.parameter_index = frameMethod.typarams.indexOf(tree);
636 } else {
637 Assert.error("Could not determine position of tree " + tree +
638 " within frame " + frame);
639 }
640 return;
641 }
642
643 case PARAMETERIZED_TYPE: {
644 if (((JCTypeApply)frame).clazz == tree) {
645 // generic: RAW; noop
646 } else if (((JCTypeApply)frame).arguments.contains(tree)) {
647 JCTypeApply taframe = (JCTypeApply) frame;
648 int arg = taframe.arguments.indexOf(tree);
649 p.location = p.location.prepend(new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg));
650
651 locateNestedTypes(taframe.type, p);
652 } else {
653 Assert.error("Could not determine type argument position of tree " + tree +
654 " within frame " + frame);
655 }
656
657 List<JCTree> newPath = path.tail;
658 resolveFrame(newPath.head, newPath.tail.head, newPath, p);
659 return;
660 }
661
662 case ARRAY_TYPE: {
663 ListBuffer<TypePathEntry> index = ListBuffer.lb();
664 index = index.append(TypePathEntry.ARRAY);
665 List<JCTree> newPath = path.tail;
666 while (true) {
667 JCTree npHead = newPath.tail.head;
668 if (npHead.hasTag(JCTree.Tag.TYPEARRAY)) {
669 newPath = newPath.tail;
670 index = index.append(TypePathEntry.ARRAY);
671 } else if (npHead.hasTag(JCTree.Tag.ANNOTATED_TYPE)) {
672 newPath = newPath.tail;
673 } else {
674 break;
675 }
676 }
677 p.location = p.location.prependList(index.toList());
678 resolveFrame(newPath.head, newPath.tail.head, newPath, p);
679 return;
680 }
681
682 case TYPE_PARAMETER:
683 if (path.tail.tail.head.hasTag(JCTree.Tag.CLASSDEF)) {
684 JCClassDecl clazz = (JCClassDecl)path.tail.tail.head;
685 p.type = TargetType.CLASS_TYPE_PARAMETER_BOUND;
686 p.parameter_index = clazz.typarams.indexOf(path.tail.head);
687 p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree);
688 if (((JCTypeParameter)frame).bounds.get(0).type.isInterface()) {
689 // Account for an implicit Object as bound 0
690 p.bound_index += 1;
691 }
692 } else if (path.tail.tail.head.hasTag(JCTree.Tag.METHODDEF)) {
693 JCMethodDecl method = (JCMethodDecl)path.tail.tail.head;
694 p.type = TargetType.METHOD_TYPE_PARAMETER_BOUND;
695 p.parameter_index = method.typarams.indexOf(path.tail.head);
696 p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree);
697 if (((JCTypeParameter)frame).bounds.get(0).type.isInterface()) {
698 // Account for an implicit Object as bound 0
699 p.bound_index += 1;
700 }
701 } else {
702 Assert.error("Could not determine position of tree " + tree +
703 " within frame " + frame);
704 }
705 p.pos = frame.pos;
706 return;
707
708 case VARIABLE:
709 VarSymbol v = ((JCVariableDecl)frame).sym;
710 p.pos = frame.pos;
711 switch (v.getKind()) {
712 case LOCAL_VARIABLE:
713 p.type = TargetType.LOCAL_VARIABLE;
714 break;
715 case FIELD:
716 p.type = TargetType.FIELD;
717 break;
718 case PARAMETER:
719 if (v.getQualifiedName().equals(names._this)) {
720 // TODO: Intro a separate ElementKind?
721 p.type = TargetType.METHOD_RECEIVER;
722 } else {
723 p.type = TargetType.METHOD_FORMAL_PARAMETER;
724 p.parameter_index = methodParamIndex(path, frame);
725 }
726 break;
727 case EXCEPTION_PARAMETER:
728 p.type = TargetType.EXCEPTION_PARAMETER;
729 break;
730 case RESOURCE_VARIABLE:
731 p.type = TargetType.RESOURCE_VARIABLE;
732 break;
733 default:
734 Assert.error("Found unexpected type annotation for variable: " + v + " with kind: " + v.getKind());
735 }
736 return;
737
738 case ANNOTATED_TYPE: {
739 if (frame == tree) {
740 // This is only true for the first annotated type we see.
741 // For any other annotated types along the path, we do
742 // not care about inner types.
743 JCAnnotatedType atypetree = (JCAnnotatedType) frame;
744 final Type utype = atypetree.underlyingType.type;
745 Symbol tsym = utype.tsym;
746 if (tsym.getKind().equals(ElementKind.TYPE_PARAMETER) ||
747 utype.getKind().equals(TypeKind.WILDCARD) ||
748 utype.getKind().equals(TypeKind.ARRAY)) {
749 // Type parameters, wildcards, and arrays have the declaring
750 // class/method as enclosing elements.
751 // There is actually nothing to do for them.
752 } else {
753 locateNestedTypes(utype, p);
754 }
755 }
756 List<JCTree> newPath = path.tail;
757 resolveFrame(newPath.head, newPath.tail.head, newPath, p);
758 return;
759 }
760
761 case UNION_TYPE: {
762 // TODO: can we store any information here to help in
763 // determining the final position?
764 List<JCTree> newPath = path.tail;
765 resolveFrame(newPath.head, newPath.tail.head, newPath, p);
766 return;
767 }
768
769 case METHOD_INVOCATION: {
770 JCMethodInvocation invocation = (JCMethodInvocation)frame;
771 if (!invocation.typeargs.contains(tree)) {
772 Assert.error("{" + tree + "} is not an argument in the invocation: " + invocation);
773 }
774 p.type = TargetType.METHOD_INVOCATION_TYPE_ARGUMENT;
775 p.pos = invocation.pos;
776 p.type_index = invocation.typeargs.indexOf(tree);
777 return;
778 }
779
780 case EXTENDS_WILDCARD:
781 case SUPER_WILDCARD: {
782 // Annotations in wildcard bounds
783 p.location = p.location.prepend(TypePathEntry.WILDCARD);
784 List<JCTree> newPath = path.tail;
785 resolveFrame(newPath.head, newPath.tail.head, newPath, p);
786 return;
787 }
788
789 case MEMBER_SELECT: {
790 List<JCTree> newPath = path.tail;
791 resolveFrame(newPath.head, newPath.tail.head, newPath, p);
792 return;
793 }
794
795 default:
796 Assert.error("Unresolved frame: " + frame + " of kind: " + frame.getKind() +
797 "\n Looking for tree: " + tree);
798 return;
799 }
800 }
801
802 private static void locateNestedTypes(Type type, TypeAnnotationPosition p) {
803 // The number of "steps" to get from the full type to the
804 // left-most outer type.
805 ListBuffer<TypePathEntry> depth = ListBuffer.lb();
806
807 Type encl = type.getEnclosingType();
808 while (encl != null &&
809 encl.getKind() != TypeKind.NONE &&
810 encl.getKind() != TypeKind.ERROR) {
811 depth = depth.append(TypePathEntry.INNER_TYPE);
812 encl = encl.getEnclosingType();
813 }
814 if (depth.nonEmpty()) {
815 p.location = p.location.prependList(depth.toList());
816 }
817 }
818
819 private static int methodParamIndex(List<JCTree> path, JCTree param) {
820 List<JCTree> curr = path;
821 while (curr.head.getTag() != Tag.METHODDEF) {
822 curr = curr.tail;
823 }
824 JCMethodDecl method = (JCMethodDecl)curr.head;
825 return method.params.indexOf(param);
826 }
827
828 // Each class (including enclosed inner classes) is visited separately.
829 // This flag is used to prevent from visiting inner classes.
830 private boolean isInClass = false;
831
832 @Override
833 public void visitClassDef(JCClassDecl tree) {
834 if (isInClass)
835 return;
836 isInClass = true;
837 if (sigOnly) {
838 scan(tree.mods);
839 scan(tree.typarams);
840 scan(tree.extending);
841 scan(tree.implementing);
842 }
843 scan(tree.defs);
844 }
845
846 /**
847 * Resolve declaration vs. type annotations in methods and
848 * then determine the positions.
849 */
850 @Override
851 public void visitMethodDef(final JCMethodDecl tree) {
852 if (tree.sym == null) {
853 // Something most be wrong, e.g. a class not found.
854 // Quietly ignore. (See test FailOver15.java)
855 return;
856 }
857 if (sigOnly) {
858 {
859 TypeAnnotationPosition pos = new TypeAnnotationPosition();
860 pos.type = TargetType.METHOD_RETURN;
861 if (tree.sym.isConstructor()) {
862 pos.pos = tree.pos;
863 // Use null to mark that the annotations go with the symbol.
864 separateAnnotationsKinds(tree, null, tree.sym, pos);
865 } else {
866 pos.pos = tree.restype.pos;
867 separateAnnotationsKinds(tree.restype, tree.sym.type.getReturnType(),
868 tree.sym, pos);
869 }
870 }
871 if (tree.recvparam != null && tree.recvparam.sym != null) {
872 // TODO: make sure there are no declaration annotations.
873 TypeAnnotationPosition pos = new TypeAnnotationPosition();
874 pos.type = TargetType.METHOD_RECEIVER;
875 pos.pos = tree.recvparam.vartype.pos;
876 separateAnnotationsKinds(tree.recvparam.vartype, tree.recvparam.sym.type,
877 tree.recvparam.sym, pos);
878 }
879 int i = 0;
880 for (JCVariableDecl param : tree.params) {
881 TypeAnnotationPosition pos = new TypeAnnotationPosition();
882 pos.type = TargetType.METHOD_FORMAL_PARAMETER;
883 pos.parameter_index = i;
884 pos.pos = param.vartype.pos;
885 separateAnnotationsKinds(param.vartype, param.sym.type, param.sym, pos);
886 ++i;
887 }
888 }
889
890 push(tree);
891 // super.visitMethodDef(tree);
892 if (sigOnly) {
893 scan(tree.mods);
894 scan(tree.restype);
895 scan(tree.typarams);
896 scan(tree.recvparam);
897 scan(tree.params);
898 scan(tree.thrown);
899 } else {
900 scan(tree.defaultValue);
901 scan(tree.body);
902 }
903 pop();
904 }
905
906 /**
907 * Resolve declaration vs. type annotations in variable declarations and
908 * then determine the positions.
909 */
910 @Override
911 public void visitVarDef(final JCVariableDecl tree) {
912 if (tree.sym == null) {
913 // Something is wrong already. Quietly ignore.
914 } else if (tree.sym.getKind() == ElementKind.FIELD) {
915 if (sigOnly) {
916 TypeAnnotationPosition pos = new TypeAnnotationPosition();
917 pos.type = TargetType.FIELD;
918 pos.pos = tree.pos;
919 separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
920 }
921 } else if (tree.sym.getKind() == ElementKind.LOCAL_VARIABLE) {
922 TypeAnnotationPosition pos = new TypeAnnotationPosition();
923 pos.type = TargetType.LOCAL_VARIABLE;
924 pos.pos = tree.pos;
925 separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
926 } else if (tree.sym.getKind() == ElementKind.EXCEPTION_PARAMETER) {
927 // System.out.println("Found exception param: " + tree);
928 TypeAnnotationPosition pos = new TypeAnnotationPosition();
929 pos.type = TargetType.EXCEPTION_PARAMETER;
930 pos.pos = tree.pos;
931 separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
932 } else if (tree.sym.getKind() == ElementKind.RESOURCE_VARIABLE) {
933 TypeAnnotationPosition pos = new TypeAnnotationPosition();
934 pos.type = TargetType.RESOURCE_VARIABLE;
935 pos.pos = tree.pos;
936 separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
937 } else {
938 // There is nothing else in a variable declaration that needs separation.
939 // System.out.println("We found a: " + tree);
940 }
941
942 push(tree);
943 // super.visitVarDef(tree);
944 scan(tree.mods);
945 scan(tree.vartype);
946 if (!sigOnly) {
947 scan(tree.init);
948 }
949 pop();
950 }
951
952 @Override
953 public void visitBlock(JCBlock tree) {
954 // Do not descend into top-level blocks when only interested
955 // in the signature.
956 if (!sigOnly) {
957 scan(tree.stats);
958 }
959 }
960
961 @Override
962 public void visitAnnotatedType(JCAnnotatedType tree) {
963 push(tree);
964 findPosition(tree, tree, tree.annotations);
965 pop();
966 super.visitAnnotatedType(tree);
967 }
968
969 @Override
970 public void visitTypeParameter(JCTypeParameter tree) {
971 findPosition(tree, peek2(), tree.annotations);
972 super.visitTypeParameter(tree);
973 }
974
975 @Override
976 public void visitNewArray(JCNewArray tree) {
977 findPosition(tree, tree, tree.annotations);
978 int dimAnnosCount = tree.dimAnnotations.size();
979 ListBuffer<TypePathEntry> depth = ListBuffer.lb();
980
981 // handle annotations associated with dimensions
982 for (int i = 0; i < dimAnnosCount; ++i) {
983 TypeAnnotationPosition p = new TypeAnnotationPosition();
984 p.pos = tree.pos;
985 p.type = TargetType.NEW;
986 if (i != 0) {
987 depth = depth.append(TypePathEntry.ARRAY);
988 p.location = p.location.appendList(depth.toList());
989 }
990
991 setTypeAnnotationPos(tree.dimAnnotations.get(i), p);
992 }
993
994 // handle "free" annotations
995 // int i = dimAnnosCount == 0 ? 0 : dimAnnosCount - 1;
996 // TODO: is depth.size == i here?
997 JCExpression elemType = tree.elemtype;
998 while (elemType != null) {
999 if (elemType.hasTag(JCTree.Tag.ANNOTATED_TYPE)) {
1000 JCAnnotatedType at = (JCAnnotatedType)elemType;
1001 TypeAnnotationPosition p = new TypeAnnotationPosition();
1002 p.type = TargetType.NEW;
1003 p.pos = tree.pos;
1004 p.location = p.location.appendList(depth.toList());
1005 setTypeAnnotationPos(at.annotations, p);
1006 elemType = at.underlyingType;
1007 } else if (elemType.hasTag(JCTree.Tag.TYPEARRAY)) {
1008 depth = depth.append(TypePathEntry.ARRAY);
1009 elemType = ((JCArrayTypeTree)elemType).elemtype;
1010 } else {
1011 break;
1012 }
1013 }
1014 scan(tree.elems);
1015 }
1016
1017 private void findPosition(JCTree tree, JCTree frame, List<JCAnnotation> annotations) {
1018 if (!annotations.isEmpty()) {
1019 /*
1020 System.out.println("Finding pos for: " + annotations);
1021 System.out.println(" tree: " + tree);
1022 System.out.println(" frame: " + frame);
1023 */
1024 TypeAnnotationPosition p = new TypeAnnotationPosition();
1025 resolveFrame(tree, frame, frames.toList(), p);
1026 setTypeAnnotationPos(annotations, p);
1027 }
1028 }
1029
1030 private static void setTypeAnnotationPos(List<JCAnnotation> annotations,
1031 TypeAnnotationPosition position) {
1032 for (JCAnnotation anno : annotations) {
1033 ((Attribute.TypeCompound) anno.attribute).position = position;
1034 }
1035 }
1036 }
1037 }

mercurial