Tue, 07 Sep 2010 17:31:54 +0100
6337171: javac should create bridge methods when type variable bounds restricted
Summary: javac should add synthetic overrides for inherited abstract methods in order to preserve binary compatibility
Reviewed-by: jjg
jjg@477 | 1 | /* |
ohair@554 | 2 | * Copyright (c) 2009, Oracle and/or its affiliates. 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 |
ohair@554 | 7 | * published by the Free Software Foundation. Oracle designates this |
jjg@477 | 8 | * particular file as subject to the "Classpath" exception as provided |
ohair@554 | 9 | * by Oracle 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 | * |
ohair@554 | 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
ohair@554 | 22 | * or visit www.oracle.com if you need additional information or have any |
ohair@554 | 23 | * 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 | } |