aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TypesUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TypesUtils.java')
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TypesUtils.java296
1 files changed, 209 insertions, 87 deletions
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TypesUtils.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TypesUtils.java
index f024a60feb..fe7456f6d2 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TypesUtils.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TypesUtils.java
@@ -1,8 +1,19 @@
package org.checkerframework.javacutil;
+import static com.sun.tools.javac.code.TypeTag.WILDCARD;
+
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.TypeTag;
+import com.sun.tools.javac.model.JavacTypes;
+import com.sun.tools.javac.processing.JavacProcessingEnvironment;
+import com.sun.tools.javac.util.Context;
import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.Element;
import javax.lang.model.element.Name;
+import javax.lang.model.element.NestingKind;
import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
@@ -12,26 +23,18 @@ import javax.lang.model.type.WildcardType;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
-import com.sun.tools.javac.code.Symtab;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.TypeTag;
-import com.sun.tools.javac.model.JavacTypes;
-import com.sun.tools.javac.processing.JavacProcessingEnvironment;
-import com.sun.tools.javac.util.Context;
-
-/**
- * A utility class that helps with {@link TypeMirror}s.
- *
- */
+/** A utility class that helps with {@link TypeMirror}s. */
// TODO: This class needs significant restructuring
public final class TypesUtils {
// Class cannot be instantiated
- private TypesUtils() { throw new AssertionError("Class TypesUtils cannot be instantiated."); }
+ private TypesUtils() {
+ throw new AssertionError("Class TypesUtils cannot be instantiated.");
+ }
/**
- * Gets the fully qualified name for a provided type. It returns an empty
- * name if type is an anonymous type.
+ * Gets the fully qualified name for a provided type. It returns an empty name if type is an
+ * anonymous type.
*
* @param type the declared type
* @return the name corresponding to that type
@@ -44,7 +47,7 @@ public final class TypesUtils {
/**
* Checks if the type represents a java.lang.Object declared type.
*
- * @param type the type
+ * @param type the type
* @return true iff type represents java.lang.Object
*/
public static boolean isObject(TypeMirror type) {
@@ -54,7 +57,7 @@ public final class TypesUtils {
/**
* Checks if the type represents a java.lang.Class declared type.
*
- * @param type the type
+ * @param type the type
* @return true iff type represents java.lang.Class
*/
public static boolean isClass(TypeMirror type) {
@@ -62,11 +65,11 @@ public final class TypesUtils {
}
/**
- * Checks if the type represents a java.lang.String declared type.
- * TODO: it would be cleaner to use String.class.getCanonicalName(), but
- * the two existing methods above don't do that, I guess for performance reasons.
+ * Checks if the type represents a java.lang.String declared type. TODO: it would be cleaner to
+ * use String.class.getCanonicalName(), but the two existing methods above don't do that, I
+ * guess for performance reasons.
*
- * @param type the type
+ * @param type the type
* @return true iff type represents java.lang.String
*/
public static boolean isString(TypeMirror type) {
@@ -74,8 +77,8 @@ public final class TypesUtils {
}
/**
- * Checks if the type represents a boolean type, that is either boolean
- * (primitive type) or java.lang.Boolean.
+ * Checks if the type represents a boolean type, that is either boolean (primitive type) or
+ * java.lang.Boolean.
*
* @param type the type to test
* @return true iff type represents a boolean type
@@ -93,14 +96,15 @@ public final class TypesUtils {
*/
public static boolean isDeclaredOfName(TypeMirror type, CharSequence qualifiedName) {
return type.getKind() == TypeKind.DECLARED
- && getQualifiedName((DeclaredType)type).contentEquals(qualifiedName);
+ && getQualifiedName((DeclaredType) type).contentEquals(qualifiedName);
}
public static boolean isBoxedPrimitive(TypeMirror type) {
- if (type.getKind() != TypeKind.DECLARED)
+ if (type.getKind() != TypeKind.DECLARED) {
return false;
+ }
- String qualifiedName = getQualifiedName((DeclaredType)type).toString();
+ String qualifiedName = getQualifiedName((DeclaredType) type).toString();
return (qualifiedName.equals("java.lang.Boolean")
|| qualifiedName.equals("java.lang.Byte")
@@ -112,44 +116,57 @@ public final class TypesUtils {
|| qualifiedName.equals("java.lang.Float"));
}
- /** @return type represents a Throwable type (e.g. Exception, Error) **/
+ /** @return type represents a Throwable type (e.g. Exception, Error) */
public static boolean isThrowable(TypeMirror type) {
while (type != null && type.getKind() == TypeKind.DECLARED) {
DeclaredType dt = (DeclaredType) type;
TypeElement elem = (TypeElement) dt.asElement();
Name name = elem.getQualifiedName();
- if ("java.lang.Throwable".contentEquals(name))
+ if ("java.lang.Throwable".contentEquals(name)) {
return true;
+ }
type = elem.getSuperclass();
}
return false;
}
/**
+ * Returns true iff the argument is an anonymous type.
+ *
+ * @return whether the argument is an anonymous type
+ */
+ public static boolean isAnonymous(TypeMirror type) {
+ return (type instanceof DeclaredType)
+ && (((TypeElement) ((DeclaredType) type).asElement())
+ .getNestingKind()
+ .equals(NestingKind.ANONYMOUS));
+ }
+
+ /**
* Returns true iff the argument is a primitive type.
*
- * @return whether the argument is a primitive type
+ * @return whether the argument is a primitive type
*/
public static boolean isPrimitive(TypeMirror type) {
switch (type.getKind()) {
- case BOOLEAN:
- case BYTE:
- case CHAR:
- case DOUBLE:
- case FLOAT:
- case INT:
- case LONG:
- case SHORT:
- return true;
- default:
- return false;
+ case BOOLEAN:
+ case BYTE:
+ case CHAR:
+ case DOUBLE:
+ case FLOAT:
+ case INT:
+ case LONG:
+ case SHORT:
+ return true;
+ default:
+ return false;
}
}
/**
* Returns true iff the arguments are both the same primitive types.
*
- * @return whether the arguments are the same primitive types
+ * @return whether the arguments are the same primitive types
*/
public static boolean areSamePrimitiveTypes(TypeMirror left, TypeMirror right) {
if (!isPrimitive(left) || !isPrimitive(right)) {
@@ -162,65 +179,64 @@ public final class TypesUtils {
/**
* Returns true iff the argument is a primitive numeric type.
*
- * @return whether the argument is a primitive numeric type
+ * @return whether the argument is a primitive numeric type
*/
public static boolean isNumeric(TypeMirror type) {
switch (type.getKind()) {
- case BYTE:
- case CHAR:
- case DOUBLE:
- case FLOAT:
- case INT:
- case LONG:
- case SHORT:
- return true;
- default:
- return false;
+ case BYTE:
+ case CHAR:
+ case DOUBLE:
+ case FLOAT:
+ case INT:
+ case LONG:
+ case SHORT:
+ return true;
+ default:
+ return false;
}
}
/**
* Returns true iff the argument is an integral type.
*
- * @return whether the argument is an integral type
+ * @return whether the argument is an integral type
*/
public static boolean isIntegral(TypeMirror type) {
switch (type.getKind()) {
- case BYTE:
- case CHAR:
- case INT:
- case LONG:
- case SHORT:
- return true;
- default:
- return false;
+ case BYTE:
+ case CHAR:
+ case INT:
+ case LONG:
+ case SHORT:
+ return true;
+ default:
+ return false;
}
}
/**
* Returns true iff the argument is a floating point type.
*
- * @return whether the argument is a floating point type
+ * @return whether the argument is a floating point type
*/
public static boolean isFloating(TypeMirror type) {
switch (type.getKind()) {
- case DOUBLE:
- case FLOAT:
- return true;
- default:
- return false;
+ case DOUBLE:
+ case FLOAT:
+ return true;
+ default:
+ return false;
}
}
/**
- * Returns the widened numeric type for an arithmetic operation
- * performed on a value of the left type and the right type.
- * Defined in JLS 5.6.2. We return a {@link TypeKind} because
- * creating a {@link TypeMirror} requires a {@link Types} object
- * from the {@link javax.annotation.processing.ProcessingEnvironment}.
+ * Returns the widened numeric type for an arithmetic operation performed on a value of the left
+ * type and the right type. Defined in JLS 5.6.2. We return a {@link TypeKind} because creating
+ * a {@link TypeMirror} requires a {@link Types} object from the {@link
+ * javax.annotation.processing.ProcessingEnvironment}.
*
- * @return the result of widening numeric conversion, or NONE when
- * the conversion cannot be performed
+ * @return the result of widening numeric conversion, or NONE when the conversion cannot be
+ * performed
*/
public static TypeKind widenedNumericType(TypeMirror left, TypeMirror right) {
if (!isNumeric(left) || !isNumeric(right)) {
@@ -246,13 +262,12 @@ public final class TypesUtils {
}
/**
- * If the argument is a bounded TypeVariable or WildcardType,
- * return its non-variable, non-wildcard upper bound. Otherwise,
- * return the type itself.
+ * If the argument is a bounded TypeVariable or WildcardType, return its non-variable,
+ * non-wildcard upper bound. Otherwise, return the type itself.
*
- * @param type a type
- * @return the non-variable, non-wildcard upper bound of a type,
- * if it has one, or itself if it has no bounds
+ * @param type a type
+ * @return the non-variable, non-wildcard upper bound of a type, if it has one, or itself if it
+ * has no bounds
*/
public static TypeMirror upperBound(TypeMirror type) {
do {
@@ -277,8 +292,28 @@ public final class TypesUtils {
return type;
}
- // Version of com.sun.tools.javac.code.Types.wildUpperBound(Type)
- // that works with both jdk8 (called upperBound there) and jdk8u.
+ /**
+ * Get the type parameter for this wildcard from the underlying type's bound field This field is
+ * sometimes null, in that case this method will return null
+ *
+ * @return the TypeParameterElement the wildcard is an argument to
+ */
+ public static TypeParameterElement wildcardToTypeParam(final Type.WildcardType wildcard) {
+
+ final Element typeParamElement;
+ if (wildcard.bound != null) {
+ typeParamElement = wildcard.bound.asElement();
+ } else {
+ typeParamElement = null;
+ }
+
+ return (TypeParameterElement) typeParamElement;
+ }
+
+ /**
+ * Version of com.sun.tools.javac.code.Types.wildUpperBound(Type) that works with both jdk8
+ * (called upperBound there) and jdk8u.
+ */
// TODO: contrast to upperBound.
public static Type wildUpperBound(ProcessingEnvironment env, TypeMirror tm) {
Type t = (Type) tm;
@@ -291,15 +326,27 @@ public final class TypesUtils {
} else {
return wildUpperBound(env, w.type);
}
- }
- else {
+ } else {
return TypeAnnotationUtils.unannotatedType(t);
}
}
/**
- * Returns the {@link TypeMirror} for a given {@link Class}.
+ * Version of com.sun.tools.javac.code.Types.wildLowerBound(Type) that works with both jdk8
+ * (called upperBound there) and jdk8u.
*/
+ public static Type wildLowerBound(ProcessingEnvironment env, TypeMirror tm) {
+ Type t = (Type) tm;
+ if (t.hasTag(WILDCARD)) {
+ Context context = ((JavacProcessingEnvironment) env).getContext();
+ Symtab syms = Symtab.instance(context);
+ Type.WildcardType w = (Type.WildcardType) TypeAnnotationUtils.unannotatedType(t);
+ return w.isExtendsBound() ? syms.botType : wildLowerBound(env, w.type);
+ } else {
+ return TypeAnnotationUtils.unannotatedType(t);
+ }
+ }
+ /** Returns the {@link TypeMirror} for a given {@link Class}. */
public static TypeMirror typeFromClass(Types types, Elements elements, Class<?> clazz) {
if (clazz == void.class) {
return types.getNoType(TypeKind.VOID);
@@ -320,11 +367,86 @@ public final class TypesUtils {
}
}
- /**
- * Returns an {@link ArrayType} with elements of type {@code componentType}.
- */
+ /** Returns an {@link ArrayType} with elements of type {@code componentType}. */
public static ArrayType createArrayType(Types types, TypeMirror componentType) {
JavacTypes t = (JavacTypes) types;
return t.getArrayType(componentType);
}
+
+ /**
+ * Returns true if declaredType is a Class that is used to box primitive type (e.g.
+ * declaredType=java.lang.Double and primitiveType=22.5d )
+ */
+ public static boolean isBoxOf(TypeMirror declaredType, TypeMirror primitiveType) {
+ if (declaredType.getKind() != TypeKind.DECLARED) {
+ return false;
+ }
+
+ final String qualifiedName = getQualifiedName((DeclaredType) declaredType).toString();
+ switch (primitiveType.getKind()) {
+ case BOOLEAN:
+ return qualifiedName.equals("java.lang.Boolean");
+ case BYTE:
+ return qualifiedName.equals("java.lang.Byte");
+ case CHAR:
+ return qualifiedName.equals("java.lang.Character");
+ case DOUBLE:
+ return qualifiedName.equals("java.lang.Double");
+ case FLOAT:
+ return qualifiedName.equals("java.lang.Float");
+ case INT:
+ return qualifiedName.equals("java.lang.Integer");
+ case LONG:
+ return qualifiedName.equals("java.lang.Long");
+ case SHORT:
+ return qualifiedName.equals("java.lang.Short");
+
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Given a bounded type (wildcard or typevar) get the concrete type of its upper bound. If the
+ * bounded type extends other bounded types, this method will iterate through their bounds until
+ * a class, interface, or intersection is found.
+ *
+ * @return a type that is not a wildcard or typevar, or null if this type is an unbounded
+ * wildcard
+ */
+ public static TypeMirror findConcreteUpperBound(final TypeMirror boundedType) {
+ TypeMirror effectiveUpper = boundedType;
+ outerLoop:
+ while (true) {
+ switch (effectiveUpper.getKind()) {
+ case WILDCARD:
+ effectiveUpper =
+ ((javax.lang.model.type.WildcardType) effectiveUpper).getExtendsBound();
+ if (effectiveUpper == null) {
+ return null;
+ }
+ break;
+
+ case TYPEVAR:
+ effectiveUpper = ((TypeVariable) effectiveUpper).getUpperBound();
+ break;
+
+ default:
+ break outerLoop;
+ }
+ }
+ return effectiveUpper;
+ }
+
+ /**
+ * Returns true if the erased type of subtype is a subtype of the erased type of supertype.
+ *
+ * @param types Types
+ * @param subtype possible subtype
+ * @param supertype possible supertype
+ * @return true if the erased type of subtype is a subtype of the erased type of supertype
+ */
+ public static boolean isErasedSubtype(Types types, TypeMirror subtype, TypeMirror supertype) {
+ return types.isSubtype(types.erasure(subtype), types.erasure(supertype));
+ }
}