use of org.checkerframework.framework.type.AnnotatedTypeMirror in project checker-framework by typetools.
the class BaseTypeVisitor method checkVarargs.
/**
* A helper method to check that the array type of actual varargs is a subtype of the
* corresponding required varargs, and issues "argument.invalid" error if it's not a subtype of
* the required one.
*
* <p>Note it's required that type checking for each element in varargs is executed by the
* caller before or after calling this method.
*
* @see #checkArguments(List, List)
* @param invokedMethod the method type to be invoked
* @param tree method or constructor invocation tree
*/
protected void checkVarargs(AnnotatedExecutableType invokedMethod, Tree tree) {
if (!invokedMethod.isVarArgs()) {
return;
}
List<AnnotatedTypeMirror> formals = invokedMethod.getParameterTypes();
int numFormals = formals.size();
int lastArgIndex = numFormals - 1;
AnnotatedArrayType lastParamAnnotatedType = (AnnotatedArrayType) formals.get(lastArgIndex);
// We will skip type checking so that we avoid duplicating error message
// if the last argument is same depth with the depth of formal varargs
// because type checking is already done in checkArguments.
List<? extends ExpressionTree> args;
switch(tree.getKind()) {
case METHOD_INVOCATION:
args = ((MethodInvocationTree) tree).getArguments();
break;
case NEW_CLASS:
args = ((NewClassTree) tree).getArguments();
break;
default:
throw new AssertionError("Unexpected kind of tree: " + tree);
}
if (numFormals == args.size()) {
AnnotatedTypeMirror lastArgType = atypeFactory.getAnnotatedType(args.get(args.size() - 1));
if (lastArgType.getKind() == TypeKind.ARRAY && AnnotatedTypes.getArrayDepth(lastParamAnnotatedType) == AnnotatedTypes.getArrayDepth((AnnotatedArrayType) lastArgType)) {
return;
}
}
AnnotatedTypeMirror wrappedVarargsType = atypeFactory.getAnnotatedTypeVarargsArray(tree);
// annotation to be checked for generated varargs array.
if (wrappedVarargsType == null) {
return;
}
// is also needed to avoid duplicating error message caused by elements in varargs
if (wrappedVarargsType.getKind() == TypeKind.ARRAY) {
((AnnotatedArrayType) wrappedVarargsType).setComponentType(lastParamAnnotatedType.getComponentType());
}
commonAssignmentCheck(lastParamAnnotatedType, wrappedVarargsType, tree, "varargs.type.incompatible");
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror in project checker-framework by typetools.
the class BaseTypeVisitor method visitAnnotation.
/* TODO: something similar to visitReturn should be done.
* public Void visitThrow(ThrowTree node, Void p) {
* return super.visitThrow(node, p);
* }
*/
/**
* Ensure that the annotation arguments comply to their declarations. This needs some special
* casing, as annotation arguments form special trees.
*/
@Override
public Void visitAnnotation(AnnotationTree node, Void p) {
List<? extends ExpressionTree> args = node.getArguments();
if (args.isEmpty()) {
// Nothing to do if there are no annotation arguments.
return null;
}
TypeElement anno = (TypeElement) TreeInfo.symbol((JCTree) node.getAnnotationType());
Name annoName = anno.getQualifiedName();
if (annoName.contentEquals(DefaultQualifier.class.getName()) || annoName.contentEquals(SuppressWarnings.class.getName())) {
// Skip these two annotations, as we don't care about the arguments to them.
return null;
}
// Mapping from argument simple name to its annotated type.
Map<String, AnnotatedTypeMirror> annoTypes = new HashMap<>();
for (Element encl : ElementFilter.methodsIn(anno.getEnclosedElements())) {
AnnotatedExecutableType exeatm = (AnnotatedExecutableType) atypeFactory.getAnnotatedType(encl);
AnnotatedTypeMirror retty = exeatm.getReturnType();
annoTypes.put(encl.getSimpleName().toString(), retty);
}
for (ExpressionTree arg : args) {
if (!(arg instanceof AssignmentTree)) {
// TODO: when can this happen?
continue;
}
AssignmentTree at = (AssignmentTree) arg;
// we don't have a type for annotations.
if (at.getExpression().getKind() == Tree.Kind.ANNOTATION) {
visitAnnotation((AnnotationTree) at.getExpression(), p);
continue;
}
if (at.getExpression().getKind() == Tree.Kind.NEW_ARRAY) {
NewArrayTree nat = (NewArrayTree) at.getExpression();
boolean isAnno = false;
for (ExpressionTree init : nat.getInitializers()) {
if (init.getKind() == Tree.Kind.ANNOTATION) {
visitAnnotation((AnnotationTree) init, p);
isAnno = true;
}
}
if (isAnno) {
continue;
}
}
AnnotatedTypeMirror expected = annoTypes.get(at.getVariable().toString());
Pair<Tree, AnnotatedTypeMirror> preAssCtxt = visitorState.getAssignmentContext();
{
// Determine and set the new assignment context.
ExpressionTree var = at.getVariable();
assert var instanceof IdentifierTree : "Expected IdentifierTree as context. Found: " + var;
AnnotatedTypeMirror meth = atypeFactory.getAnnotatedType(var);
assert meth instanceof AnnotatedExecutableType : "Expected AnnotatedExecutableType as context. Found: " + meth;
AnnotatedTypeMirror newctx = ((AnnotatedExecutableType) meth).getReturnType();
visitorState.setAssignmentContext(Pair.of((Tree) null, newctx));
}
try {
AnnotatedTypeMirror actual = atypeFactory.getAnnotatedType(at.getExpression());
if (expected.getKind() != TypeKind.ARRAY) {
// Expected is not an array -> direct comparison.
commonAssignmentCheck(expected, actual, at.getExpression(), "annotation.type.incompatible");
} else {
if (actual.getKind() == TypeKind.ARRAY) {
// Both actual and expected are arrays.
commonAssignmentCheck(expected, actual, at.getExpression(), "annotation.type.incompatible");
} else {
// The declaration is an array type, but just a single
// element is given.
commonAssignmentCheck(((AnnotatedArrayType) expected).getComponentType(), actual, at.getExpression(), "annotation.type.incompatible");
}
}
} finally {
visitorState.setAssignmentContext(preAssCtxt);
}
}
return null;
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror in project checker-framework by typetools.
the class BaseTypeVisitor method visitMethodInvocation.
/**
* Performs a method invocation check.
*
* <p>An invocation of a method, m, on the receiver, r is valid only if:
*
* <ul>
* <li>passed arguments are subtypes of corresponding m parameters
* <li>r is a subtype of m receiver type
* <li>if m is generic, passed type arguments are subtypes of m type variables
* </ul>
*/
@Override
public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
// hard to check), also see CFGBuilder.visitMethodInvocation.
if (TreeUtils.elementFromUse(node) == null || TreeUtils.isEnumSuper(node)) {
return super.visitMethodInvocation(node, p);
}
if (shouldSkipUses(node)) {
return super.visitMethodInvocation(node, p);
}
Pair<AnnotatedExecutableType, List<AnnotatedTypeMirror>> mfuPair = atypeFactory.methodFromUse(node);
AnnotatedExecutableType invokedMethod = mfuPair.first;
List<AnnotatedTypeMirror> typeargs = mfuPair.second;
if (!atypeFactory.ignoreUninferredTypeArguments) {
for (AnnotatedTypeMirror typearg : typeargs) {
if (typearg.getKind() == TypeKind.WILDCARD && ((AnnotatedWildcardType) typearg).isUninferredTypeArgument()) {
checker.report(Result.failure("type.arguments.not.inferred", invokedMethod.getElement().getSimpleName()), node);
// only issue error once per method
break;
}
}
}
List<AnnotatedTypeParameterBounds> paramBounds = new ArrayList<>();
for (AnnotatedTypeVariable param : invokedMethod.getTypeVariables()) {
paramBounds.add(param.getBounds());
}
checkTypeArguments(node, paramBounds, typeargs, node.getTypeArguments());
List<AnnotatedTypeMirror> params = AnnotatedTypes.expandVarArgs(atypeFactory, invokedMethod, node.getArguments());
checkArguments(params, node.getArguments());
checkVarargs(invokedMethod, node);
if (isVectorCopyInto(invokedMethod)) {
typeCheckVectorCopyIntoArgument(node, params);
}
ExecutableElement invokedMethodElement = invokedMethod.getElement();
if (!ElementUtils.isStatic(invokedMethodElement) && !TreeUtils.isSuperCall(node)) {
checkMethodInvocability(invokedMethod, node);
}
// check precondition annotations
checkPreconditions(node, contractsUtils.getPreconditions(invokedMethodElement));
// Do not call super, as that would observe the arguments without
// a set assignment context.
scan(node.getMethodSelect(), p);
// super.visitMethodInvocation(node, p);
return null;
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror in project checker-framework by typetools.
the class BaseTypeVisitor method visitEnhancedForLoop.
/**
* Performs a subtype check, to test whether the node expression iterable type is a subtype of
* the variable type in the enhanced for loop.
*
* <p>If the subtype check fails, it issues a "enhancedfor.type.incompatible" error.
*/
@Override
public Void visitEnhancedForLoop(EnhancedForLoopTree node, Void p) {
AnnotatedTypeMirror var = atypeFactory.getAnnotatedTypeLhs(node.getVariable());
AnnotatedTypeMirror iterableType = atypeFactory.getAnnotatedType(node.getExpression());
AnnotatedTypeMirror iteratedType = AnnotatedTypes.getIteratedType(checker.getProcessingEnvironment(), atypeFactory, iterableType);
boolean valid = validateTypeOf(node.getVariable());
if (valid) {
commonAssignmentCheck(var, iteratedType, node.getExpression(), "enhancedfor.type.incompatible");
}
return super.visitEnhancedForLoop(node, p);
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror in project checker-framework by typetools.
the class BaseTypeVisitor method checkExceptionParameter.
// **********************************************************************
// Helper methods to provide a single overriding point
// **********************************************************************
/**
* Issue error if the exception parameter is not a supertype of the annotation specified by
* {@link #getExceptionParameterLowerBoundAnnotations()}, which is top by default.
*
* <p>Subclasses may override this method to change the behavior of this check. Subclasses
* wishing to enforce that exception parameter be annotated with other annotations can just
* override {@link #getExceptionParameterLowerBoundAnnotations()}.
*
* @param node CatchTree to check
*/
protected void checkExceptionParameter(CatchTree node) {
Set<? extends AnnotationMirror> requiredAnnotations = getExceptionParameterLowerBoundAnnotations();
AnnotatedTypeMirror exPar = atypeFactory.getAnnotatedType(node.getParameter());
for (AnnotationMirror required : requiredAnnotations) {
AnnotationMirror found = exPar.getAnnotationInHierarchy(required);
assert found != null;
if (!atypeFactory.getQualifierHierarchy().isSubtype(required, found)) {
checker.report(Result.failure("exception.parameter.invalid", found, required), node.getParameter());
}
if (exPar.getKind() == TypeKind.UNION) {
AnnotatedUnionType aut = (AnnotatedUnionType) exPar;
for (AnnotatedTypeMirror alterntive : aut.getAlternatives()) {
AnnotationMirror foundAltern = alterntive.getAnnotationInHierarchy(required);
if (!atypeFactory.getQualifierHierarchy().isSubtype(required, foundAltern)) {
checker.report(Result.failure("exception.parameter.invalid", foundAltern, required), node.getParameter());
}
}
}
}
}
Aggregations