use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.
the class WholeProgramInferenceScenes method updateInferredMethodReceiverType.
/**
* Updates the receiver type of the method {@code methodElt} in the Scene of the method's
* enclosing class based on the overridden method {@code overriddenMethod} receiver type.
*
* <p>For the receiver in methodElt:
*
* <ul>
* <li>If the Scene does not contain an annotated type for the receiver, then the type of the
* receiver on the overridden method will be added to the receiver in the Scene.
* <li>If the Scene previously contained an annotated type for the receiver, then its new type
* will be the LUB between the previous type and the type of the receiver on the
* overridden method.
* </ul>
*
* <p>
*
* @param methodTree the tree of the method that contains the receiver
* @param methodElt the element of the method
* @param overriddenMethod the overridden method
* @param atf the annotated type factory of a given type system, whose type hierarchy will be
* used to update the receiver type
*/
@Override
public void updateInferredMethodReceiverType(MethodTree methodTree, ExecutableElement methodElt, AnnotatedExecutableType overriddenMethod, AnnotatedTypeFactory atf) {
ClassSymbol classSymbol = getEnclosingClassSymbol(methodTree);
String className = classSymbol.flatname.toString();
String jaifPath = helper.getJaifPath(className);
AClass clazz = helper.getAClass(className, jaifPath);
String methodName = JVMNames.getJVMMethodName(methodElt);
AMethod method = clazz.methods.vivify(methodName);
AnnotatedDeclaredType argADT = overriddenMethod.getReceiverType();
if (argADT != null) {
AnnotatedTypeMirror paramATM = atf.getAnnotatedType(methodTree).getReceiverType();
if (paramATM != null) {
AField receiver = method.receiver;
helper.updateAnnotationSetInScene(receiver.type, atf, jaifPath, argADT, paramATM, TypeUseLocation.RECEIVER);
}
}
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.
the class CFAbstractTransfer method initialStore.
/**
* The initial store maps method formal parameters to their currently most refined type.
*/
@Override
public S initialStore(UnderlyingAST underlyingAST, @Nullable List<LocalVariableNode> parameters) {
if (fixedInitialStore != null && underlyingAST.getKind() != Kind.LAMBDA && underlyingAST.getKind() != Kind.METHOD) {
return fixedInitialStore;
}
S info = analysis.createEmptyStore(sequentialSemantics);
if (underlyingAST.getKind() == Kind.METHOD) {
if (fixedInitialStore != null) {
// copy knowledge
info = analysis.createCopiedStore(fixedInitialStore);
}
AnnotatedTypeFactory factory = analysis.getTypeFactory();
for (LocalVariableNode p : parameters) {
AnnotatedTypeMirror anno = factory.getAnnotatedType(p.getElement());
info.initializeMethodParameter(p, analysis.createAbstractValue(anno));
}
// add properties known through precondition
CFGMethod method = (CFGMethod) underlyingAST;
MethodTree methodTree = method.getMethod();
ExecutableElement methodElem = TreeUtils.elementFromDeclaration(methodTree);
addInformationFromPreconditions(info, factory, method, methodTree, methodElem);
final ClassTree classTree = method.getClassTree();
addFieldValues(info, factory, classTree, methodTree);
addFinalLocalValues(info, methodElem);
if (shouldPerformWholeProgramInference(methodTree, methodElem)) {
Map<AnnotatedDeclaredType, ExecutableElement> overriddenMethods = AnnotatedTypes.overriddenMethods(analysis.atypeFactory.getElementUtils(), analysis.atypeFactory, methodElem);
for (Map.Entry<AnnotatedDeclaredType, ExecutableElement> pair : overriddenMethods.entrySet()) {
AnnotatedExecutableType overriddenMethod = AnnotatedTypes.asMemberOf(analysis.atypeFactory.getProcessingEnv().getTypeUtils(), analysis.atypeFactory, pair.getKey(), pair.getValue());
// Infers parameter and receiver types of the method based
// on the overridden method.
analysis.atypeFactory.getWholeProgramInference().updateInferredMethodParameterTypes(methodTree, methodElem, overriddenMethod, analysis.getTypeFactory());
analysis.atypeFactory.getWholeProgramInference().updateInferredMethodReceiverType(methodTree, methodElem, overriddenMethod, analysis.getTypeFactory());
}
}
return info;
} else if (underlyingAST.getKind() == Kind.LAMBDA) {
// Create a copy and keep only the field values (nothing else applies).
info = analysis.createCopiedStore(fixedInitialStore);
info.localVariableValues.clear();
info.classValues.clear();
info.arrayValues.clear();
info.methodValues.clear();
AnnotatedTypeFactory factory = analysis.getTypeFactory();
for (LocalVariableNode p : parameters) {
AnnotatedTypeMirror anno = factory.getAnnotatedType(p.getElement());
info.initializeMethodParameter(p, analysis.createAbstractValue(anno));
}
CFGLambda lambda = (CFGLambda) underlyingAST;
Tree enclosingTree = TreeUtils.enclosingOfKind(factory.getPath(lambda.getLambdaTree()), new HashSet<>(Arrays.asList(Tree.Kind.METHOD, // Tree.Kind for which TreeUtils.isClassTree is true
Tree.Kind.CLASS, Tree.Kind.INTERFACE, Tree.Kind.ANNOTATION_TYPE, Tree.Kind.ENUM)));
Element enclosingElement = null;
if (enclosingTree.getKind() == Tree.Kind.METHOD) {
// If it is in an initializer, we need to use locals from the initializer.
enclosingElement = TreeUtils.elementFromTree(enclosingTree);
} else if (TreeUtils.isClassTree(enclosingTree)) {
// Try to find an enclosing initializer block
// Would love to know if there was a better way
// Find any enclosing element of the lambda (using trees)
// Then go up the elements to find an initializer element (which can't be found with
// the tree).
TreePath loopTree = factory.getPath(lambda.getLambdaTree()).getParentPath();
Element anEnclosingElement = null;
while (loopTree.getLeaf() != enclosingTree) {
Element sym = TreeUtils.elementFromTree(loopTree.getLeaf());
if (sym != null) {
anEnclosingElement = sym;
break;
}
loopTree = loopTree.getParentPath();
}
while (anEnclosingElement != null && !anEnclosingElement.equals(TreeUtils.elementFromTree(enclosingTree))) {
if (anEnclosingElement.getKind() == ElementKind.INSTANCE_INIT || anEnclosingElement.getKind() == ElementKind.STATIC_INIT) {
enclosingElement = anEnclosingElement;
break;
}
anEnclosingElement = anEnclosingElement.getEnclosingElement();
}
}
if (enclosingElement != null) {
addFinalLocalValues(info, enclosingElement);
}
// We want the initialization stuff, but need to throw out any refinements.
Map<FieldAccess, V> fieldValuesClone = new HashMap<>(info.fieldValues);
for (Entry<FieldAccess, V> fieldValue : fieldValuesClone.entrySet()) {
AnnotatedTypeMirror declaredType = factory.getAnnotatedType(fieldValue.getKey().getField());
V lubbedValue = analysis.createAbstractValue(declaredType).leastUpperBound(fieldValue.getValue());
info.fieldValues.put(fieldValue.getKey(), lubbedValue);
}
}
return info;
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.
the class StubParser method processEnum.
/**
* Gathers and returns a list of AnnotatedTypeVariable of the enum's type parameter
* declarations.
*
* @param decl actual enum declaration
* @param elt element representing enum
* @param atypes map of annotated types
* @param declAnnos map of declarations annotations
* @return list of AnnotatedTypeVariable of the enum's type parameter declarations
*/
private List<AnnotatedTypeVariable> processEnum(EnumDeclaration decl, TypeElement elt) {
annotateDecl(declAnnos, elt, decl.getAnnotations());
AnnotatedDeclaredType type = atypeFactory.fromElement(elt);
annotate(type, decl.getAnnotations());
putNew(atypes, elt, type);
List<AnnotatedTypeVariable> typeVariables = new ArrayList<>();
for (AnnotatedTypeMirror typeV : type.getTypeArguments()) {
if (typeV.getKind() != TypeKind.TYPEVAR) {
stubWarn("expected an AnnotatedTypeVariable but found type kind " + typeV.getKind() + ": " + typeV);
} else {
typeVariables.add((AnnotatedTypeVariable) typeV);
}
}
return typeVariables;
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.
the class ElementAnnotationUtil method getLocationTypeADT.
/**
* Given a TypePath into a declared type, return the component type that is located at the end
* of the TypePath
*
* @param type a type containing the type specified by location
* @param location a type path into type
* @return the type specified by location
*/
private static AnnotatedTypeMirror getLocationTypeADT(AnnotatedDeclaredType type, List<TypeAnnotationPosition.TypePathEntry> location) {
// List order by outer most type to inner most type.
ArrayDeque<AnnotatedDeclaredType> outerToInner = new ArrayDeque<>();
AnnotatedDeclaredType enclosing = type;
while (enclosing != null) {
outerToInner.addFirst(enclosing);
enclosing = enclosing.getEnclosingType();
}
// Create a linked list of the location, so removing the first element is easier.
// Also, the `tail` operation wouldn't work with a Deque.
@SuppressWarnings("JdkObsolete") LinkedList<TypePathEntry> tailOfLocations = new LinkedList<>(location);
boolean error = false;
while (!tailOfLocations.isEmpty()) {
TypePathEntry currentLocation = tailOfLocations.removeFirst();
switch(currentLocation.tag) {
case INNER_TYPE:
outerToInner.removeFirst();
break;
case TYPE_ARGUMENT:
AnnotatedDeclaredType innerType = outerToInner.getFirst();
if (currentLocation.arg < innerType.getTypeArguments().size()) {
AnnotatedTypeMirror typeArg = innerType.getTypeArguments().get(currentLocation.arg);
return getTypeAtLocation(typeArg, tailOfLocations);
} else {
error = true;
break;
}
default:
error = true;
}
if (error) {
break;
}
}
if (outerToInner.isEmpty() || error) {
ErrorReporter.errorAbort("ElementAnnotationUtil.getLocationTypeADT: invalid location %s for type: %s", location, type);
}
return outerToInner.getFirst();
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.
the class AnnotatedTypeFactory method adaptGetClassReturnTypeToReceiver.
/**
* Java special-cases the return type of {@link java.lang.Class#getClass() getClass()}. Though
* the method has a return type of {@code Class<?>}, the compiler special cases this return-type
* and changes the bound of the type argument to the erasure of the receiver type. For example:
*
* <ul>
* <li>{@code x.getClass()} has the type {@code Class< ? extends erasure_of_x >}
* <li>{@code someInteger.getClass()} has the type {@code Class< ? extends Integer >}
* </ul>
*
* @param getClassType this must be a type representing a call to Object.getClass otherwise a
* runtime exception will be thrown. It is modified by side effect.
* @param receiverType the receiver type of the method invocation (not the declared receiver
* type)
*/
protected void adaptGetClassReturnTypeToReceiver(final AnnotatedExecutableType getClassType, final AnnotatedTypeMirror receiverType) {
// TODO: should the receiver type ever be a declaration??
// Work on removing the asUse() call.
final AnnotatedTypeMirror newBound = receiverType.getErased().asUse();
final AnnotatedTypeMirror returnType = getClassType.getReturnType();
if (returnType == null || !(returnType.getKind() == TypeKind.DECLARED) || ((AnnotatedDeclaredType) returnType).getTypeArguments().size() != 1) {
ErrorReporter.errorAbort("Unexpected type passed to AnnotatedTypes.adaptGetClassReturnTypeToReceiver\n" + "getClassType=" + getClassType + "\n" + "receiverType=" + receiverType);
}
final AnnotatedDeclaredType returnAdt = (AnnotatedDeclaredType) getClassType.getReturnType();
final List<AnnotatedTypeMirror> typeArgs = returnAdt.getTypeArguments();
// Usually, the only locations that will add annotations to the return type are getClass in
// stub files defaults and propagation tree annotator. Since getClass is final they cannot
// come from source code. Also, since the newBound is an erased type we have no type
// arguments. So, we just copy the annotations from the bound of the declared type to the
// new bound.
final AnnotatedWildcardType classWildcardArg = (AnnotatedWildcardType) typeArgs.get(0);
newBound.replaceAnnotations(classWildcardArg.getExtendsBound().getAnnotations());
classWildcardArg.setExtendsBound(newBound);
}
Aggregations