< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java

Print this page

  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.javac.code;
  27 
  28 import java.lang.annotation.Annotation;
  29 import java.util.ArrayDeque;
  30 import java.util.Collections;
  31 import java.util.EnumMap;
  32 import java.util.Map;
  33 import java.util.function.Predicate;
  34 
  35 import javax.lang.model.type.*;
  36 
  37 import com.sun.tools.javac.code.Symbol.*;

  38 import com.sun.tools.javac.code.TypeMetadata.Entry;
  39 import com.sun.tools.javac.code.Types.TypeMapping;
  40 import com.sun.tools.javac.code.Types.UniqueType;
  41 import com.sun.tools.javac.comp.Infer.IncorporationAction;
  42 import com.sun.tools.javac.jvm.ClassFile;
  43 import com.sun.tools.javac.jvm.PoolConstant;
  44 import com.sun.tools.javac.util.*;
  45 import com.sun.tools.javac.util.DefinedBy.Api;
  46 
  47 import static com.sun.tools.javac.code.BoundKind.*;
  48 import static com.sun.tools.javac.code.Flags.*;
  49 import static com.sun.tools.javac.code.Kinds.Kind.*;
  50 import static com.sun.tools.javac.code.TypeTag.*;
  51 
  52 /** This class represents Java types. The class itself defines the behavior of
  53  *  the following types:
  54  *  <pre>
  55  *  base types (tags: BYTE, CHAR, SHORT, INT, LONG, FLOAT, DOUBLE, BOOLEAN),
  56  *  type `void' (tag: VOID),
  57  *  the bottom type (tag: BOT),

 219         return lb.toList();
 220     }
 221 
 222     /**For ErrorType, returns the original type, otherwise returns the type itself.
 223      */
 224     public Type getOriginalType() {
 225         return this;
 226     }
 227 
 228     public <R,S> R accept(Type.Visitor<R,S> v, S s) { return v.visitType(this, s); }
 229 
 230     /** Define a type given its tag, type symbol, and type annotations
 231      */
 232 
 233     public Type(TypeSymbol tsym, TypeMetadata metadata) {
 234         Assert.checkNonNull(metadata);
 235         this.tsym = tsym;
 236         this.metadata = metadata;
 237     }
 238 





































































 239     /**
 240      * A subclass of {@link Types.TypeMapping} which applies a mapping recursively to the subterms
 241      * of a given type expression. This mapping returns the original type is no changes occurred
 242      * when recursively mapping the original type's subterms.
 243      */
 244     public abstract static class StructuralTypeMapping<S> extends Types.TypeMapping<S> {
 245 
 246         @Override
 247         public Type visitClassType(ClassType t, S s) {
 248             Type outer = t.getEnclosingType();
 249             Type outer1 = visit(outer, s);
 250             List<Type> typarams = t.getTypeArguments();
 251             List<Type> typarams1 = visit(typarams, s);
 252             if (outer1 == outer && typarams1 == typarams) return t;
 253             else return new ClassType(outer1, typarams1, t.tsym, t.metadata) {
 254                 @Override
 255                 protected boolean needsStripping() {
 256                     return true;
 257                 }
 258             };
 259         }
 260 
 261         @Override
 262         public Type visitWildcardType(WildcardType wt, S s) {
 263             Type t = wt.type;
 264             if (t != null)
 265                 t = visit(t, s);
 266             if (t == wt.type)
 267                 return wt;
 268             else
 269                 return new WildcardType(t, wt.kind, wt.tsym, wt.bound, wt.metadata) {
 270                     @Override
 271                     protected boolean needsStripping() {
 272                         return true;
 273                     }

 929 
 930         @DefinedBy(Api.LANGUAGE_MODEL)
 931         public Type getSuperBound() {
 932             if (kind == SUPER)
 933                 return type;
 934             else
 935                 return null;
 936         }
 937 
 938         @DefinedBy(Api.LANGUAGE_MODEL)
 939         public TypeKind getKind() {
 940             return TypeKind.WILDCARD;
 941         }
 942 
 943         @DefinedBy(Api.LANGUAGE_MODEL)
 944         public <R, P> R accept(TypeVisitor<R, P> v, P p) {
 945             return v.visitWildcard(this, p);
 946         }
 947     }
 948 


































 949     public static class ClassType extends Type implements DeclaredType, LoadableConstant,
 950                                                           javax.lang.model.type.ErrorType {
 951 














































































 952         /** The enclosing type of this type. If this is the type of an inner
 953          *  class, outer_field refers to the type of its enclosing
 954          *  instance class, in all other cases it refers to noType.
 955          */
 956         private Type outer_field;
 957 
 958         /** The type parameters of this type (to be set once class is loaded).
 959          */
 960         public List<Type> typarams_field;
 961 
 962         /** A cache variable for the type parameters of this type,
 963          *  appended to all parameters of its enclosing class.
 964          *  @see #allparams
 965          */
 966         public List<Type> allparams_field;
 967 
 968         /** The supertype of this class (to be set once class is loaded).
 969          */
 970         public Type supertype_field;
 971 
 972         /** The interfaces of this class (to be set once class is loaded).
 973          */
 974         public List<Type> interfaces_field;
 975 
 976         /** All the interfaces of this class, including missing ones.
 977          */
 978         public List<Type> all_interfaces_field;
 979 













 980         public ClassType(Type outer, List<Type> typarams, TypeSymbol tsym) {
 981             this(outer, typarams, tsym, TypeMetadata.EMPTY);
 982         }
 983 
 984         public ClassType(Type outer, List<Type> typarams, TypeSymbol tsym,
 985                          TypeMetadata metadata) {
 986             super(tsym, metadata);
 987             this.outer_field = outer;
 988             this.typarams_field = typarams;
 989             this.allparams_field = null;
 990             this.supertype_field = null;
 991             this.interfaces_field = null;

 992         }
 993 
 994         public int poolTag() {
 995             return ClassFile.CONSTANT_Class;
 996         }
 997 
 998         @Override
 999         public ClassType cloneWithMetadata(TypeMetadata md) {
1000             return new ClassType(outer_field, typarams_field, tsym, md) {
1001                 @Override
1002                 public Type baseType() { return ClassType.this.baseType(); }
1003             };
1004         }
1005 
1006         @Override
1007         public TypeTag getTag() {
1008             return CLASS;
1009         }
1010 
1011         @Override
1012         public <R,S> R accept(Type.Visitor<R,S> v, S s) {
1013             return v.visitClassType(this, s);
1014         }
1015 
1016         public Type constType(Object constValue) {
1017             final Object value = constValue;
1018             return new ClassType(getEnclosingType(), typarams_field, tsym, metadata) {
1019                     @Override
1020                     public Object constValue() {
1021                         return value;
1022                     }
1023                     @Override
1024                     public Type baseType() {
1025                         return tsym.type;
1026                     }
1027                 };
1028         }
1029 
1030         /** The Java source which this type represents.
1031          */
1032         @DefinedBy(Api.LANGUAGE_MODEL)
1033         public String toString() {
1034             StringBuilder buf = new StringBuilder();
1035             if (getEnclosingType().hasTag(CLASS) && tsym.owner.kind == TYP) {
1036                 buf.append(getEnclosingType().toString());
1037                 buf.append(".");
1038                 appendAnnotationsString(buf);
1039                 buf.append(className(tsym, false));
1040             } else {
1041                 if (isAnnotated()) {
1042                     if (!tsym.packge().isUnnamed()) {
1043                         buf.append(tsym.packge());
1044                         buf.append(".");
1045                     }
1046                     appendAnnotationsString(buf);
1047                     buf.append(tsym.name);
1048                 } else {
1049                     buf.append(className(tsym, true));
1050                 }
1051             }
1052 











1053             if (getTypeArguments().nonEmpty()) {
1054                 buf.append('<');
1055                 buf.append(getTypeArguments().toString());
1056                 buf.append(">");
1057             }
1058             return buf.toString();
1059         }
1060 //where
1061             private String className(Symbol sym, boolean longform) {
1062                 if (sym.name.isEmpty() && (sym.flags() & COMPOUND) != 0) {
1063                     StringBuilder s = new StringBuilder(supertype_field.toString());
1064                     for (List<Type> is=interfaces_field; is.nonEmpty(); is = is.tail) {
1065                         s.append("&");
1066                         s.append(is.head.toString());
1067                     }
1068                     return s.toString();
1069                 } else if (sym.name.isEmpty()) {
1070                     String s;
1071                     ClassType norm = (ClassType) tsym.type;
1072                     if (norm == null) {
1073                         s = Log.getLocalizedString("anonymous.class", (Object)null);
1074                     } else if (norm.interfaces_field != null && norm.interfaces_field.nonEmpty()) {
1075                         s = Log.getLocalizedString("anonymous.class",
1076                                                    norm.interfaces_field.head);
1077                     } else {
1078                         s = Log.getLocalizedString("anonymous.class",
1079                                                    norm.supertype_field);
1080                     }
1081                     if (moreInfo)
1082                         s += String.valueOf(sym.hashCode());
1083                     return s;
1084                 } else if (longform) {
1085                     return sym.getQualifiedName().toString();


1086                 } else {
1087                     return sym.name.toString();
1088                 }

1089             }
1090 




1091         @DefinedBy(Api.LANGUAGE_MODEL)
1092         public List<Type> getTypeArguments() {
1093             if (typarams_field == null) {
1094                 complete();
1095                 if (typarams_field == null)
1096                     typarams_field = List.nil();
1097             }
1098             return typarams_field;
1099         }
1100 
1101         public boolean hasErasedSupertypes() {
1102             return isRaw();
1103         }
1104 
1105         @DefinedBy(Api.LANGUAGE_MODEL)
1106         public Type getEnclosingType() {



1107             return outer_field;
1108         }
1109 
1110         public void setEnclosingType(Type outer) {
1111             outer_field = outer;
1112         }
1113 
1114         public List<Type> allparams() {
1115             if (allparams_field == null) {
1116                 allparams_field = getTypeArguments().prependList(getEnclosingType().allparams());
1117             }
1118             return allparams_field;
1119         }
1120 
1121         public boolean isErroneous() {
1122             return
1123                 getEnclosingType().isErroneous() ||
1124                 isErroneous(getTypeArguments()) ||
1125                 this != tsym.type && tsym.type.isErroneous();
1126         }
1127 
1128         public boolean isParameterized() {
1129             return allparams().tail != null;
1130             // optimization, was: allparams().nonEmpty();
1131         }
1132 
1133         @Override
1134         public boolean isReference() {
1135             return true;
1136         }
1137 










































































1138         @Override
1139         public boolean isNullOrReference() {
1140             return true;
1141         }
1142 
1143         /** A cache for the rank. */
1144         int rank_field = -1;
1145 
1146         /** A class type is raw if it misses some
1147          *  of its type parameter sections.
1148          *  After validation, this is equivalent to:
1149          *  {@code allparams.isEmpty() && tsym.type.allparams.nonEmpty(); }
1150          */
1151         public boolean isRaw() {
1152             return
1153                 this != tsym.type && // necessary, but not sufficient condition
1154                 tsym.type.allparams().nonEmpty() &&
1155                 allparams().isEmpty();
1156         }
1157 

1166 
1167         public void complete() {
1168             tsym.complete();
1169         }
1170 
1171         @DefinedBy(Api.LANGUAGE_MODEL)
1172         public TypeKind getKind() {
1173             tsym.apiComplete();
1174             return tsym.kind == TYP ? TypeKind.DECLARED : TypeKind.ERROR;
1175         }
1176 
1177         @DefinedBy(Api.LANGUAGE_MODEL)
1178         public <R, P> R accept(TypeVisitor<R, P> v, P p) {
1179             return v.visitDeclared(this, p);
1180         }
1181     }
1182 
1183     public static class ErasedClassType extends ClassType {
1184         public ErasedClassType(Type outer, TypeSymbol tsym,
1185                                TypeMetadata metadata) {
1186             super(outer, List.nil(), tsym, metadata);
1187         }
1188 
1189         @Override
1190         public boolean hasErasedSupertypes() {
1191             return true;
1192         }
1193     }
1194 
1195     // a clone of a ClassType that knows about the alternatives of a union type.
1196     public static class UnionClassType extends ClassType implements UnionType {
1197         final List<? extends Type> alternatives_field;
1198 
1199         public UnionClassType(ClassType ct, List<? extends Type> alternatives) {
1200             // Presently no way to refer to this type directly, so we
1201             // cannot put annotations directly on it.
1202             super(ct.outer_field, ct.typarams_field, ct.tsym);
1203             allparams_field = ct.allparams_field;
1204             supertype_field = ct.supertype_field;
1205             interfaces_field = ct.interfaces_field;
1206             all_interfaces_field = ct.interfaces_field;

2333         @Override
2334         public boolean isNullOrReference() {
2335             return true;
2336         }
2337 
2338     }
2339 
2340     public static class ErrorType extends ClassType
2341             implements javax.lang.model.type.ErrorType {
2342 
2343         private Type originalType = null;
2344 
2345         public ErrorType(ClassSymbol c, Type originalType) {
2346             this(originalType, c);
2347             c.type = this;
2348             c.kind = ERR;
2349             c.members_field = new Scope.ErrorScope(c);
2350         }
2351 
2352         public ErrorType(Type originalType, TypeSymbol tsym) {
2353             super(noType, List.nil(), null);
2354             this.tsym = tsym;
2355             this.originalType = (originalType == null ? noType : originalType);
2356         }
2357 
2358         private ErrorType(Type originalType, TypeSymbol tsym,
2359                           TypeMetadata metadata) {
2360             super(noType, List.nil(), null, metadata);
2361             this.tsym = tsym;
2362             this.originalType = (originalType == null ? noType : originalType);
2363         }
2364 
2365         @Override
2366         public ErrorType cloneWithMetadata(TypeMetadata md) {
2367             return new ErrorType(originalType, tsym, md) {
2368                 @Override
2369                 public Type baseType() { return ErrorType.this.baseType(); }
2370             };
2371         }
2372 
2373         @Override
2374         public TypeTag getTag() {
2375             return ERROR;
2376         }
2377 
2378         @Override
2379         public boolean isPartial() {
2380             return true;
2381         }
2382 
2383         @Override
2384         public boolean isReference() {
2385             return true;
2386         }
2387 

  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.javac.code;
  27 
  28 import java.lang.annotation.Annotation;
  29 import java.util.ArrayDeque;
  30 import java.util.Collections;
  31 import java.util.EnumMap;
  32 import java.util.Map;
  33 import java.util.function.Predicate;
  34 
  35 import javax.lang.model.type.*;
  36 
  37 import com.sun.tools.javac.code.Symbol.*;
  38 import com.sun.tools.javac.code.Type.ClassType.Flavor;
  39 import com.sun.tools.javac.code.TypeMetadata.Entry;
  40 import com.sun.tools.javac.code.Types.TypeMapping;
  41 import com.sun.tools.javac.code.Types.UniqueType;
  42 import com.sun.tools.javac.comp.Infer.IncorporationAction;
  43 import com.sun.tools.javac.jvm.ClassFile;
  44 import com.sun.tools.javac.jvm.PoolConstant;
  45 import com.sun.tools.javac.util.*;
  46 import com.sun.tools.javac.util.DefinedBy.Api;
  47 
  48 import static com.sun.tools.javac.code.BoundKind.*;
  49 import static com.sun.tools.javac.code.Flags.*;
  50 import static com.sun.tools.javac.code.Kinds.Kind.*;
  51 import static com.sun.tools.javac.code.TypeTag.*;
  52 
  53 /** This class represents Java types. The class itself defines the behavior of
  54  *  the following types:
  55  *  <pre>
  56  *  base types (tags: BYTE, CHAR, SHORT, INT, LONG, FLOAT, DOUBLE, BOOLEAN),
  57  *  type `void' (tag: VOID),
  58  *  the bottom type (tag: BOT),

 220         return lb.toList();
 221     }
 222 
 223     /**For ErrorType, returns the original type, otherwise returns the type itself.
 224      */
 225     public Type getOriginalType() {
 226         return this;
 227     }
 228 
 229     public <R,S> R accept(Type.Visitor<R,S> v, S s) { return v.visitType(this, s); }
 230 
 231     /** Define a type given its tag, type symbol, and type annotations
 232      */
 233 
 234     public Type(TypeSymbol tsym, TypeMetadata metadata) {
 235         Assert.checkNonNull(metadata);
 236         this.tsym = tsym;
 237         this.metadata = metadata;
 238     }
 239 
 240     public boolean isPrimitiveClass() {
 241         return false;
 242     }
 243 
 244     public boolean isValueClass() {
 245         return false;
 246     }
 247 
 248     public boolean isValueInterface() {
 249         return false;
 250     }
 251 
 252     public boolean isIdentityClass() {
 253         return false;
 254     }
 255 
 256     public boolean isIdentityInterface() {
 257         return false;
 258     }
 259 
 260     // Does this type need to be preloaded in the context of the referring class ??
 261     public boolean requiresPreload(Symbol referringClass) {
 262         if (this.tsym == referringClass)
 263             return false; // pointless
 264         if (this.isReferenceProjection())
 265             return true;
 266         return this.isValueClass() && !this.isPrimitiveClass();
 267     }
 268 
 269     /**
 270      * Return the `flavor' associated with a ClassType.
 271      * @see ClassType.Flavor
 272      */
 273     public Flavor getFlavor() {
 274         throw new AssertionError("Unexpected call to getFlavor() on a Type that is not a ClassType: " + this);
 275     }
 276 
 277     /**
 278      * @return true IFF the receiver is a reference projection of a primitive class type and false
 279      * for primitives or plain references
 280      */
 281     public boolean isReferenceProjection() {
 282         return false;
 283     }
 284 
 285     /**
 286      * @return the value projection type IFF the receiver is a reference projection of a primitive class type
 287      * and null otherwise
 288      */
 289     public Type valueProjection() {
 290         return null;
 291     }
 292 
 293     /**
 294      * @return the reference projection type IFF the receiver is a primitive class type
 295      * and null otherwise
 296      */
 297     public Type referenceProjection() {
 298         return null;
 299     }
 300 
 301     /**
 302      * @return the reference projection type IFF the receiver is a primitive class type or self otherwise.
 303      */
 304     public Type referenceProjectionOrSelf() {
 305         Type projection = referenceProjection();
 306         return projection != null ? projection : this;
 307     }
 308 
 309     /**
 310      * A subclass of {@link Types.TypeMapping} which applies a mapping recursively to the subterms
 311      * of a given type expression. This mapping returns the original type is no changes occurred
 312      * when recursively mapping the original type's subterms.
 313      */
 314     public abstract static class StructuralTypeMapping<S> extends Types.TypeMapping<S> {
 315 
 316         @Override
 317         public Type visitClassType(ClassType t, S s) {
 318             Type outer = t.getEnclosingType();
 319             Type outer1 = visit(outer, s);
 320             List<Type> typarams = t.getTypeArguments();
 321             List<Type> typarams1 = visit(typarams, s);
 322             if (outer1 == outer && typarams1 == typarams) return t;
 323             else return new ClassType(outer1, typarams1, t.tsym, t.metadata, t.getFlavor()) {
 324                 @Override
 325                 protected boolean needsStripping() {
 326                     return true;
 327                 }
 328             };
 329         }
 330 
 331         @Override
 332         public Type visitWildcardType(WildcardType wt, S s) {
 333             Type t = wt.type;
 334             if (t != null)
 335                 t = visit(t, s);
 336             if (t == wt.type)
 337                 return wt;
 338             else
 339                 return new WildcardType(t, wt.kind, wt.tsym, wt.bound, wt.metadata) {
 340                     @Override
 341                     protected boolean needsStripping() {
 342                         return true;
 343                     }

 999 
1000         @DefinedBy(Api.LANGUAGE_MODEL)
1001         public Type getSuperBound() {
1002             if (kind == SUPER)
1003                 return type;
1004             else
1005                 return null;
1006         }
1007 
1008         @DefinedBy(Api.LANGUAGE_MODEL)
1009         public TypeKind getKind() {
1010             return TypeKind.WILDCARD;
1011         }
1012 
1013         @DefinedBy(Api.LANGUAGE_MODEL)
1014         public <R, P> R accept(TypeVisitor<R, P> v, P p) {
1015             return v.visitWildcard(this, p);
1016         }
1017     }
1018 
1019     public static class ConstantPoolQType implements PoolConstant {
1020 
1021         public final Type type;
1022         final Types types;
1023 
1024         public ConstantPoolQType(Type type, Types types) {
1025             this.type = type;
1026             this.types = types;
1027         }
1028 
1029         @Override
1030         public Object poolKey(Types types) {
1031             return this;
1032         }
1033 
1034         @Override
1035         public int poolTag() {
1036             return ClassFile.CONSTANT_Class;
1037         }
1038 
1039         public int hashCode() {
1040             return types.hashCode(type);
1041         }
1042 
1043         public boolean equals(Object obj) {
1044             return (obj instanceof ConstantPoolQType) &&
1045                     types.isSameType(type, ((ConstantPoolQType)obj).type);
1046         }
1047 
1048         public String toString() {
1049             return type.toString();
1050         }
1051     }
1052 
1053     public static class ClassType extends Type implements DeclaredType, LoadableConstant,
1054                                                           javax.lang.model.type.ErrorType {
1055 
1056         /**
1057          * The 'flavor' of a ClassType indicates its reference/primitive projectionness
1058          * viewed against the default nature of the associated class.
1059          */
1060         public enum Flavor {
1061 
1062             /**
1063              * Classic reference type. Also reference projection type of a reference-favoring aka
1064              * reference-default primitive class type
1065              */
1066             L_TypeOf_L,
1067 
1068             /**
1069              * Reference projection type of a primitive-favoring aka primitive-default
1070              * plain vanilla primitive class type,
1071              */
1072             L_TypeOf_Q,
1073 
1074             /**
1075              * Value projection type of a primitive-favoring aka primitive-default
1076              * plain vanilla primitive class type,
1077              */
1078             Q_TypeOf_Q,
1079 
1080             /**
1081              * Value projection type of a reference-favoring aka
1082              * reference-default primitive class type
1083              */
1084             Q_TypeOf_L,
1085 
1086             /**
1087              * Reference projection type of a class type of an as yet unknown default provenance, 'X' will be
1088              * discovered to be 'L' or 'Q' in "due course" and mutated suitably.
1089              */
1090             L_TypeOf_X,
1091 
1092             /**
1093              * Value projection type of a class type of an as yet unknown default provenance, 'X' will be
1094              * discovered to be 'L' or 'Q' in "due course" and mutated suitably.
1095              */
1096             Q_TypeOf_X,
1097 
1098             /**
1099              *  As yet unknown projection type of an as yet unknown default provenance class.
1100              */
1101             X_Typeof_X,
1102 
1103             /**
1104              *  An error type - we don't care to discriminate them any further.
1105              */
1106              E_Typeof_X;
1107 
1108             // We don't seem to need X_Typeof_L or X_Typeof_Q so far.
1109 
1110             // Transform a larval form into a more evolved form
1111             public Flavor metamorphose(boolean isPrimtiveClass) {
1112 
1113                 switch (this) {
1114 
1115                     case E_Typeof_X:  // stunted form
1116                     case L_TypeOf_L:
1117                     case L_TypeOf_Q:
1118                     case Q_TypeOf_L:
1119                     case Q_TypeOf_Q:
1120                             // These are fully evolved sealed forms or stunted - no futher transformation
1121                             return this;
1122                     case L_TypeOf_X:
1123                             return isPrimtiveClass ? L_TypeOf_Q : L_TypeOf_L;
1124                     case Q_TypeOf_X:
1125                             return isPrimtiveClass ? Q_TypeOf_Q : Q_TypeOf_L;
1126                     case X_Typeof_X:
1127                             return isPrimtiveClass ? Q_TypeOf_Q : L_TypeOf_L;
1128                     default:
1129                             throw new AssertionError("Unexpected class type flavor");
1130                 }
1131             }
1132         }
1133 
1134         /** The enclosing type of this type. If this is the type of an inner
1135          *  class, outer_field refers to the type of its enclosing
1136          *  instance class, in all other cases it refers to noType.
1137          */
1138         private Type outer_field;
1139 
1140         /** The type parameters of this type (to be set once class is loaded).
1141          */
1142         public List<Type> typarams_field;
1143 
1144         /** A cache variable for the type parameters of this type,
1145          *  appended to all parameters of its enclosing class.
1146          *  @see #allparams
1147          */
1148         public List<Type> allparams_field;
1149 
1150         /** The supertype of this class (to be set once class is loaded).
1151          */
1152         public Type supertype_field;
1153 
1154         /** The interfaces of this class (to be set once class is loaded).
1155          */
1156         public List<Type> interfaces_field;
1157 
1158         /** All the interfaces of this class, including missing ones.
1159          */
1160         public List<Type> all_interfaces_field;
1161 
1162         /** The 'other' projection: If 'this' is type of a primitive class, then 'projection' is the
1163          *  reference projection type and vice versa. Lazily initialized, not to be accessed directly.
1164         */
1165         public ClassType projection;
1166 
1167         /** Is this L of default {L, Q, X} or Q of default {L, Q, X} ?
1168          */
1169         public Flavor flavor;
1170 
1171         /*
1172          * Use of this constructor is kinda sorta deprecated, use the other constructor
1173          * that forces the call site to consider and include the class type flavor.
1174          */
1175         public ClassType(Type outer, List<Type> typarams, TypeSymbol tsym) {
1176             this(outer, typarams, tsym, TypeMetadata.EMPTY, Flavor.L_TypeOf_L);
1177         }
1178 
1179         public ClassType(Type outer, List<Type> typarams, TypeSymbol tsym,
1180                          TypeMetadata metadata, Flavor flavor) {
1181             super(tsym, metadata);
1182             this.outer_field = outer;
1183             this.typarams_field = typarams;
1184             this.allparams_field = null;
1185             this.supertype_field = null;
1186             this.interfaces_field = null;
1187             this.flavor = flavor;
1188         }
1189 
1190         public int poolTag() {
1191             return ClassFile.CONSTANT_Class;
1192         }
1193 
1194         @Override
1195         public ClassType cloneWithMetadata(TypeMetadata md) {
1196             return new ClassType(outer_field, typarams_field, tsym, md, flavor) {
1197                 @Override
1198                 public Type baseType() { return ClassType.this.baseType(); }
1199             };
1200         }
1201 
1202         @Override
1203         public TypeTag getTag() {
1204             return CLASS;
1205         }
1206 
1207         @Override
1208         public <R,S> R accept(Type.Visitor<R,S> v, S s) {
1209             return v.visitClassType(this, s);
1210         }
1211 
1212         public Type constType(Object constValue) {
1213             final Object value = constValue;
1214             return new ClassType(getEnclosingType(), typarams_field, tsym, metadata, flavor) {
1215                     @Override
1216                     public Object constValue() {
1217                         return value;
1218                     }
1219                     @Override
1220                     public Type baseType() {
1221                         return tsym.type;
1222                     }
1223                 };
1224         }
1225 
1226         /** The Java source which this type represents.
1227          */
1228         @DefinedBy(Api.LANGUAGE_MODEL)
1229         public String toString() {
1230             StringBuilder buf = new StringBuilder();
1231             if (getEnclosingType().hasTag(CLASS) && tsym.owner.kind == TYP) {
1232                 buf.append(getEnclosingType().toString());
1233                 buf.append(".");
1234                 appendAnnotationsString(buf);
1235                 buf.append(className(tsym, false));
1236             } else {
1237                 if (isAnnotated()) {
1238                     if (!tsym.packge().isUnnamed()) {
1239                         buf.append(tsym.packge());
1240                         buf.append(".");
1241                     }
1242                     appendAnnotationsString(buf);
1243                     buf.append(tsym.name);
1244                 } else {
1245                     buf.append(className(tsym, true));
1246                 }
1247             }
1248 
1249             boolean isReferenceProjection;
1250             try {
1251                 isReferenceProjection = isReferenceProjection();
1252             } catch (CompletionFailure cf) {
1253                 isReferenceProjection = false; // handle missing types gracefully.
1254             }
1255             if (isReferenceProjection) {
1256                 buf.append('.');
1257                 buf.append(tsym.name.table.names.ref);
1258             }
1259 
1260             if (getTypeArguments().nonEmpty()) {
1261                 buf.append('<');
1262                 buf.append(getTypeArguments().toString());
1263                 buf.append(">");
1264             }
1265             return buf.toString();
1266         }
1267 //where
1268             private String className(Symbol sym, boolean longform) {
1269                 if (sym.name.isEmpty() && (sym.flags() & COMPOUND) != 0) {
1270                     StringBuilder s = new StringBuilder(supertype_field.toString());
1271                     for (List<Type> is=interfaces_field; is.nonEmpty(); is = is.tail) {
1272                         s.append("&");
1273                         s.append(is.head.toString());
1274                     }
1275                     return s.toString();
1276                 } else if (sym.name.isEmpty()) {
1277                     String s;
1278                     ClassType norm = (ClassType) tsym.type;
1279                     if (norm == null) {
1280                         s = Log.getLocalizedString("anonymous.class", (Object)null);
1281                     } else if (norm.interfaces_field != null && norm.interfaces_field.nonEmpty()) {
1282                         s = Log.getLocalizedString("anonymous.class",
1283                                                    norm.interfaces_field.head);
1284                     } else {
1285                         s = Log.getLocalizedString("anonymous.class",
1286                                                    norm.supertype_field);
1287                     }
1288                     if (moreInfo)
1289                         s += String.valueOf(sym.hashCode());
1290                     return s;
1291                 }
1292                 String s;
1293                 if (longform) {
1294                     s =  sym.getQualifiedName().toString();
1295                 } else {
1296                     s = sym.name.toString();
1297                 }
1298                 return s;
1299             }
1300 
1301         public Flavor getFlavor() {
1302             return flavor;
1303         }
1304 
1305         @DefinedBy(Api.LANGUAGE_MODEL)
1306         public List<Type> getTypeArguments() {
1307             if (typarams_field == null) {
1308                 complete();
1309                 if (typarams_field == null)
1310                     typarams_field = List.nil();
1311             }
1312             return typarams_field;
1313         }
1314 
1315         public boolean hasErasedSupertypes() {
1316             return isRaw();
1317         }
1318 
1319         @DefinedBy(Api.LANGUAGE_MODEL)
1320         public Type getEnclosingType() {
1321             if (outer_field != null && outer_field.isReferenceProjection()) {
1322                 outer_field = outer_field.valueProjection();
1323             }
1324             return outer_field;
1325         }
1326 
1327         public void setEnclosingType(Type outer) {
1328             outer_field = outer;
1329         }
1330 
1331         public List<Type> allparams() {
1332             if (allparams_field == null) {
1333                 allparams_field = getTypeArguments().prependList(getEnclosingType().allparams());
1334             }
1335             return allparams_field;
1336         }
1337 
1338         public boolean isErroneous() {
1339             return
1340                 getEnclosingType().isErroneous() ||
1341                 isErroneous(getTypeArguments()) ||
1342                 this != tsym.type && tsym.type.isErroneous();
1343         }
1344 
1345         public boolean isParameterized() {
1346             return allparams().tail != null;
1347             // optimization, was: allparams().nonEmpty();
1348         }
1349 
1350         @Override
1351         public boolean isReference() {
1352             return true;
1353         }
1354 
1355         @Override
1356         public boolean isPrimitiveClass() {
1357             return !isReferenceProjection() && tsym != null && tsym.isPrimitiveClass();
1358         }
1359 
1360         @Override
1361         public boolean isValueClass() {
1362             return !isReferenceProjection() && tsym != null && tsym.isValueClass();
1363         }
1364 
1365         @Override
1366         public boolean isValueInterface() {
1367             return tsym != null && tsym.isValueInterface();
1368         }
1369 
1370         @Override
1371         public boolean isIdentityClass() {
1372             return !isReferenceProjection() && tsym != null && tsym.isIdentityClass();
1373         }
1374 
1375         @Override
1376         public boolean isIdentityInterface() {
1377             return isInterface() && tsym.isIdentityInterface();
1378         }
1379 
1380         @Override
1381         public boolean isReferenceProjection() {
1382             // gaurd against over-eager and/or inopportune completion
1383             if (tsym != null) {
1384                 if (flavor == Flavor.L_TypeOf_X || tsym.isCompleted()) {
1385                     flavor = flavor.metamorphose(tsym.isPrimitiveClass());
1386                 }
1387             }
1388             return flavor == Flavor.L_TypeOf_Q;
1389         }
1390 
1391         @Override
1392         public Type valueProjection() {
1393             if (!isReferenceProjection())
1394                 return null;
1395 
1396             if (projection !=  null)
1397                 return projection;
1398 
1399             projection = new ClassType(outer_field, typarams_field, tsym, getMetadata(), Flavor.Q_TypeOf_Q);
1400             projection.allparams_field = allparams_field;
1401             projection.supertype_field = supertype_field;
1402 
1403             projection.interfaces_field = interfaces_field;
1404             projection.all_interfaces_field = all_interfaces_field;
1405             projection.projection = this;
1406             return projection;
1407         }
1408 
1409         // return the reference projection type preserving parameterizations
1410         @Override
1411         public ClassType referenceProjection() {
1412 
1413             if (!isPrimitiveClass())
1414                 return null;
1415 
1416             if (projection != null)
1417                 return projection;
1418 
1419             projection = new ClassType(outer_field, typarams_field, tsym, getMetadata(), Flavor.L_TypeOf_Q);
1420             projection.allparams_field = allparams_field;
1421             projection.supertype_field = supertype_field;
1422 
1423             projection.interfaces_field = interfaces_field;
1424             projection.all_interfaces_field = all_interfaces_field;
1425             projection.projection = this;
1426             return projection;
1427         }
1428 
1429         @Override
1430         public boolean isNullOrReference() {
1431             return true;
1432         }
1433 
1434         /** A cache for the rank. */
1435         int rank_field = -1;
1436 
1437         /** A class type is raw if it misses some
1438          *  of its type parameter sections.
1439          *  After validation, this is equivalent to:
1440          *  {@code allparams.isEmpty() && tsym.type.allparams.nonEmpty(); }
1441          */
1442         public boolean isRaw() {
1443             return
1444                 this != tsym.type && // necessary, but not sufficient condition
1445                 tsym.type.allparams().nonEmpty() &&
1446                 allparams().isEmpty();
1447         }
1448 

1457 
1458         public void complete() {
1459             tsym.complete();
1460         }
1461 
1462         @DefinedBy(Api.LANGUAGE_MODEL)
1463         public TypeKind getKind() {
1464             tsym.apiComplete();
1465             return tsym.kind == TYP ? TypeKind.DECLARED : TypeKind.ERROR;
1466         }
1467 
1468         @DefinedBy(Api.LANGUAGE_MODEL)
1469         public <R, P> R accept(TypeVisitor<R, P> v, P p) {
1470             return v.visitDeclared(this, p);
1471         }
1472     }
1473 
1474     public static class ErasedClassType extends ClassType {
1475         public ErasedClassType(Type outer, TypeSymbol tsym,
1476                                TypeMetadata metadata) {
1477             super(outer, List.nil(), tsym, metadata, tsym.type.getFlavor());
1478         }
1479 
1480         @Override
1481         public boolean hasErasedSupertypes() {
1482             return true;
1483         }
1484     }
1485 
1486     // a clone of a ClassType that knows about the alternatives of a union type.
1487     public static class UnionClassType extends ClassType implements UnionType {
1488         final List<? extends Type> alternatives_field;
1489 
1490         public UnionClassType(ClassType ct, List<? extends Type> alternatives) {
1491             // Presently no way to refer to this type directly, so we
1492             // cannot put annotations directly on it.
1493             super(ct.outer_field, ct.typarams_field, ct.tsym);
1494             allparams_field = ct.allparams_field;
1495             supertype_field = ct.supertype_field;
1496             interfaces_field = ct.interfaces_field;
1497             all_interfaces_field = ct.interfaces_field;

2624         @Override
2625         public boolean isNullOrReference() {
2626             return true;
2627         }
2628 
2629     }
2630 
2631     public static class ErrorType extends ClassType
2632             implements javax.lang.model.type.ErrorType {
2633 
2634         private Type originalType = null;
2635 
2636         public ErrorType(ClassSymbol c, Type originalType) {
2637             this(originalType, c);
2638             c.type = this;
2639             c.kind = ERR;
2640             c.members_field = new Scope.ErrorScope(c);
2641         }
2642 
2643         public ErrorType(Type originalType, TypeSymbol tsym) {
2644             super(noType, List.nil(), tsym, TypeMetadata.EMPTY, Flavor.E_Typeof_X);

2645             this.originalType = (originalType == null ? noType : originalType);
2646         }
2647 
2648         private ErrorType(Type originalType, TypeSymbol tsym,
2649                           TypeMetadata metadata, Flavor flavor) {
2650             super(noType, List.nil(), null, metadata, flavor);
2651             this.tsym = tsym;
2652             this.originalType = (originalType == null ? noType : originalType);
2653         }
2654 
2655         @Override
2656         public ErrorType cloneWithMetadata(TypeMetadata md) {
2657             return new ErrorType(originalType, tsym, md, getFlavor()) {
2658                 @Override
2659                 public Type baseType() { return ErrorType.this.baseType(); }
2660             };
2661         }
2662 
2663         @Override
2664         public TypeTag getTag() {
2665             return ERROR;
2666         }
2667 
2668         @Override
2669         public boolean isPartial() {
2670             return true;
2671         }
2672 
2673         @Override
2674         public boolean isReference() {
2675             return true;
2676         }
2677 
< prev index next >