framework.src.org.checkerframework.qualframework.util.WrappedAnnotatedTypeMirror Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of checker Show documentation
Show all versions of checker Show documentation
The Checker Framework enhances Java’s type system to
make it more powerful and useful. This lets software developers
detect and prevent errors in their Java programs.
The Checker Framework includes compiler plug-ins ("checkers")
that find bugs or verify their absence. It also permits you to
write your own compiler plug-ins.
package org.checkerframework.qualframework.util;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedIntersectionType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedNoType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedNullType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedPrimitiveType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedUnionType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.IntersectionType;
import javax.lang.model.type.NoType;
import javax.lang.model.type.NullType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.type.UnionType;
import javax.lang.model.type.WildcardType;
/**
* A wrapper to adapt an {@link AnnotatedTypeMirror} to the {@link
* ExtendedTypeMirror} interface. Instances of this class are immutable.
*/
public abstract class WrappedAnnotatedTypeMirror implements ExtendedTypeMirror {
private final AnnotatedTypeMirror underlying;
private WrappedAnnotatedTypeMirror(AnnotatedTypeMirror underlying) {
if (underlying == null) {
throw new IllegalArgumentException("underlying ATM must be non-null");
}
this.underlying = underlying;
}
/**
* Constructs a {@link WrappedAnnotatedTypeMirror} from an {@link
* AnnotatedTypeMirror}. The {@link WrappedAnnotatedTypeMirror} returned
* by this method will be backed by a deep copy of the input
* {@link AnnotatedTypeMirror}, so later mutations of the input will not
* affect the wrapped version.
*/
public static WrappedAnnotatedTypeMirror wrap(AnnotatedTypeMirror atm) {
return wrapImpl(atm.deepCopy());
}
private static WrappedAnnotatedTypeMirror wrapImpl(AnnotatedTypeMirror atm) {
if (atm == null) {
return null;
}
switch (atm.getKind()) {
case ARRAY:
return new WrappedAnnotatedArrayType((AnnotatedArrayType)atm);
case DECLARED:
return new WrappedAnnotatedDeclaredType((AnnotatedDeclaredType)atm);
case EXECUTABLE:
return new WrappedAnnotatedExecutableType((AnnotatedExecutableType)atm);
case VOID:
case PACKAGE:
case NONE:
return new WrappedAnnotatedNoType((AnnotatedNoType)atm);
case NULL:
return new WrappedAnnotatedNullType((AnnotatedNullType)atm);
case TYPEVAR:
return new WrappedAnnotatedTypeVariable((AnnotatedTypeVariable)atm);
case WILDCARD:
return new WrappedAnnotatedWildcardType((AnnotatedWildcardType)atm);
case INTERSECTION:
return new WrappedAnnotatedIntersectionType((AnnotatedIntersectionType)atm);
case UNION:
return new WrappedAnnotatedUnionType((AnnotatedUnionType)atm);
default:
if (atm.getKind().isPrimitive()) {
return new WrappedAnnotatedPrimitiveType((AnnotatedPrimitiveType)atm);
}
throw new IllegalArgumentException("unexpected type kind: " + atm.getKind());
}
}
private static List wrapList(List atms) {
List watms = new ArrayList<>();
for (AnnotatedTypeMirror atm : atms) {
watms.add(wrapImpl(atm));
}
return watms;
}
private static List wrapTypeVarList(List atms) {
List watms = new ArrayList<>();
for (AnnotatedTypeVariable atm : atms) {
watms.add((WrappedAnnotatedTypeVariable)wrapImpl(atm));
}
return watms;
}
/**
* Unwrap a {@link WrappedAnnotatedTypeMirror} to obtain the original
* {@link AnnotatedTypeMirror}.
*/
public AnnotatedTypeMirror unwrap() {
return this.underlying;
}
@Override
public TypeMirror getOriginalType() {
return underlying.getUnderlyingType();
}
@Override
public TypeKind getKind() {
return underlying.getKind();
}
@Override
public boolean isDeclaration() {
return underlying.isDeclaration();
}
@Override
public A getAnnotation(Class annotationType) {
throw new UnsupportedOperationException("ATM doesn't support getAnnotation");
}
@Override
public List getAnnotationMirrors() {
List result = new ArrayList<>();
result.addAll(underlying.getAnnotations());
return result;
}
@Override
public A[] getAnnotationsByType(Class annotationType) {
throw new UnsupportedOperationException("ATM doesn't support getAnnotationsByType");
}
@Override
public String toString() {
return underlying.toString();
}
@Override
public boolean equals(Object obj) {
if (obj == null || obj.getClass() != this.getClass()) {
return false;
}
WrappedAnnotatedTypeMirror other = (WrappedAnnotatedTypeMirror)obj;
return this.underlying.equals(other.underlying);
}
@Override
public int hashCode() {
return underlying.hashCode();
}
public static class WrappedAnnotatedArrayType extends WrappedAnnotatedReferenceType implements ExtendedArrayType {
private final WrappedAnnotatedTypeMirror componentType;
private WrappedAnnotatedArrayType(AnnotatedArrayType underlying) {
super(underlying);
this.componentType = wrapImpl(underlying.getComponentType());
}
@Override
public ArrayType getOriginalType() {
return (ArrayType)super.getOriginalType();
}
@Override
public AnnotatedArrayType unwrap() {
return (AnnotatedArrayType)super.unwrap();
}
@Override
public R accept(ExtendedTypeVisitor v, P p) {
return v.visitArray(this, p);
}
@Override
public WrappedAnnotatedTypeMirror getComponentType() {
return componentType;
}
}
public static class WrappedAnnotatedDeclaredType extends WrappedAnnotatedReferenceType
implements ExtendedDeclaredType, ExtendedTypeDeclaration {
private final WrappedAnnotatedTypeMirror enclosingType;
private final List typeArguments;
private WrappedAnnotatedDeclaredType(AnnotatedDeclaredType underlying) {
super(underlying);
this.enclosingType = wrapImpl(underlying.getEnclosingType());
this.typeArguments = wrapList(underlying.getTypeArguments());
}
@Override
public DeclaredType getOriginalType() {
return (DeclaredType)super.getOriginalType();
}
@Override
public AnnotatedDeclaredType unwrap() {
return (AnnotatedDeclaredType)super.unwrap();
}
@Override
public R accept(ExtendedTypeVisitor v, P p) {
if (isDeclaration()) {
return v.visitTypeDeclaration(this, p);
} else {
return v.visitDeclared(this, p);
}
}
@Override
public Element asElement() {
return getOriginalType().asElement();
}
@Override
public WrappedAnnotatedTypeMirror getEnclosingType() {
return enclosingType;
}
@Override
public List getTypeArguments() {
return typeArguments;
}
@Override
@SuppressWarnings("unchecked")
public List getTypeParameters() {
return (List)(List)typeArguments;
}
}
public static class WrappedAnnotatedExecutableType extends WrappedAnnotatedTypeMirror implements ExtendedExecutableType {
private final List parameterTypes;
private final WrappedAnnotatedTypeMirror receiverType;
private final WrappedAnnotatedTypeMirror returnType;
private final List thrownTypes;
private final List typeParameters;
private WrappedAnnotatedExecutableType(AnnotatedExecutableType underlying) {
super(underlying);
this.parameterTypes = wrapList(underlying.getParameterTypes());
this.receiverType = wrapImpl(underlying.getReceiverType());
this.returnType = wrapImpl(underlying.getReturnType());
this.thrownTypes = wrapList(underlying.getThrownTypes());
this.typeParameters = wrapTypeVarList(underlying.getTypeVariables());
}
@Override
public ExecutableType getOriginalType() {
return (ExecutableType)super.getOriginalType();
}
@Override
public AnnotatedExecutableType unwrap() {
return (AnnotatedExecutableType)super.unwrap();
}
@Override
public R accept(ExtendedTypeVisitor v, P p) {
return v.visitExecutable(this, p);
}
@Override
public ExecutableElement asElement() {
return unwrap().getElement();
}
@Override
public List getParameterTypes() {
return parameterTypes;
}
@Override
public WrappedAnnotatedTypeMirror getReceiverType() {
return receiverType;
}
@Override
public WrappedAnnotatedTypeMirror getReturnType() {
return returnType;
}
@Override
public List getThrownTypes() {
return thrownTypes;
}
@Override
public List getTypeParameters() {
return typeParameters;
}
}
public static class WrappedAnnotatedIntersectionType extends WrappedAnnotatedTypeMirror implements ExtendedIntersectionType {
private final List bounds;
private WrappedAnnotatedIntersectionType(AnnotatedIntersectionType underlying) {
super(underlying);
this.bounds = wrapList(underlying.directSuperTypes());
}
@Override
public IntersectionType getOriginalType() {
return (IntersectionType)super.getOriginalType();
}
@Override
public AnnotatedIntersectionType unwrap() {
return (AnnotatedIntersectionType)super.unwrap();
}
@Override
public R accept(ExtendedTypeVisitor v, P p) {
return v.visitIntersection(this, p);
}
@Override
public List getBounds() {
return bounds;
}
}
public static class WrappedAnnotatedNoType extends WrappedAnnotatedTypeMirror implements ExtendedNoType {
private WrappedAnnotatedNoType(AnnotatedNoType underlying) {
super(underlying);
}
@Override
public NoType getOriginalType() {
return (NoType)super.getOriginalType();
}
@Override
public AnnotatedNoType unwrap() {
return (AnnotatedNoType)super.unwrap();
}
@Override
public R accept(ExtendedTypeVisitor v, P p) {
return v.visitNoType(this, p);
}
}
public static class WrappedAnnotatedNullType extends WrappedAnnotatedReferenceType implements ExtendedNullType {
private WrappedAnnotatedNullType(AnnotatedNullType underlying) {
super(underlying);
}
@Override
public NullType getOriginalType() {
return (NullType)super.getOriginalType();
}
@Override
public AnnotatedNullType unwrap() {
return (AnnotatedNullType)super.unwrap();
}
@Override
public R accept(ExtendedTypeVisitor v, P p) {
return v.visitNull(this, p);
}
}
public static class WrappedAnnotatedPrimitiveType extends WrappedAnnotatedTypeMirror implements ExtendedPrimitiveType {
private WrappedAnnotatedPrimitiveType(AnnotatedPrimitiveType underlying) {
super(underlying);
}
@Override
public PrimitiveType getOriginalType() {
return (PrimitiveType)super.getOriginalType();
}
@Override
public AnnotatedPrimitiveType unwrap() {
return (AnnotatedPrimitiveType)super.unwrap();
}
@Override
public R accept(ExtendedTypeVisitor v, P p) {
return v.visitPrimitive(this, p);
}
}
static abstract class WrappedAnnotatedReferenceType extends WrappedAnnotatedTypeMirror implements ExtendedReferenceType {
private WrappedAnnotatedReferenceType(AnnotatedTypeMirror underlying) {
super(underlying);
}
}
public static class WrappedAnnotatedTypeVariable extends WrappedAnnotatedReferenceType
implements ExtendedTypeVariable, ExtendedParameterDeclaration {
private WrappedAnnotatedTypeVariable(AnnotatedTypeVariable underlying) {
super(underlying);
}
@Override
public TypeVariable getOriginalType() {
return (TypeVariable)super.getOriginalType();
}
@Override
public AnnotatedTypeVariable unwrap() {
return (AnnotatedTypeVariable)super.unwrap();
}
@Override
public R accept(ExtendedTypeVisitor v, P p) {
if (isDeclaration()) {
return v.visitParameterDeclaration(this, p);
} else {
return v.visitTypeVariable(this, p);
}
}
@Override
public Element asElement() {
return getOriginalType().asElement();
}
@Override
public ExtendedParameterDeclaration getDeclaration() {
AnnotatedTypeVariable copy = unwrap().deepCopy();
copy.clearAnnotations();
copy.setDeclaration(true);
return (ExtendedParameterDeclaration)wrap(copy);
}
}
public static class WrappedAnnotatedUnionType extends WrappedAnnotatedTypeMirror implements ExtendedUnionType {
private final List alternatives;
private WrappedAnnotatedUnionType(AnnotatedUnionType underlying) {
super(underlying);
this.alternatives = wrapList(underlying.getAlternatives());
}
@Override
public UnionType getOriginalType() {
return (UnionType)super.getOriginalType();
}
@Override
public AnnotatedUnionType unwrap() {
return (AnnotatedUnionType)super.unwrap();
}
@Override
public R accept(ExtendedTypeVisitor v, P p) {
return v.visitUnion(this, p);
}
@Override
public List getAlternatives() {
return alternatives;
}
}
public static class WrappedAnnotatedWildcardType extends WrappedAnnotatedTypeMirror implements ExtendedWildcardType {
private final WrappedAnnotatedTypeMirror extendsBound;
private final WrappedAnnotatedTypeMirror superBound;
private WrappedAnnotatedWildcardType(AnnotatedWildcardType underlying) {
super(underlying);
this.extendsBound = wrapImpl(underlying.getExtendsBound());
this.superBound = wrapImpl(underlying.getSuperBound());
}
@Override
public WildcardType getOriginalType() {
return (WildcardType)super.getOriginalType();
}
@Override
public AnnotatedWildcardType unwrap() {
return (AnnotatedWildcardType)super.unwrap();
}
@Override
public R accept(ExtendedTypeVisitor v, P p) {
return v.visitWildcard(this, p);
}
@Override
public WrappedAnnotatedTypeMirror getExtendsBound() {
return extendsBound;
}
@Override
public WrappedAnnotatedTypeMirror getSuperBound() {
return superBound;
}
@Override
public boolean equals(Object obj) {
// AnnotatedWildcardType.equals is non-reflexive. I hate everything.
if (obj == null || obj.getClass() != this.getClass()) {
return false;
}
WrappedAnnotatedWildcardType other = (WrappedAnnotatedWildcardType)obj;
return (this.extendsBound == null ?
other.extendsBound == null :
this.extendsBound.equals(other.extendsBound))
&& (this.superBound == null ?
other.superBound == null :
this.superBound.equals(other.superBound));
}
}
}