use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.
the class AnnotatedTypeFactory method getStringType.
/**
* Returns AnnotatedDeclaredType with underlying type String and annotations copied from type.
* Subclasses may change the annotations.
*
* @param type type to convert to String
* @return AnnotatedTypeMirror that results from converting type to a String type
*/
// TODO: Test that this is called in all the correct locations
// See Issue #715
// https://github.com/typetools/checker-framework/issues/715
public AnnotatedDeclaredType getStringType(AnnotatedTypeMirror type) {
TypeMirror stringTypeMirror = TypesUtils.typeFromClass(String.class, types, elements);
AnnotatedDeclaredType stringATM = (AnnotatedDeclaredType) AnnotatedTypeMirror.createType(stringTypeMirror, this, type.isDeclaration());
stringATM.addAnnotations(type.getEffectiveAnnotations());
return stringATM;
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType 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.AnnotatedDeclaredType in project checker-framework by typetools.
the class AsSuperVisitor method ensurePrimaryIsCorrectForUnionsAndIntersections.
/**
* The code in this class is assuming that the primary annotation of an {@link
* AnnotatedIntersectionType} is the greatest lower bound of the annotations on its direct super
* types and that the primary annotation of an {@link AnnotatedUnionType} is the least upper
* bound of its alternatives. This method makes this assumption true.
*/
private void ensurePrimaryIsCorrectForUnionsAndIntersections(AnnotatedTypeMirror type) {
if (type.getKind() == TypeKind.INTERSECTION) {
AnnotatedIntersectionType intersectionType = (AnnotatedIntersectionType) type;
Set<AnnotationMirror> glbs = null;
for (AnnotatedDeclaredType directST : intersectionType.directSuperTypes()) {
if (glbs == null) {
glbs = directST.getAnnotations();
} else {
Set<AnnotationMirror> newGlbs = AnnotationUtils.createAnnotationSet();
for (AnnotationMirror glb : glbs) {
AnnotationMirror anno = directST.getAnnotationInHierarchy(glb);
newGlbs.add(annotatedTypeFactory.getQualifierHierarchy().greatestLowerBound(anno, glb));
}
glbs = newGlbs;
}
}
type.replaceAnnotations(glbs);
} else if (type.getKind() == TypeKind.UNION) {
AnnotatedUnionType annotatedUnionType = (AnnotatedUnionType) type;
Set<AnnotationMirror> lubs = null;
for (AnnotatedDeclaredType altern : annotatedUnionType.getAlternatives()) {
if (lubs == null) {
lubs = altern.getAnnotations();
} else {
Set<AnnotationMirror> newLubs = AnnotationUtils.createAnnotationSet();
for (AnnotationMirror lub : lubs) {
AnnotationMirror anno = altern.getAnnotationInHierarchy(lub);
newLubs.add(annotatedTypeFactory.getQualifierHierarchy().leastUpperBound(anno, lub));
}
lubs = newLubs;
}
}
type.replaceAnnotations(lubs);
}
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType 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.AnnotatedDeclaredType in project checker-framework by typetools.
the class BaseTypeVisitor method visitReturn.
/**
* Checks that the type of the return expression is a subtype of the enclosing method required
* return type. If not, it issues a "return.type.incompatible" error.
*/
@Override
public Void visitReturn(ReturnTree node, Void p) {
// Don't try to check return expressions for void methods.
if (node.getExpression() == null) {
return super.visitReturn(node, p);
}
Pair<Tree, AnnotatedTypeMirror> preAssCtxt = visitorState.getAssignmentContext();
try {
Tree enclosing = TreeUtils.enclosingOfKind(getCurrentPath(), new HashSet<>(Arrays.asList(Tree.Kind.METHOD, Tree.Kind.LAMBDA_EXPRESSION)));
AnnotatedTypeMirror ret = null;
if (enclosing.getKind() == Tree.Kind.METHOD) {
MethodTree enclosingMethod = TreeUtils.enclosingMethod(getCurrentPath());
boolean valid = validateTypeOf(enclosing);
if (valid) {
ret = atypeFactory.getMethodReturnType(enclosingMethod, node);
}
} else {
Pair<AnnotatedDeclaredType, AnnotatedExecutableType> result = atypeFactory.getFnInterfaceFromTree((LambdaExpressionTree) enclosing);
ret = result.second.getReturnType();
}
if (ret != null) {
visitorState.setAssignmentContext(Pair.of((Tree) node, ret));
commonAssignmentCheck(ret, node.getExpression(), "return.type.incompatible");
}
return super.visitReturn(node, p);
} finally {
visitorState.setAssignmentContext(preAssCtxt);
}
}
Aggregations