framework.src.org.checkerframework.qualframework.poly.QualifierParameterTreeAnnotator 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 javax.lang.model.type.TypeKind;
import com.sun.source.tree.*;
import org.checkerframework.qualframework.base.TreeAnnotator;
import org.checkerframework.qualframework.base.SetQualifierVisitor;
import org.checkerframework.qualframework.base.QualifiedTypeMirror;
import org.checkerframework.qualframework.base.QualifiedTypeMirror.QualifiedDeclaredType;
import org.checkerframework.qualframework.util.ExtendedTypeMirror;
/** {@code TreeAnnotator} instance for qualifier parameter checkers. */
public class QualifierParameterTreeAnnotator extends TreeAnnotator> {
private QualifierParameterTypeFactory factory;
public QualifierParameterTreeAnnotator(QualifierParameterTypeFactory factory) {
super();
this.factory = factory;
}
// These overrides are intended to avoid adding invalid qualifier
// parameters due to the Checker Framework's default annotation handling.
// In particular, we want to prevent the framework from adding more
// qualifier parameters than the type actually declares, such as producing
// the type "C<>" when C only declares "C<>".
@Override
public QualifiedTypeMirror> visitCompoundAssignment(CompoundAssignmentTree node, ExtendedTypeMirror type) {
QualifiedTypeMirror> result = super.visitCompoundAssignment(node, type);
return filterParams(result);
}
@Override
public QualifiedTypeMirror> visitBinary(BinaryTree node, ExtendedTypeMirror type) {
QualifiedTypeMirror> result = super.visitBinary(node, type);
return filterParams(result);
}
@Override
public QualifiedTypeMirror> visitUnary(UnaryTree node, ExtendedTypeMirror type) {
QualifiedTypeMirror> result = super.visitUnary(node, type);
return filterParams(result);
}
@Override
public QualifiedTypeMirror> visitConditionalExpression(ConditionalExpressionTree node, ExtendedTypeMirror type) {
QualifiedTypeMirror> result = super.visitConditionalExpression(node, type);
return filterParams(result);
}
@Override
public QualifiedTypeMirror> visitTypeCast(TypeCastTree node, ExtendedTypeMirror type) {
QualifiedTypeMirror> result = super.visitTypeCast(node, type);
return filterParams(result);
}
/** Filter the {@link QualParams} on a {@link QualifiedTypeMirror} to
* ensure that only the type's declared parameters are present.
*/
private QualifiedTypeMirror> filterParams(QualifiedTypeMirror> type) {
if (type.getKind() != TypeKind.DECLARED) {
return type;
}
QualifiedDeclaredType> declType = (QualifiedDeclaredType>)type;
Element elt = declType.getUnderlyingType().asElement();
Set validParams = factory.getAnnotationConverter().getDeclaredParameters(
elt, factory.getDeclAnnotations(elt), factory.getDecoratedElement(elt));
if (validParams.equals(type.getQualifier().keySet())) {
return type;
}
Map> params = new HashMap<>(type.getQualifier());
params.keySet().retainAll(validParams);
return SetQualifierVisitor.apply(type, new QualParams<>(params, type.getQualifier().getPrimary()));
}
}