1 /*
   2  * Copyright 2004-2005 Sun Microsystems, Inc.  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.  Sun designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22  * CA 95054 USA or visit www.sun.com if you need additional information or
  23  * have any questions.
  24  */
  25 
  26 package com.sun.tools.apt.mirror.util;
  27 
  28 
  29 import java.util.Collection;
  30 
  31 import com.sun.mirror.declaration.*;
  32 import com.sun.mirror.type.*;
  33 import com.sun.mirror.util.Types;
  34 import com.sun.tools.apt.mirror.AptEnv;
  35 import com.sun.tools.apt.mirror.declaration.*;
  36 import com.sun.tools.apt.mirror.type.TypeMirrorImpl;
  37 import com.sun.tools.javac.code.BoundKind;
  38 import com.sun.tools.javac.code.Type;
  39 import com.sun.tools.javac.code.Symbol.ClassSymbol;
  40 import com.sun.tools.javac.util.Context;
  41 import com.sun.tools.javac.util.ListBuffer;
  42 
  43 
  44 /**
  45  * Implementation of Types utility methods for annotation processors
  46  */
  47 @SuppressWarnings("deprecation")
  48 public class TypesImpl implements Types {
  49 
  50     private final AptEnv env;
  51 
  52 
  53     private static final Context.Key<Types> typesKey =
  54             new Context.Key<Types>();
  55 
  56     public static Types instance(Context context) {
  57         Types instance = context.get(typesKey);
  58         if (instance == null) {
  59             instance = new TypesImpl(context);
  60         }
  61         return instance;
  62     }
  63 
  64     private TypesImpl(Context context) {
  65         context.put(typesKey, this);
  66         env = AptEnv.instance(context);
  67     }
  68 
  69 
  70     /**
  71      * {@inheritDoc}
  72      */
  73     public boolean isSubtype(TypeMirror t1, TypeMirror t2) {
  74         return env.jctypes.isSubtype(((TypeMirrorImpl) t1).type,
  75                                      ((TypeMirrorImpl) t2).type);
  76     }
  77 
  78     /**
  79      * {@inheritDoc}
  80      */
  81     public boolean isAssignable(TypeMirror t1, TypeMirror t2) {
  82         return env.jctypes.isAssignable(((TypeMirrorImpl) t1).type,
  83                                         ((TypeMirrorImpl) t2).type);
  84     }
  85 
  86     /**
  87      * {@inheritDoc}
  88      */
  89     public TypeMirror getErasure(TypeMirror t) {
  90         return env.typeMaker.getType(
  91                 env.jctypes.erasure(((TypeMirrorImpl) t).type));
  92     }
  93 
  94     /**
  95      * {@inheritDoc}
  96      */
  97     public PrimitiveType getPrimitiveType(PrimitiveType.Kind kind) {
  98         Type prim = null;
  99         switch (kind) {
 100         case BOOLEAN:   prim = env.symtab.booleanType;  break;
 101         case BYTE:      prim = env.symtab.byteType;     break;
 102         case SHORT:     prim = env.symtab.shortType;    break;
 103         case INT:       prim = env.symtab.intType;      break;
 104         case LONG:      prim = env.symtab.longType;     break;
 105         case CHAR:      prim = env.symtab.charType;     break;
 106         case FLOAT:     prim = env.symtab.floatType;    break;
 107         case DOUBLE:    prim = env.symtab.doubleType;   break;
 108         default:        assert false;
 109         }
 110         return (PrimitiveType) env.typeMaker.getType(prim);
 111     }
 112 
 113     /**
 114      * {@inheritDoc}
 115      */
 116     public VoidType getVoidType() {
 117         return (VoidType) env.typeMaker.getType(env.symtab.voidType);
 118     }
 119 
 120     /**
 121      * {@inheritDoc}
 122      */
 123     public ArrayType getArrayType(TypeMirror componentType) {
 124         if (componentType instanceof VoidType) {
 125             throw new IllegalArgumentException("void");
 126         }
 127         return (ArrayType) env.typeMaker.getType(
 128                 new Type.ArrayType(((TypeMirrorImpl) componentType).type,
 129                                    env.symtab.arrayClass));
 130     }
 131 
 132     /**
 133      * {@inheritDoc}
 134      */
 135     public TypeVariable getTypeVariable(TypeParameterDeclaration tparam) {
 136         return (TypeVariable) env.typeMaker.getType(
 137                                 ((DeclarationImpl) tparam).sym.type);
 138     }
 139 
 140     /**
 141      * {@inheritDoc}
 142      */
 143     public WildcardType getWildcardType(Collection<ReferenceType> upperBounds,
 144                                         Collection<ReferenceType> lowerBounds) {
 145         BoundKind kind;
 146         Type bound;
 147         int uppers  = upperBounds.size();
 148         int downers = lowerBounds.size();
 149 
 150         if (uppers + downers > 1) {
 151             throw new IllegalArgumentException("Multiple bounds not allowed");
 152 
 153         } else if (uppers + downers == 0) {
 154             kind = BoundKind.UNBOUND;
 155             bound = env.symtab.objectType;
 156 
 157         } else if (uppers == 1) {
 158             assert downers == 0;
 159             kind = BoundKind.EXTENDS;
 160             bound = ((TypeMirrorImpl) upperBounds.iterator().next()).type;
 161 
 162         } else {
 163             assert uppers == 0 && downers == 1;
 164             kind = BoundKind.SUPER;
 165             bound = ((TypeMirrorImpl) lowerBounds.iterator().next()).type;
 166         }
 167 
 168         if (bound instanceof Type.WildcardType)
 169             throw new IllegalArgumentException(bound.toString());
 170 
 171         return (WildcardType) env.typeMaker.getType(
 172                 new Type.WildcardType(bound, kind, env.symtab.boundClass));
 173     }
 174 
 175     /**
 176      * {@inheritDoc}
 177      */
 178     public DeclaredType getDeclaredType(TypeDeclaration decl,
 179                                         TypeMirror... typeArgs) {
 180         ClassSymbol sym = ((TypeDeclarationImpl) decl).sym;
 181 
 182         if (typeArgs.length == 0)
 183             return (DeclaredType) env.typeMaker.getType(
 184                                         env.jctypes.erasure(sym.type));
 185         if (sym.type.getEnclosingType().isParameterized())
 186             throw new IllegalArgumentException(decl.toString());
 187 
 188         return getDeclaredType(sym.type.getEnclosingType(), sym, typeArgs);
 189     }
 190 
 191     /**
 192      * {@inheritDoc}
 193      */
 194     public DeclaredType getDeclaredType(DeclaredType containing,
 195                                         TypeDeclaration decl,
 196                                         TypeMirror... typeArgs) {
 197         if (containing == null)
 198             return getDeclaredType(decl, typeArgs);
 199 
 200         ClassSymbol sym = ((TypeDeclarationImpl) decl).sym;
 201         Type outer = ((TypeMirrorImpl) containing).type;
 202 
 203         if (outer.tsym != sym.owner.enclClass())
 204             throw new IllegalArgumentException(containing.toString());
 205         if (!outer.isParameterized())
 206             return getDeclaredType(decl, typeArgs);
 207 
 208         return getDeclaredType(outer, sym, typeArgs);
 209     }
 210 
 211     private DeclaredType getDeclaredType(Type outer,
 212                                          ClassSymbol sym,
 213                                          TypeMirror... typeArgs) {
 214         if (typeArgs.length != sym.type.getTypeArguments().length())
 215             throw new IllegalArgumentException(
 216                                 "Incorrect number of type arguments");
 217 
 218         ListBuffer<Type> targs = new ListBuffer<Type>();
 219         for (TypeMirror t : typeArgs) {
 220             if (!(t instanceof ReferenceType || t instanceof WildcardType))
 221                 throw new IllegalArgumentException(t.toString());
 222             targs.append(((TypeMirrorImpl) t).type);
 223         }
 224         //### Need a way to check that type args match formals.
 225 
 226         return (DeclaredType) env.typeMaker.getType(
 227                 new Type.ClassType(outer, targs.toList(), sym));
 228     }
 229 }