1 /*
   2  * Copyright (c) 2004, 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  */
  25 
  26 package com.sun.tools.apt.mirror.type;
  27 
  28 
  29 import java.util.Collection;
  30 import java.util.ArrayList;
  31 
  32 import com.sun.mirror.type.*;
  33 import com.sun.mirror.type.PrimitiveType.Kind;
  34 import com.sun.tools.apt.mirror.AptEnv;
  35 import com.sun.tools.javac.code.*;
  36 import com.sun.tools.javac.util.Context;
  37 
  38 import static com.sun.tools.javac.code.TypeTags.*;
  39 
  40 
  41 /**
  42  * Utilities for constructing type objects.
  43  */
  44 @SuppressWarnings("deprecation")
  45 public class TypeMaker {
  46 
  47     private final AptEnv env;
  48     private final VoidType voidType;
  49     private PrimitiveType[] primTypes = new PrimitiveType[VOID];
  50                                                 // VOID is past all prim types
  51 
  52 
  53     private static final Context.Key<TypeMaker> typeMakerKey =
  54             new Context.Key<TypeMaker>();
  55 
  56     public static TypeMaker instance(Context context) {
  57         TypeMaker instance = context.get(typeMakerKey);
  58         if (instance == null) {
  59             instance = new TypeMaker(context);
  60         }
  61         return instance;
  62     }
  63 
  64     private TypeMaker(Context context) {
  65         context.put(typeMakerKey, this);
  66         env = AptEnv.instance(context);
  67 
  68         voidType = new VoidTypeImpl(env);
  69         primTypes[BOOLEAN] = new PrimitiveTypeImpl(env, Kind.BOOLEAN);
  70         primTypes[BYTE]    = new PrimitiveTypeImpl(env, Kind.BYTE);
  71         primTypes[SHORT]   = new PrimitiveTypeImpl(env, Kind.SHORT);
  72         primTypes[INT]     = new PrimitiveTypeImpl(env, Kind.INT);
  73         primTypes[LONG]    = new PrimitiveTypeImpl(env, Kind.LONG);
  74         primTypes[CHAR]    = new PrimitiveTypeImpl(env, Kind.CHAR);
  75         primTypes[FLOAT]   = new PrimitiveTypeImpl(env, Kind.FLOAT);
  76         primTypes[DOUBLE]  = new PrimitiveTypeImpl(env, Kind.DOUBLE);
  77     }
  78 
  79 
  80     /**
  81      * Returns the TypeMirror corresponding to a javac Type object.
  82      */
  83     public TypeMirror getType(Type t) {
  84         if (t.isPrimitive()) {
  85             return primTypes[t.tag];
  86         }
  87         switch (t.tag) {
  88         case ERROR:     // fall through
  89         case CLASS:     return getDeclaredType((Type.ClassType) t);
  90         case WILDCARD:  return new WildcardTypeImpl(env, (Type.WildcardType) t);
  91         case TYPEVAR:   return new TypeVariableImpl(env, (Type.TypeVar) t);
  92         case ARRAY:     return new ArrayTypeImpl(env, (Type.ArrayType) t);
  93         case VOID:      return voidType;
  94         default:        throw new AssertionError();
  95         }
  96     }
  97 
  98     /**
  99      * Returns the declared type corresponding to a given ClassType.
 100      */
 101     public DeclaredType getDeclaredType(Type.ClassType t) {
 102         return
 103             hasFlag(t.tsym, Flags.ANNOTATION) ? new AnnotationTypeImpl(env, t) :
 104             hasFlag(t.tsym, Flags.INTERFACE)  ? new InterfaceTypeImpl(env, t) :
 105             hasFlag(t.tsym, Flags.ENUM)       ? new EnumTypeImpl(env, t) :
 106                                                 new ClassTypeImpl(env, t);
 107     }
 108 
 109     /**
 110      * Returns a collection of types corresponding to a list of javac Type
 111      * objects.
 112      */
 113     public Collection<TypeMirror> getTypes(Iterable<Type> types) {
 114         return getTypes(types, TypeMirror.class);
 115     }
 116 
 117     /**
 118      * Returns a collection of types corresponding to a list of javac Type
 119      * objects.  The element type of the result is specified explicitly.
 120      */
 121     public <T extends TypeMirror> Collection<T> getTypes(Iterable<Type> types,
 122                                                          Class<T> resType) {
 123         ArrayList<T> res = new ArrayList<T>();
 124         for (Type t : types) {
 125             TypeMirror mir = getType(t);
 126             if (resType.isInstance(mir)) {
 127                 res.add(resType.cast(mir));
 128             }
 129         }
 130         return res;
 131     }
 132 
 133     /**
 134      * Returns the string representation of a type.
 135      * Bounds of type variables are not included; bounds of wildcard types are.
 136      * Type names are qualified.
 137      */
 138     public String typeToString(Type t) {
 139         switch (t.tag) {
 140         case ARRAY:
 141             return typeToString(env.jctypes.elemtype(t)) + "[]";
 142         case CLASS:
 143             Type.ClassType c = (Type.ClassType) t;
 144             return DeclaredTypeImpl.toString(env, c);
 145         case WILDCARD:
 146             Type.WildcardType a = (Type.WildcardType) t;
 147             return WildcardTypeImpl.toString(env, a);
 148         default:
 149             return t.tsym.toString();
 150         }
 151     }
 152 
 153 
 154     /**
 155      * Does a symbol have a given flag?
 156      */
 157     private static boolean hasFlag(Symbol s, long flag) {
 158         return AptEnv.hasFlag(s, flag);
 159     }
 160 }