use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType 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.AnnotatedExecutableType in project checker-framework by typetools.
the class AnnotatedTypeFactory method methodFromUse.
public Pair<AnnotatedExecutableType, List<AnnotatedTypeMirror>> methodFromUse(ExpressionTree tree, ExecutableElement methodElt, AnnotatedTypeMirror receiverType) {
AnnotatedExecutableType methodType = AnnotatedTypes.asMemberOf(types, this, receiverType, methodElt);
List<AnnotatedTypeMirror> typeargs = new ArrayList<>(methodType.getTypeVariables().size());
Map<TypeVariable, AnnotatedTypeMirror> typeVarMapping = AnnotatedTypes.findTypeArguments(processingEnv, this, tree, methodElt, methodType);
if (!typeVarMapping.isEmpty()) {
for (AnnotatedTypeVariable tv : methodType.getTypeVariables()) {
if (typeVarMapping.get(tv.getUnderlyingType()) == null) {
ErrorReporter.errorAbort("AnnotatedTypeFactory.methodFromUse:" + "mismatch between declared method type variables and the inferred method type arguments! " + "Method type variables: " + methodType.getTypeVariables() + "; " + "Inferred method type arguments: " + typeVarMapping);
}
typeargs.add(typeVarMapping.get(tv.getUnderlyingType()));
}
methodType = (AnnotatedExecutableType) typeVarSubstitutor.substitute(typeVarMapping, methodType);
}
if (tree.getKind() == Tree.Kind.METHOD_INVOCATION && TreeUtils.isGetClassInvocation((MethodInvocationTree) tree)) {
adaptGetClassReturnTypeToReceiver(methodType, receiverType);
}
return Pair.of(methodType, typeargs);
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType in project checker-framework by typetools.
the class AnnotatedTypeFactory method getMethodReturnType.
/**
* Returns the return type of the method {@code m} at the return statement {@code r}.
*/
public AnnotatedTypeMirror getMethodReturnType(MethodTree m, ReturnTree r) {
AnnotatedExecutableType methodType = getAnnotatedType(m);
AnnotatedTypeMirror ret = methodType.getReturnType();
return ret;
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType in project checker-framework by typetools.
the class AnnotatedTypeFactory method constructorFromUse.
/**
* Determines the type of the invoked constructor based on the passed new class tree.
*
* <p>The returned method type has all type variables resolved, whether based on receiver type,
* passed type parameters if any, and constructor invocation parameter.
*
* <p>Subclasses may override this method to customize inference of types or qualifiers based on
* constructor invocation parameters.
*
* <p>As an implementation detail, this method depends on {@link
* AnnotatedTypes#asMemberOf(Types, AnnotatedTypeFactory, AnnotatedTypeMirror, Element)}, and
* customization based on receiver type should be in accordance with its specification.
*
* <p>The return type is a pair of the type of the invoked constructor and the (inferred) type
* arguments. Note that neither the explicitly passed nor the inferred type arguments are
* guaranteed to be subtypes of the corresponding upper bounds. See method {@link
* org.checkerframework.common.basetype.BaseTypeVisitor#checkTypeArguments(Tree, List, List,
* List)} for the checks of type argument well-formedness.
*
* <p>Note that "this" and "super" constructor invocations are handled by method {@link
* #methodFromUse}. This method only handles constructor invocations in a "new" expression.
*
* @param tree the constructor invocation tree
* @return the annotated type of the invoked constructor (as an executable type) and the
* (inferred) type arguments
*/
public Pair<AnnotatedExecutableType, List<AnnotatedTypeMirror>> constructorFromUse(NewClassTree tree) {
ExecutableElement ctor = TreeUtils.constructor(tree);
AnnotatedTypeMirror type = fromNewClass(tree);
addComputedTypeAnnotations(tree.getIdentifier(), type);
AnnotatedExecutableType con = AnnotatedTypes.asMemberOf(types, this, type, ctor);
if (tree.getArguments().size() == con.getParameterTypes().size() + 1 && isSyntheticArgument(tree.getArguments().get(0))) {
// happens for anonymous constructors of inner classes
List<AnnotatedTypeMirror> actualParams = new ArrayList<>();
actualParams.add(getAnnotatedType(tree.getArguments().get(0)));
actualParams.addAll(con.getParameterTypes());
con.setParameterTypes(actualParams);
}
List<AnnotatedTypeMirror> typeargs = new ArrayList<>(con.getTypeVariables().size());
Map<TypeVariable, AnnotatedTypeMirror> typeVarMapping = AnnotatedTypes.findTypeArguments(processingEnv, this, tree, ctor, con);
if (!typeVarMapping.isEmpty()) {
for (AnnotatedTypeVariable tv : con.getTypeVariables()) {
typeargs.add(typeVarMapping.get(tv.getUnderlyingType()));
}
con = (AnnotatedExecutableType) typeVarSubstitutor.substitute(typeVarMapping, con);
}
return Pair.of(con, typeargs);
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType in project checker-framework by typetools.
the class AnnotatedTypeFactory method getMethodReturnType.
/**
* Returns the return type of the method {@code m}.
*/
public AnnotatedTypeMirror getMethodReturnType(MethodTree m) {
AnnotatedExecutableType methodType = getAnnotatedType(m);
AnnotatedTypeMirror ret = methodType.getReturnType();
return ret;
}
Aggregations