aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/InternalUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/InternalUtils.java')
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/InternalUtils.java291
1 files changed, 195 insertions, 96 deletions
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/InternalUtils.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/InternalUtils.java
index 40cb4747f5..10a48cd719 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/InternalUtils.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/InternalUtils.java
@@ -1,19 +1,5 @@
package org.checkerframework.javacutil;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.type.TypeVariable;
-import javax.lang.model.type.WildcardType;
-import javax.lang.model.util.Elements;
-
import com.sun.source.tree.AnnotatedTypeTree;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.ArrayAccessTree;
@@ -29,6 +15,7 @@ import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Type.CapturedType;
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
@@ -43,15 +30,29 @@ import com.sun.tools.javac.tree.JCTree.JCNewClass;
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeVariable;
+import javax.lang.model.type.WildcardType;
+import javax.lang.model.util.Elements;
/*>>>
- import org.checkerframework.checker.nullness.qual.*;
- */
+import org.checkerframework.checker.nullness.qual.*;
+*/
/**
- * Static utility methods used by annotation abstractions in this package. Some
- * methods in this class depend on the use of Sun javac internals; any procedure
- * in the Checker Framework that uses a non-public API should be placed here.
+ * Static utility methods used by annotation abstractions in this package. Some methods in this
+ * class depend on the use of Sun javac internals; any procedure in the Checker Framework that uses
+ * a non-public API should be placed here.
*/
public class InternalUtils {
@@ -64,11 +65,9 @@ public class InternalUtils {
* Gets the {@link Element} ("symbol") for the given Tree API node.
*
* @param tree the {@link Tree} node to get the symbol for
- * @throws IllegalArgumentException
- * if {@code tree} is null or is not a valid javac-internal tree
- * (JCTree)
- * @return the {@code {@link Symbol}} for the given tree, or null if one
- * could not be found
+ * @throws IllegalArgumentException if {@code tree} is null or is not a valid javac-internal
+ * tree (JCTree)
+ * @return the {@link Symbol} for the given tree, or null if one could not be found
*/
public static /*@Nullable*/ Element symbol(Tree tree) {
if (tree == null) {
@@ -95,19 +94,19 @@ public class InternalUtils {
case TYPE_PARAMETER:
return TreeInfo.symbolFor((JCTree) tree);
- // symbol() only works on MethodSelects, so we need to get it manually
- // for method invocations.
+ // symbol() only works on MethodSelects, so we need to get it manually
+ // for method invocations.
case METHOD_INVOCATION:
return TreeInfo.symbol(((JCMethodInvocation) tree).getMethodSelect());
case ASSIGNMENT:
- return TreeInfo.symbol((JCTree)((AssignmentTree)tree).getVariable());
+ return TreeInfo.symbol((JCTree) ((AssignmentTree) tree).getVariable());
case ARRAY_ACCESS:
- return symbol(((ArrayAccessTree)tree).getExpression());
+ return symbol(((ArrayAccessTree) tree).getExpression());
case NEW_CLASS:
- return ((JCNewClass)tree).constructor;
+ return ((JCNewClass) tree).constructor;
case MEMBER_REFERENCE:
// TreeInfo.symbol, which is used in the default case, didn't handle
@@ -120,43 +119,40 @@ public class InternalUtils {
}
/**
- * Determines whether or not the node referred to by the given
- * {@link TreePath} is an anonymous constructor (the constructor for an
- * anonymous class.
+ * Determines whether or not the node referred to by the given {@link TreePath} is an anonymous
+ * constructor (the constructor for an anonymous class.
*
- * @param method the {@link TreePath} for a node that may be an anonymous
- * constructor
- * @return true if the given path points to an anonymous constructor, false
- * if it does not
+ * @param method the {@link TreePath} for a node that may be an anonymous constructor
+ * @return true if the given path points to an anonymous constructor, false if it does not
*/
public static boolean isAnonymousConstructor(final MethodTree method) {
/*@Nullable*/ Element e = InternalUtils.symbol(method);
- if (e == null || !(e instanceof Symbol))
+ if (e == null || !(e instanceof Symbol)) {
return false;
+ }
- if ((((/*@NonNull*/ Symbol)e).flags() & Flags.ANONCONSTR) != 0)
+ if ((((/*@NonNull*/ Symbol) e).flags() & Flags.ANONCONSTR) != 0) {
return true;
+ }
return false;
}
/**
- * indicates whether it should return the constructor that gets invoked
- * in cases of anonymous classes
+ * indicates whether it should return the constructor that gets invoked in cases of anonymous
+ * classes
*/
private static final boolean RETURN_INVOKE_CONSTRUCTOR = true;
/**
- * Determines the symbol for a constructor given an invocation via
- * {@code new}.
+ * Determines the symbol for a constructor given an invocation via {@code new}.
*
- * If the tree is a declaration of an anonymous class, then method returns
- * constructor that gets invoked in the extended class, rather than the
- * anonymous constructor implicitly added by the constructor (JLS 15.9.5.1)
+ * <p>If the tree is a declaration of an anonymous class, then method returns constructor that
+ * gets invoked in the extended class, rather than the anonymous constructor implicitly added by
+ * the constructor (JLS 15.9.5.1)
*
* @param tree the constructor invocation
- * @return the {@link ExecutableElement} corresponding to the constructor
- * call in {@code tree}
+ * @return the {@link ExecutableElement} corresponding to the constructor call in {@code tree}
*/
public static ExecutableElement constructor(NewClassTree tree) {
@@ -178,7 +174,7 @@ public class InternalUtils {
// the method call is guaranteed to return nonnull
JCMethodDecl anonConstructor =
- (JCMethodDecl) TreeInfo.declarationFor(newClassTree.constructor, newClassTree);
+ (JCMethodDecl) TreeInfo.declarationFor(newClassTree.constructor, newClassTree);
assert anonConstructor != null;
assert anonConstructor.body.stats.size() == 1;
JCExpressionStatement stmt = (JCExpressionStatement) anonConstructor.body.stats.head;
@@ -193,22 +189,31 @@ public class InternalUtils {
return (ExecutableElement) e;
}
- public final static List<AnnotationMirror> annotationsFromTypeAnnotationTrees(List<? extends AnnotationTree> annos) {
+ public static final List<AnnotationMirror> annotationsFromTypeAnnotationTrees(
+ List<? extends AnnotationTree> annos) {
List<AnnotationMirror> annotations = new ArrayList<AnnotationMirror>(annos.size());
- for (AnnotationTree anno : annos)
- annotations.add(((JCAnnotation)anno).attribute);
+ for (AnnotationTree anno : annos) {
+ annotations.add(annotationFromAnnotationTree(anno));
+ }
return annotations;
}
- public final static List<? extends AnnotationMirror> annotationsFromTree(AnnotatedTypeTree node) {
- return annotationsFromTypeAnnotationTrees(((JCAnnotatedType)node).annotations);
+ public static AnnotationMirror annotationFromAnnotationTree(AnnotationTree tree) {
+ return ((JCAnnotation) tree).attribute;
+ }
+
+ public static final List<? extends AnnotationMirror> annotationsFromTree(
+ AnnotatedTypeTree node) {
+ return annotationsFromTypeAnnotationTrees(((JCAnnotatedType) node).annotations);
}
- public final static List<? extends AnnotationMirror> annotationsFromTree(TypeParameterTree node) {
- return annotationsFromTypeAnnotationTrees(((JCTypeParameter)node).annotations);
+ public static final List<? extends AnnotationMirror> annotationsFromTree(
+ TypeParameterTree node) {
+ return annotationsFromTypeAnnotationTrees(((JCTypeParameter) node).annotations);
}
- public final static List<? extends AnnotationMirror> annotationsFromArrayCreation(NewArrayTree node, int level) {
+ public static final List<? extends AnnotationMirror> annotationsFromArrayCreation(
+ NewArrayTree node, int level) {
assert node instanceof JCNewArray;
final JCNewArray newArray = ((JCNewArray) node);
@@ -229,32 +234,40 @@ public class InternalUtils {
return ((JCTree) tree).type;
}
- /**
- * Returns whether a TypeVariable represents a captured type.
- */
+ /** Returns whether a TypeVariable represents a captured type. */
public static boolean isCaptured(TypeVariable typeVar) {
- return ((Type.TypeVar) typeVar).isCaptured();
+ return ((Type.TypeVar) TypeAnnotationUtils.unannotatedType(typeVar)).isCaptured();
}
- /**
- * Returns whether a TypeMirror represents a class type.
- */
+ /** If typeVar is a captured wildcard, returns that wildcard; otherwise returns null. */
+ public static WildcardType getCapturedWildcard(TypeVariable typeVar) {
+ if (isCaptured(typeVar)) {
+ return ((CapturedType) TypeAnnotationUtils.unannotatedType(typeVar)).wildcard;
+ }
+ return null;
+ }
+
+ /** Returns whether a TypeMirror represents a class type. */
public static boolean isClassType(TypeMirror type) {
return (type instanceof Type.ClassType);
}
/**
- * Returns the least upper bound of two {@link TypeMirror}s.
+ * Returns the least upper bound of two {@link TypeMirror}s, ignoring any annotations on the
+ * types.
*
- * @param processingEnv The {@link ProcessingEnvironment} to use.
- * @param tm1 A {@link TypeMirror}.
- * @param tm2 A {@link TypeMirror}.
- * @return The least upper bound of {@code tm1} and {@code tm2}.
+ * <p>Wrapper around Types.lub to add special handling for null types, primitives, and
+ * wildcards.
+ *
+ * @param processingEnv the {@link ProcessingEnvironment} to use
+ * @param tm1 a {@link TypeMirror}
+ * @param tm2 a {@link TypeMirror}
+ * @return the least upper bound of {@code tm1} and {@code tm2}.
*/
public static TypeMirror leastUpperBound(
ProcessingEnvironment processingEnv, TypeMirror tm1, TypeMirror tm2) {
- Type t1 = (Type) tm1;
- Type t2 = (Type) tm2;
+ Type t1 = TypeAnnotationUtils.unannotatedType(tm1);
+ Type t2 = TypeAnnotationUtils.unannotatedType(tm2);
JavacProcessingEnvironment javacEnv = (JavacProcessingEnvironment) processingEnv;
Types types = Types.instance(javacEnv.getContext());
if (types.isSameType(t1, t2)) {
@@ -268,16 +281,6 @@ public class InternalUtils {
if (t2.getKind() == TypeKind.NULL) {
return t1;
}
- // Special case for primitives.
- if (TypesUtils.isPrimitive(t1) || TypesUtils.isPrimitive(t2)) {
- if (types.isAssignable(t1, t2)) {
- return t2;
- } else if (types.isAssignable(t2, t1)) {
- return t1;
- } else {
- return processingEnv.getTypeUtils().getNoType(TypeKind.NONE);
- }
- }
if (t1.getKind() == TypeKind.WILDCARD) {
WildcardType wc1 = (WildcardType) t1;
Type bound = (Type) wc1.getExtendsBound();
@@ -298,21 +301,36 @@ public class InternalUtils {
}
t2 = bound;
}
+ // Special case for primitives.
+ if (TypesUtils.isPrimitive(t1) || TypesUtils.isPrimitive(t2)) {
+ if (types.isAssignable(t1, t2)) {
+ return t2;
+ } else if (types.isAssignable(t2, t1)) {
+ return t1;
+ } else {
+ Elements elements = processingEnv.getElementUtils();
+ return elements.getTypeElement("java.lang.Object").asType();
+ }
+ }
return types.lub(t1, t2);
}
/**
- * Returns the greatest lower bound of two {@link TypeMirror}s.
+ * Returns the greatest lower bound of two {@link TypeMirror}s, ignoring any annotations on the
+ * types.
*
- * @param processingEnv The {@link ProcessingEnvironment} to use.
- * @param tm1 A {@link TypeMirror}.
- * @param tm2 A {@link TypeMirror}.
- * @return The greatest lower bound of {@code tm1} and {@code tm2}.
+ * <p>Wrapper around Types.glb to add special handling for null types, primitives, and
+ * wildcards.
+ *
+ * @param processingEnv the {@link ProcessingEnvironment} to use
+ * @param tm1 a {@link TypeMirror}
+ * @param tm2 a {@link TypeMirror}
+ * @return the greatest lower bound of {@code tm1} and {@code tm2}.
*/
public static TypeMirror greatestLowerBound(
ProcessingEnvironment processingEnv, TypeMirror tm1, TypeMirror tm2) {
- Type t1 = (Type) tm1;
- Type t2 = (Type) tm2;
+ Type t1 = TypeAnnotationUtils.unannotatedType(tm1);
+ Type t2 = TypeAnnotationUtils.unannotatedType(tm2);
JavacProcessingEnvironment javacEnv = (JavacProcessingEnvironment) processingEnv;
Types types = Types.instance(javacEnv.getContext());
if (types.isSameType(t1, t2)) {
@@ -345,21 +363,24 @@ public class InternalUtils {
if (t2.getKind() == TypeKind.WILDCARD) {
return t1;
}
+
+ // If neither type is a primitive type, null type, or wildcard
+ // and if the types are not the same, use javac types.glb
return types.glb(t1, t2);
}
/**
- * Returns the return type of a method, where the "raw" return type of that
- * method is given (i.e., the return type might still contain unsubstituted
- * type variables), given the receiver of the method call.
+ * Returns the return type of a method, where the "raw" return type of that method is given
+ * (i.e., the return type might still contain unsubstituted type variables), given the receiver
+ * of the method call.
*/
- public static TypeMirror substituteMethodReturnType(TypeMirror methodType,
- TypeMirror substitutedReceiverType) {
+ public static TypeMirror substituteMethodReturnType(
+ TypeMirror methodType, TypeMirror substitutedReceiverType) {
if (methodType.getKind() != TypeKind.TYPEVAR) {
return methodType;
}
// TODO: find a nicer way to substitute type variables
- String t = methodType.toString();
+ String t = TypeAnnotationUtils.unannotatedType(methodType).toString();
Type finalReceiverType = (Type) substitutedReceiverType;
int i = 0;
for (TypeSymbol typeParam : finalReceiverType.tsym.getTypeParameters()) {
@@ -372,13 +393,91 @@ public class InternalUtils {
return null;
}
- /** Helper function to extract the javac Context from the
- * javac processing environment.
+ /**
+ * Helper function to extract the javac Context from the javac processing environment.
*
* @param env the processing environment
* @return the javac Context
*/
public static Context getJavacContext(ProcessingEnvironment env) {
- return ((JavacProcessingEnvironment)env).getContext();
+ return ((JavacProcessingEnvironment) env).getContext();
+ }
+
+ /**
+ * Returns the type element for {@code type} if {@code type} is a class, interface, annotation
+ * type, or enum. Otherwise, returns null.
+ *
+ * @param type whose element is returned
+ * @return the type element for {@code type} if {@code type} is a class, interface, annotation
+ * type, or enum; otherwise, returns null
+ */
+ public static TypeElement getTypeElement(TypeMirror type) {
+ Element element = ((Type) type).asElement();
+ switch (element.getKind()) {
+ case ANNOTATION_TYPE:
+ case CLASS:
+ case ENUM:
+ case INTERFACE:
+ return (TypeElement) element;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Obtain the class loader for {@code clazz}. If that is not available, return the system class
+ * loader.
+ *
+ * @param clazz the class whose class loader to find
+ * @return the class loader used to {@code clazz}, or the system class loader, or null if both
+ * are unavailable
+ */
+ public static ClassLoader getClassLoaderForClass(Class<? extends Object> clazz) {
+ ClassLoader classLoader = clazz.getClassLoader();
+ return classLoader == null ? ClassLoader.getSystemClassLoader() : classLoader;
+ }
+
+ /**
+ * Compares tree1 to tree2 by the position at which a diagnostic (e.g., an error message) for
+ * the tree should be printed.
+ */
+ public static int compareDiagnosticPosition(Tree tree1, Tree tree2) {
+ DiagnosticPosition pos1 = (DiagnosticPosition) tree1;
+ DiagnosticPosition pos2 = (DiagnosticPosition) tree2;
+
+ int preferred = Integer.compare(pos1.getPreferredPosition(), pos2.getPreferredPosition());
+ if (preferred != 0) {
+ return preferred;
+ }
+
+ return Integer.compare(pos1.getStartPosition(), pos2.getStartPosition());
+ }
+
+ /**
+ * Returns whether or not {@code type} is a functional interface type (as defined in JLS 9.8).
+ *
+ * @param type possible functional interface type
+ * @param env ProcessingEnvironment
+ * @return whether or not {@code type} is a functional interface type (as defined in JLS 9.8)
+ */
+ public static boolean isFunctionalInterface(TypeMirror type, ProcessingEnvironment env) {
+ Context ctx = ((JavacProcessingEnvironment) env).getContext();
+ com.sun.tools.javac.code.Types javacTypes = com.sun.tools.javac.code.Types.instance(ctx);
+ return javacTypes.isFunctionalInterface((Type) type);
+ }
+
+ /**
+ * The type of the lambda or method reference tree is a functional interface type. This method
+ * returns the single abstract method declared by that functional interface. (The type of this
+ * method is referred to as the function type.)
+ *
+ * @param tree lambda or member reference tree
+ * @param env ProcessingEnvironment
+ * @return the single abstract method declared by the type of the tree
+ */
+ public static Symbol findFunction(Tree tree, ProcessingEnvironment env) {
+ Context ctx = ((JavacProcessingEnvironment) env).getContext();
+ com.sun.tools.javac.code.Types javacTypes = com.sun.tools.javac.code.Types.instance(ctx);
+ return javacTypes.findDescriptorSymbol(((Type) typeOf(tree)).asElement());
}
}