use of org.checkerframework.javacutil.BugInCF in project checker-framework by typetools.
the class QualifierDefaults method getTypeVarBoundType.
/**
* Returns the boundType (UPPER or UNBOUNDED) of the declaration of typeParamElem.
*
* @param typeParamElem the type parameter element
* @return the boundType (UPPER or UNBOUNDED) of the declaration of typeParamElem
*/
// Results are cached in {@link elementToBoundType}.
private BoundType getTypeVarBoundType(final TypeParameterElement typeParamElem) {
final BoundType prev = elementToBoundType.get(typeParamElem);
if (prev != null) {
return prev;
}
TreePath declaredTypeVarEle = atypeFactory.getTreeUtils().getPath(typeParamElem);
Tree typeParamDecl = declaredTypeVarEle == null ? null : declaredTypeVarEle.getLeaf();
final BoundType boundType;
if (typeParamDecl == null) {
// when the compilation unit is no-longer available.
if (typeParamElem.getBounds().size() == 1 && TypesUtils.isObject(typeParamElem.getBounds().get(0))) {
// If the bound was Object, then it may or may not have been explicitly written.
// Assume that it was not.
boundType = BoundType.UNBOUNDED;
} else {
// The bound is not Object, so it must have been explicitly written and thus the
// type variable has an upper bound.
boundType = BoundType.UPPER;
}
} else {
if (typeParamDecl.getKind() == Tree.Kind.TYPE_PARAMETER) {
final TypeParameterTree tptree = (TypeParameterTree) typeParamDecl;
List<? extends Tree> bnds = tptree.getBounds();
if (bnds != null && !bnds.isEmpty()) {
boundType = BoundType.UPPER;
} else {
boundType = BoundType.UNBOUNDED;
}
} else {
throw new BugInCF(StringsPlume.joinLines("Unexpected tree type for typeVar Element:", "typeParamElem=" + typeParamElem, typeParamDecl));
}
}
elementToBoundType.put(typeParamElem, boundType);
return boundType;
}
use of org.checkerframework.javacutil.BugInCF in project checker-framework by typetools.
the class DependentTypesHelper method atInvocation.
/**
* Viewpoint-adapts a method or constructor invocation.
*
* <p>{@code methodType} has been viewpoint-adapted to the call site, except for any dependent
* type annotations. (For example, type variables have been substituted and polymorphic qualifiers
* have been resolved.) This method viewpoint-adapts the dependent type annotations.
*
* @param methodType type of the method or constructor invocation; is side-effected by this method
* @param tree invocation of the method or constructor
*/
private void atInvocation(AnnotatedExecutableType methodType, ExpressionTree tree) {
assert hasDependentAnnotations();
Element methodElt = TreeUtils.elementFromUse(tree);
// Because methodType is the type post type variable substitution, it has annotations from
// both the method declaration and the type arguments at the use of the method. Annotations
// from type arguments must not be viewpoint-adapted to the call site. For example:
// Map<String, String> map = ...;
// List<@KeyFor("this.map") String> list = ...;
// list.get(0)
//
// methodType is @KeyFor("this.map") String get(int)
// "this.map" must not be viewpoint-adapted to the invocation because it is not from
// the method declaration, but added during type variable substitution.
//
// So this implementation gets the declared type of the method, declaredMethodType,
// viewpoint-adapts all dependent type annotations in declaredMethodType to the call site,
// and then copies the viewpoint-adapted annotations from methodType except for types that
// are replaced by type variable substitution. (Those annotations are viewpoint-adapted
// before type variable substitution.)
// The annotations on `declaredMethodType` will be copied to `methodType`.
AnnotatedExecutableType declaredMethodType = (AnnotatedExecutableType) factory.getAnnotatedType(methodElt);
if (!hasDependentType(declaredMethodType)) {
return;
}
StringToJavaExpression stringToJavaExpr;
if (tree instanceof MethodInvocationTree) {
stringToJavaExpr = stringExpr -> StringToJavaExpression.atMethodInvocation(stringExpr, (MethodInvocationTree) tree, factory.getChecker());
if (debugStringToJavaExpression) {
System.out.printf("atInvocation(%s, %s) 1 created %s%n", methodType, TreeUtils.toStringTruncated(tree, 65), stringToJavaExpr);
}
} else if (tree instanceof NewClassTree) {
stringToJavaExpr = stringExpr -> StringToJavaExpression.atConstructorInvocation(stringExpr, (NewClassTree) tree, factory.getChecker());
if (debugStringToJavaExpression) {
System.out.printf("atInvocation(%s, %s) 2 created %s%n", methodType, TreeUtils.toStringTruncated(tree, 65), stringToJavaExpr);
}
} else {
throw new BugInCF("Unexpected tree: %s kind: %s", tree, tree.getKind());
}
convertAnnotatedTypeMirror(stringToJavaExpr, declaredMethodType);
this.viewpointAdaptedCopier.visit(declaredMethodType, methodType);
}
use of org.checkerframework.javacutil.BugInCF 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);
base = (AnnotatedDeclaredType) atypeFactory.applyCaptureConversion(base);
final List<AnnotatedTypeVariable> ownerParams = new ArrayList<>(enclosingType.getTypeArguments().size());
for (final AnnotatedTypeMirror typeParam : enclosingType.getTypeArguments()) {
if (typeParam.getKind() != TypeKind.TYPEVAR) {
throw new BugInCF(StringsPlume.joinLines("Type arguments of a declaration should be type variables.", " enclosingClassOfElem=" + enclosingClassOfElem, " enclosingType=" + enclosingType, " typeMirror=" + t));
}
ownerParams.add((AnnotatedTypeVariable) typeParam);
}
List<AnnotatedTypeMirror> baseParams = base.getTypeArguments();
if (ownerParams.size() != baseParams.size() && !base.isUnderlyingTypeRaw()) {
throw new BugInCF(StringsPlume.joinLines("Unexpected number of parameters.", "enclosingType=" + enclosingType, "baseType=" + base));
}
if (!ownerParams.isEmpty() && baseParams.isEmpty() && base.isUnderlyingTypeRaw()) {
// 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).
baseParams = CollectionsPlume.mapList(AnnotatedTypeVariable::getErased, ownerParams);
}
for (int i = 0; i < ownerParams.size(); ++i) {
mappings.put(ownerParams.get(i).getUnderlyingType(), baseParams.get(i));
}
}
use of org.checkerframework.javacutil.BugInCF 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.
throw new BugInCF("AnnotatedTypes.findTypeArguments: unexpected tree: " + expr);
}
// 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.javacutil.BugInCF in project checker-framework by typetools.
the class AnnotatedTypes method findEffectiveAnnotations.
/**
* When comparing types against the bounds of a type variable, we may encounter other type
* variables, wildcards, and intersections in those bounds. This method traverses the bounds until
* it finds a concrete type from which it can pull an annotation. This occurs for every hierarchy
* in QualifierHierarchy.
*
* @return the set of effective annotation mirrors in all hierarchies
*/
public static Set<AnnotationMirror> findEffectiveAnnotations(final QualifierHierarchy qualifierHierarchy, final AnnotatedTypeMirror toSearch) {
AnnotatedTypeMirror source = toSearch;
TypeKind kind = source.getKind();
while (kind == TypeKind.TYPEVAR || kind == TypeKind.WILDCARD || kind == TypeKind.INTERSECTION) {
switch(source.getKind()) {
case TYPEVAR:
source = ((AnnotatedTypeVariable) source).getUpperBound();
break;
case WILDCARD:
source = ((AnnotatedWildcardType) source).getExtendsBound();
break;
case INTERSECTION:
// if there are multiple conflicting annotations, choose the lowest
final Set<AnnotationMirror> glb = glbOfBounds((AnnotatedIntersectionType) source, qualifierHierarchy);
return glb;
default:
throw new BugInCF("Unexpected AnnotatedTypeMirror with no primary annotation;" + " toSearch=" + toSearch + " source=" + source);
}
kind = source.getKind();
}
return source.getAnnotations();
}
Aggregations