use of org.checkerframework.framework.type.AnnotatedTypeMirror in project checker-framework by typetools.
the class BaseTypeVisitor method checkThrownExpression.
/**
* Checks the type of the thrown expression.
*
* <p>By default, this method checks that the thrown expression is a subtype of top.
*
* <p>Issue error if the thrown expression is not a sub type of the annotation given by {@link
* #getThrowUpperBoundAnnotations()}, the same as {@link
* #getExceptionParameterLowerBoundAnnotations()} by default.
*
* <p>Subclasses may override this method to change the behavior of this check. Subclasses
* wishing to enforce that the thrown expression be a subtype of a type besides {@link
* #getExceptionParameterLowerBoundAnnotations}, should override {@link
* #getThrowUpperBoundAnnotations()}.
*
* @param node ThrowTree to check
*/
protected void checkThrownExpression(ThrowTree node) {
AnnotatedTypeMirror throwType = atypeFactory.getAnnotatedType(node.getExpression());
Set<? extends AnnotationMirror> required = getThrowUpperBoundAnnotations();
switch(throwType.getKind()) {
case NULL:
case DECLARED:
Set<AnnotationMirror> found = throwType.getAnnotations();
if (!atypeFactory.getQualifierHierarchy().isSubtype(found, required)) {
checker.report(Result.failure("throw.type.invalid", found, required), node.getExpression());
}
break;
case TYPEVAR:
case WILDCARD:
// TODO: this code might change after the type var changes.
Set<AnnotationMirror> foundEffective = throwType.getEffectiveAnnotations();
if (!atypeFactory.getQualifierHierarchy().isSubtype(foundEffective, required)) {
checker.report(Result.failure("throw.type.invalid", foundEffective, required), node.getExpression());
}
break;
case UNION:
AnnotatedUnionType unionType = (AnnotatedUnionType) throwType;
Set<AnnotationMirror> foundPrimary = unionType.getAnnotations();
if (!atypeFactory.getQualifierHierarchy().isSubtype(foundPrimary, required)) {
checker.report(Result.failure("throw.type.invalid", foundPrimary, required), node.getExpression());
}
for (AnnotatedTypeMirror altern : unionType.getAlternatives()) {
if (!atypeFactory.getQualifierHierarchy().isSubtype(altern.getAnnotations(), required)) {
checker.report(Result.failure("throw.type.invalid", altern.getAnnotations(), required), node.getExpression());
}
}
break;
default:
ErrorReporter.errorAbort("Unexpected throw expression type: " + throwType.getKind());
break;
}
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror in project checker-framework by typetools.
the class BaseTypeVisitor method checkMethodInvocability.
/**
* Tests whether the method can be invoked using the receiver of the 'node' method invocation,
* and issues a "method.invocation.invalid" if the invocation is invalid.
*
* <p>This implementation tests whether the receiver in the method invocation is a subtype of
* the method receiver type. This behavior can be specialized by overriding
* skipReceiverSubtypeCheck.
*
* @param method the type of the invoked method
* @param node the method invocation node
*/
protected void checkMethodInvocability(AnnotatedExecutableType method, MethodInvocationTree node) {
if (method.getReceiverType() == null) {
// Static methods don't have a receiver.
return;
}
if (method.getElement().getKind() == ElementKind.CONSTRUCTOR) {
// ((AnnotatedExecutableType)atypeFactory.getAnnotatedType(atypeFactory.getEnclosingMethod(node))).getReceiverType();
return;
}
AnnotatedTypeMirror methodReceiver = method.getReceiverType().getErased();
AnnotatedTypeMirror treeReceiver = methodReceiver.shallowCopy(false);
AnnotatedTypeMirror rcv = atypeFactory.getReceiverType(node);
treeReceiver.addAnnotations(rcv.getEffectiveAnnotations());
if (!skipReceiverSubtypeCheck(node, methodReceiver, rcv) && !atypeFactory.getTypeHierarchy().isSubtype(treeReceiver, methodReceiver)) {
checker.report(Result.failure("method.invocation.invalid", TreeUtils.elementFromUse(node), treeReceiver.toString(), methodReceiver.toString()), node);
}
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror in project checker-framework by typetools.
the class BaseTypeVisitor method visitNewClass.
/**
* Performs a new class invocation check.
*
* <p>An invocation of a constructor, c, is valid only if:
*
* <ul>
* <li>passed arguments are subtypes of corresponding c parameters
* <li>if c is generic, passed type arguments are subtypes of c type variables
* </ul>
*/
@Override
public Void visitNewClass(NewClassTree node, Void p) {
if (checker.shouldSkipUses(TreeUtils.constructor(node))) {
return super.visitNewClass(node, p);
}
Pair<AnnotatedExecutableType, List<AnnotatedTypeMirror>> fromUse = atypeFactory.constructorFromUse(node);
AnnotatedExecutableType constructor = fromUse.first;
List<AnnotatedTypeMirror> typeargs = fromUse.second;
List<? extends ExpressionTree> passedArguments = node.getArguments();
List<AnnotatedTypeMirror> params = AnnotatedTypes.expandVarArgs(atypeFactory, constructor, passedArguments);
checkArguments(params, passedArguments);
checkVarargs(constructor, node);
List<AnnotatedTypeParameterBounds> paramBounds = new ArrayList<>();
for (AnnotatedTypeVariable param : constructor.getTypeVariables()) {
paramBounds.add(param.getBounds());
}
checkTypeArguments(node, paramBounds, typeargs, node.getTypeArguments());
boolean valid = validateTypeOf(node);
if (valid) {
AnnotatedDeclaredType dt = atypeFactory.getAnnotatedType(node);
if (atypeFactory.getDependentTypesHelper() != null) {
atypeFactory.getDependentTypesHelper().checkType(dt, node);
}
checkConstructorInvocation(dt, constructor, node);
}
// Do not call super, as that would observe the arguments without
// a set assignment context.
scan(node.getEnclosingExpression(), p);
scan(node.getIdentifier(), p);
scan(node.getClassBody(), p);
return null;
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror in project checker-framework by typetools.
the class BaseTypeVisitor method visitTypeCast.
@Override
public Void visitTypeCast(TypeCastTree node, Void p) {
// validate "node" instead of "node.getType()" to prevent duplicate errors.
boolean valid = validateTypeOf(node) && validateTypeOf(node.getExpression());
if (valid) {
checkTypecastSafety(node, p);
checkTypecastRedundancy(node, p);
}
if (atypeFactory.getDependentTypesHelper() != null) {
AnnotatedTypeMirror type = atypeFactory.getAnnotatedType(node);
atypeFactory.getDependentTypesHelper().checkType(type, node.getType());
}
return super.visitTypeCast(node, p);
// return scan(node.getExpression(), p);
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror in project checker-framework by typetools.
the class BaseTypeVisitor method checkFieldInvariantDeclarations.
/**
* Check that the field invariant declaration annotations meet the following requirements:
*
* <ol>
* <!-- The item numbering is referred to in the body of the method.-->
* <li value="1">If the superclass of {@code classTree} has a field invariant, then the field
* invariant for {@code classTree} must include all the fields in the superclass invariant
* and those fields' annotations must be a subtype (or equal) to the annotations for those
* fields in the superclass.
* <li value="2">The fields in the invariant must be a.) final and b.) declared in a
* superclass of {@code classTree}.
* <li value="3">The qualifier for each field must be a subtype of the annotation on the
* declaration of that field.
* <li value="4">The field invariant has an equal number of fields and qualifiers, or it has
* one qualifier and at least one field.
* </ol>
*
* @param classTree class that might have a field invariant
* @checker_framework.manual #field-invariants Field invariants
*/
protected void checkFieldInvariantDeclarations(ClassTree classTree) {
TypeElement elt = TreeUtils.elementFromDeclaration(classTree);
FieldInvariants invariants = atypeFactory.getFieldInvariants(elt);
if (invariants == null) {
// No invariants to check
return;
}
// Where to issue an error, if any.
Tree errorTree = atypeFactory.getFieldInvariantAnnotationTree(classTree.getModifiers().getAnnotations());
if (errorTree == null) {
// If the annotation was inherited, then there is no annotation tree, so issue the
// error on the class.
errorTree = classTree;
}
// Checks #4 (see method Javadoc)
if (!invariants.isWellFormed()) {
checker.report(Result.failure("field.invariant.not.wellformed"), errorTree);
return;
}
TypeMirror superClass = elt.getSuperclass();
List<String> fieldsNotFound = new ArrayList<>(invariants.getFields());
Set<VariableElement> fieldElts = ElementUtils.findFieldsInTypeOrSuperType(superClass, fieldsNotFound);
// Checks that fields are declared in super class. (#2b)
if (!fieldsNotFound.isEmpty()) {
String notFoundString = PluginUtil.join(", ", fieldsNotFound);
checker.report(Result.failure("field.invariant.not.found", notFoundString), errorTree);
}
FieldInvariants superInvar = atypeFactory.getFieldInvariants(TypesUtils.getTypeElement(superClass));
if (superInvar != null) {
// Checks #3 (see method Javadoc)
Result superError = invariants.isSuperInvariant(superInvar, atypeFactory);
if (superError != null) {
checker.report(superError, errorTree);
}
}
List<String> notFinal = new ArrayList<>();
for (VariableElement field : fieldElts) {
String fieldName = field.getSimpleName().toString();
if (!ElementUtils.isFinal(field)) {
notFinal.add(fieldName);
}
AnnotatedTypeMirror type = atypeFactory.getAnnotatedType(field);
List<AnnotationMirror> annos = invariants.getQualifiersFor(field.getSimpleName());
for (AnnotationMirror invariantAnno : annos) {
AnnotationMirror declaredAnno = type.getEffectiveAnnotationInHierarchy(invariantAnno);
if (declaredAnno == null) {
// invariant anno isn't in this hierarchy
continue;
}
if (!atypeFactory.getQualifierHierarchy().isSubtype(invariantAnno, declaredAnno)) {
// Checks #3
checker.report(Result.failure("field.invariant.not.subtype", fieldName, invariantAnno, declaredAnno), errorTree);
}
}
}
// Checks #2a
if (!notFinal.isEmpty()) {
String notFinalString = PluginUtil.join(", ", notFinal);
checker.report(Result.failure("field.invariant.not.final", notFinalString), errorTree);
}
}
Aggregations