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

Tue, 25 May 2010 15:54:51 -0700

author
ohair
date
Tue, 25 May 2010 15:54:51 -0700
changeset 554
9d9f26857129
parent 489
4b4e282a3146
child 682
6e2ccba61117
permissions
-rw-r--r--

6943119: Rebrand source copyright notices
Reviewed-by: darcy

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

mercurial