use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable in project checker-framework by typetools.
the class AnnotatedTypes method addTypeVarMappings.
private static void addTypeVarMappings(Types types, AnnotatedTypeFactory atypeFactory, AnnotatedTypeMirror t, TypeElement enclosingClassOfElem, Map<TypeVariable, AnnotatedTypeMirror> mappings) {
if (enclosingClassOfElem.getTypeParameters().isEmpty()) {
return;
}
AnnotatedDeclaredType enclosingType = atypeFactory.getAnnotatedType(enclosingClassOfElem);
AnnotatedDeclaredType base = (AnnotatedDeclaredType) asOuterSuper(types, atypeFactory, t, enclosingType);
final List<AnnotatedTypeVariable> ownerParams = new ArrayList<>(enclosingType.getTypeArguments().size());
for (final AnnotatedTypeMirror typeParam : enclosingType.getTypeArguments()) {
if (typeParam.getKind() != TypeKind.TYPEVAR) {
ErrorReporter.errorAbort("Type arguments of a declaration should be type variables\n" + "enclosingClassOfElem=" + enclosingClassOfElem + "\n" + "enclosingType=" + enclosingType + "\n" + "typeMirror=" + t);
}
ownerParams.add((AnnotatedTypeVariable) typeParam);
}
List<AnnotatedTypeMirror> baseParams = base.getTypeArguments();
if (ownerParams.size() != baseParams.size() && !base.wasRaw()) {
ErrorReporter.errorAbort("Unexpected number of parameters.\n" + "enclosingType=" + enclosingType + "\n" + "baseType=" + base);
}
if (!ownerParams.isEmpty() && baseParams.isEmpty() && base.wasRaw()) {
List<AnnotatedTypeMirror> newBaseParams = new ArrayList<>();
for (AnnotatedTypeVariable arg : ownerParams) {
// If base type was raw and the type arguments are missing,
// set them to the erased type of the type variable.
// (which is the erased type of the upper bound.)
newBaseParams.add(arg.getErased());
}
baseParams = newBaseParams;
}
for (int i = 0; i < ownerParams.size(); ++i) {
mappings.put(ownerParams.get(i).getUnderlyingType(), baseParams.get(i));
}
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable in project checker-framework by typetools.
the class AnnotatedTypes method findTypeArguments.
/**
* Given a method or constructor invocation, return a mapping of the type variables to their
* type arguments, if any exist.
*
* <p>It uses the method or constructor invocation type arguments if they were specified and
* otherwise it infers them based on the passed arguments or the return type context, according
* to JLS 15.12.2.
*
* @param atypeFactory the annotated type factory
* @param expr the method or constructor invocation tree; the passed argument has to be a
* subtype of MethodInvocationTree or NewClassTree
* @param elt the element corresponding to the tree
* @param preType the (partially annotated) type corresponding to the tree - the result of
* AnnotatedTypes.asMemberOf with the receiver and elt.
* @return the mapping of the type variables to type arguments for this method or constructor
* invocation
*/
public static Map<TypeVariable, AnnotatedTypeMirror> findTypeArguments(final ProcessingEnvironment processingEnv, final AnnotatedTypeFactory atypeFactory, final ExpressionTree expr, final ExecutableElement elt, final AnnotatedExecutableType preType) {
// Is the method a generic method?
if (elt.getTypeParameters().isEmpty()) {
return Collections.emptyMap();
}
List<? extends Tree> targs;
if (expr instanceof MethodInvocationTree) {
targs = ((MethodInvocationTree) expr).getTypeArguments();
} else if (expr instanceof NewClassTree) {
targs = ((NewClassTree) expr).getTypeArguments();
} else if (expr instanceof MemberReferenceTree) {
targs = ((MemberReferenceTree) expr).getTypeArguments();
if (targs == null) {
// TODO: Add type argument inference as part of fix for #979
return new HashMap<>();
}
} else {
// This case should never happen.
ErrorReporter.errorAbort("AnnotatedTypes.findTypeArguments: unexpected tree: " + expr);
// dead code
return null;
}
// Has the user supplied type arguments?
if (!targs.isEmpty()) {
List<? extends AnnotatedTypeVariable> tvars = preType.getTypeVariables();
Map<TypeVariable, AnnotatedTypeMirror> typeArguments = new HashMap<>();
for (int i = 0; i < elt.getTypeParameters().size(); ++i) {
AnnotatedTypeVariable typeVar = tvars.get(i);
AnnotatedTypeMirror typeArg = atypeFactory.getAnnotatedTypeFromTypeTree(targs.get(i));
// TODO: the call to getTypeParameterDeclaration shouldn't be necessary - typeVar
// already should be a declaration.
typeArguments.put(typeVar.getUnderlyingType(), typeArg);
}
return typeArguments;
} else {
return atypeFactory.getTypeArgumentInference().inferTypeArgs(atypeFactory, expr, elt, preType);
}
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable 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.AnnotatedTypeVariable in project checker-framework by typetools.
the class BaseTypeVisitor method testTypevarContainment.
/**
* @return true if both types are type variables and outer contains inner Outer contains inner
* implies: {@literal inner.upperBound <: outer.upperBound outer.lowerBound <:
* inner.lowerBound }
*/
protected boolean testTypevarContainment(final AnnotatedTypeMirror inner, final AnnotatedTypeMirror outer) {
if (inner.getKind() == TypeKind.TYPEVAR && outer.getKind() == TypeKind.TYPEVAR) {
final AnnotatedTypeVariable innerAtv = (AnnotatedTypeVariable) inner;
final AnnotatedTypeVariable outerAtv = (AnnotatedTypeVariable) outer;
if (AnnotatedTypes.areCorrespondingTypeVariables(elements, innerAtv, outerAtv)) {
final TypeHierarchy typeHierarchy = atypeFactory.getTypeHierarchy();
return typeHierarchy.isSubtype(innerAtv.getUpperBound(), outerAtv.getUpperBound()) && typeHierarchy.isSubtype(outerAtv.getLowerBound(), innerAtv.getLowerBound());
}
}
return false;
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable 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;
}
Aggregations