use of org.checkerframework.framework.type.AnnotatedTypeFactory in project checker-framework by typetools.
the class BaseTypeVisitor method createTypeFactory.
/**
* Constructs an instance of the appropriate type factory for the implemented type system.
*
* <p>The default implementation uses the checker naming convention to create the appropriate type
* factory. If no factory is found, it returns {@link BaseAnnotatedTypeFactory}. It reflectively
* invokes the constructor that accepts this checker and compilation unit tree (in that order) as
* arguments.
*
* <p>Subclasses have to override this method to create the appropriate visitor if they do not
* follow the checker naming convention.
*
* @return the appropriate type factory
*/
// unchecked cast to type variable
@SuppressWarnings("unchecked")
protected Factory createTypeFactory() {
// Try to reflectively load the type factory.
Class<?> checkerClass = checker.getClass();
while (checkerClass != BaseTypeChecker.class) {
AnnotatedTypeFactory result = BaseTypeChecker.invokeConstructorFor(BaseTypeChecker.getRelatedClassName(checkerClass, "AnnotatedTypeFactory"), new Class<?>[] { BaseTypeChecker.class }, new Object[] { checker });
if (result != null) {
return (Factory) result;
}
checkerClass = checkerClass.getSuperclass();
}
try {
return (Factory) new BaseAnnotatedTypeFactory(checker);
} catch (Throwable t) {
throw new BugInCF("Unexpected " + t.getClass().getSimpleName() + " when invoking BaseAnnotatedTypeFactory for checker " + checker.getClass().getSimpleName(), t);
}
}
use of org.checkerframework.framework.type.AnnotatedTypeFactory in project checker-framework by typetools.
the class MethodNameValidator method visitDeclared.
@Override
public Void visitDeclared(AnnotatedDeclaredType type, Tree tree) {
AnnotationMirror methodVal = type.getAnnotation(MethodVal.class);
if (methodVal != null) {
AnnotatedTypeFactory atypeFactory = checker.getTypeFactory();
List<String> classNames = AnnotationUtils.getElementValueArray(methodVal, atypeFactory.methodValClassNameElement, String.class);
List<String> methodNames = AnnotationUtils.getElementValueArray(methodVal, atypeFactory.methodValMethodNameElement, String.class);
List<Integer> params = AnnotationUtils.getElementValueArray(methodVal, atypeFactory.methodValParamsElement, Integer.class);
if (!(classNames.size() == methodNames.size() && classNames.size() == params.size())) {
checker.reportError(tree, "invalid.methodval", methodVal);
}
for (String methodName : methodNames) {
if (!legalMethodName(methodName)) {
checker.reportError(tree, "illegal.methodname", methodName, type);
}
}
}
return super.visitDeclared(type, tree);
}
use of org.checkerframework.framework.type.AnnotatedTypeFactory 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, List<LocalVariableNode> parameters) {
if (underlyingAST.getKind() != UnderlyingAST.Kind.LAMBDA && underlyingAST.getKind() != UnderlyingAST.Kind.METHOD) {
if (fixedInitialStore != null) {
return fixedInitialStore;
} else {
return analysis.createEmptyStore(sequentialSemantics);
}
}
S store;
if (underlyingAST.getKind() == UnderlyingAST.Kind.METHOD) {
if (fixedInitialStore != null) {
// copy knowledge
store = analysis.createCopiedStore(fixedInitialStore);
} else {
store = analysis.createEmptyStore(sequentialSemantics);
}
AnnotatedTypeFactory factory = analysis.getTypeFactory();
for (LocalVariableNode p : parameters) {
AnnotatedTypeMirror anno = factory.getAnnotatedType(p.getElement());
store.initializeMethodParameter(p, analysis.createAbstractValue(anno));
}
// add properties known through precondition
CFGMethod method = (CFGMethod) underlyingAST;
MethodTree methodDeclTree = method.getMethod();
ExecutableElement methodElem = TreeUtils.elementFromDeclaration(methodDeclTree);
addInformationFromPreconditions(store, factory, method, methodDeclTree, methodElem);
addInitialFieldValues(store, method.getClassTree(), methodDeclTree);
addFinalLocalValues(store, methodElem);
if (shouldPerformWholeProgramInference(methodDeclTree, 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().updateFromOverride(methodDeclTree, methodElem, overriddenMethod);
}
}
} else if (underlyingAST.getKind() == UnderlyingAST.Kind.LAMBDA) {
// Create a copy and keep only the field values (nothing else applies).
store = analysis.createCopiedStore(fixedInitialStore);
// Allow that local variables are retained; they are effectively final,
// otherwise Java wouldn't allow access from within the lambda.
// TODO: what about the other information? Can code further down be simplified?
// store.localVariableValues.clear();
store.classValues.clear();
store.arrayValues.clear();
store.methodValues.clear();
AnnotatedTypeFactory factory = analysis.getTypeFactory();
for (LocalVariableNode p : parameters) {
AnnotatedTypeMirror anno = factory.getAnnotatedType(p.getElement());
store.initializeMethodParameter(p, analysis.createAbstractValue(anno));
}
CFGLambda lambda = (CFGLambda) underlyingAST;
// used in == tests
@SuppressWarnings("interning:assignment") @InternedDistinct Tree enclosingTree = TreePathUtil.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(store, enclosingElement);
}
// We want the initialization stuff, but need to throw out any refinements.
Map<FieldAccess, V> fieldValuesClone = new HashMap<>(store.fieldValues);
for (Map.Entry<FieldAccess, V> fieldValue : fieldValuesClone.entrySet()) {
AnnotatedTypeMirror declaredType = factory.getAnnotatedType(fieldValue.getKey().getField());
V lubbedValue = analysis.createAbstractValue(declaredType).leastUpperBound(fieldValue.getValue());
store.fieldValues.put(fieldValue.getKey(), lubbedValue);
}
} else {
assert false : "Unexpected tree: " + underlyingAST;
store = null;
}
return store;
}
use of org.checkerframework.framework.type.AnnotatedTypeFactory in project checker-framework by typetools.
the class CFAbstractTransfer method addInformationFromPreconditions.
/**
* Add the information from all the preconditions of a method to the initial store in the method
* body.
*
* @param initialStore the initial store for the method body
* @param factory the type factory
* @param methodAst the AST for a method declaration
* @param methodDeclTree the declaration of the method; is a field of {@code methodAst}
* @param methodElement the element for the method
*/
protected void addInformationFromPreconditions(S initialStore, AnnotatedTypeFactory factory, CFGMethod methodAst, MethodTree methodDeclTree, ExecutableElement methodElement) {
ContractsFromMethod contractsUtils = analysis.atypeFactory.getContractsFromMethod();
Set<Precondition> preconditions = contractsUtils.getPreconditions(methodElement);
StringToJavaExpression stringToJavaExpr = stringExpr -> StringToJavaExpression.atMethodBody(stringExpr, methodDeclTree, analysis.checker);
for (Precondition p : preconditions) {
String stringExpr = p.expressionString;
AnnotationMirror annotation = p.viewpointAdaptDependentTypeAnnotation(analysis.atypeFactory, stringToJavaExpr, /*errorTree=*/
null);
JavaExpression exprJe;
try {
// TODO: currently, these expressions are parsed at the declaration (i.e. here) and for
// every use. this could be optimized to store the result the first time.
// (same for other annotations)
exprJe = StringToJavaExpression.atMethodBody(stringExpr, methodDeclTree, analysis.checker);
} catch (JavaExpressionParseException e) {
// Errors are reported by BaseTypeVisitor.checkContractsAtMethodDeclaration().
continue;
}
initialStore.insertValuePermitNondeterministic(exprJe, annotation);
}
}
use of org.checkerframework.framework.type.AnnotatedTypeFactory in project checker-framework by typetools.
the class CFAbstractStore method isMonotonicUpdate.
/**
* Return true if fieldAcc is an update of a monotonic qualifier to its target qualifier.
* (e.g. @MonotonicNonNull to @NonNull). Always returns false if {@code sequentialSemantics} is
* true.
*
* @return true if fieldAcc is an update of a monotonic qualifier to its target qualifier
* (e.g. @MonotonicNonNull to @NonNull)
*/
protected boolean isMonotonicUpdate(FieldAccess fieldAcc, V value) {
if (analysis.atypeFactory.getSupportedMonotonicTypeQualifiers().isEmpty()) {
return false;
}
boolean isMonotonic = false;
// TODO: Update the javadoc of this method when the above to-do item is addressed.
if (!sequentialSemantics) {
// only compute if necessary
AnnotatedTypeFactory atypeFactory = this.analysis.atypeFactory;
List<Pair<AnnotationMirror, AnnotationMirror>> fieldAnnotations = atypeFactory.getAnnotationWithMetaAnnotation(fieldAcc.getField(), MonotonicQualifier.class);
for (Pair<AnnotationMirror, AnnotationMirror> fieldAnnotation : fieldAnnotations) {
AnnotationMirror monotonicAnnotation = fieldAnnotation.second;
// permitted for use in the framework
@SuppressWarnings("deprecation") Name annotation = AnnotationUtils.getElementValueClassName(monotonicAnnotation, "value", false);
AnnotationMirror target = AnnotationBuilder.fromName(atypeFactory.getElementUtils(), annotation);
// Make sure the 'target' annotation is present.
if (AnnotationUtils.containsSame(value.getAnnotations(), target)) {
isMonotonic = true;
break;
}
}
}
return isMonotonic;
}
Aggregations