src/share/classes/com/sun/tools/javac/comp/TransTypes.java

changeset 308
03944ee4fac4
parent 133
c0372d1097c0
child 344
6d0add6ad778
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Fri Jun 26 12:22:40 2009 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Fri Jun 26 18:51:39 2009 -0700
     1.3 @@ -27,6 +27,8 @@
     1.4  
     1.5  import java.util.*;
     1.6  
     1.7 +import javax.lang.model.element.ElementKind;
     1.8 +
     1.9  import com.sun.tools.javac.code.*;
    1.10  import com.sun.tools.javac.code.Symbol.*;
    1.11  import com.sun.tools.javac.tree.*;
    1.12 @@ -59,6 +61,8 @@
    1.13          return instance;
    1.14      }
    1.15  
    1.16 +    private boolean debugJSR308;
    1.17 +
    1.18      private Names names;
    1.19      private Log log;
    1.20      private Symtab syms;
    1.21 @@ -88,6 +92,7 @@
    1.22          types = Types.instance(context);
    1.23          make = TreeMaker.instance(context);
    1.24          resolve = Resolve.instance(context);
    1.25 +        debugJSR308 = Options.instance(context).get("TA:trans") != null;
    1.26      }
    1.27  
    1.28      /** A hashtable mapping bridge methods to the methods they override after
    1.29 @@ -435,12 +440,15 @@
    1.30      }
    1.31  
    1.32      public void visitClassDef(JCClassDecl tree) {
    1.33 +        new TypeAnnotationPositions().scan(tree);
    1.34 +        new TypeAnnotationLift().scan(tree);
    1.35          translateClass(tree.sym);
    1.36          result = tree;
    1.37      }
    1.38  
    1.39      JCMethodDecl currentMethod = null;
    1.40      public void visitMethodDef(JCMethodDecl tree) {
    1.41 +        tree.sym.typeAnnotations = tree.sym.typeAnnotations;
    1.42          JCMethodDecl previousMethod = currentMethod;
    1.43          try {
    1.44              currentMethod = tree;
    1.45 @@ -726,8 +734,8 @@
    1.46      /** Visitor method for parameterized types.
    1.47       */
    1.48      public void visitTypeApply(JCTypeApply tree) {
    1.49 -        // Delete all type parameters.
    1.50 -        result = translate(tree.clazz, null);
    1.51 +        JCTree clazz = translate(tree.clazz, null);
    1.52 +        result = clazz;
    1.53      }
    1.54  
    1.55  /**************************************************************************
    1.56 @@ -793,4 +801,342 @@
    1.57          pt = null;
    1.58          return translate(cdef, null);
    1.59      }
    1.60 +
    1.61 +    private class TypeAnnotationPositions extends TreeScanner {
    1.62 +
    1.63 +        private ListBuffer<JCTree> frames = ListBuffer.lb();
    1.64 +        private void push(JCTree t) { frames = frames.prepend(t); }
    1.65 +        private JCTree pop() { return frames.next(); }
    1.66 +        private JCTree peek() { return frames.first(); }
    1.67 +        private JCTree peek2() { return frames.toList().tail.head; }
    1.68 +
    1.69 +        @Override
    1.70 +        public void scan(JCTree tree) {
    1.71 +            push(tree);
    1.72 +            super.scan(tree);
    1.73 +            pop();
    1.74 +        }
    1.75 +
    1.76 +        private TypeAnnotationPosition resolveFrame(JCTree tree, JCTree frame,
    1.77 +                List<JCTree> path, TypeAnnotationPosition p) {
    1.78 +            switch (frame.getKind()) {
    1.79 +                case TYPE_CAST:
    1.80 +                    p.type = TargetType.TYPECAST;
    1.81 +                    p.pos = frame.pos;
    1.82 +                    return p;
    1.83 +
    1.84 +                case INSTANCE_OF:
    1.85 +                    p.type = TargetType.INSTANCEOF;
    1.86 +                    p.pos = frame.pos;
    1.87 +                    return p;
    1.88 +
    1.89 +                case NEW_CLASS:
    1.90 +                    p.type = TargetType.NEW;
    1.91 +                    p.pos = frame.pos;
    1.92 +                    return p;
    1.93 +
    1.94 +                case NEW_ARRAY:
    1.95 +                    p.type = TargetType.NEW;
    1.96 +                    p.pos = frame.pos;
    1.97 +                    return p;
    1.98 +
    1.99 +                case CLASS:
   1.100 +                    p.pos = frame.pos;
   1.101 +                    if (((JCClassDecl)frame).extending == tree) {
   1.102 +                        p.type = TargetType.CLASS_EXTENDS;
   1.103 +                        p.type_index = -1;
   1.104 +                    } else if (((JCClassDecl)frame).implementing.contains(tree)) {
   1.105 +                        p.type = TargetType.CLASS_EXTENDS;
   1.106 +                        p.type_index = ((JCClassDecl)frame).implementing.indexOf(tree);
   1.107 +                    } else if (((JCClassDecl)frame).typarams.contains(tree)) {
   1.108 +                        p.type = TargetType.CLASS_TYPE_PARAMETER;
   1.109 +                        p.parameter_index = ((JCClassDecl)frame).typarams.indexOf(tree);
   1.110 +                    } else
   1.111 +                        throw new AssertionError();
   1.112 +                    return p;
   1.113 +
   1.114 +                case METHOD: {
   1.115 +                    JCMethodDecl frameMethod = (JCMethodDecl)frame;
   1.116 +                    p.pos = frame.pos;
   1.117 +                    if (frameMethod.receiverAnnotations.contains(tree))
   1.118 +                        p.type = TargetType.METHOD_RECEIVER;
   1.119 +                    else if (frameMethod.thrown.contains(tree)) {
   1.120 +                        p.type = TargetType.THROWS;
   1.121 +                        p.type_index = frameMethod.thrown.indexOf(tree);
   1.122 +                    } else if (((JCMethodDecl)frame).restype == tree) {
   1.123 +                        p.type = TargetType.METHOD_RETURN_GENERIC_OR_ARRAY;
   1.124 +                    } else if (frameMethod.typarams.contains(tree)) {
   1.125 +                        p.type = TargetType.METHOD_TYPE_PARAMETER;
   1.126 +                        p.parameter_index = frameMethod.typarams.indexOf(tree);
   1.127 +                    } else
   1.128 +                        throw new AssertionError();
   1.129 +                    return p;
   1.130 +                }
   1.131 +                case MEMBER_SELECT: {
   1.132 +                    JCFieldAccess fieldFrame = (JCFieldAccess)frame;
   1.133 +                    if (fieldFrame.name == names._class) {
   1.134 +                        p.type = TargetType.CLASS_LITERAL;
   1.135 +                        if (fieldFrame.selected instanceof JCAnnotatedType) {
   1.136 +                            p.pos = TreeInfo.typeIn(fieldFrame).pos;
   1.137 +                        } else if (fieldFrame.selected instanceof JCArrayTypeTree) {
   1.138 +                            p.pos = fieldFrame.selected.pos;
   1.139 +                        }
   1.140 +                    } else
   1.141 +                        throw new AssertionError();
   1.142 +                    return p;
   1.143 +                }
   1.144 +                case PARAMETERIZED_TYPE: {
   1.145 +                    TypeAnnotationPosition nextP;
   1.146 +                    if (((JCTypeApply)frame).clazz == tree)
   1.147 +                        nextP = p; // generic: RAW; noop
   1.148 +                    else if (((JCTypeApply)frame).arguments.contains(tree))
   1.149 +                        p.location = p.location.prepend(
   1.150 +                                ((JCTypeApply)frame).arguments.indexOf(tree));
   1.151 +                    else
   1.152 +                        throw new AssertionError();
   1.153 +
   1.154 +                    List<JCTree> newPath = path.tail;
   1.155 +                    return resolveFrame(newPath.head, newPath.tail.head, newPath, p);
   1.156 +                }
   1.157 +
   1.158 +                case ARRAY_TYPE: {
   1.159 +                    p.location = p.location.prepend(0);
   1.160 +                    List<JCTree> newPath = path.tail;
   1.161 +                    return resolveFrame(newPath.head, newPath.tail.head, newPath, p);
   1.162 +                }
   1.163 +
   1.164 +                case TYPE_PARAMETER:
   1.165 +                    if (path.tail.tail.head.getTag() == JCTree.CLASSDEF) {
   1.166 +                        JCClassDecl clazz = (JCClassDecl)path.tail.tail.head;
   1.167 +                        p.type = TargetType.CLASS_TYPE_PARAMETER_BOUND;
   1.168 +                        p.parameter_index = clazz.typarams.indexOf(path.tail.head);
   1.169 +                        p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree);
   1.170 +                    } else if (path.tail.tail.head.getTag() == JCTree.METHODDEF) {
   1.171 +                        JCMethodDecl method = (JCMethodDecl)path.tail.tail.head;
   1.172 +                        p.type = TargetType.METHOD_TYPE_PARAMETER_BOUND;
   1.173 +                        p.parameter_index = method.typarams.indexOf(path.tail.head);
   1.174 +                        p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree);
   1.175 +                    } else
   1.176 +                        throw new AssertionError();
   1.177 +                    p.pos = frame.pos;
   1.178 +                    return p;
   1.179 +
   1.180 +                case VARIABLE:
   1.181 +                    VarSymbol v = ((JCVariableDecl)frame).sym;
   1.182 +                    p.pos = frame.pos;
   1.183 +                    switch (v.getKind()) {
   1.184 +                        case LOCAL_VARIABLE:
   1.185 +                            p.type = TargetType.LOCAL_VARIABLE; break;
   1.186 +                        case FIELD:
   1.187 +                            p.type = TargetType.FIELD_GENERIC_OR_ARRAY; break;
   1.188 +                        case PARAMETER:
   1.189 +                            p.type = TargetType.METHOD_PARAMETER_GENERIC_OR_ARRAY;
   1.190 +                            p.parameter_index = methodParamIndex(path, frame);
   1.191 +                            break;
   1.192 +                        default: throw new AssertionError();
   1.193 +                    }
   1.194 +                    return p;
   1.195 +
   1.196 +                case ANNOTATED_TYPE: {
   1.197 +                    List<JCTree> newPath = path.tail;
   1.198 +                    return resolveFrame(newPath.head, newPath.tail.head,
   1.199 +                            newPath, p);
   1.200 +                }
   1.201 +
   1.202 +                case METHOD_INVOCATION: {
   1.203 +                    JCMethodInvocation invocation = (JCMethodInvocation)frame;
   1.204 +                    if (!invocation.typeargs.contains(tree))
   1.205 +                        throw new AssertionError("{" + tree + "} is not an argument in the invocation: " + invocation);
   1.206 +                    p.type = TargetType.METHOD_TYPE_ARGUMENT;
   1.207 +                    p.pos = invocation.pos;
   1.208 +                    p.type_index = invocation.typeargs.indexOf(tree);
   1.209 +                    return p;
   1.210 +                }
   1.211 +
   1.212 +                case EXTENDS_WILDCARD:
   1.213 +                case SUPER_WILDCARD: {
   1.214 +                    p.type = TargetType.WILDCARD_BOUND;
   1.215 +                    List<JCTree> newPath = path.tail;
   1.216 +
   1.217 +                    TypeAnnotationPosition wildcard =
   1.218 +                        resolveFrame(newPath.head, newPath.tail.head, newPath,
   1.219 +                                new TypeAnnotationPosition());
   1.220 +                    if (!wildcard.location.isEmpty())
   1.221 +                        wildcard.type = wildcard.type.getGenericComplement();
   1.222 +                    p.wildcard_position = wildcard;
   1.223 +                    p.pos = frame.pos;
   1.224 +                    return p;
   1.225 +                }
   1.226 +            }
   1.227 +            return p;
   1.228 +        }
   1.229 +
   1.230 +        @Override
   1.231 +        public void visitApply(JCMethodInvocation tree) {
   1.232 +            scan(tree.meth);
   1.233 +            scan(tree.typeargs);
   1.234 +            scan(tree.args);
   1.235 +        }
   1.236 +
   1.237 +        private void setTypeAnnotationPos(List<JCTypeAnnotation> annotations, TypeAnnotationPosition position) {
   1.238 +            for (JCTypeAnnotation anno : annotations) {
   1.239 +                anno.annotation_position = position;
   1.240 +                anno.attribute_field.position = position;
   1.241 +            }
   1.242 +        }
   1.243 +
   1.244 +        @Override
   1.245 +        public void visitNewArray(JCNewArray tree) {
   1.246 +            findPosition(tree, tree, tree.annotations);
   1.247 +            int dimAnnosCount = tree.dimAnnotations.size();
   1.248 +
   1.249 +            // handle annotations associated with dimentions
   1.250 +            for (int i = 0; i < dimAnnosCount; ++i) {
   1.251 +                TypeAnnotationPosition p = new TypeAnnotationPosition();
   1.252 +                p.type = TargetType.NEW_GENERIC_OR_ARRAY;
   1.253 +                p.pos = tree.pos;
   1.254 +                p.location = p.location.append(i);
   1.255 +                setTypeAnnotationPos(tree.dimAnnotations.get(i), p);
   1.256 +            }
   1.257 +
   1.258 +            // handle "free" annotations
   1.259 +            int i = dimAnnosCount == 0 ? 0 : dimAnnosCount - 1;
   1.260 +            JCExpression elemType = tree.elemtype;
   1.261 +            while (elemType != null) {
   1.262 +                if (elemType.getTag() == JCTree.ANNOTATED_TYPE) {
   1.263 +                    JCAnnotatedType at = (JCAnnotatedType)elemType;
   1.264 +                    TypeAnnotationPosition p = new TypeAnnotationPosition();
   1.265 +                    p.type = TargetType.NEW_GENERIC_OR_ARRAY;
   1.266 +                    p.pos = tree.pos;
   1.267 +                    p.location = p.location.append(i);
   1.268 +                    setTypeAnnotationPos(at.annotations, p);
   1.269 +                    elemType = at.underlyingType;
   1.270 +                } else if (elemType.getTag() == JCTree.TYPEARRAY) {
   1.271 +                    ++i;
   1.272 +                    elemType = ((JCArrayTypeTree)elemType).elemtype;
   1.273 +                } else
   1.274 +                    break;
   1.275 +            }
   1.276 +
   1.277 +            // find annotations locations of initializer elements
   1.278 +            scan(tree.elems);
   1.279 +        }
   1.280 +
   1.281 +        @Override
   1.282 +        public void visitAnnotatedType(JCAnnotatedType tree) {
   1.283 +            findPosition(tree, peek2(), tree.annotations);
   1.284 +            super.visitAnnotatedType(tree);
   1.285 +        }
   1.286 +
   1.287 +        @Override
   1.288 +        public void visitMethodDef(JCMethodDecl tree) {
   1.289 +            TypeAnnotationPosition p = new TypeAnnotationPosition();
   1.290 +            p.type = TargetType.METHOD_RECEIVER;
   1.291 +            setTypeAnnotationPos(tree.receiverAnnotations, p);
   1.292 +            super.visitMethodDef(tree);
   1.293 +        }
   1.294 +        @Override
   1.295 +        public void visitTypeParameter(JCTypeParameter tree) {
   1.296 +            findPosition(tree, peek2(), tree.annotations);
   1.297 +            super.visitTypeParameter(tree);
   1.298 +        }
   1.299 +
   1.300 +        void findPosition(JCTree tree, JCTree frame, List<JCTypeAnnotation> annotations) {
   1.301 +            if (!annotations.isEmpty()) {
   1.302 +                TypeAnnotationPosition p =
   1.303 +                        resolveFrame(tree, frame, frames.toList(),
   1.304 +                                new TypeAnnotationPosition());
   1.305 +                if (!p.location.isEmpty())
   1.306 +                    p.type = p.type.getGenericComplement();
   1.307 +                setTypeAnnotationPos(annotations, p);
   1.308 +                if (debugJSR308) {
   1.309 +                    System.out.println("trans: " + tree);
   1.310 +                    System.out.println("  target: " + p);
   1.311 +                }
   1.312 +            }
   1.313 +        }
   1.314 +
   1.315 +        private int methodParamIndex(List<JCTree> path, JCTree param) {
   1.316 +            List<JCTree> curr = path;
   1.317 +            if (curr.head != param)
   1.318 +                curr = path.tail;
   1.319 +            JCMethodDecl method = (JCMethodDecl)curr.tail.head;
   1.320 +            return method.params.indexOf(param);
   1.321 +        }
   1.322 +    }
   1.323 +
   1.324 +    private class TypeAnnotationLift extends TreeScanner {
   1.325 +        List<Attribute.TypeCompound> recordedTypeAnnotations = List.nil();
   1.326 +
   1.327 +        boolean isInner = false;
   1.328 +        @Override
   1.329 +        public void visitClassDef(JCClassDecl tree) {
   1.330 +            if (isInner) {
   1.331 +                // tree is an inner class tree.  stop now.
   1.332 +                // TransTypes.visitClassDef makes an invocation for each class
   1.333 +                // seperately.
   1.334 +                return;
   1.335 +            }
   1.336 +            isInner = true;
   1.337 +            List<Attribute.TypeCompound> prevTAs = recordedTypeAnnotations;
   1.338 +            recordedTypeAnnotations = List.nil();
   1.339 +            try {
   1.340 +                super.visitClassDef(tree);
   1.341 +            } finally {
   1.342 +                tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations);
   1.343 +                recordedTypeAnnotations = prevTAs;
   1.344 +            }
   1.345 +        }
   1.346 +
   1.347 +        @Override
   1.348 +        public void visitMethodDef(JCMethodDecl tree) {
   1.349 +            List<Attribute.TypeCompound> prevTAs = recordedTypeAnnotations;
   1.350 +            recordedTypeAnnotations = List.nil();
   1.351 +            try {
   1.352 +                super.visitMethodDef(tree);
   1.353 +            } finally {
   1.354 +                tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations);
   1.355 +                recordedTypeAnnotations = prevTAs;
   1.356 +            }
   1.357 +        }
   1.358 +
   1.359 +        @Override
   1.360 +        public void visitVarDef(JCVariableDecl tree) {
   1.361 +            List<Attribute.TypeCompound> prevTAs = recordedTypeAnnotations;
   1.362 +            recordedTypeAnnotations = List.nil();
   1.363 +            ElementKind kind = tree.sym.getKind();
   1.364 +            if (kind == ElementKind.LOCAL_VARIABLE && tree.mods.annotations.nonEmpty()) {
   1.365 +                // need to lift the annotations
   1.366 +                TypeAnnotationPosition position = new TypeAnnotationPosition();
   1.367 +                position.pos = tree.pos;
   1.368 +                position.type = TargetType.LOCAL_VARIABLE;
   1.369 +                for (Attribute.Compound attribute : tree.sym.attributes_field) {
   1.370 +                    Attribute.TypeCompound tc =
   1.371 +                        new Attribute.TypeCompound(attribute.type, attribute.values, position);
   1.372 +                    recordedTypeAnnotations = recordedTypeAnnotations.append(tc);
   1.373 +                }
   1.374 +            }
   1.375 +            try {
   1.376 +                super.visitVarDef(tree);
   1.377 +            } finally {
   1.378 +                if (kind.isField() || kind == ElementKind.LOCAL_VARIABLE)
   1.379 +                    tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations);
   1.380 +                recordedTypeAnnotations = kind.isField() ? prevTAs : prevTAs.appendList(recordedTypeAnnotations);
   1.381 +            }
   1.382 +        }
   1.383 +
   1.384 +        @Override
   1.385 +        public void visitApply(JCMethodInvocation tree) {
   1.386 +            scan(tree.meth);
   1.387 +            scan(tree.typeargs);
   1.388 +            scan(tree.args);
   1.389 +        }
   1.390 +
   1.391 +        public void visitAnnotation(JCAnnotation tree) {
   1.392 +            if (tree instanceof JCTypeAnnotation)
   1.393 +                recordedTypeAnnotations = recordedTypeAnnotations.append(((JCTypeAnnotation)tree).attribute_field);
   1.394 +            super.visitAnnotation(tree);
   1.395 +        }
   1.396 +    }
   1.397 +
   1.398  }

mercurial