framework.src.org.checkerframework.qualframework.poly.QualifierParameterTypeAnnotator 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.poly;
import java.util.*;
import javax.lang.model.element.Element;
import org.checkerframework.qualframework.base.TypeAnnotator;
import org.checkerframework.qualframework.base.QualifierHierarchy;
import org.checkerframework.qualframework.util.ExtendedDeclaredType;
import org.checkerframework.qualframework.util.ExtendedExecutableType;
import org.checkerframework.qualframework.util.ExtendedTypeMirror;
import org.checkerframework.qualframework.util.QualifierContext;
/*
import org.checkerframework.qualframework.base.QualifiedTypeMirror;
import org.checkerframework.qualframework.util.QualifierMapVisitor;
import org.checkerframework.qualframework.util.SetQualifierVisitor;
import org.checkerframework.qualframework.base.QualifiedTypeMirror.QualifiedExecutableType;
import org.checkerframework.qualframework.base.QualifiedTypeMirror.QualifiedTypeVariable;
*/
/** {@link TypeAnnotator} implementation for qualifier parameter checkers. */
public class QualifierParameterTypeAnnotator extends TypeAnnotator> {
private QualifierHierarchy> containmentHierarchy;
public QualifierParameterTypeAnnotator(
QualifierContext> qualContext,
QualifierParameterAnnotationConverter annotationConverter,
QualifierHierarchy> containmentHierarchy) {
super(qualContext, annotationConverter, new QualParams());
this.containmentHierarchy = containmentHierarchy;
}
public QualifierHierarchy> getContainmentHierarchy() {
return containmentHierarchy;
}
public QualifierParameterAnnotationConverter getAnnotationConverter() {
return (QualifierParameterAnnotationConverter)super.getAnnotationConverter();
}
@Override
protected QualParams getQualifier(ExtendedTypeMirror type) {
// Use the appropriate top qualifier by default. The top qualifier in
// this system assigns an unbounded wildcard to every parameter.
QualParams result = super.getQualifier(type);
// Find the names of all parameters that are valid on this type.
Set names;
switch (type.getKind()) {
case DECLARED:
Element declElt = ((ExtendedDeclaredType)type).asElement();
names = getAnnotationConverter().getDeclaredParameters(declElt,
qualContext.getTypeFactory().getDeclAnnotations(declElt),
qualContext.getTypeFactory().getDecoratedElement(declElt));
break;
case EXECUTABLE:
Element executableElt = ((ExtendedExecutableType)type).asElement();
names = getAnnotationConverter().getDeclaredParameters(executableElt,
qualContext.getTypeFactory().getDeclAnnotations(executableElt),
qualContext.getTypeFactory().getDecoratedElement(executableElt));
break;
case VOID:
case PACKAGE:
case NONE:
case TYPEVAR:
case ARRAY:
names = Collections.emptySet();
break;
case INTERSECTION:
case UNION:
case NULL:
case WILDCARD:
// TODO - figure out the correct behavior for these cases
names = Collections.emptySet();
break;
default:
// TODO: the checker should get to make this decision. Maybe
// take the parameters from the declaration of the boxed
// version of the primitive type?
if (type.getKind().isPrimitive()) {
names = Collections.emptySet();
break;
}
throw new IllegalArgumentException("unexpected type kind: " + type.getKind());
}
if (names.isEmpty()) {
return result;
}
// Add an unbounded wildcard for each parameter that wasn't set.
Map> newParams = new HashMap<>(result);
for (String name : names) {
if (!newParams.containsKey(name)) {
newParams.put(name, containmentHierarchy.getTop());
}
}
return new QualParams<>(newParams, result.getPrimary());
}
}