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-qual Show documentation
Show all versions of checker-qual Show documentation
Checker Qual is the set of annotations (qualifiers) and supporting classes
used by the Checker Framework to type check Java source code. Please
see artifact:
org.checkerframework:checker
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()));
}
}