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

Thu, 04 Feb 2010 10:14:28 -0800

author
jjg
date
Thu, 04 Feb 2010 10:14:28 -0800
changeset 489
4b4e282a3146
parent 484
732510cc3538
child 554
9d9f26857129
permissions
-rw-r--r--

6923080: TreeScanner.visitNewClass should scan tree.typeargs
Reviewed-by: darcy

jjg@477 1 /*
jjg@477 2 * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
jjg@477 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jjg@477 4 *
jjg@477 5 * This code is free software; you can redistribute it and/or modify it
jjg@477 6 * under the terms of the GNU General Public License version 2 only, as
jjg@477 7 * published by the Free Software Foundation. Sun designates this
jjg@477 8 * particular file as subject to the "Classpath" exception as provided
jjg@477 9 * by Sun in the LICENSE file that accompanied this code.
jjg@477 10 *
jjg@477 11 * This code is distributed in the hope that it will be useful, but WITHOUT
jjg@477 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jjg@477 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jjg@477 14 * version 2 for more details (a copy is included in the LICENSE file that
jjg@477 15 * accompanied this code).
jjg@477 16 *
jjg@477 17 * You should have received a copy of the GNU General Public License version
jjg@477 18 * 2 along with this work; if not, write to the Free Software Foundation,
jjg@477 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jjg@477 20 *
jjg@477 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
jjg@477 22 * CA 95054 USA or visit www.sun.com if you need additional information or
jjg@477 23 * have any questions.
jjg@477 24 */
jjg@477 25
jjg@477 26 package com.sun.tools.javac.code;
jjg@477 27
jjg@477 28 import javax.lang.model.element.ElementKind;
jjg@477 29
jjg@477 30 import com.sun.tools.javac.code.Symbol.VarSymbol;
jjg@477 31 import com.sun.tools.javac.tree.JCTree;
jjg@477 32 import com.sun.tools.javac.tree.TreeInfo;
jjg@477 33 import com.sun.tools.javac.tree.TreeScanner;
jjg@477 34 import com.sun.tools.javac.tree.JCTree.*;
jjg@477 35 import com.sun.tools.javac.util.Context;
jjg@477 36 import com.sun.tools.javac.util.List;
jjg@477 37 import com.sun.tools.javac.util.ListBuffer;
jjg@477 38
jjg@477 39 /**
jjg@477 40 * Contains operations specific to processing type annotations
jjg@477 41 */
jjg@477 42 public class TypeAnnotations {
jjg@477 43 private static final Context.Key<TypeAnnotations> key
jjg@477 44 = new Context.Key<TypeAnnotations>();
jjg@477 45
jjg@477 46 public static TypeAnnotations instance(Context context) {
jjg@477 47 TypeAnnotations instance = context.get(key);
jjg@477 48 if (instance == null)
jjg@477 49 instance = new TypeAnnotations(context);
jjg@477 50 return instance;
jjg@477 51 }
jjg@477 52
jjg@477 53 protected TypeAnnotations(Context context) {
jjg@477 54 context.put(key, this);
jjg@477 55 }
jjg@477 56
jjg@477 57 public void taFillAndLift(JCClassDecl tree, boolean visitBodies) {
jjg@477 58 new TypeAnnotationPositions().scan(tree);
jjg@477 59 new TypeAnnotationLift().scan(tree);
jjg@477 60 }
jjg@477 61
jjg@477 62 private static class TypeAnnotationPositions extends TreeScanner {
jjg@477 63
jjg@477 64 private ListBuffer<JCTree> frames = ListBuffer.lb();
jjg@477 65 private void push(JCTree t) { frames = frames.prepend(t); }
jjg@477 66 private JCTree pop() { return frames.next(); }
jjg@477 67 private JCTree peek2() { return frames.toList().tail.head; }
jjg@477 68
jjg@477 69 @Override
jjg@477 70 public void scan(JCTree tree) {
jjg@477 71 push(tree);
jjg@477 72 super.scan(tree);
jjg@477 73 pop();
jjg@477 74 }
jjg@477 75
jjg@477 76 private boolean inClass = false;
jjg@477 77
jjg@477 78 @Override
jjg@477 79 public void visitClassDef(JCClassDecl tree) {
jjg@477 80 if (!inClass) {
jjg@477 81 // Do not recurse into nested and inner classes since
jjg@477 82 // TransTypes.visitClassDef makes an invocation for each class
jjg@477 83 // separately.
jjg@477 84 inClass = true;
jjg@477 85 try {
jjg@477 86 super.visitClassDef(tree);
jjg@477 87 } finally {
jjg@477 88 inClass = false;
jjg@477 89 }
jjg@477 90 }
jjg@477 91 }
jjg@477 92
jjg@477 93 private TypeAnnotationPosition resolveFrame(JCTree tree, JCTree frame,
jjg@477 94 List<JCTree> path, TypeAnnotationPosition p) {
jjg@477 95 switch (frame.getKind()) {
jjg@477 96 case TYPE_CAST:
jjg@477 97 p.type = TargetType.TYPECAST;
jjg@477 98 p.pos = frame.pos;
jjg@477 99 return p;
jjg@477 100
jjg@477 101 case INSTANCE_OF:
jjg@477 102 p.type = TargetType.INSTANCEOF;
jjg@477 103 p.pos = frame.pos;
jjg@477 104 return p;
jjg@477 105
jjg@477 106 case NEW_CLASS:
jjg@477 107 p.type = TargetType.NEW;
jjg@477 108 p.pos = frame.pos;
jjg@477 109 return p;
jjg@477 110
jjg@477 111 case NEW_ARRAY:
jjg@477 112 p.type = TargetType.NEW;
jjg@477 113 p.pos = frame.pos;
jjg@477 114 return p;
jjg@477 115
jjg@477 116 case CLASS:
jjg@477 117 p.pos = frame.pos;
jjg@477 118 if (((JCClassDecl)frame).extending == tree) {
jjg@477 119 p.type = TargetType.CLASS_EXTENDS;
jjg@477 120 p.type_index = -1;
jjg@477 121 } else if (((JCClassDecl)frame).implementing.contains(tree)) {
jjg@477 122 p.type = TargetType.CLASS_EXTENDS;
jjg@477 123 p.type_index = ((JCClassDecl)frame).implementing.indexOf(tree);
jjg@477 124 } else if (((JCClassDecl)frame).typarams.contains(tree)) {
jjg@477 125 p.type = TargetType.CLASS_TYPE_PARAMETER;
jjg@477 126 p.parameter_index = ((JCClassDecl)frame).typarams.indexOf(tree);
jjg@477 127 } else
jjg@477 128 throw new AssertionError();
jjg@477 129 return p;
jjg@477 130
jjg@477 131 case METHOD: {
jjg@477 132 JCMethodDecl frameMethod = (JCMethodDecl)frame;
jjg@477 133 p.pos = frame.pos;
jjg@477 134 if (frameMethod.receiverAnnotations.contains(tree))
jjg@477 135 p.type = TargetType.METHOD_RECEIVER;
jjg@477 136 else if (frameMethod.thrown.contains(tree)) {
jjg@477 137 p.type = TargetType.THROWS;
jjg@477 138 p.type_index = frameMethod.thrown.indexOf(tree);
jjg@477 139 } else if (((JCMethodDecl)frame).restype == tree) {
jjg@477 140 p.type = TargetType.METHOD_RETURN_GENERIC_OR_ARRAY;
jjg@477 141 } else if (frameMethod.typarams.contains(tree)) {
jjg@477 142 p.type = TargetType.METHOD_TYPE_PARAMETER;
jjg@477 143 p.parameter_index = frameMethod.typarams.indexOf(tree);
jjg@477 144 } else
jjg@477 145 throw new AssertionError();
jjg@477 146 return p;
jjg@477 147 }
jjg@477 148 case MEMBER_SELECT: {
jjg@477 149 JCFieldAccess fieldFrame = (JCFieldAccess)frame;
jjg@477 150 if ("class".contentEquals(fieldFrame.name)) {
jjg@477 151 p.type = TargetType.CLASS_LITERAL;
jjg@484 152 p.pos = TreeInfo.innermostType(fieldFrame.selected).pos;
jjg@477 153 } else
jjg@477 154 throw new AssertionError();
jjg@477 155 return p;
jjg@477 156 }
jjg@477 157 case PARAMETERIZED_TYPE: {
jjg@477 158 TypeAnnotationPosition nextP;
jjg@477 159 if (((JCTypeApply)frame).clazz == tree)
jjg@477 160 nextP = p; // generic: RAW; noop
jjg@477 161 else if (((JCTypeApply)frame).arguments.contains(tree))
jjg@477 162 p.location = p.location.prepend(
jjg@477 163 ((JCTypeApply)frame).arguments.indexOf(tree));
jjg@477 164 else
jjg@477 165 throw new AssertionError();
jjg@477 166
jjg@477 167 List<JCTree> newPath = path.tail;
jjg@477 168 return resolveFrame(newPath.head, newPath.tail.head, newPath, p);
jjg@477 169 }
jjg@477 170
jjg@477 171 case ARRAY_TYPE: {
jjg@477 172 p.location = p.location.prepend(0);
jjg@477 173 List<JCTree> newPath = path.tail;
jjg@477 174 return resolveFrame(newPath.head, newPath.tail.head, newPath, p);
jjg@477 175 }
jjg@477 176
jjg@477 177 case TYPE_PARAMETER:
jjg@477 178 if (path.tail.tail.head.getTag() == JCTree.CLASSDEF) {
jjg@477 179 JCClassDecl clazz = (JCClassDecl)path.tail.tail.head;
jjg@477 180 p.type = TargetType.CLASS_TYPE_PARAMETER_BOUND;
jjg@477 181 p.parameter_index = clazz.typarams.indexOf(path.tail.head);
jjg@477 182 p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree);
jjg@477 183 } else if (path.tail.tail.head.getTag() == JCTree.METHODDEF) {
jjg@477 184 JCMethodDecl method = (JCMethodDecl)path.tail.tail.head;
jjg@477 185 p.type = TargetType.METHOD_TYPE_PARAMETER_BOUND;
jjg@477 186 p.parameter_index = method.typarams.indexOf(path.tail.head);
jjg@477 187 p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree);
jjg@477 188 } else
jjg@477 189 throw new AssertionError();
jjg@477 190 p.pos = frame.pos;
jjg@477 191 return p;
jjg@477 192
jjg@477 193 case VARIABLE:
jjg@477 194 VarSymbol v = ((JCVariableDecl)frame).sym;
jjg@477 195 p.pos = frame.pos;
jjg@477 196 switch (v.getKind()) {
jjg@477 197 case LOCAL_VARIABLE:
jjg@477 198 p.type = TargetType.LOCAL_VARIABLE; break;
jjg@477 199 case FIELD:
jjg@477 200 p.type = TargetType.FIELD_GENERIC_OR_ARRAY; break;
jjg@477 201 case PARAMETER:
jjg@477 202 p.type = TargetType.METHOD_PARAMETER_GENERIC_OR_ARRAY;
jjg@477 203 p.parameter_index = methodParamIndex(path, frame);
jjg@477 204 break;
jjg@477 205 default: throw new AssertionError();
jjg@477 206 }
jjg@477 207 return p;
jjg@477 208
jjg@477 209 case ANNOTATED_TYPE: {
jjg@477 210 List<JCTree> newPath = path.tail;
jjg@477 211 return resolveFrame(newPath.head, newPath.tail.head,
jjg@477 212 newPath, p);
jjg@477 213 }
jjg@477 214
jjg@477 215 case METHOD_INVOCATION: {
jjg@477 216 JCMethodInvocation invocation = (JCMethodInvocation)frame;
jjg@477 217 if (!invocation.typeargs.contains(tree))
jjg@477 218 throw new AssertionError("{" + tree + "} is not an argument in the invocation: " + invocation);
jjg@477 219 p.type = TargetType.METHOD_TYPE_ARGUMENT;
jjg@477 220 p.pos = invocation.pos;
jjg@477 221 p.type_index = invocation.typeargs.indexOf(tree);
jjg@477 222 return p;
jjg@477 223 }
jjg@477 224
jjg@477 225 case EXTENDS_WILDCARD:
jjg@477 226 case SUPER_WILDCARD: {
jjg@477 227 p.type = TargetType.WILDCARD_BOUND;
jjg@477 228 List<JCTree> newPath = path.tail;
jjg@477 229
jjg@477 230 TypeAnnotationPosition wildcard =
jjg@477 231 resolveFrame(newPath.head, newPath.tail.head, newPath,
jjg@477 232 new TypeAnnotationPosition());
jjg@477 233 if (!wildcard.location.isEmpty())
jjg@477 234 wildcard.type = wildcard.type.getGenericComplement();
jjg@477 235 p.wildcard_position = wildcard;
jjg@477 236 p.pos = frame.pos;
jjg@477 237 return p;
jjg@477 238 }
jjg@477 239 }
jjg@477 240 return p;
jjg@477 241 }
jjg@477 242
jjg@477 243 private void setTypeAnnotationPos(List<JCTypeAnnotation> annotations, TypeAnnotationPosition position) {
jjg@477 244 for (JCTypeAnnotation anno : annotations) {
jjg@477 245 anno.annotation_position = position;
jjg@477 246 anno.attribute_field.position = position;
jjg@477 247 }
jjg@477 248 }
jjg@477 249
jjg@477 250 @Override
jjg@477 251 public void visitNewArray(JCNewArray tree) {
jjg@477 252 findPosition(tree, tree, tree.annotations);
jjg@477 253 int dimAnnosCount = tree.dimAnnotations.size();
jjg@477 254
jjg@477 255 // handle annotations associated with dimentions
jjg@477 256 for (int i = 0; i < dimAnnosCount; ++i) {
jjg@477 257 TypeAnnotationPosition p = new TypeAnnotationPosition();
jjg@477 258 p.type = TargetType.NEW_GENERIC_OR_ARRAY;
jjg@477 259 p.pos = tree.pos;
jjg@477 260 p.location = p.location.append(i);
jjg@477 261 setTypeAnnotationPos(tree.dimAnnotations.get(i), p);
jjg@477 262 }
jjg@477 263
jjg@477 264 // handle "free" annotations
jjg@477 265 int i = dimAnnosCount == 0 ? 0 : dimAnnosCount - 1;
jjg@477 266 JCExpression elemType = tree.elemtype;
jjg@477 267 while (elemType != null) {
jjg@477 268 if (elemType.getTag() == JCTree.ANNOTATED_TYPE) {
jjg@477 269 JCAnnotatedType at = (JCAnnotatedType)elemType;
jjg@477 270 TypeAnnotationPosition p = new TypeAnnotationPosition();
jjg@477 271 p.type = TargetType.NEW_GENERIC_OR_ARRAY;
jjg@477 272 p.pos = tree.pos;
jjg@477 273 p.location = p.location.append(i);
jjg@477 274 setTypeAnnotationPos(at.annotations, p);
jjg@477 275 elemType = at.underlyingType;
jjg@477 276 } else if (elemType.getTag() == JCTree.TYPEARRAY) {
jjg@477 277 ++i;
jjg@477 278 elemType = ((JCArrayTypeTree)elemType).elemtype;
jjg@477 279 } else
jjg@477 280 break;
jjg@477 281 }
jjg@477 282
jjg@477 283 // find annotations locations of initializer elements
jjg@477 284 scan(tree.elems);
jjg@477 285 }
jjg@477 286
jjg@477 287 @Override
jjg@477 288 public void visitAnnotatedType(JCAnnotatedType tree) {
jjg@477 289 findPosition(tree, peek2(), tree.annotations);
jjg@477 290 super.visitAnnotatedType(tree);
jjg@477 291 }
jjg@477 292
jjg@477 293 @Override
jjg@477 294 public void visitMethodDef(JCMethodDecl tree) {
jjg@477 295 TypeAnnotationPosition p = new TypeAnnotationPosition();
jjg@477 296 p.type = TargetType.METHOD_RECEIVER;
jjg@477 297 setTypeAnnotationPos(tree.receiverAnnotations, p);
jjg@477 298 super.visitMethodDef(tree);
jjg@477 299 }
jjg@477 300 @Override
jjg@477 301 public void visitTypeParameter(JCTypeParameter tree) {
jjg@477 302 findPosition(tree, peek2(), tree.annotations);
jjg@477 303 super.visitTypeParameter(tree);
jjg@477 304 }
jjg@477 305
jjg@477 306 void findPosition(JCTree tree, JCTree frame, List<JCTypeAnnotation> annotations) {
jjg@477 307 if (!annotations.isEmpty()) {
jjg@477 308 TypeAnnotationPosition p =
jjg@477 309 resolveFrame(tree, frame, frames.toList(),
jjg@477 310 new TypeAnnotationPosition());
jjg@477 311 if (!p.location.isEmpty())
jjg@477 312 p.type = p.type.getGenericComplement();
jjg@477 313 setTypeAnnotationPos(annotations, p);
jjg@477 314 }
jjg@477 315 }
jjg@477 316
jjg@477 317 private int methodParamIndex(List<JCTree> path, JCTree param) {
jjg@477 318 List<JCTree> curr = path;
jjg@477 319 if (curr.head != param)
jjg@477 320 curr = path.tail;
jjg@477 321 JCMethodDecl method = (JCMethodDecl)curr.tail.head;
jjg@477 322 return method.params.indexOf(param);
jjg@477 323 }
jjg@477 324 }
jjg@477 325
jjg@477 326 private static class TypeAnnotationLift extends TreeScanner {
jjg@477 327 List<Attribute.TypeCompound> recordedTypeAnnotations = List.nil();
jjg@477 328
jjg@477 329 boolean isInner = false;
jjg@477 330 @Override
jjg@477 331 public void visitClassDef(JCClassDecl tree) {
jjg@477 332 if (isInner) {
jjg@477 333 // tree is an inner class tree. stop now.
jjg@477 334 // TransTypes.visitClassDef makes an invocation for each class
jjg@477 335 // separately.
jjg@477 336 return;
jjg@477 337 }
jjg@477 338 isInner = true;
jjg@477 339 List<Attribute.TypeCompound> prevTAs = recordedTypeAnnotations;
jjg@477 340 recordedTypeAnnotations = List.nil();
jjg@477 341 try {
jjg@477 342 super.visitClassDef(tree);
jjg@477 343 } finally {
jjg@477 344 tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations);
jjg@477 345 recordedTypeAnnotations = prevTAs;
jjg@477 346 }
jjg@477 347 }
jjg@477 348
jjg@477 349 @Override
jjg@477 350 public void visitMethodDef(JCMethodDecl tree) {
jjg@477 351 List<Attribute.TypeCompound> prevTAs = recordedTypeAnnotations;
jjg@477 352 recordedTypeAnnotations = List.nil();
jjg@477 353 try {
jjg@477 354 super.visitMethodDef(tree);
jjg@477 355 } finally {
jjg@477 356 tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations);
jjg@477 357 recordedTypeAnnotations = prevTAs;
jjg@477 358 }
jjg@477 359 }
jjg@477 360
jjg@477 361 @Override
jjg@477 362 public void visitVarDef(JCVariableDecl tree) {
jjg@477 363 List<Attribute.TypeCompound> prevTAs = recordedTypeAnnotations;
jjg@477 364 recordedTypeAnnotations = List.nil();
jjg@477 365 ElementKind kind = tree.sym.getKind();
jjg@477 366 if (kind == ElementKind.LOCAL_VARIABLE && tree.mods.annotations.nonEmpty()) {
jjg@477 367 // need to lift the annotations
jjg@477 368 TypeAnnotationPosition position = new TypeAnnotationPosition();
jjg@477 369 position.pos = tree.pos;
jjg@477 370 position.type = TargetType.LOCAL_VARIABLE;
jjg@477 371 for (Attribute.Compound attribute : tree.sym.attributes_field) {
jjg@477 372 Attribute.TypeCompound tc =
jjg@477 373 new Attribute.TypeCompound(attribute.type, attribute.values, position);
jjg@477 374 recordedTypeAnnotations = recordedTypeAnnotations.append(tc);
jjg@477 375 }
jjg@477 376 }
jjg@477 377 try {
jjg@477 378 super.visitVarDef(tree);
jjg@477 379 } finally {
jjg@477 380 if (kind.isField() || kind == ElementKind.LOCAL_VARIABLE)
jjg@477 381 tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations);
jjg@477 382 recordedTypeAnnotations = kind.isField() ? prevTAs : prevTAs.appendList(recordedTypeAnnotations);
jjg@477 383 }
jjg@477 384 }
jjg@477 385
jjg@477 386 @Override
jjg@477 387 public void visitApply(JCMethodInvocation tree) {
jjg@477 388 scan(tree.meth);
jjg@477 389 scan(tree.typeargs);
jjg@477 390 scan(tree.args);
jjg@477 391 }
jjg@477 392
jjg@477 393 public void visitAnnotation(JCAnnotation tree) {
jjg@477 394 if (tree instanceof JCTypeAnnotation)
jjg@477 395 recordedTypeAnnotations = recordedTypeAnnotations.append(((JCTypeAnnotation)tree).attribute_field);
jjg@477 396 super.visitAnnotation(tree);
jjg@477 397 }
jjg@477 398 }
jjg@477 399
jjg@477 400 }

mercurial