All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.checkerframework.common.wholeprograminference.WholeProgramInference Maven / Gradle / Ivy

Go to download

The Checker Framework enhances Java's type system to make it more powerful and useful. This lets software developers detect and prevent errors in their Java programs. The Checker Framework includes compiler plug-ins ("checkers") that find bugs or verify their absence. It also permits you to write your own compiler plug-ins.

There is a newer version: 3.48.2
Show newest version
package org.checkerframework.common.wholeprograminference;

import com.sun.source.tree.ClassTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import java.util.Map;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import org.checkerframework.checker.index.qual.Positive;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.dataflow.analysis.Analysis;
import org.checkerframework.dataflow.cfg.node.LocalVariableNode;
import org.checkerframework.dataflow.cfg.node.MethodInvocationNode;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.dataflow.cfg.node.ObjectCreationNode;
import org.checkerframework.dataflow.cfg.node.ReturnNode;
import org.checkerframework.framework.flow.CFAbstractStore;
import org.checkerframework.framework.qual.IgnoreInWholeProgramInference;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;

/**
 * Interface for recording facts at (pseudo-)assignments. It is used by the -Ainfer command-line
 * argument. The -Ainfer command-line argument is used by the whole-program-inference loop, but this
 * class does not implement that loop and its name {@code WholeProgramInference} is misleading.
 *
 * 

This interface has update* methods that should be called at certain (pseudo-)assignments, and * they may update the type of the LHS of the (pseudo-)assignment based on the type of the RHS. In * case the element on the LHS already had an inferred type, its new type will be the LUB between * the previous and new types. * * @checker_framework.manual #whole-program-inference Whole-program inference */ public interface WholeProgramInference { /** * Updates the parameter types of the constructor {@code constructorElt} based on the arguments in * {@code objectCreationNode}. * *

For each parameter in constructorElt: * *

    *
  • If there is no stored annotated type for that parameter, then use the type of the * corresponding argument in the object creation call objectCreationNode. *
  • If there was a stored annotated type for that parameter, then its new type will be the * LUB between the previous type and the type of the corresponding argument in the object * creation call. *
* * @param objectCreationNode the Node that invokes the constructor * @param constructorElt the Element of the constructor * @param store the store just before the call */ void updateFromObjectCreation( ObjectCreationNode objectCreationNode, ExecutableElement constructorElt, CFAbstractStore store); /** * Updates the parameter types of the method {@code methodElt} based on the arguments in the * method invocation {@code methodInvNode}. * *

For each formal parameter in methodElt (including the receiver): * *

    *
  • If there is no stored annotated type for that parameter, then use the type of the * corresponding argument in the method call methodInvNode. *
  • If there was a stored annotated type for that parameter, then its new type will be the * LUB between the previous type and the type of the corresponding argument in the method * call. *
* * @param methodInvNode the node representing a method invocation * @param methodElt the element of the method being invoked * @param store the store before the method call, used for inferring method preconditions */ void updateFromMethodInvocation( MethodInvocationNode methodInvNode, ExecutableElement methodElt, CFAbstractStore store); /** * Updates the parameter types (including the receiver) of the method {@code methodTree} based on * the parameter types of the overridden method {@code overriddenMethod}. * *

For each formal parameter in methodElt: * *

    *
  • If there is no stored annotated type for that parameter, then use the type of the * corresponding parameter on the overridden method. *
  • If there is a stored annotated type for that parameter, then its new type will be the LUB * between the previous type and the type of the corresponding parameter on the overridden * method. *
* * @param methodTree the tree of the method that contains the parameter(s) * @param methodElt the element of the method * @param overriddenMethod the AnnotatedExecutableType of the overridden method */ void updateFromOverride( MethodTree methodTree, ExecutableElement methodElt, AnnotatedExecutableType overriddenMethod); /** * Updates the type of {@code lhs} based on an assignment of {@code rhs} to {@code lhs}. * *
    *
  • If there is no stored annotated type for lhs, then use the type of the corresponding * argument in the method call methodInvNode. *
  • If there is a stored annotated type for lhs, then its new type will be the LUB between * the previous type and the type of the corresponding argument in the method call. *
* * @param lhs the node representing the formal parameter * @param rhs the node being assigned to the parameter in the method body * @param paramElt the formal parameter */ void updateFromFormalParameterAssignment( LocalVariableNode lhs, Node rhs, VariableElement paramElt); /** * Updates the type of {@code field} based on an assignment of {@code rhs} to {@code field}. If * the field has a declaration annotation with the {@link IgnoreInWholeProgramInference} * meta-annotation, no type annotation will be inferred for that field. * *

If there is no stored entry for the field lhs, the entry will be created and its type will * be the type of rhs. If there is a stored entry/type for lhs, its new type will be the LUB * between the previous type and the type of rhs. * * @param field the field whose type will be refined. Must be either a FieldAccessNode or a * LocalVariableNode whose element kind is FIELD. * @param rhs the expression being assigned to the field */ void updateFromFieldAssignment(Node field, Node rhs); /** * Updates the type of {@code field} based on an assignment whose right-hand side has type {@code * rhsATM}. See more details at {@link #updateFromFieldAssignment}. * * @param lhsTree the tree for the field whose type will be refined * @param element the element for the field whose type will be refined * @param fieldName the name of the field whose type will be refined * @param rhsATM the type of the expression being assigned to the field */ void updateFieldFromType( Tree lhsTree, Element element, String fieldName, AnnotatedTypeMirror rhsATM); /** * Updates the return type of the method {@code methodTree} based on {@code returnedExpression}. * Also updates the return types of any methods that this method overrides that are available as * source code. * *

If there is no stored annotated return type for the method methodTree, then the type of the * return expression will be added to the return type of that method. If there is a stored * annotated return type for the method methodTree, its new type will be the LUB between the * previous type and the type of the return expression. * * @param retNode the node that contains the expression returned * @param classSymbol the symbol of the class that contains the method * @param methodTree the tree of the method whose return type may be updated * @param overriddenMethods the methods that the given method return overrides, indexed by the * annotated type of the superclass in which each method is defined */ void updateFromReturn( ReturnNode retNode, ClassSymbol classSymbol, MethodTree methodTree, Map overriddenMethods); /** * Updates the preconditions or postconditions of the current method, from a store. * * @param methodElement the method or constructor whose preconditions or postconditions to update * @param preOrPost whether to update preconditions or postconditions * @param store the store at the method's entry or normal exit, for reading types of expressions */ void updateContracts( Analysis.BeforeOrAfter preOrPost, ExecutableElement methodElement, CFAbstractStore store); // TODO: This Javadoc should explain why this method is in WholeProgramInference and not in some // AnnotatedTypeMirror related class. /** * Updates sourceCodeATM to contain the LUB between sourceCodeATM and ajavaATM, ignoring missing * AnnotationMirrors from ajavaATM -- it considers the LUB between an AnnotationMirror am and a * missing AnnotationMirror to be am. The results are stored in sourceCodeATM. * * @param sourceCodeATM the annotated type on the source code; side effected by this method * @param ajavaATM the annotated type on the annotation file */ public void updateAtmWithLub(AnnotatedTypeMirror sourceCodeATM, AnnotatedTypeMirror ajavaATM); /** * Updates a method to add a declaration annotation. * * @param methodElt the method to annotate * @param anno the declaration annotation to add to the method */ void addMethodDeclarationAnnotation(ExecutableElement methodElt, AnnotationMirror anno); /** * Updates a method to add a declaration annotation. Optionally, may replace the current purity * annotation on {@code elt} with the logical least upper bound between that purity annotation and * {@code anno}, if {@code anno} is also a purity annotation. * * @param elt the method to annotate * @param anno the declaration annotation to add to the method * @param lubPurity if true and {@code anno} is a purity annotation, replaces the current purity * annotation with a least upper bound rather than just adding {@code anno} */ void addMethodDeclarationAnnotation( ExecutableElement elt, AnnotationMirror anno, boolean lubPurity); /** * Updates a field to add a declaration annotation. * * @param fieldElt the field to annotate * @param anno the declaration annotation to add to the field */ void addFieldDeclarationAnnotation(VariableElement fieldElt, AnnotationMirror anno); /** * Adds a declaration annotation to a formal parameter. * * @param methodElt the method whose formal parameter will be annotated * @param index_1based the index of the parameter (1-indexed) * @param anno the annotation to add */ void addDeclarationAnnotationToFormalParameter( ExecutableElement methodElt, @Positive int index_1based, AnnotationMirror anno); /** * Adds an annotation to a class declaration. * * @param classElt the class declaration to annotate * @param anno the annotation to add */ void addClassDeclarationAnnotation(TypeElement classElt, AnnotationMirror anno); /** * Writes the inferred results to a file. Ideally, it should be called at the end of the * type-checking process. In practice, it is called after each class, because we don't know which * class will be the last one in the type-checking process. * * @param format the file format in which to write the results * @param checker the checker from which this method is called, for naming annotation files */ void writeResultsToFile(OutputFormat format, BaseTypeChecker checker); /** * Performs any preparation required for inference on Elements of a class. Should be called on * each toplevel class declaration in a compilation unit before processing it. * * @param classTree the class to preprocess */ void preprocessClassTree(ClassTree classTree); /** The kinds of output that whole-program inference can produce. */ enum OutputFormat { /** * Output the results of whole-program inference as a stub file that can be parsed back into the * Checker Framework by the Stub Parser. */ STUB(), /** * Output the results of whole-program inference as a Java annotation index file. The Annotation * File Utilities project contains code for reading and writing .jaif files. */ JAIF(), /** * Output the results of whole-program inference as an ajava file that can be read in using the * {@code -Aajava} option. */ AJAVA(), } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy