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

Fri, 29 Oct 2010 12:47:49 -0700

author
jjg
date
Fri, 29 Oct 2010 12:47:49 -0700
changeset 727
460b2f588d0d
parent 722
4851ff2ffc10
child 798
4868a36f6fd8
permissions
-rw-r--r--

6993304: JavacTrees.getAttrContext not updated to Tree.Kind.{ANNOTATION_TYPE,ENUM,INTERFACE}
Reviewed-by: mcimadamore

     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 //308        new TypeAnnotationPositions().scan(tree);
    59 //308        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 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;
   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();
   170                     List<JCTree> newPath = path.tail;
   171                     return resolveFrame(newPath.head, newPath.tail.head, newPath, p);
   172                 }
   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                 }
   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;
   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;
   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                }
   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                 }
   228                 case EXTENDS_WILDCARD:
   229                 case SUPER_WILDCARD: {
   230                     p.type = TargetType.WILDCARD_BOUND;
   231                     List<JCTree> newPath = path.tail;
   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         }
   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         }
   253         @Override
   254         public void visitNewArray(JCNewArray tree) {
   255             findPosition(tree, tree, tree.annotations);
   256             int dimAnnosCount = tree.dimAnnotations.size();
   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             }
   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             }
   286             // find annotations locations of initializer elements
   287             scan(tree.elems);
   288         }
   290         @Override
   291         public void visitAnnotatedType(JCAnnotatedType tree) {
   292             findPosition(tree, peek2(), tree.annotations);
   293             super.visitAnnotatedType(tree);
   294         }
   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         }
   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         }
   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     }
   329     private static class TypeAnnotationLift extends TreeScanner {
   330         List<Attribute.TypeCompound> recordedTypeAnnotations = List.nil();
   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         }
   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         }
   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         }
   389         @Override
   390         public void visitApply(JCMethodInvocation tree) {
   391             scan(tree.meth);
   392             scan(tree.typeargs);
   393             scan(tree.args);
   394         }
   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     }
   403 }

mercurial