use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable in project checker-framework by typetools.
the class AnnotatedTypeFactory method typeVariablesFromUse.
/**
* Adapt the upper bounds of the type variables of a class relative to the type instantiation.
* In some type systems, the upper bounds depend on the instantiation of the class. For example,
* in the Generic Universe Type system, consider a class declaration
*
* <pre>{@code class C<X extends @Peer Object> }</pre>
*
* then the instantiation
*
* <pre>{@code @Rep C<@Rep Object> }</pre>
*
* is legal. The upper bounds of class C have to be adapted by the main modifier.
*
* <p>An example of an adaptation follows. Suppose, I have a declaration:
*
* <pre>{@code class MyClass<E extends List<E>>}</pre>
*
* And an instantiation:
*
* <pre>{@code new MyClass<@NonNull String>()}</pre>
*
* <p>The upper bound of E adapted to the argument String, would be {@code List<@NonNull
* String>} and the lower bound would be an AnnotatedNullType.
*
* <p>TODO: ensure that this method is consistently used instead of directly querying the type
* variables.
*
* @param type the use of the type
* @param element the corresponding element
* @return the adapted bounds of the type parameters
*/
public List<AnnotatedTypeParameterBounds> typeVariablesFromUse(AnnotatedDeclaredType type, TypeElement element) {
AnnotatedDeclaredType generic = getAnnotatedType(element);
List<AnnotatedTypeMirror> targs = type.getTypeArguments();
List<AnnotatedTypeMirror> tvars = generic.getTypeArguments();
assert targs.size() == tvars.size() : "Mismatch in type argument size between " + type + " and " + generic;
// System.err.printf("TVFU\n type: %s\n generic: %s\n", type, generic);
Map<TypeVariable, AnnotatedTypeMirror> mapping = new HashMap<>();
AnnotatedDeclaredType enclosing = type;
while (enclosing != null) {
List<AnnotatedTypeMirror> enclosingTArgs = enclosing.getTypeArguments();
AnnotatedDeclaredType declaredType = getAnnotatedType((TypeElement) enclosing.getUnderlyingType().asElement());
List<AnnotatedTypeMirror> enclosingTVars = declaredType.getTypeArguments();
for (int i = 0; i < enclosingTArgs.size(); i++) {
AnnotatedTypeVariable enclosingTVar = (AnnotatedTypeVariable) enclosingTVars.get(i);
mapping.put(enclosingTVar.getUnderlyingType(), enclosingTArgs.get(i));
}
enclosing = enclosing.getEnclosingType();
}
List<AnnotatedTypeParameterBounds> res = new ArrayList<>(tvars.size());
for (AnnotatedTypeMirror atm : tvars) {
AnnotatedTypeVariable atv = (AnnotatedTypeVariable) atm;
AnnotatedTypeMirror upper = typeVarSubstitutor.substitute(mapping, atv.getUpperBound());
AnnotatedTypeMirror lower = typeVarSubstitutor.substitute(mapping, atv.getLowerBound());
res.add(new AnnotatedTypeParameterBounds(upper, lower));
}
return res;
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable in project checker-framework by typetools.
the class BoundsInitializer method initializeTypeArgs.
// ============================================================================================
// Static helper methods called from AnnotatedTypeMirror to initialize bounds of wildcards or
// type variables
// ============================================================================================
/**
* Initializes the type arguments of {@code declaredType}. The upper bound of unbound wildcards
* is set to the upper bound of the type parameter for which it is an argument. If {@code
* declaredType} is raw, then the type arguments are uninferred wildcards.
*
* @param declaredType type whose arguments are initialized.
*/
public static void initializeTypeArgs(AnnotatedDeclaredType declaredType) {
final DeclaredType actualType = (DeclaredType) declaredType.actualType;
if (actualType.getTypeArguments().isEmpty() && !declaredType.wasRaw()) {
// No type arguments to infer.
return;
}
final TypeElement typeElement = (TypeElement) declaredType.atypeFactory.types.asElement(actualType);
final List<AnnotatedTypeMirror> typeArgs = new ArrayList<>();
// Create AnnotatedTypeMirror for each type argument and store them in the typeArgsMap.
Map<TypeVariable, AnnotatedTypeMirror> typeArgMap = new HashMap<>();
for (int i = 0; i < typeElement.getTypeParameters().size(); i++) {
TypeMirror javaTypeArg;
if (declaredType.wasRaw()) {
TypeVariable typeVariable = (TypeVariable) typeElement.getTypeParameters().get(i).asType();
javaTypeArg = getUpperBoundAsWildcard(typeVariable, declaredType.atypeFactory);
} else {
javaTypeArg = declaredType.getUnderlyingType().getTypeArguments().get(i);
}
final AnnotatedTypeMirror typeArg = AnnotatedTypeMirror.createType(javaTypeArg, declaredType.atypeFactory, false);
if (typeArg.getKind() == TypeKind.WILDCARD) {
AnnotatedWildcardType wildcardType = (AnnotatedWildcardType) typeArg;
wildcardType.setTypeVariable(typeElement.getTypeParameters().get(i));
if (declaredType.wasRaw()) {
wildcardType.setUninferredTypeArgument();
}
}
typeArgs.add(typeArg);
typeArgMap.put((TypeVariable) typeElement.getTypeParameters().get(i).asType(), typeArg);
}
// Initialize type argument bounds using the typeArgsMap.
for (AnnotatedTypeMirror typeArg : typeArgs) {
switch(typeArg.getKind()) {
case WILDCARD:
AnnotatedWildcardType wildcardType = (AnnotatedWildcardType) typeArg;
initializeExtendsBound(wildcardType, typeArgMap);
initializeSuperBound(wildcardType, typeArgMap);
break;
case TYPEVAR:
initializeBounds((AnnotatedTypeVariable) typeArg, typeArgMap);
break;
default:
}
}
declaredType.typeArgs = Collections.unmodifiableList(typeArgs);
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable in project checker-framework by typetools.
the class DefaultInferredTypesApplier method removePrimaryAnnotationTypeVar.
private void removePrimaryAnnotationTypeVar(AnnotatedTypeVariable annotatedTypeVariable, TypeMirror inferredTypeMirror, AnnotationMirror top, AnnotationMirror previousAnnotation) {
if (inferredTypeMirror.getKind() == TypeKind.WILDCARD) {
// actually type variables. Use the type variable instead.
while (inferredTypeMirror.getKind() == TypeKind.WILDCARD) {
inferredTypeMirror = ((WildcardType) inferredTypeMirror).getExtendsBound();
}
}
if (inferredTypeMirror.getKind() != TypeKind.TYPEVAR) {
ErrorReporter.errorAbort("Missing annos");
return;
}
TypeVariable typeVar = (TypeVariable) inferredTypeMirror;
AnnotatedTypeVariable typeVariableDecl = (AnnotatedTypeVariable) factory.getAnnotatedType(typeVar.asElement());
AnnotationMirror upperBound = typeVariableDecl.getEffectiveAnnotationInHierarchy(top);
if (omitSubtypingCheck || hierarchy.isSubtype(upperBound, previousAnnotation)) {
annotatedTypeVariable.removeAnnotationInHierarchy(top);
AnnotationMirror ub = typeVariableDecl.getUpperBound().getAnnotationInHierarchy(top);
apply(annotatedTypeVariable.getUpperBound(), ub, typeVar.getUpperBound(), top);
AnnotationMirror lb = typeVariableDecl.getLowerBound().getAnnotationInHierarchy(top);
apply(annotatedTypeVariable.getLowerBound(), lb, typeVar.getLowerBound(), top);
}
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable in project checker-framework by typetools.
the class TypeFromTypeTreeVisitor method forTypeVariable.
private AnnotatedTypeMirror forTypeVariable(AnnotatedTypeMirror type, AnnotatedTypeFactory f) {
if (type.getKind() != TypeKind.TYPEVAR) {
ErrorReporter.errorAbort("TypeFromTree.forTypeVariable: should only be called on type variables");
// dead code
return null;
}
TypeVariable typeVar = (TypeVariable) type.getUnderlyingType();
TypeParameterElement tpe = (TypeParameterElement) typeVar.asElement();
Element elt = tpe.getGenericElement();
if (elt instanceof TypeElement) {
TypeElement typeElt = (TypeElement) elt;
int idx = typeElt.getTypeParameters().indexOf(tpe);
ClassTree cls = (ClassTree) f.declarationFromElement(typeElt);
if (cls != null) {
// `forTypeVariable` is called for Identifier, MemberSelect and UnionType trees,
// none of which are declarations. But `cls.getTypeParameters()` returns a list
// of type parameter declarations (`TypeParameterTree`), so this recursive call
// to `visit` will return a declaration ATV. So we must copy the result and set
// its `isDeclaration` field to `false`.
AnnotatedTypeMirror result = visit(cls.getTypeParameters().get(idx), f).shallowCopy();
((AnnotatedTypeVariable) result).setDeclaration(false);
return result;
} else {
// We already have all info from the element -> nothing to do.
return type;
}
} else if (elt instanceof ExecutableElement) {
ExecutableElement exElt = (ExecutableElement) elt;
int idx = exElt.getTypeParameters().indexOf(tpe);
MethodTree meth = (MethodTree) f.declarationFromElement(exElt);
if (meth != null) {
// This works the same as the case above. Even though `meth` itself is not a
// type declaration tree, the elements of `meth.getTypeParameters()` still are.
AnnotatedTypeMirror result = visit(meth.getTypeParameters().get(idx), f).shallowCopy();
((AnnotatedTypeVariable) result).setDeclaration(false);
return result;
} else {
// " + elt);
return type;
}
} else {
// not an element at all, namely Symtab.noSymbol.
if (TypesUtils.isCaptured(typeVar)) {
return type;
} else {
ErrorReporter.errorAbort("TypeFromTree.forTypeVariable: not a supported element: " + elt);
// dead code
return null;
}
}
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable in project checker-framework by typetools.
the class TypesIntoElements method storeTypeParameters.
private static void storeTypeParameters(ProcessingEnvironment processingEnv, Types types, AnnotatedTypeFactory atypeFactory, java.util.List<? extends TypeParameterTree> tps, Symbol sym) {
boolean isClassOrInterface = sym.getKind().isClass() || sym.getKind().isInterface();
List<Attribute.TypeCompound> tcs = List.nil();
int tpidx = 0;
for (TypeParameterTree tp : tps) {
AnnotatedTypeVariable typeVar = (AnnotatedTypeVariable) atypeFactory.getAnnotatedTypeFromTypeTree(tp);
// System.out.println("The Type for type parameter " + tp + " is " + type);
TypeAnnotationPosition tapos;
// the bounds may not be explicit and we couldn't look up separate pos.
if (isClassOrInterface) {
tapos = TypeAnnotationUtils.typeParameterTAPosition(tpidx, ((JCTree) tp).pos);
} else {
tapos = TypeAnnotationUtils.methodTypeParameterTAPosition(tpidx, ((JCTree) tp).pos);
}
{
// This block is essentially direct annotations, perhaps we should refactor that
// method out
List<Attribute.TypeCompound> res = List.nil();
for (AnnotationMirror am : typeVar.getLowerBound().getAnnotations()) {
Attribute.TypeCompound tc = TypeAnnotationUtils.createTypeCompoundFromAnnotationMirror(am, tapos, processingEnv);
res = res.prepend(tc);
}
tcs = tcs.appendList(res);
}
AnnotatedTypeMirror tpbound = typeVar.getUpperBound();
java.util.List<? extends AnnotatedTypeMirror> bounds;
if (tpbound.getKind() == TypeKind.INTERSECTION) {
bounds = ((AnnotatedTypeMirror.AnnotatedIntersectionType) tpbound).directSuperTypes();
} else {
bounds = List.of(tpbound);
}
int bndidx = 0;
for (AnnotatedTypeMirror bound : bounds) {
if (bndidx == 0 && ((Type) bound.getUnderlyingType()).isInterface()) {
// If the first bound is an interface, there is an implicit java.lang.Object
++bndidx;
}
if (isClassOrInterface) {
tapos = TypeAnnotationUtils.typeParameterBoundTAPosition(tpidx, bndidx, ((JCTree) tp).pos);
} else {
tapos = TypeAnnotationUtils.methodTypeParameterBoundTAPosition(tpidx, bndidx, ((JCTree) tp).pos);
}
tcs = tcs.appendList(generateTypeCompounds(processingEnv, bound, tapos));
++bndidx;
}
++tpidx;
}
// System.out.println("Adding " + tcs + " to " + sym);
addUniqueTypeCompounds(types, sym, tcs);
}
Aggregations