package checkers.util; import checkers.nullness.quals.Nullable; import checkers.quals.*; import javax.lang.model.element.*; import javax.lang.model.type.TypeMirror; /** * A Utility class for analyzing {@code Element}s * */ public class ElementUtils { // Cannot be instantiated private ElementUtils() { throw new AssertionError("un-initializable class"); } /** * Returns the innermost type element enclosing the given element * * @param elem the enclosed element of a class * @return the innermost type element */ public static TypeElement enclosingClass(final Element elem) { Element result = elem; while (result != null && !result.getKind().isClass() && !result.getKind().isInterface()) { @Nullable Element encl = result.getEnclosingElement(); result = encl; } return (TypeElement) result; } /** * Returns true if the element is a static element: whether it is a static * field, static method, or static class * * @param element * @return true if element is static */ public static boolean isStatic(Element element) { return element.getModifiers().contains(Modifier.STATIC); } /** * Returns true if the element is a final element: a final field, final * method, or final class * * @param element * @return true if the element is final */ public static boolean isFinal(Element element) { return element.getModifiers().contains(Modifier.FINAL); } /** * Returns the {@code TypeMirror} for usage of Element as a value. It * returns the return type of a method element, the class type of a * constructor, or simply the type mirror of the element itself. * * @param element * @return the type for the element used as a value */ public static TypeMirror getType(Element element) { if (element.getKind() == ElementKind.METHOD) return ((ExecutableElement)element).getReturnType(); else if (element.getKind() == ElementKind.CONSTRUCTOR) return enclosingClass(element).asType(); else return element.asType(); } /** * Returns the qualified name of the inner most class enclosing * the provided {@code Element} * * @param element * an element enclosed by a class, or a * {@code TypeElement} * @return The qualified {@code Name} of the innermost class * enclosing the element */ public static @Nullable Name getQualifiedClassName(Element element) { if (element.getKind() == ElementKind.PACKAGE) { PackageElement elem = (PackageElement) element; return elem.getQualifiedName(); } TypeElement elem = enclosingClass(element); if (elem == null) return null; return elem.getQualifiedName(); } /** * Check if the element is an element for 'java.lang.Object' * * @param element the type element * @return true iff the element is java.lang.Object element */ public static boolean isObject(TypeElement element) { return element.getQualifiedName().contentEquals("java.lang.Object"); } /** * Returns true if the element is a constant time reference */ public static boolean isCompileTimeConstant(Element elt) { return elt != null && elt.getKind() == ElementKind.FIELD && ((VariableElement)elt).getConstantValue() != null; } }