Fri, 26 Jun 2009 18:51:39 -0700
6843077: JSR 308: Annotations on types
Reviewed-by: jjg, mcimadamore, darcy
Contributed-by: mernst@cs.washington.edu, mali@csail.mit.edu, mpapi@csail.mit.edu
1 /*
2 * Copyright 1999-2008 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
26 package com.sun.tools.javac.comp;
28 import java.util.*;
30 import javax.lang.model.element.ElementKind;
32 import com.sun.tools.javac.code.*;
33 import com.sun.tools.javac.code.Symbol.*;
34 import com.sun.tools.javac.tree.*;
35 import com.sun.tools.javac.tree.JCTree.*;
36 import com.sun.tools.javac.util.*;
37 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
38 import com.sun.tools.javac.util.List;
40 import static com.sun.tools.javac.code.Flags.*;
41 import static com.sun.tools.javac.code.Kinds.*;
42 import static com.sun.tools.javac.code.TypeTags.*;
44 /** This pass translates Generic Java to conventional Java.
45 *
46 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
47 * you write code that depends on this, you do so at your own risk.
48 * This code and its internal interfaces are subject to change or
49 * deletion without notice.</b>
50 */
51 public class TransTypes extends TreeTranslator {
52 /** The context key for the TransTypes phase. */
53 protected static final Context.Key<TransTypes> transTypesKey =
54 new Context.Key<TransTypes>();
56 /** Get the instance for this context. */
57 public static TransTypes instance(Context context) {
58 TransTypes instance = context.get(transTypesKey);
59 if (instance == null)
60 instance = new TransTypes(context);
61 return instance;
62 }
64 private boolean debugJSR308;
66 private Names names;
67 private Log log;
68 private Symtab syms;
69 private TreeMaker make;
70 private Enter enter;
71 private boolean allowEnums;
72 private Types types;
73 private final Resolve resolve;
75 /**
76 * Flag to indicate whether or not to generate bridge methods.
77 * For pre-Tiger source there is no need for bridge methods, so it
78 * can be skipped to get better performance for -source 1.4 etc.
79 */
80 private final boolean addBridges;
82 protected TransTypes(Context context) {
83 context.put(transTypesKey, this);
84 names = Names.instance(context);
85 log = Log.instance(context);
86 syms = Symtab.instance(context);
87 enter = Enter.instance(context);
88 overridden = new HashMap<MethodSymbol,MethodSymbol>();
89 Source source = Source.instance(context);
90 allowEnums = source.allowEnums();
91 addBridges = source.addBridges();
92 types = Types.instance(context);
93 make = TreeMaker.instance(context);
94 resolve = Resolve.instance(context);
95 debugJSR308 = Options.instance(context).get("TA:trans") != null;
96 }
98 /** A hashtable mapping bridge methods to the methods they override after
99 * type erasure.
100 */
101 Map<MethodSymbol,MethodSymbol> overridden;
103 /** Construct an attributed tree for a cast of expression to target type,
104 * unless it already has precisely that type.
105 * @param tree The expression tree.
106 * @param target The target type.
107 */
108 JCExpression cast(JCExpression tree, Type target) {
109 int oldpos = make.pos;
110 make.at(tree.pos);
111 if (!types.isSameType(tree.type, target)) {
112 if (!resolve.isAccessible(env, target.tsym))
113 resolve.logAccessError(env, tree, target);
114 tree = make.TypeCast(make.Type(target), tree).setType(target);
115 }
116 make.pos = oldpos;
117 return tree;
118 }
120 /** Construct an attributed tree to coerce an expression to some erased
121 * target type, unless the expression is already assignable to that type.
122 * If target type is a constant type, use its base type instead.
123 * @param tree The expression tree.
124 * @param target The target type.
125 */
126 JCExpression coerce(JCExpression tree, Type target) {
127 Type btarget = target.baseType();
128 if (tree.type.isPrimitive() == target.isPrimitive()) {
129 return types.isAssignable(tree.type, btarget, Warner.noWarnings)
130 ? tree
131 : cast(tree, btarget);
132 }
133 return tree;
134 }
136 /** Given an erased reference type, assume this type as the tree's type.
137 * Then, coerce to some given target type unless target type is null.
138 * This operation is used in situations like the following:
139 *
140 * class Cell<A> { A value; }
141 * ...
142 * Cell<Integer> cell;
143 * Integer x = cell.value;
144 *
145 * Since the erasure of Cell.value is Object, but the type
146 * of cell.value in the assignment is Integer, we need to
147 * adjust the original type of cell.value to Object, and insert
148 * a cast to Integer. That is, the last assignment becomes:
149 *
150 * Integer x = (Integer)cell.value;
151 *
152 * @param tree The expression tree whose type might need adjustment.
153 * @param erasedType The expression's type after erasure.
154 * @param target The target type, which is usually the erasure of the
155 * expression's original type.
156 */
157 JCExpression retype(JCExpression tree, Type erasedType, Type target) {
158 // System.err.println("retype " + tree + " to " + erasedType);//DEBUG
159 if (erasedType.tag > lastBaseTag) {
160 if (target != null && target.isPrimitive())
161 target = erasure(tree.type);
162 tree.type = erasedType;
163 if (target != null) return coerce(tree, target);
164 }
165 return tree;
166 }
168 /** Translate method argument list, casting each argument
169 * to its corresponding type in a list of target types.
170 * @param _args The method argument list.
171 * @param parameters The list of target types.
172 * @param varargsElement The erasure of the varargs element type,
173 * or null if translating a non-varargs invocation
174 */
175 <T extends JCTree> List<T> translateArgs(List<T> _args,
176 List<Type> parameters,
177 Type varargsElement) {
178 if (parameters.isEmpty()) return _args;
179 List<T> args = _args;
180 while (parameters.tail.nonEmpty()) {
181 args.head = translate(args.head, parameters.head);
182 args = args.tail;
183 parameters = parameters.tail;
184 }
185 Type parameter = parameters.head;
186 assert varargsElement != null || args.length() == 1;
187 if (varargsElement != null) {
188 while (args.nonEmpty()) {
189 args.head = translate(args.head, varargsElement);
190 args = args.tail;
191 }
192 } else {
193 args.head = translate(args.head, parameter);
194 }
195 return _args;
196 }
198 /** Add a bridge definition and enter corresponding method symbol in
199 * local scope of origin.
200 *
201 * @param pos The source code position to be used for the definition.
202 * @param meth The method for which a bridge needs to be added
203 * @param impl That method's implementation (possibly the method itself)
204 * @param origin The class to which the bridge will be added
205 * @param hypothetical
206 * True if the bridge method is not strictly necessary in the
207 * binary, but is represented in the symbol table to detect
208 * erasure clashes.
209 * @param bridges The list buffer to which the bridge will be added
210 */
211 void addBridge(DiagnosticPosition pos,
212 MethodSymbol meth,
213 MethodSymbol impl,
214 ClassSymbol origin,
215 boolean hypothetical,
216 ListBuffer<JCTree> bridges) {
217 make.at(pos);
218 Type origType = types.memberType(origin.type, meth);
219 Type origErasure = erasure(origType);
221 // Create a bridge method symbol and a bridge definition without a body.
222 Type bridgeType = meth.erasure(types);
223 long flags = impl.flags() & AccessFlags | SYNTHETIC | BRIDGE;
224 if (hypothetical) flags |= HYPOTHETICAL;
225 MethodSymbol bridge = new MethodSymbol(flags,
226 meth.name,
227 bridgeType,
228 origin);
229 if (!hypothetical) {
230 JCMethodDecl md = make.MethodDef(bridge, null);
232 // The bridge calls this.impl(..), if we have an implementation
233 // in the current class, super.impl(...) otherwise.
234 JCExpression receiver = (impl.owner == origin)
235 ? make.This(origin.erasure(types))
236 : make.Super(types.supertype(origin.type).tsym.erasure(types), origin);
238 // The type returned from the original method.
239 Type calltype = erasure(impl.type.getReturnType());
241 // Construct a call of this.impl(params), or super.impl(params),
242 // casting params and possibly results as needed.
243 JCExpression call =
244 make.Apply(
245 null,
246 make.Select(receiver, impl).setType(calltype),
247 translateArgs(make.Idents(md.params), origErasure.getParameterTypes(), null))
248 .setType(calltype);
249 JCStatement stat = (origErasure.getReturnType().tag == VOID)
250 ? make.Exec(call)
251 : make.Return(coerce(call, bridgeType.getReturnType()));
252 md.body = make.Block(0, List.of(stat));
254 // Add bridge to `bridges' buffer
255 bridges.append(md);
256 }
258 // Add bridge to scope of enclosing class and `overridden' table.
259 origin.members().enter(bridge);
260 overridden.put(bridge, meth);
261 }
263 /** Add bridge if given symbol is a non-private, non-static member
264 * of the given class, which is either defined in the class or non-final
265 * inherited, and one of the two following conditions holds:
266 * 1. The method's type changes in the given class, as compared to the
267 * class where the symbol was defined, (in this case
268 * we have extended a parameterized class with non-trivial parameters).
269 * 2. The method has an implementation with a different erased return type.
270 * (in this case we have used co-variant returns).
271 * If a bridge already exists in some other class, no new bridge is added.
272 * Instead, it is checked that the bridge symbol overrides the method symbol.
273 * (Spec ???).
274 * todo: what about bridges for privates???
275 *
276 * @param pos The source code position to be used for the definition.
277 * @param sym The symbol for which a bridge might have to be added.
278 * @param origin The class in which the bridge would go.
279 * @param bridges The list buffer to which the bridge would be added.
280 */
281 void addBridgeIfNeeded(DiagnosticPosition pos,
282 Symbol sym,
283 ClassSymbol origin,
284 ListBuffer<JCTree> bridges) {
285 if (sym.kind == MTH &&
286 sym.name != names.init &&
287 (sym.flags() & (PRIVATE | SYNTHETIC | STATIC)) == 0 &&
288 sym.isMemberOf(origin, types))
289 {
290 MethodSymbol meth = (MethodSymbol)sym;
291 MethodSymbol bridge = meth.binaryImplementation(origin, types);
292 MethodSymbol impl = meth.implementation(origin, types, true);
293 if (bridge == null ||
294 bridge == meth ||
295 (impl != null && !bridge.owner.isSubClass(impl.owner, types))) {
296 // No bridge was added yet.
297 if (impl != null && isBridgeNeeded(meth, impl, origin.type)) {
298 addBridge(pos, meth, impl, origin, bridge==impl, bridges);
299 } else if (impl == meth
300 && impl.owner != origin
301 && (impl.flags() & FINAL) == 0
302 && (meth.flags() & (ABSTRACT|PUBLIC)) == PUBLIC
303 && (origin.flags() & PUBLIC) > (impl.owner.flags() & PUBLIC)) {
304 // this is to work around a horrible but permanent
305 // reflection design error.
306 addBridge(pos, meth, impl, origin, false, bridges);
307 }
308 } else if ((bridge.flags() & SYNTHETIC) != 0) {
309 MethodSymbol other = overridden.get(bridge);
310 if (other != null && other != meth) {
311 if (impl == null || !impl.overrides(other, origin, types, true)) {
312 // Bridge for other symbol pair was added
313 log.error(pos, "name.clash.same.erasure.no.override",
314 other, other.location(origin.type, types),
315 meth, meth.location(origin.type, types));
316 }
317 }
318 } else if (!bridge.overrides(meth, origin, types, true)) {
319 // Accidental binary override without source override.
320 if (bridge.owner == origin ||
321 types.asSuper(bridge.owner.type, meth.owner) == null)
322 // Don't diagnose the problem if it would already
323 // have been reported in the superclass
324 log.error(pos, "name.clash.same.erasure.no.override",
325 bridge, bridge.location(origin.type, types),
326 meth, meth.location(origin.type, types));
327 }
328 }
329 }
330 // where
331 /**
332 * @param method The symbol for which a bridge might have to be added
333 * @param impl The implementation of method
334 * @param dest The type in which the bridge would go
335 */
336 private boolean isBridgeNeeded(MethodSymbol method,
337 MethodSymbol impl,
338 Type dest) {
339 if (impl != method) {
340 // If either method or impl have different erasures as
341 // members of dest, a bridge is needed.
342 Type method_erasure = method.erasure(types);
343 if (!isSameMemberWhenErased(dest, method, method_erasure))
344 return true;
345 Type impl_erasure = impl.erasure(types);
346 if (!isSameMemberWhenErased(dest, impl, impl_erasure))
347 return true;
349 // If the erasure of the return type is different, a
350 // bridge is needed.
351 return !types.isSameType(impl_erasure.getReturnType(),
352 method_erasure.getReturnType());
353 } else {
354 // method and impl are the same...
355 if ((method.flags() & ABSTRACT) != 0) {
356 // ...and abstract so a bridge is not needed.
357 // Concrete subclasses will bridge as needed.
358 return false;
359 }
361 // The erasure of the return type is always the same
362 // for the same symbol. Reducing the three tests in
363 // the other branch to just one:
364 return !isSameMemberWhenErased(dest, method, method.erasure(types));
365 }
366 }
367 /**
368 * Lookup the method as a member of the type. Compare the
369 * erasures.
370 * @param type the class where to look for the method
371 * @param method the method to look for in class
372 * @param erasure the erasure of method
373 */
374 private boolean isSameMemberWhenErased(Type type,
375 MethodSymbol method,
376 Type erasure) {
377 return types.isSameType(erasure(types.memberType(type, method)),
378 erasure);
379 }
381 void addBridges(DiagnosticPosition pos,
382 TypeSymbol i,
383 ClassSymbol origin,
384 ListBuffer<JCTree> bridges) {
385 for (Scope.Entry e = i.members().elems; e != null; e = e.sibling)
386 addBridgeIfNeeded(pos, e.sym, origin, bridges);
387 for (List<Type> l = types.interfaces(i.type); l.nonEmpty(); l = l.tail)
388 addBridges(pos, l.head.tsym, origin, bridges);
389 }
391 /** Add all necessary bridges to some class appending them to list buffer.
392 * @param pos The source code position to be used for the bridges.
393 * @param origin The class in which the bridges go.
394 * @param bridges The list buffer to which the bridges are added.
395 */
396 void addBridges(DiagnosticPosition pos, ClassSymbol origin, ListBuffer<JCTree> bridges) {
397 Type st = types.supertype(origin.type);
398 while (st.tag == CLASS) {
399 // if (isSpecialization(st))
400 addBridges(pos, st.tsym, origin, bridges);
401 st = types.supertype(st);
402 }
403 for (List<Type> l = types.interfaces(origin.type); l.nonEmpty(); l = l.tail)
404 // if (isSpecialization(l.head))
405 addBridges(pos, l.head.tsym, origin, bridges);
406 }
408 /* ************************************************************************
409 * Visitor methods
410 *************************************************************************/
412 /** Visitor argument: proto-type.
413 */
414 private Type pt;
416 /** Visitor method: perform a type translation on tree.
417 */
418 public <T extends JCTree> T translate(T tree, Type pt) {
419 Type prevPt = this.pt;
420 try {
421 this.pt = pt;
422 return translate(tree);
423 } finally {
424 this.pt = prevPt;
425 }
426 }
428 /** Visitor method: perform a type translation on list of trees.
429 */
430 public <T extends JCTree> List<T> translate(List<T> trees, Type pt) {
431 Type prevPt = this.pt;
432 List<T> res;
433 try {
434 this.pt = pt;
435 res = translate(trees);
436 } finally {
437 this.pt = prevPt;
438 }
439 return res;
440 }
442 public void visitClassDef(JCClassDecl tree) {
443 new TypeAnnotationPositions().scan(tree);
444 new TypeAnnotationLift().scan(tree);
445 translateClass(tree.sym);
446 result = tree;
447 }
449 JCMethodDecl currentMethod = null;
450 public void visitMethodDef(JCMethodDecl tree) {
451 tree.sym.typeAnnotations = tree.sym.typeAnnotations;
452 JCMethodDecl previousMethod = currentMethod;
453 try {
454 currentMethod = tree;
455 tree.restype = translate(tree.restype, null);
456 tree.typarams = List.nil();
457 tree.params = translateVarDefs(tree.params);
458 tree.thrown = translate(tree.thrown, null);
459 tree.body = translate(tree.body, tree.sym.erasure(types).getReturnType());
460 tree.type = erasure(tree.type);
461 result = tree;
462 } finally {
463 currentMethod = previousMethod;
464 }
466 // Check that we do not introduce a name clash by erasing types.
467 for (Scope.Entry e = tree.sym.owner.members().lookup(tree.name);
468 e.sym != null;
469 e = e.next()) {
470 if (e.sym != tree.sym &&
471 types.isSameType(erasure(e.sym.type), tree.type)) {
472 log.error(tree.pos(),
473 "name.clash.same.erasure", tree.sym,
474 e.sym);
475 return;
476 }
477 }
478 }
480 public void visitVarDef(JCVariableDecl tree) {
481 tree.vartype = translate(tree.vartype, null);
482 tree.init = translate(tree.init, tree.sym.erasure(types));
483 tree.type = erasure(tree.type);
484 result = tree;
485 }
487 public void visitDoLoop(JCDoWhileLoop tree) {
488 tree.body = translate(tree.body);
489 tree.cond = translate(tree.cond, syms.booleanType);
490 result = tree;
491 }
493 public void visitWhileLoop(JCWhileLoop tree) {
494 tree.cond = translate(tree.cond, syms.booleanType);
495 tree.body = translate(tree.body);
496 result = tree;
497 }
499 public void visitForLoop(JCForLoop tree) {
500 tree.init = translate(tree.init, null);
501 if (tree.cond != null)
502 tree.cond = translate(tree.cond, syms.booleanType);
503 tree.step = translate(tree.step, null);
504 tree.body = translate(tree.body);
505 result = tree;
506 }
508 public void visitForeachLoop(JCEnhancedForLoop tree) {
509 tree.var = translate(tree.var, null);
510 Type iterableType = tree.expr.type;
511 tree.expr = translate(tree.expr, erasure(tree.expr.type));
512 if (types.elemtype(tree.expr.type) == null)
513 tree.expr.type = iterableType; // preserve type for Lower
514 tree.body = translate(tree.body);
515 result = tree;
516 }
518 public void visitSwitch(JCSwitch tree) {
519 Type selsuper = types.supertype(tree.selector.type);
520 boolean enumSwitch = selsuper != null &&
521 selsuper.tsym == syms.enumSym;
522 Type target = enumSwitch ? erasure(tree.selector.type) : syms.intType;
523 tree.selector = translate(tree.selector, target);
524 tree.cases = translateCases(tree.cases);
525 result = tree;
526 }
528 public void visitCase(JCCase tree) {
529 tree.pat = translate(tree.pat, null);
530 tree.stats = translate(tree.stats);
531 result = tree;
532 }
534 public void visitSynchronized(JCSynchronized tree) {
535 tree.lock = translate(tree.lock, erasure(tree.lock.type));
536 tree.body = translate(tree.body);
537 result = tree;
538 }
540 public void visitConditional(JCConditional tree) {
541 tree.cond = translate(tree.cond, syms.booleanType);
542 tree.truepart = translate(tree.truepart, erasure(tree.type));
543 tree.falsepart = translate(tree.falsepart, erasure(tree.type));
544 tree.type = erasure(tree.type);
545 result = retype(tree, tree.type, pt);
546 }
548 public void visitIf(JCIf tree) {
549 tree.cond = translate(tree.cond, syms.booleanType);
550 tree.thenpart = translate(tree.thenpart);
551 tree.elsepart = translate(tree.elsepart);
552 result = tree;
553 }
555 public void visitExec(JCExpressionStatement tree) {
556 tree.expr = translate(tree.expr, null);
557 result = tree;
558 }
560 public void visitReturn(JCReturn tree) {
561 tree.expr = translate(tree.expr, currentMethod.sym.erasure(types).getReturnType());
562 result = tree;
563 }
565 public void visitThrow(JCThrow tree) {
566 tree.expr = translate(tree.expr, erasure(tree.expr.type));
567 result = tree;
568 }
570 public void visitAssert(JCAssert tree) {
571 tree.cond = translate(tree.cond, syms.booleanType);
572 if (tree.detail != null)
573 tree.detail = translate(tree.detail, erasure(tree.detail.type));
574 result = tree;
575 }
577 public void visitApply(JCMethodInvocation tree) {
578 tree.meth = translate(tree.meth, null);
579 Symbol meth = TreeInfo.symbol(tree.meth);
580 Type mt = meth.erasure(types);
581 List<Type> argtypes = mt.getParameterTypes();
582 if (allowEnums &&
583 meth.name==names.init &&
584 meth.owner == syms.enumSym)
585 argtypes = argtypes.tail.tail;
586 if (tree.varargsElement != null)
587 tree.varargsElement = types.erasure(tree.varargsElement);
588 else
589 assert tree.args.length() == argtypes.length();
590 tree.args = translateArgs(tree.args, argtypes, tree.varargsElement);
592 // Insert casts of method invocation results as needed.
593 result = retype(tree, mt.getReturnType(), pt);
594 }
596 public void visitNewClass(JCNewClass tree) {
597 if (tree.encl != null)
598 tree.encl = translate(tree.encl, erasure(tree.encl.type));
599 tree.clazz = translate(tree.clazz, null);
600 if (tree.varargsElement != null)
601 tree.varargsElement = types.erasure(tree.varargsElement);
602 tree.args = translateArgs(
603 tree.args, tree.constructor.erasure(types).getParameterTypes(), tree.varargsElement);
604 tree.def = translate(tree.def, null);
605 tree.type = erasure(tree.type);
606 result = tree;
607 }
609 public void visitNewArray(JCNewArray tree) {
610 tree.elemtype = translate(tree.elemtype, null);
611 translate(tree.dims, syms.intType);
612 tree.elems = translate(tree.elems,
613 (tree.type == null) ? null
614 : erasure(types.elemtype(tree.type)));
615 tree.type = erasure(tree.type);
617 result = tree;
618 }
620 public void visitParens(JCParens tree) {
621 tree.expr = translate(tree.expr, pt);
622 tree.type = erasure(tree.type);
623 result = tree;
624 }
626 public void visitAssign(JCAssign tree) {
627 tree.lhs = translate(tree.lhs, null);
628 tree.rhs = translate(tree.rhs, erasure(tree.lhs.type));
629 tree.type = erasure(tree.type);
630 result = tree;
631 }
633 public void visitAssignop(JCAssignOp tree) {
634 tree.lhs = translate(tree.lhs, tree.operator.type.getParameterTypes().head);
635 tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head);
636 tree.type = erasure(tree.type);
637 result = tree;
638 }
640 public void visitUnary(JCUnary tree) {
641 tree.arg = translate(tree.arg, tree.operator.type.getParameterTypes().head);
642 result = tree;
643 }
645 public void visitBinary(JCBinary tree) {
646 tree.lhs = translate(tree.lhs, tree.operator.type.getParameterTypes().head);
647 tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head);
648 result = tree;
649 }
651 public void visitTypeCast(JCTypeCast tree) {
652 tree.clazz = translate(tree.clazz, null);
653 tree.type = erasure(tree.type);
654 tree.expr = translate(tree.expr, tree.type);
655 result = tree;
656 }
658 public void visitTypeTest(JCInstanceOf tree) {
659 tree.expr = translate(tree.expr, null);
660 tree.clazz = translate(tree.clazz, null);
661 result = tree;
662 }
664 public void visitIndexed(JCArrayAccess tree) {
665 tree.indexed = translate(tree.indexed, erasure(tree.indexed.type));
666 tree.index = translate(tree.index, syms.intType);
668 // Insert casts of indexed expressions as needed.
669 result = retype(tree, types.elemtype(tree.indexed.type), pt);
670 }
672 // There ought to be nothing to rewrite here;
673 // we don't generate code.
674 public void visitAnnotation(JCAnnotation tree) {
675 result = tree;
676 }
678 public void visitIdent(JCIdent tree) {
679 Type et = tree.sym.erasure(types);
681 // Map type variables to their bounds.
682 if (tree.sym.kind == TYP && tree.sym.type.tag == TYPEVAR) {
683 result = make.at(tree.pos).Type(et);
684 } else
685 // Map constants expressions to themselves.
686 if (tree.type.constValue() != null) {
687 result = tree;
688 }
689 // Insert casts of variable uses as needed.
690 else if (tree.sym.kind == VAR) {
691 result = retype(tree, et, pt);
692 }
693 else {
694 tree.type = erasure(tree.type);
695 result = tree;
696 }
697 }
699 public void visitSelect(JCFieldAccess tree) {
700 Type t = tree.selected.type;
701 while (t.tag == TYPEVAR)
702 t = t.getUpperBound();
703 if (t.isCompound()) {
704 if ((tree.sym.flags() & IPROXY) != 0) {
705 tree.sym = ((MethodSymbol)tree.sym).
706 implemented((TypeSymbol)tree.sym.owner, types);
707 }
708 tree.selected = cast(
709 translate(tree.selected, erasure(tree.selected.type)),
710 erasure(tree.sym.owner.type));
711 } else
712 tree.selected = translate(tree.selected, erasure(t));
714 // Map constants expressions to themselves.
715 if (tree.type.constValue() != null) {
716 result = tree;
717 }
718 // Insert casts of variable uses as needed.
719 else if (tree.sym.kind == VAR) {
720 result = retype(tree, tree.sym.erasure(types), pt);
721 }
722 else {
723 tree.type = erasure(tree.type);
724 result = tree;
725 }
726 }
728 public void visitTypeArray(JCArrayTypeTree tree) {
729 tree.elemtype = translate(tree.elemtype, null);
730 tree.type = erasure(tree.type);
731 result = tree;
732 }
734 /** Visitor method for parameterized types.
735 */
736 public void visitTypeApply(JCTypeApply tree) {
737 JCTree clazz = translate(tree.clazz, null);
738 result = clazz;
739 }
741 /**************************************************************************
742 * utility methods
743 *************************************************************************/
745 private Type erasure(Type t) {
746 return types.erasure(t);
747 }
749 /**************************************************************************
750 * main method
751 *************************************************************************/
753 private Env<AttrContext> env;
755 void translateClass(ClassSymbol c) {
756 Type st = types.supertype(c.type);
758 // process superclass before derived
759 if (st.tag == CLASS)
760 translateClass((ClassSymbol)st.tsym);
762 Env<AttrContext> myEnv = enter.typeEnvs.remove(c);
763 if (myEnv == null)
764 return;
765 Env<AttrContext> oldEnv = env;
766 try {
767 env = myEnv;
768 // class has not been translated yet
770 TreeMaker savedMake = make;
771 Type savedPt = pt;
772 make = make.forToplevel(env.toplevel);
773 pt = null;
774 try {
775 JCClassDecl tree = (JCClassDecl) env.tree;
776 tree.typarams = List.nil();
777 super.visitClassDef(tree);
778 make.at(tree.pos);
779 if (addBridges) {
780 ListBuffer<JCTree> bridges = new ListBuffer<JCTree>();
781 if ((tree.sym.flags() & INTERFACE) == 0)
782 addBridges(tree.pos(), tree.sym, bridges);
783 tree.defs = bridges.toList().prependList(tree.defs);
784 }
785 tree.type = erasure(tree.type);
786 } finally {
787 make = savedMake;
788 pt = savedPt;
789 }
790 } finally {
791 env = oldEnv;
792 }
793 }
795 /** Translate a toplevel class definition.
796 * @param cdef The definition to be translated.
797 */
798 public JCTree translateTopLevelClass(JCTree cdef, TreeMaker make) {
799 // note that this method does NOT support recursion.
800 this.make = make;
801 pt = null;
802 return translate(cdef, null);
803 }
805 private class TypeAnnotationPositions extends TreeScanner {
807 private ListBuffer<JCTree> frames = ListBuffer.lb();
808 private void push(JCTree t) { frames = frames.prepend(t); }
809 private JCTree pop() { return frames.next(); }
810 private JCTree peek() { return frames.first(); }
811 private JCTree peek2() { return frames.toList().tail.head; }
813 @Override
814 public void scan(JCTree tree) {
815 push(tree);
816 super.scan(tree);
817 pop();
818 }
820 private TypeAnnotationPosition resolveFrame(JCTree tree, JCTree frame,
821 List<JCTree> path, TypeAnnotationPosition p) {
822 switch (frame.getKind()) {
823 case TYPE_CAST:
824 p.type = TargetType.TYPECAST;
825 p.pos = frame.pos;
826 return p;
828 case INSTANCE_OF:
829 p.type = TargetType.INSTANCEOF;
830 p.pos = frame.pos;
831 return p;
833 case NEW_CLASS:
834 p.type = TargetType.NEW;
835 p.pos = frame.pos;
836 return p;
838 case NEW_ARRAY:
839 p.type = TargetType.NEW;
840 p.pos = frame.pos;
841 return p;
843 case CLASS:
844 p.pos = frame.pos;
845 if (((JCClassDecl)frame).extending == tree) {
846 p.type = TargetType.CLASS_EXTENDS;
847 p.type_index = -1;
848 } else if (((JCClassDecl)frame).implementing.contains(tree)) {
849 p.type = TargetType.CLASS_EXTENDS;
850 p.type_index = ((JCClassDecl)frame).implementing.indexOf(tree);
851 } else if (((JCClassDecl)frame).typarams.contains(tree)) {
852 p.type = TargetType.CLASS_TYPE_PARAMETER;
853 p.parameter_index = ((JCClassDecl)frame).typarams.indexOf(tree);
854 } else
855 throw new AssertionError();
856 return p;
858 case METHOD: {
859 JCMethodDecl frameMethod = (JCMethodDecl)frame;
860 p.pos = frame.pos;
861 if (frameMethod.receiverAnnotations.contains(tree))
862 p.type = TargetType.METHOD_RECEIVER;
863 else if (frameMethod.thrown.contains(tree)) {
864 p.type = TargetType.THROWS;
865 p.type_index = frameMethod.thrown.indexOf(tree);
866 } else if (((JCMethodDecl)frame).restype == tree) {
867 p.type = TargetType.METHOD_RETURN_GENERIC_OR_ARRAY;
868 } else if (frameMethod.typarams.contains(tree)) {
869 p.type = TargetType.METHOD_TYPE_PARAMETER;
870 p.parameter_index = frameMethod.typarams.indexOf(tree);
871 } else
872 throw new AssertionError();
873 return p;
874 }
875 case MEMBER_SELECT: {
876 JCFieldAccess fieldFrame = (JCFieldAccess)frame;
877 if (fieldFrame.name == names._class) {
878 p.type = TargetType.CLASS_LITERAL;
879 if (fieldFrame.selected instanceof JCAnnotatedType) {
880 p.pos = TreeInfo.typeIn(fieldFrame).pos;
881 } else if (fieldFrame.selected instanceof JCArrayTypeTree) {
882 p.pos = fieldFrame.selected.pos;
883 }
884 } else
885 throw new AssertionError();
886 return p;
887 }
888 case PARAMETERIZED_TYPE: {
889 TypeAnnotationPosition nextP;
890 if (((JCTypeApply)frame).clazz == tree)
891 nextP = p; // generic: RAW; noop
892 else if (((JCTypeApply)frame).arguments.contains(tree))
893 p.location = p.location.prepend(
894 ((JCTypeApply)frame).arguments.indexOf(tree));
895 else
896 throw new AssertionError();
898 List<JCTree> newPath = path.tail;
899 return resolveFrame(newPath.head, newPath.tail.head, newPath, p);
900 }
902 case ARRAY_TYPE: {
903 p.location = p.location.prepend(0);
904 List<JCTree> newPath = path.tail;
905 return resolveFrame(newPath.head, newPath.tail.head, newPath, p);
906 }
908 case TYPE_PARAMETER:
909 if (path.tail.tail.head.getTag() == JCTree.CLASSDEF) {
910 JCClassDecl clazz = (JCClassDecl)path.tail.tail.head;
911 p.type = TargetType.CLASS_TYPE_PARAMETER_BOUND;
912 p.parameter_index = clazz.typarams.indexOf(path.tail.head);
913 p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree);
914 } else if (path.tail.tail.head.getTag() == JCTree.METHODDEF) {
915 JCMethodDecl method = (JCMethodDecl)path.tail.tail.head;
916 p.type = TargetType.METHOD_TYPE_PARAMETER_BOUND;
917 p.parameter_index = method.typarams.indexOf(path.tail.head);
918 p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree);
919 } else
920 throw new AssertionError();
921 p.pos = frame.pos;
922 return p;
924 case VARIABLE:
925 VarSymbol v = ((JCVariableDecl)frame).sym;
926 p.pos = frame.pos;
927 switch (v.getKind()) {
928 case LOCAL_VARIABLE:
929 p.type = TargetType.LOCAL_VARIABLE; break;
930 case FIELD:
931 p.type = TargetType.FIELD_GENERIC_OR_ARRAY; break;
932 case PARAMETER:
933 p.type = TargetType.METHOD_PARAMETER_GENERIC_OR_ARRAY;
934 p.parameter_index = methodParamIndex(path, frame);
935 break;
936 default: throw new AssertionError();
937 }
938 return p;
940 case ANNOTATED_TYPE: {
941 List<JCTree> newPath = path.tail;
942 return resolveFrame(newPath.head, newPath.tail.head,
943 newPath, p);
944 }
946 case METHOD_INVOCATION: {
947 JCMethodInvocation invocation = (JCMethodInvocation)frame;
948 if (!invocation.typeargs.contains(tree))
949 throw new AssertionError("{" + tree + "} is not an argument in the invocation: " + invocation);
950 p.type = TargetType.METHOD_TYPE_ARGUMENT;
951 p.pos = invocation.pos;
952 p.type_index = invocation.typeargs.indexOf(tree);
953 return p;
954 }
956 case EXTENDS_WILDCARD:
957 case SUPER_WILDCARD: {
958 p.type = TargetType.WILDCARD_BOUND;
959 List<JCTree> newPath = path.tail;
961 TypeAnnotationPosition wildcard =
962 resolveFrame(newPath.head, newPath.tail.head, newPath,
963 new TypeAnnotationPosition());
964 if (!wildcard.location.isEmpty())
965 wildcard.type = wildcard.type.getGenericComplement();
966 p.wildcard_position = wildcard;
967 p.pos = frame.pos;
968 return p;
969 }
970 }
971 return p;
972 }
974 @Override
975 public void visitApply(JCMethodInvocation tree) {
976 scan(tree.meth);
977 scan(tree.typeargs);
978 scan(tree.args);
979 }
981 private void setTypeAnnotationPos(List<JCTypeAnnotation> annotations, TypeAnnotationPosition position) {
982 for (JCTypeAnnotation anno : annotations) {
983 anno.annotation_position = position;
984 anno.attribute_field.position = position;
985 }
986 }
988 @Override
989 public void visitNewArray(JCNewArray tree) {
990 findPosition(tree, tree, tree.annotations);
991 int dimAnnosCount = tree.dimAnnotations.size();
993 // handle annotations associated with dimentions
994 for (int i = 0; i < dimAnnosCount; ++i) {
995 TypeAnnotationPosition p = new TypeAnnotationPosition();
996 p.type = TargetType.NEW_GENERIC_OR_ARRAY;
997 p.pos = tree.pos;
998 p.location = p.location.append(i);
999 setTypeAnnotationPos(tree.dimAnnotations.get(i), p);
1000 }
1002 // handle "free" annotations
1003 int i = dimAnnosCount == 0 ? 0 : dimAnnosCount - 1;
1004 JCExpression elemType = tree.elemtype;
1005 while (elemType != null) {
1006 if (elemType.getTag() == JCTree.ANNOTATED_TYPE) {
1007 JCAnnotatedType at = (JCAnnotatedType)elemType;
1008 TypeAnnotationPosition p = new TypeAnnotationPosition();
1009 p.type = TargetType.NEW_GENERIC_OR_ARRAY;
1010 p.pos = tree.pos;
1011 p.location = p.location.append(i);
1012 setTypeAnnotationPos(at.annotations, p);
1013 elemType = at.underlyingType;
1014 } else if (elemType.getTag() == JCTree.TYPEARRAY) {
1015 ++i;
1016 elemType = ((JCArrayTypeTree)elemType).elemtype;
1017 } else
1018 break;
1019 }
1021 // find annotations locations of initializer elements
1022 scan(tree.elems);
1023 }
1025 @Override
1026 public void visitAnnotatedType(JCAnnotatedType tree) {
1027 findPosition(tree, peek2(), tree.annotations);
1028 super.visitAnnotatedType(tree);
1029 }
1031 @Override
1032 public void visitMethodDef(JCMethodDecl tree) {
1033 TypeAnnotationPosition p = new TypeAnnotationPosition();
1034 p.type = TargetType.METHOD_RECEIVER;
1035 setTypeAnnotationPos(tree.receiverAnnotations, p);
1036 super.visitMethodDef(tree);
1037 }
1038 @Override
1039 public void visitTypeParameter(JCTypeParameter tree) {
1040 findPosition(tree, peek2(), tree.annotations);
1041 super.visitTypeParameter(tree);
1042 }
1044 void findPosition(JCTree tree, JCTree frame, List<JCTypeAnnotation> annotations) {
1045 if (!annotations.isEmpty()) {
1046 TypeAnnotationPosition p =
1047 resolveFrame(tree, frame, frames.toList(),
1048 new TypeAnnotationPosition());
1049 if (!p.location.isEmpty())
1050 p.type = p.type.getGenericComplement();
1051 setTypeAnnotationPos(annotations, p);
1052 if (debugJSR308) {
1053 System.out.println("trans: " + tree);
1054 System.out.println(" target: " + p);
1055 }
1056 }
1057 }
1059 private int methodParamIndex(List<JCTree> path, JCTree param) {
1060 List<JCTree> curr = path;
1061 if (curr.head != param)
1062 curr = path.tail;
1063 JCMethodDecl method = (JCMethodDecl)curr.tail.head;
1064 return method.params.indexOf(param);
1065 }
1066 }
1068 private class TypeAnnotationLift extends TreeScanner {
1069 List<Attribute.TypeCompound> recordedTypeAnnotations = List.nil();
1071 boolean isInner = false;
1072 @Override
1073 public void visitClassDef(JCClassDecl tree) {
1074 if (isInner) {
1075 // tree is an inner class tree. stop now.
1076 // TransTypes.visitClassDef makes an invocation for each class
1077 // seperately.
1078 return;
1079 }
1080 isInner = true;
1081 List<Attribute.TypeCompound> prevTAs = recordedTypeAnnotations;
1082 recordedTypeAnnotations = List.nil();
1083 try {
1084 super.visitClassDef(tree);
1085 } finally {
1086 tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations);
1087 recordedTypeAnnotations = prevTAs;
1088 }
1089 }
1091 @Override
1092 public void visitMethodDef(JCMethodDecl tree) {
1093 List<Attribute.TypeCompound> prevTAs = recordedTypeAnnotations;
1094 recordedTypeAnnotations = List.nil();
1095 try {
1096 super.visitMethodDef(tree);
1097 } finally {
1098 tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations);
1099 recordedTypeAnnotations = prevTAs;
1100 }
1101 }
1103 @Override
1104 public void visitVarDef(JCVariableDecl tree) {
1105 List<Attribute.TypeCompound> prevTAs = recordedTypeAnnotations;
1106 recordedTypeAnnotations = List.nil();
1107 ElementKind kind = tree.sym.getKind();
1108 if (kind == ElementKind.LOCAL_VARIABLE && tree.mods.annotations.nonEmpty()) {
1109 // need to lift the annotations
1110 TypeAnnotationPosition position = new TypeAnnotationPosition();
1111 position.pos = tree.pos;
1112 position.type = TargetType.LOCAL_VARIABLE;
1113 for (Attribute.Compound attribute : tree.sym.attributes_field) {
1114 Attribute.TypeCompound tc =
1115 new Attribute.TypeCompound(attribute.type, attribute.values, position);
1116 recordedTypeAnnotations = recordedTypeAnnotations.append(tc);
1117 }
1118 }
1119 try {
1120 super.visitVarDef(tree);
1121 } finally {
1122 if (kind.isField() || kind == ElementKind.LOCAL_VARIABLE)
1123 tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations);
1124 recordedTypeAnnotations = kind.isField() ? prevTAs : prevTAs.appendList(recordedTypeAnnotations);
1125 }
1126 }
1128 @Override
1129 public void visitApply(JCMethodInvocation tree) {
1130 scan(tree.meth);
1131 scan(tree.typeargs);
1132 scan(tree.args);
1133 }
1135 public void visitAnnotation(JCAnnotation tree) {
1136 if (tree instanceof JCTypeAnnotation)
1137 recordedTypeAnnotations = recordedTypeAnnotations.append(((JCTypeAnnotation)tree).attribute_field);
1138 super.visitAnnotation(tree);
1139 }
1140 }
1142 }