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

Thu, 30 Sep 2010 10:47:12 -0700

author
jjg
date
Thu, 30 Sep 2010 10:47:12 -0700
changeset 700
7b413ac1a720
parent 682
6e2ccba61117
child 722
4851ff2ffc10
permissions
-rw-r--r--

6988436: Cleanup javac option handling
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                 case INTERFACE:
   118                 case ENUM:
   119                     p.pos = frame.pos;
   120                     if (((JCClassDecl)frame).extending == tree) {
   121                         p.type = TargetType.CLASS_EXTENDS;
   122                         p.type_index = -1;
   123                     } else if (((JCClassDecl)frame).implementing.contains(tree)) {
   124                         p.type = TargetType.CLASS_EXTENDS;
   125                         p.type_index = ((JCClassDecl)frame).implementing.indexOf(tree);
   126                     } else if (((JCClassDecl)frame).typarams.contains(tree)) {
   127                         p.type = TargetType.CLASS_TYPE_PARAMETER;
   128                         p.parameter_index = ((JCClassDecl)frame).typarams.indexOf(tree);
   129                     } else
   130                         throw new AssertionError();
   131                     return p;
   133                 case METHOD: {
   134                     JCMethodDecl frameMethod = (JCMethodDecl)frame;
   135                     p.pos = frame.pos;
   136                     if (frameMethod.receiverAnnotations.contains(tree))
   137                         p.type = TargetType.METHOD_RECEIVER;
   138                     else if (frameMethod.thrown.contains(tree)) {
   139                         p.type = TargetType.THROWS;
   140                         p.type_index = frameMethod.thrown.indexOf(tree);
   141                     } else if (((JCMethodDecl)frame).restype == tree) {
   142                         p.type = TargetType.METHOD_RETURN_GENERIC_OR_ARRAY;
   143                     } else if (frameMethod.typarams.contains(tree)) {
   144                         p.type = TargetType.METHOD_TYPE_PARAMETER;
   145                         p.parameter_index = frameMethod.typarams.indexOf(tree);
   146                     } else
   147                         throw new AssertionError();
   148                     return p;
   149                 }
   150                 case MEMBER_SELECT: {
   151                     JCFieldAccess fieldFrame = (JCFieldAccess)frame;
   152                     if ("class".contentEquals(fieldFrame.name)) {
   153                         p.type = TargetType.CLASS_LITERAL;
   154                         p.pos = TreeInfo.innermostType(fieldFrame.selected).pos;
   155                     } else
   156                         throw new AssertionError();
   157                     return p;
   158                 }
   159                 case PARAMETERIZED_TYPE: {
   160                     TypeAnnotationPosition nextP;
   161                     if (((JCTypeApply)frame).clazz == tree)
   162                         nextP = p; // generic: RAW; noop
   163                     else if (((JCTypeApply)frame).arguments.contains(tree))
   164                         p.location = p.location.prepend(
   165                                 ((JCTypeApply)frame).arguments.indexOf(tree));
   166                     else
   167                         throw new AssertionError();
   169                     List<JCTree> newPath = path.tail;
   170                     return resolveFrame(newPath.head, newPath.tail.head, newPath, p);
   171                 }
   173                 case ARRAY_TYPE: {
   174                     p.location = p.location.prepend(0);
   175                     List<JCTree> newPath = path.tail;
   176                     return resolveFrame(newPath.head, newPath.tail.head, newPath, p);
   177                 }
   179                 case TYPE_PARAMETER:
   180                     if (path.tail.tail.head.getTag() == JCTree.CLASSDEF) {
   181                         JCClassDecl clazz = (JCClassDecl)path.tail.tail.head;
   182                         p.type = TargetType.CLASS_TYPE_PARAMETER_BOUND;
   183                         p.parameter_index = clazz.typarams.indexOf(path.tail.head);
   184                         p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree);
   185                     } else if (path.tail.tail.head.getTag() == JCTree.METHODDEF) {
   186                         JCMethodDecl method = (JCMethodDecl)path.tail.tail.head;
   187                         p.type = TargetType.METHOD_TYPE_PARAMETER_BOUND;
   188                         p.parameter_index = method.typarams.indexOf(path.tail.head);
   189                         p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree);
   190                     } else
   191                         throw new AssertionError();
   192                     p.pos = frame.pos;
   193                     return p;
   195                 case VARIABLE:
   196                     VarSymbol v = ((JCVariableDecl)frame).sym;
   197                     p.pos = frame.pos;
   198                     switch (v.getKind()) {
   199                         case LOCAL_VARIABLE:
   200                             p.type = TargetType.LOCAL_VARIABLE; break;
   201                         case FIELD:
   202                             p.type = TargetType.FIELD_GENERIC_OR_ARRAY; break;
   203                         case PARAMETER:
   204                             p.type = TargetType.METHOD_PARAMETER_GENERIC_OR_ARRAY;
   205                             p.parameter_index = methodParamIndex(path, frame);
   206                             break;
   207                         default: throw new AssertionError();
   208                     }
   209                     return p;
   211                 case ANNOTATED_TYPE: {
   212                     List<JCTree> newPath = path.tail;
   213                     return resolveFrame(newPath.head, newPath.tail.head,
   214                             newPath, p);
   215                 }
   217                 case METHOD_INVOCATION: {
   218                     JCMethodInvocation invocation = (JCMethodInvocation)frame;
   219                     if (!invocation.typeargs.contains(tree))
   220                         throw new AssertionError("{" + tree + "} is not an argument in the invocation: " + invocation);
   221                     p.type = TargetType.METHOD_TYPE_ARGUMENT;
   222                     p.pos = invocation.pos;
   223                     p.type_index = invocation.typeargs.indexOf(tree);
   224                     return p;
   225                 }
   227                 case EXTENDS_WILDCARD:
   228                 case SUPER_WILDCARD: {
   229                     p.type = TargetType.WILDCARD_BOUND;
   230                     List<JCTree> newPath = path.tail;
   232                     TypeAnnotationPosition wildcard =
   233                         resolveFrame(newPath.head, newPath.tail.head, newPath,
   234                                 new TypeAnnotationPosition());
   235                     if (!wildcard.location.isEmpty())
   236                         wildcard.type = wildcard.type.getGenericComplement();
   237                     p.wildcard_position = wildcard;
   238                     p.pos = frame.pos;
   239                     return p;
   240                 }
   241             }
   242             return p;
   243         }
   245         private void setTypeAnnotationPos(List<JCTypeAnnotation> annotations, TypeAnnotationPosition position) {
   246             for (JCTypeAnnotation anno : annotations) {
   247                 anno.annotation_position = position;
   248                 anno.attribute_field.position = position;
   249             }
   250         }
   252         @Override
   253         public void visitNewArray(JCNewArray tree) {
   254             findPosition(tree, tree, tree.annotations);
   255             int dimAnnosCount = tree.dimAnnotations.size();
   257             // handle annotations associated with dimentions
   258             for (int i = 0; i < dimAnnosCount; ++i) {
   259                 TypeAnnotationPosition p = new TypeAnnotationPosition();
   260                 p.type = TargetType.NEW_GENERIC_OR_ARRAY;
   261                 p.pos = tree.pos;
   262                 p.location = p.location.append(i);
   263                 setTypeAnnotationPos(tree.dimAnnotations.get(i), p);
   264             }
   266             // handle "free" annotations
   267             int i = dimAnnosCount == 0 ? 0 : dimAnnosCount - 1;
   268             JCExpression elemType = tree.elemtype;
   269             while (elemType != null) {
   270                 if (elemType.getTag() == JCTree.ANNOTATED_TYPE) {
   271                     JCAnnotatedType at = (JCAnnotatedType)elemType;
   272                     TypeAnnotationPosition p = new TypeAnnotationPosition();
   273                     p.type = TargetType.NEW_GENERIC_OR_ARRAY;
   274                     p.pos = tree.pos;
   275                     p.location = p.location.append(i);
   276                     setTypeAnnotationPos(at.annotations, p);
   277                     elemType = at.underlyingType;
   278                 } else if (elemType.getTag() == JCTree.TYPEARRAY) {
   279                     ++i;
   280                     elemType = ((JCArrayTypeTree)elemType).elemtype;
   281                 } else
   282                     break;
   283             }
   285             // find annotations locations of initializer elements
   286             scan(tree.elems);
   287         }
   289         @Override
   290         public void visitAnnotatedType(JCAnnotatedType tree) {
   291             findPosition(tree, peek2(), tree.annotations);
   292             super.visitAnnotatedType(tree);
   293         }
   295         @Override
   296         public void visitMethodDef(JCMethodDecl tree) {
   297             TypeAnnotationPosition p = new TypeAnnotationPosition();
   298             p.type = TargetType.METHOD_RECEIVER;
   299             setTypeAnnotationPos(tree.receiverAnnotations, p);
   300             super.visitMethodDef(tree);
   301         }
   302         @Override
   303         public void visitTypeParameter(JCTypeParameter tree) {
   304             findPosition(tree, peek2(), tree.annotations);
   305             super.visitTypeParameter(tree);
   306         }
   308         void findPosition(JCTree tree, JCTree frame, List<JCTypeAnnotation> annotations) {
   309             if (!annotations.isEmpty()) {
   310                 TypeAnnotationPosition p =
   311                         resolveFrame(tree, frame, frames.toList(),
   312                                 new TypeAnnotationPosition());
   313                 if (!p.location.isEmpty())
   314                     p.type = p.type.getGenericComplement();
   315                 setTypeAnnotationPos(annotations, p);
   316             }
   317         }
   319         private int methodParamIndex(List<JCTree> path, JCTree param) {
   320             List<JCTree> curr = path;
   321             if (curr.head != param)
   322                 curr = path.tail;
   323             JCMethodDecl method = (JCMethodDecl)curr.tail.head;
   324             return method.params.indexOf(param);
   325         }
   326     }
   328     private static class TypeAnnotationLift extends TreeScanner {
   329         List<Attribute.TypeCompound> recordedTypeAnnotations = List.nil();
   331         boolean isInner = false;
   332         @Override
   333         public void visitClassDef(JCClassDecl tree) {
   334             if (isInner) {
   335                 // tree is an inner class tree.  stop now.
   336                 // TransTypes.visitClassDef makes an invocation for each class
   337                 // separately.
   338                 return;
   339             }
   340             isInner = true;
   341             List<Attribute.TypeCompound> prevTAs = recordedTypeAnnotations;
   342             recordedTypeAnnotations = List.nil();
   343             try {
   344                 super.visitClassDef(tree);
   345             } finally {
   346                 tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations);
   347                 recordedTypeAnnotations = prevTAs;
   348             }
   349         }
   351         @Override
   352         public void visitMethodDef(JCMethodDecl tree) {
   353             List<Attribute.TypeCompound> prevTAs = recordedTypeAnnotations;
   354             recordedTypeAnnotations = List.nil();
   355             try {
   356                 super.visitMethodDef(tree);
   357             } finally {
   358                 tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations);
   359                 recordedTypeAnnotations = prevTAs;
   360             }
   361         }
   363         @Override
   364         public void visitVarDef(JCVariableDecl tree) {
   365             List<Attribute.TypeCompound> prevTAs = recordedTypeAnnotations;
   366             recordedTypeAnnotations = List.nil();
   367             ElementKind kind = tree.sym.getKind();
   368             if (kind == ElementKind.LOCAL_VARIABLE && tree.mods.annotations.nonEmpty()) {
   369                 // need to lift the annotations
   370                 TypeAnnotationPosition position = new TypeAnnotationPosition();
   371                 position.pos = tree.pos;
   372                 position.type = TargetType.LOCAL_VARIABLE;
   373                 for (Attribute.Compound attribute : tree.sym.attributes_field) {
   374                     Attribute.TypeCompound tc =
   375                         new Attribute.TypeCompound(attribute.type, attribute.values, position);
   376                     recordedTypeAnnotations = recordedTypeAnnotations.append(tc);
   377                 }
   378             }
   379             try {
   380                 super.visitVarDef(tree);
   381             } finally {
   382                 if (kind.isField() || kind == ElementKind.LOCAL_VARIABLE)
   383                     tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations);
   384                 recordedTypeAnnotations = kind.isField() ? prevTAs : prevTAs.appendList(recordedTypeAnnotations);
   385             }
   386         }
   388         @Override
   389         public void visitApply(JCMethodInvocation tree) {
   390             scan(tree.meth);
   391             scan(tree.typeargs);
   392             scan(tree.args);
   393         }
   395         public void visitAnnotation(JCAnnotation tree) {
   396             if (tree instanceof JCTypeAnnotation)
   397                 recordedTypeAnnotations = recordedTypeAnnotations.append(((JCTypeAnnotation)tree).attribute_field);
   398             super.visitAnnotation(tree);
   399         }
   400     }
   402 }

mercurial