framework.src.org.checkerframework.framework.type.DefaultRawnessComparer 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.framework.type;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeVariable;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
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.AnnotatedWildcardType;
import org.checkerframework.framework.type.visitor.AbstractAtmComboVisitor;
import org.checkerframework.framework.type.visitor.VisitHistory;
import org.checkerframework.framework.util.AtmCombo;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.InternalUtils;
/**
* Our
* //TODO: USING THE SAME LOGIC AS THE OLD TYPE_HIERARCHY.isSubtypeAsTypeArgument but only for
* //TODO: RAW TypeArguments, we can replace this later if we think there is a more sensible thing to do
* //TODO: LOOK AT OLD TYPE_HIERARCHY FOR MORE INFORAMTION
*/
public class DefaultRawnessComparer extends AbstractAtmComboVisitor {
private final DefaultTypeHierarchy typeHierarchy;
private AnnotationMirror currentTop;
public DefaultRawnessComparer(final DefaultTypeHierarchy typeHierarchy) {
this.typeHierarchy = typeHierarchy;
}
@Override
protected String defaultErrorMessage(
AnnotatedTypeMirror subtype, AnnotatedTypeMirror supertype, VisitHistory visited) {
return "DefaultRawnessComparer: Unexpected AnnotatedTypeMirror combination.\n"
+ "type1 = "
+ subtype.getClass().getSimpleName()
+ "( "
+ subtype
+ " )\n"
+ "type2 = "
+ supertype.getClass().getSimpleName()
+ "( "
+ supertype
+ " )\n"
+ "visitHistory = "
+ visited;
}
public boolean isValid(
final AnnotatedTypeMirror subtype,
final AnnotatedTypeMirror supertype,
VisitHistory visited) {
return AtmCombo.accept(subtype, supertype, visited, this);
}
public boolean isValidInHierarchy(
final AnnotatedTypeMirror subtype,
final AnnotatedTypeMirror supertype,
AnnotationMirror top,
VisitHistory visited) {
this.currentTop = top;
boolean result = AtmCombo.accept(subtype, supertype, visited, this);
this.currentTop = null;
return result;
}
//TODO: GENERAL CASE IF THE OTHERS HAVEN"T OCCURED SUCH AS DECLARED_DECLARED
protected boolean arePrimaryAnnotationsEqual(
final AnnotatedTypeMirror subtype, final AnnotatedTypeMirror supertype) {
if (currentTop != null) {
return AnnotationUtils.areSame(
subtype.getAnnotationInHierarchy(currentTop),
supertype.getAnnotationInHierarchy(currentTop));
} // else
return AnnotationUtils.areSame(subtype.getAnnotations(), supertype.getAnnotations());
}
@Override
public Boolean visitDeclared_Declared(
AnnotatedDeclaredType subtype, AnnotatedDeclaredType supertype, VisitHistory visited) {
if (checkOrAdd(subtype, supertype, visited)) {
return true;
}
if (!arePrimaryAnnotationsEqual(subtype, supertype)) {
return false;
}
return typeHierarchy.visitTypeArgs(
subtype, supertype, visited, subtype.wasRaw(), supertype.wasRaw());
}
@Override
public Boolean visitWildcard_Wildcard(
AnnotatedWildcardType subtype, AnnotatedWildcardType supertype, VisitHistory visited) {
if (checkOrAdd(subtype, supertype, visited)) {
return true;
}
if (supertype.getExtendsBoundField() == null
|| supertype.getExtendsBoundField().getAnnotations().isEmpty()) {
// TODO: the LHS extends bound hasn't been unfolded or defaulted.
// Stop looking, we should be fine.
// See tests/nullness/generics/WildcardSubtyping.java
return true;
}
AnnotatedTypeMirror subtypeUpper = subtype.getExtendsBound();
AnnotatedTypeMirror supertypeUpper = supertype.getExtendsBound();
if (supertypeUpper.getKind() == TypeKind.TYPEVAR
&& InternalUtils.isCaptured((TypeVariable) supertypeUpper.getUnderlyingType())) {
supertypeUpper = ((AnnotatedTypeVariable) supertypeUpper).getUpperBound();
}
if (checkOrAdd(subtypeUpper, supertypeUpper, visited)) {
return true;
}
if (currentTop == null) {
return typeHierarchy.isSubtype(subtypeUpper, supertypeUpper);
}
return typeHierarchy.isSubtype(subtypeUpper, supertypeUpper, currentTop);
}
@Override
public Boolean visitArray_Array(
AnnotatedArrayType subtype, AnnotatedArrayType supertype, VisitHistory visited) {
if (!arePrimaryAnnotationsEqual(subtype, supertype)) {
return false;
}
return this.isValid(subtype.getComponentType(), supertype.getComponentType(), visited);
}
@Override
public Boolean visitNull_Declared(
AnnotatedNullType subtype, AnnotatedDeclaredType supertype, VisitHistory visited) {
if (checkOrAdd(subtype, supertype, visited)) {
return true;
}
if (!arePrimaryAnnotationsEqual(subtype, supertype)) {
return false;
}
return !supertype.wasRaw();
}
@Override
public Boolean visitNull_Typevar(
AnnotatedNullType subtype, AnnotatedTypeVariable supertype, VisitHistory visited) {
return visitTypevarSupertype(subtype, supertype, visited);
}
@Override
public Boolean visitArray_Declared(
AnnotatedArrayType subtype, AnnotatedDeclaredType supertype, VisitHistory visited) {
return arePrimaryAnnotationsEqual(subtype, supertype);
}
@Override
public Boolean visitPrimitive_Primitive(
AnnotatedPrimitiveType subtype,
AnnotatedPrimitiveType supertype,
VisitHistory visited) {
return arePrimaryAnnotationsEqual(subtype, supertype);
}
@Override
public Boolean visitDeclared_Wildcard(
AnnotatedDeclaredType subtype, AnnotatedWildcardType supertype, VisitHistory visited) {
return visitWildcardSupertype(subtype, supertype, visited);
}
@Override
public Boolean visitArray_Wildcard(
AnnotatedArrayType subtype, AnnotatedWildcardType supertype, VisitHistory visited) {
return visitWildcardSupertype(subtype, supertype, visited);
}
@Override
public Boolean visitTypevar_Wildcard(
AnnotatedTypeVariable subtype, AnnotatedWildcardType supertype, VisitHistory visited) {
return visitWildcardSupertype(subtype, supertype, visited);
}
@Override
public Boolean visitDeclared_Typevar(
AnnotatedDeclaredType subtype, AnnotatedTypeVariable supertype, VisitHistory visited) {
return visitTypevarSupertype(subtype, supertype, visited);
}
@Override
public Boolean visitArray_Typevar(
AnnotatedArrayType subtype, AnnotatedTypeVariable supertype, VisitHistory visited) {
return visitTypevarSupertype(subtype, supertype, visited);
}
@Override
public Boolean visitTypevar_Declared(
AnnotatedTypeVariable subtype, AnnotatedDeclaredType supertype, VisitHistory visited) {
return visitTypeVarSubtype(subtype, supertype, visited);
}
@Override
public Boolean visitTypevar_Null(
AnnotatedTypeVariable subtype, AnnotatedNullType supertype, VisitHistory visited) {
return visitTypeVarSubtype(subtype, supertype, visited);
}
@Override
public Boolean visitTypevar_Typevar(
AnnotatedTypeVariable subtype, AnnotatedTypeVariable supertype, VisitHistory visited) {
return visitTypevarSupertype(subtype, supertype, visited);
}
// See FromApac5Tests - iterator for when this would occur
@Override
public Boolean visitWildcard_Array(
AnnotatedWildcardType subtype, AnnotatedArrayType supertype, VisitHistory visited) {
return arePrimaryAnnotationsEqual(subtype.getExtendsBound(), supertype);
}
@Override
public Boolean visitWildcard_Declared(
AnnotatedWildcardType subtype, AnnotatedDeclaredType supertype, VisitHistory visited) {
return arePrimaryAnnotationsEqual(subtype.getExtendsBound(), supertype);
}
@Override
public Boolean visitWildcard_Typevar(
AnnotatedWildcardType subtype, AnnotatedTypeVariable supertype, VisitHistory visited) {
return visitTypevarSupertype(subtype, supertype, visited);
}
public Boolean visitWildcardSupertype(
AnnotatedTypeMirror subtype, AnnotatedWildcardType supertype, VisitHistory visited) {
if (checkOrAdd(subtype, supertype, visited)) {
return true;
}
if (!supertype.getAnnotations().isEmpty()
&& !supertype.getEffectiveAnnotations().equals(subtype.getEffectiveAnnotations())) {
return false;
}
final AnnotatedTypeMirror superExtendsBound = supertype.getExtendsBound();
if (superExtendsBound == null) {
return true;
}
if (checkOrAdd(subtype, superExtendsBound, visited)) {
return true;
}
return this.visit(subtype, superExtendsBound, visited);
}
public Boolean visitTypevarSupertype(
AnnotatedTypeMirror subtype, AnnotatedTypeVariable supertype, VisitHistory visited) {
if (checkOrAdd(subtype, supertype, visited)) {
return true;
}
final AnnotatedTypeMirror supertypeUb = supertype.getUpperBound();
if (checkOrAdd(subtype, supertypeUb, visited)) {
return true;
}
return this.visit(subtype, supertypeUb, visited);
}
public Boolean visitTypeVarSubtype(
AnnotatedTypeVariable subtype, AnnotatedTypeMirror supertype, VisitHistory visited) {
if (checkOrAdd(subtype, supertype, visited)) {
return true;
}
final AnnotatedTypeMirror subtypeUb = subtype.getUpperBound();
if (checkOrAdd(subtypeUb, supertype, visited)) {
return true;
}
return this.visit(subtype, subtypeUb, visited);
}
private boolean checkOrAdd(
final AnnotatedTypeMirror subtype,
final AnnotatedTypeMirror supertype,
final VisitHistory visited) {
if (visited.contains(subtype, supertype)) {
return true;
}
visited.add(subtype, supertype);
return false;
}
}