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

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

mercurial