public abstract class GenericAnnotatedTypeFactory<Value extends CFAbstractValue<Value>,Store extends CFAbstractStore<Value,Store>,TransferFunction extends CFAbstractTransfer<Value,Store,TransferFunction>,FlowAnalysis extends CFAbstractAnalysis<Value,Store,TransferFunction>> extends AnnotatedTypeFactory
AnnotatedTypeFactory
to optionally use
flow-sensitive qualifier inference, qualifier polymorphism, implicit
annotations via ImplicitFor
, and user-specified defaults via
DefaultQualifier
.Modifier and Type | Class and Description |
---|---|
protected static class |
GenericAnnotatedTypeFactory.ScanState
Track the state of org.checkerframework.dataflow analysis scanning for each class tree in the
compilation unit.
|
AnnotatedTypeFactory.InheritedFromClassAnnotator
Modifier and Type | Field and Description |
---|---|
protected java.util.Deque<FlowAnalysis> |
analyses |
protected QualifierDefaults |
defaults
to handle defaults specified by the user
|
protected static boolean |
FLOW_BY_DEFAULT
should use flow by default
|
protected AnalysisResult<Value,Store> |
flowResult
The result of the flow analysis.
|
protected Store |
initializationStaticStore |
protected Store |
initializationStore |
protected java.util.IdentityHashMap<com.sun.source.tree.MethodInvocationTree,Store> |
methodInvocationStores
A mapping from methods to their a list with all return statements and the
corresponding store.
|
protected QualifierPolymorphism |
poly
to handle any polymorphic types
|
protected java.util.IdentityHashMap<com.sun.source.tree.Tree,Store> |
regularExitStores
A mapping from methods (or other code blocks) to their regular exit store (used to check
postconditions).
|
protected java.util.IdentityHashMap<com.sun.source.tree.MethodTree,java.util.List<Pair<ReturnNode,TransferResult<Value,Store>>>> |
returnStatementStores
A mapping from methods to their a list with all return statements and the
corresponding store.
|
protected java.util.Map<com.sun.source.tree.ClassTree,GenericAnnotatedTypeFactory.ScanState> |
scannedClasses |
protected TreeAnnotator |
treeAnnotator
to annotate types based on the given un-annotated types
|
protected TypeAnnotator |
typeAnnotator
to annotate types based on the given tree
|
protected boolean |
useFlow
Should use flow analysis?
|
checker, elements, fromTreeCache, processingEnv, qualHierarchy, root, SHOULD_CACHE, SHOULD_READ_CACHE, shouldCache, shouldReadCache, trees, typeHierarchy, types, uid, visitorState
Constructor and Description |
---|
GenericAnnotatedTypeFactory(BaseTypeChecker checker)
Creates a type factory for checking the given compilation unit with
respect to the given annotation.
|
GenericAnnotatedTypeFactory(BaseTypeChecker checker,
boolean useFlow)
Creates a type factory for checking the given compilation unit with
respect to the given annotation.
|
Modifier and Type | Method and Description |
---|---|
protected void |
analyze(java.util.Queue<com.sun.source.tree.ClassTree> queue,
UnderlyingAST ast,
java.util.List<Pair<javax.lang.model.element.VariableElement,Value>> fieldValues,
com.sun.source.tree.ClassTree currentClass,
boolean isInitializationCode,
boolean isStatic)
Analyze the AST
ast and store the result. |
void |
annotateImplicit(javax.lang.model.element.Element elt,
AnnotatedTypeMirror type)
Adds implicit annotations to a type obtained from a
Element . |
void |
annotateImplicit(com.sun.source.tree.Tree tree,
AnnotatedTypeMirror type)
This method is final.
|
protected void |
annotateImplicit(com.sun.source.tree.Tree tree,
AnnotatedTypeMirror type,
boolean iUseFlow) |
protected void |
annotateImplicitWithFlow(com.sun.source.tree.Tree tree,
AnnotatedTypeMirror type)
We perform flow analysis on each
ClassTree that is
passed to annotateImplicitWithFlow. |
protected void |
applyInferredAnnotations(AnnotatedTypeMirror type,
Value as)
Applies the annotations inferred by the org.checkerframework.dataflow analysis to the type
type . |
Pair<AnnotatedTypeMirror.AnnotatedExecutableType,java.util.List<AnnotatedTypeMirror>> |
constructorFromUse(com.sun.source.tree.NewClassTree tree)
Determines the
AnnotatedTypeMirror.AnnotatedExecutableType of a constructor
invocation. |
protected FlowAnalysis |
createFlowAnalysis(java.util.List<Pair<javax.lang.model.element.VariableElement,Value>> fieldValues)
Returns the appropriate flow analysis class that is used for the org.checkerframework.dataflow
analysis.
|
TransferFunction |
createFlowTransferFunction(CFAbstractAnalysis<Value,Store,TransferFunction> analysis)
Returns the appropriate transfer function that is used for the org.checkerframework.dataflow
analysis.
|
protected QualifierDefaults |
createQualifierDefaults()
Create
QualifierDefaults which handles user specified defaults |
protected QualifierPolymorphism |
createQualifierPolymorphism()
Creates
QualifierPolymorphism which supports
QualifierPolymorphism mechanism |
protected TreeAnnotator |
createTreeAnnotator()
Returns a
TreeAnnotator that adds annotations to a type based
on the contents of a tree. |
protected TypeAnnotator |
createTypeAnnotator()
Returns a
TypeAnnotator that adds annotations to a type based
on the content of the type itself. |
protected java.lang.String |
dotOutputFileName(UnderlyingAST ast) |
AnnotatedTypeMirror |
getDefaultedAnnotatedType(com.sun.source.tree.Tree tree,
com.sun.source.tree.ExpressionTree valueTree)
Get the defaulted type of a variable, without considering
flow inference from the initializer expression.
|
Store |
getEmptyStore() |
java.util.HashMap<javax.lang.model.element.Element,Value> |
getFinalLocalValues() |
Value |
getInferredValueFor(com.sun.source.tree.Tree tree)
Returns the inferred value (by the org.checkerframework.dataflow analysis) for a given tree.
|
Node |
getNodeForTree(com.sun.source.tree.Tree tree) |
Store |
getRegularExitStore(com.sun.source.tree.Tree t)
Returns the regular exit store for a method or another code block (such as static initializers).
|
java.util.List<Pair<ReturnNode,TransferResult<Value,Store>>> |
getReturnStatementStores(com.sun.source.tree.MethodTree methodTree) |
Store |
getStoreAfter(com.sun.source.tree.Tree tree) |
Store |
getStoreBefore(com.sun.source.tree.Tree tree) |
java.util.Set<java.lang.Class<? extends java.lang.annotation.Annotation>> |
getSupportedMonotonicTypeQualifiers()
Returns an immutable set of the monotonic type qualifiers supported by this
checker.
|
boolean |
getUseFlow() |
Pair<AnnotatedTypeMirror.AnnotatedExecutableType,java.util.List<AnnotatedTypeMirror>> |
methodFromUse(com.sun.source.tree.MethodInvocationTree tree)
Determines the type of the invoked method based on the passed method
invocation tree.
|
protected void |
performFlowAnalysis(com.sun.source.tree.ClassTree classTree)
Perform a org.checkerframework.dataflow analysis over a single class tree and its nested
classes.
|
protected void |
postDirectSuperTypes(AnnotatedTypeMirror type,
java.util.List<? extends AnnotatedTypeMirror> supertypes)
A callback method for the AnnotatedTypeFactory subtypes to customize
directSuperTypes().
|
protected void |
postInit()
Actions that logically belong in the constructor, but need to run
after the subclass constructor has completed.
|
void |
setRoot(@Nullable com.sun.source.tree.CompilationUnitTree root) |
void |
setUseFlow(boolean useFlow) |
addAliasedAnnotation, addAliasedDeclAnnotation, aliasedAnnotation, annotateInheritedFromClass, annotateInheritedFromClass, buildIndexTypes, createLRUCache, createQualifierHierarchy, createQualifierHierarchy, createQualifierHierarchy, createQualifierHierarchyFactory, createSupportedTypeQualifiers, createTypeHierarchy, declarationFromElement, fromClass, fromElement, fromElement, fromElement, fromExpression, fromMember, fromNewClass, fromTypeTree, getAnnotatedType, getAnnotatedType, getAnnotatedType, getAnnotatedType, getAnnotatedType, getAnnotatedType, getAnnotatedType, getAnnotatedType, getAnnotatedTypeFromTypeTree, getAnnotationMirror, getAnnotationWithMetaAnnotation, getBoxedType, getCurrentClassTree, getCurrentClassType, getCurrentMethodReceiver, getDeclAnnotation, getDeclAnnotations, getDeclAnnotationWithMetaAnnotation, getElementUtils, getEnclosingMethod, getEnclosingType, getImplicitReceiverType, getMethodReturnType, getMethodReturnType, getPath, getProcessingEnv, getQualifierHierarchy, getReceiverType, getSelfType, getSupportedTypeQualifiers, getTreeUtils, getTypeHierarchy, getUnboxedType, getUninferredWildcardType, getVisitorState, getWildcardBoundedBy, isAnyEnclosingThisDeref, isFromByteCode, isFromStubFile, isMostEnclosingThisDeref, isSupportedQualifier, isWithinConstructor, postAsMemberOf, postProcessClassTree, setPathHack, toAnnotatedType, toString, type, typeVariablesFromUse
protected static boolean FLOW_BY_DEFAULT
protected TypeAnnotator typeAnnotator
protected TreeAnnotator treeAnnotator
protected QualifierPolymorphism poly
protected QualifierDefaults defaults
protected boolean useFlow
protected final java.util.Map<com.sun.source.tree.ClassTree,GenericAnnotatedTypeFactory.ScanState> scannedClasses
protected AnalysisResult<Value extends CFAbstractValue<Value>,Store extends CFAbstractStore<Value,Store>> flowResult
scannedClasses.get(c) == FINISHED for some class c ⇒ flowResult != nullNote that flowResult contains analysis results for Trees from multiple classes which are produced by multiple calls to performFlowAnalysis.
protected java.util.IdentityHashMap<com.sun.source.tree.Tree,Store extends CFAbstractStore<Value,Store>> regularExitStores
protected java.util.IdentityHashMap<com.sun.source.tree.MethodTree,java.util.List<Pair<ReturnNode,TransferResult<Value extends CFAbstractValue<Value>,Store extends CFAbstractStore<Value,Store>>>>> returnStatementStores
protected java.util.IdentityHashMap<com.sun.source.tree.MethodInvocationTree,Store extends CFAbstractStore<Value,Store>> methodInvocationStores
protected final java.util.Deque<FlowAnalysis extends CFAbstractAnalysis<Value,Store,TransferFunction>> analyses
protected Store extends CFAbstractStore<Value,Store> initializationStore
protected Store extends CFAbstractStore<Value,Store> initializationStaticStore
public GenericAnnotatedTypeFactory(BaseTypeChecker checker, boolean useFlow)
checker
- the checker to which this type factory belongsuseFlow
- whether flow analysis should be performedpublic GenericAnnotatedTypeFactory(BaseTypeChecker checker)
checker
- the checker to which this type factory belongsprotected void postInit()
AnnotatedTypeFactory
postInit
in class AnnotatedTypeFactory
public void setRoot(@Nullable com.sun.source.tree.CompilationUnitTree root)
setRoot
in class AnnotatedTypeFactory
public final java.util.Set<java.lang.Class<? extends java.lang.annotation.Annotation>> getSupportedMonotonicTypeQualifiers()
MonotonicQualifier
protected TreeAnnotator createTreeAnnotator()
TreeAnnotator
that adds annotations to a type based
on the contents of a tree.
Subclasses may override this method to specify more appriopriate
TreeAnnotator
protected TypeAnnotator createTypeAnnotator()
TypeAnnotator
that adds annotations to a type based
on the content of the type itself.protected FlowAnalysis createFlowAnalysis(java.util.List<Pair<javax.lang.model.element.VariableElement,Value>> fieldValues)
This implementation uses the checker naming convention to create the
appropriate analysis. If no transfer function is found, it returns an
instance of CFAnalysis
.
Subclasses have to override this method to create the appropriate analysis if they do not follow the checker naming convention.
public TransferFunction createFlowTransferFunction(CFAbstractAnalysis<Value,Store,TransferFunction> analysis)
This implementation uses the checker naming convention to create the
appropriate transfer function. If no transfer function is found, it
returns an instance of CFTransfer
.
Subclasses have to override this method to create the appropriate transfer function if they do not follow the checker naming convention.
protected QualifierDefaults createQualifierDefaults()
QualifierDefaults
which handles user specified defaultsprotected QualifierPolymorphism createQualifierPolymorphism()
QualifierPolymorphism
which supports
QualifierPolymorphism mechanismprotected void postDirectSuperTypes(AnnotatedTypeMirror type, java.util.List<? extends AnnotatedTypeMirror> supertypes)
AnnotatedTypeFactory
type
annotations to
supertypes
. This allows the type
and its supertypes
to have the qualifiers, e.g. the supertypes of an Immutable
type are also Immutable
.postDirectSuperTypes
in class AnnotatedTypeFactory
type
- the type whose supertypes are desiredsupertypes
- the supertypes as specified by the base AnnotatedTypeFactorypublic Store getRegularExitStore(com.sun.source.tree.Tree t)
null
, if there is no such
store (because the method cannot exit through the regular exit
block).public java.util.List<Pair<ReturnNode,TransferResult<Value,Store>>> getReturnStatementStores(com.sun.source.tree.MethodTree methodTree)
public Store getStoreBefore(com.sun.source.tree.Tree tree)
Tree
.public Store getStoreAfter(com.sun.source.tree.Tree tree)
Tree
.public Node getNodeForTree(com.sun.source.tree.Tree tree)
Node
for a given Tree
.public java.util.HashMap<javax.lang.model.element.Element,Value> getFinalLocalValues()
protected void performFlowAnalysis(com.sun.source.tree.ClassTree classTree)
protected void analyze(java.util.Queue<com.sun.source.tree.ClassTree> queue, UnderlyingAST ast, java.util.List<Pair<javax.lang.model.element.VariableElement,Value>> fieldValues, com.sun.source.tree.ClassTree currentClass, boolean isInitializationCode, boolean isStatic)
ast
and store the result.queue
- The queue to add more things to scan.fieldValues
- The abstract values for all fields of the same class.ast
- The AST to analyze.currentClass
- The class we are currently looking at.isInitializationCode
- Are we analyzing a (non-static) initializer block of a class.protected java.lang.String dotOutputFileName(UnderlyingAST ast)
public AnnotatedTypeMirror getDefaultedAnnotatedType(com.sun.source.tree.Tree tree, com.sun.source.tree.ExpressionTree valueTree)
public Pair<AnnotatedTypeMirror.AnnotatedExecutableType,java.util.List<AnnotatedTypeMirror>> constructorFromUse(com.sun.source.tree.NewClassTree tree)
AnnotatedTypeFactory
AnnotatedTypeMirror.AnnotatedExecutableType
of a constructor
invocation. Note that this is different than calling
AnnotatedTypeFactory.getAnnotatedType(Tree)
or
AnnotatedTypeFactory.fromExpression(ExpressionTree)
on the constructor invocation;
those determine the type of the result of invoking the
constructor, which is probably an AnnotatedTypeMirror.AnnotatedDeclaredType
.
TODO: Should the result of getAnnotatedType be the return type
from the AnnotatedExecutableType computed here?
Note that "this" and "super" constructor invocations are handled by
method AnnotatedTypeFactory.methodFromUse(com.sun.source.tree.MethodInvocationTree)
. This method only handles constructor invocations
in a "new" expression.constructorFromUse
in class AnnotatedTypeFactory
tree
- the constructor invocation treeprotected void annotateImplicit(com.sun.source.tree.Tree tree, AnnotatedTypeMirror type, boolean iUseFlow)
public final void annotateImplicit(com.sun.source.tree.Tree tree, AnnotatedTypeMirror type)
annotateImplicit(Tree, AnnotatedTypeMirror, boolean)
instead.annotateImplicit
in class AnnotatedTypeFactory
tree
- an AST nodetype
- the type obtained from tree
protected void annotateImplicitWithFlow(com.sun.source.tree.Tree tree, AnnotatedTypeMirror type)
ClassTree
that is
passed to annotateImplicitWithFlow. This works correctly when
a ClassTree
is passed to this method before any of its
sub-trees. It also helps to satisfy the requirement that a
ClassTree
has been advanced to annotation before we
analyze it.public Value getInferredValueFor(com.sun.source.tree.Tree tree)
protected void applyInferredAnnotations(AnnotatedTypeMirror type, Value as)
type
.public void annotateImplicit(javax.lang.model.element.Element elt, AnnotatedTypeMirror type)
AnnotatedTypeFactory
Element
. By
default, this method does nothing. Subclasses should use this method to
implement implicit annotations specific to their type systems.annotateImplicit
in class AnnotatedTypeFactory
elt
- an elementtype
- the type obtained from elt
public Pair<AnnotatedTypeMirror.AnnotatedExecutableType,java.util.List<AnnotatedTypeMirror>> methodFromUse(com.sun.source.tree.MethodInvocationTree tree)
AnnotatedTypeFactory
AnnotatedTypes.asMemberOf(Types, AnnotatedTypeFactory, AnnotatedTypeMirror, Element)
,
and customization based on receiver type should be in accordance to its
specification.
The return type is a pair of the type of the invoked method 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
BaseTypeVisitor.checkTypeArguments(Tree, List, List, List)
for the checks of type argument well-formedness.
Note that "this" and "super" constructor invocations are also handled by this
method. Method AnnotatedTypeFactory.constructorFromUse(NewClassTree)
is only used for a constructor
invocation in a "new" expression.methodFromUse
in class AnnotatedTypeFactory
tree
- the method invocation treepublic Store getEmptyStore()
public boolean getUseFlow()
public void setUseFlow(boolean useFlow)