public abstract class AbstractFlow<ST extends FlowState> extends TreePathScanner<Void,Void> implements Flow
This implementation is based largely on javac
's dataflow analysis
module, which may be found in com.sun.tools.javac.comp.Flow
from 13
Sep 2007. It differs from that class in two ways:
javac
's Flow
.
It does not perform exception analysis, and performs liveness analysis only
to the extent required for the GEN-KILL analysis.
BitSet
, the Compiler Tree API) over those in
com.sun.tools.javac
(for these reasons, examining a diff against that
class would not be particularly enlightening).
javac
's Flow
class, methods named "visit*" perform
analysis for a particular type of tree node, while methods named "scan*"
perform the analysis for a general, higher-level class of structural element.
Typically "visit*" methods delegate to "scan*" methods. As an example,
visitIf(com.sun.source.tree.IfTree, java.lang.Void)
, visitWhileLoop(com.sun.source.tree.WhileLoopTree, java.lang.Void)
, visitAssert(com.sun.source.tree.AssertTree, java.lang.Void)
, and
visitConditionalExpression(com.sun.source.tree.ConditionalExpressionTree, java.lang.Void)
all use scanCond(com.sun.source.tree.ExpressionTree)
for analyzing
conditions and handling branching.
A separate instance of the analysis must be created for each compilation unit.
Modifier and Type | Field and Description |
---|---|
protected boolean |
alive
Stores the result of liveness analysis, required by the GEN-KILL analysis
for proper handling of jumps (break, return, throw, etc.).
|
protected QualifierHierarchy |
annoRelations
The hierarchy for the type qualifiers that this class infers.
|
protected AnnotatedTypeFactory |
atypeFactory
Utility class for determining annotated types.
|
protected SourceChecker |
checker
The checker to which this instance belongs.
|
protected PrintStream |
debug
Where to print debugging messages; set via
setDebug(java.io.PrintStream) . |
protected Map<Tree,Set<AnnotationMirror>> |
flowResults
Stores the results of the analysis (source location to qualifier).
|
protected ST |
flowState
Tracks the state of the inference.
|
protected ST |
flowState_whenFalse
Tracks the state of the inference in a false branch.
|
protected ST |
flowState_whenTrue
Tracks the state of the inference in a true branch.
|
protected CompilationUnitTree |
root
The file that's being analyzed.
|
Constructor and Description |
---|
AbstractFlow(BaseTypeChecker checker,
CompilationUnitTree root,
Set<AnnotationMirror> annotations,
AnnotatedTypeFactory factory)
Creates a new analysis.
|
Modifier and Type | Method and Description |
---|---|
static void |
addFlowResult(Map<Tree,Set<AnnotationMirror>> flowResults,
Tree tree,
AnnotationMirror anno) |
protected abstract void |
clearOnCall(@Nullable MethodTree enclMeth,
ExecutableElement method)
Clear whatever part of the state that gets invalidated by
invoking the method.
|
protected static boolean |
containsKey(Tree tree,
Collection<String> keys) |
protected ST |
copyState(ST in)
Copy the current state.
|
protected abstract ST |
createFlowState(Set<AnnotationMirror> annotations)
Create the correct instance of FlowState.
|
protected static boolean |
inferFromAssert(AssertTree node,
SourceChecker checker)
Determine whether information should be inferred from the assert tree.
|
protected static boolean |
isNonFinalField(Element element)
Tests whether the element is of a non-final field
|
protected abstract void |
newVar(VariableTree tree)
Registers a new variable for flow tracking.
|
protected abstract void |
propagate(Tree lhs,
ExpressionTree rhs)
Moves bits as assignments are made.
|
protected abstract void |
propagateFromType(Tree lhs,
AnnotatedTypeMirror rhs)
Moves bits in an assignment using a type instead of a tree.
|
protected void |
recordBits(TreePath path)
Record the value of the annotation bit for the given usage of a
variable, so that a type-checker may use its value after the analysis
has finished.
|
protected abstract void |
recordBitsImps(Tree tree,
Element elt) |
protected void |
removeFlowResult(Map<Tree,Set<AnnotationMirror>> flowResults,
Tree tree,
AnnotationMirror anno) |
void |
scan(Tree tree)
Scan the given (root) tree and infer the refined types.
|
Void |
scan(Tree tree,
Void p) |
protected void |
scanCond(ExpressionTree tree)
Called whenever a conditional expression is scanned.
|
protected void |
scanDef(Tree tree)
Called whenever a definition is scanned.
|
protected void |
scanExpr(ExpressionTree tree)
Called whenever an expression is scanned.
|
protected void |
scanStat(StatementTree tree)
Called whenever a statement is scanned.
|
protected void |
scanStats(List<? extends StatementTree> trees)
Called whenever a block of statements is scanned.
|
void |
setDebug(PrintStream debug)
Sets the
PrintStream for printing debug messages, such as
System.out or System.err , or null if no debugging output
should be emitted (the default). |
Set<AnnotationMirror> |
test(Tree tree)
Determines the inference result for tree.
|
protected boolean |
varDefHasAnnotation(@Nullable MethodTree enclMeth,
AnnotationMirror annotation,
Element var)
Determines whether a variable definition has been annotated.
|
Void |
visitAnnotation(AnnotationTree tree,
Void p) |
Void |
visitArrayAccess(ArrayAccessTree node,
Void p) |
Void |
visitAssert(AssertTree node,
Void p) |
Void |
visitAssignment(AssignmentTree node,
Void p) |
Void |
visitBlock(BlockTree node,
Void p) |
Void |
visitBreak(BreakTree node,
Void p) |
Void |
visitClass(ClassTree node,
Void p) |
Void |
visitCompoundAssignment(CompoundAssignmentTree node,
Void p) |
Void |
visitConditionalExpression(ConditionalExpressionTree node,
Void p) |
Void |
visitContinue(ContinueTree node,
Void p) |
Void |
visitDoWhileLoop(DoWhileLoopTree node,
Void p) |
Void |
visitEnhancedForLoop(EnhancedForLoopTree node,
Void p) |
Void |
visitForLoop(ForLoopTree node,
Void p) |
Void |
visitIdentifier(IdentifierTree node,
Void p) |
Void |
visitIf(IfTree node,
Void p) |
Void |
visitImport(ImportTree tree,
Void p) |
Void |
visitMemberSelect(MemberSelectTree node,
Void p) |
Void |
visitMethod(MethodTree node,
Void p) |
void |
visitMethodEndCallback(MethodTree node)
This method is invoked by visitMethod before restoring the previous
state before visiting the method.
|
Void |
visitMethodInvocation(MethodInvocationTree node,
Void p) |
Void |
visitReturn(ReturnTree node,
Void p) |
Void |
visitThrow(ThrowTree node,
Void p) |
Void |
visitTry(TryTree node,
Void p) |
Void |
visitTypeCast(TypeCastTree node,
Void p) |
Void |
visitVariable(VariableTree node,
Void p) |
Void |
visitWhileLoop(WhileLoopTree node,
Void p) |
getCurrentPath, scan
reduce, scan, visitAnnotatedType, visitArrayType, visitBinary, visitCase, visitCatch, visitCompilationUnit, visitEmptyStatement, visitErroneous, visitExpressionStatement, visitInstanceOf, visitIntersectionType, visitLabeledStatement, visitLambdaExpression, visitLiteral, visitMemberReference, visitModifiers, visitNewArray, visitNewClass, visitOther, visitParameterizedType, visitParenthesized, visitPrimitiveType, visitSwitch, visitSynchronized, visitTypeParameter, visitUnary, visitUnionType, visitWildcard
protected PrintStream debug
setDebug(java.io.PrintStream)
.protected final SourceChecker checker
protected final CompilationUnitTree root
protected final AnnotatedTypeFactory atypeFactory
protected final Map<Tree,Set<AnnotationMirror>> flowResults
protected ST extends FlowState flowState
protected ST extends FlowState flowState_whenTrue
javac
's Flow
, saving/restoring via local variables
handles nested branches.
This field is only non-null/valid if flowState is null.flowState
protected ST extends FlowState flowState_whenFalse
javac
's Flow
, saving/restoring via local variables
handles nested branches.
This field is only non-null/valid if flowState is null.flowState
protected boolean alive
protected final QualifierHierarchy annoRelations
public AbstractFlow(BaseTypeChecker checker, CompilationUnitTree root, Set<AnnotationMirror> annotations, AnnotatedTypeFactory factory)
AnnotatedTypeFactory
to obtain annotated types.checker
- the current checkerroot
- the compilation unit that will be scannedannotations
- the annotations to trackfactory
- the factory class that will be used to get annotated
types, or null
if the default factory should be usedprotected abstract ST createFlowState(Set<AnnotationMirror> annotations)
annotations
- The annotations that can be inferred.public void setDebug(PrintStream debug)
Flow
PrintStream
for printing debug messages, such as
System.out
or System.err
, or null if no debugging output
should be emitted (the default).public void scan(Tree tree)
Flow
public Set<AnnotationMirror> test(Tree tree)
public static void addFlowResult(Map<Tree,Set<AnnotationMirror>> flowResults, Tree tree, AnnotationMirror anno)
protected void removeFlowResult(Map<Tree,Set<AnnotationMirror>> flowResults, Tree tree, AnnotationMirror anno)
protected abstract void newVar(VariableTree tree)
tree
- the variable to registerprotected abstract void propagate(Tree lhs, ExpressionTree rhs)
If only type information (and not a Tree
) is available, use
propagateFromType(Tree, AnnotatedTypeMirror)
instead.
lhs
- the left-hand side of the assignmentrhs
- the right-hand side of the assignmentprotected abstract void propagateFromType(Tree lhs, AnnotatedTypeMirror rhs)
#propagate(Tree, Tree)
is preferred, since it is able to use
extra information about the right-hand side (such as its element). This
method should only be used when a type (and nothing else) is available,
such as when checking the variable in an enhanced for loop against the
iterated type (which is the type argument of an Iterable
).
lhs
- the left-hand side of the assignmentrhs
- the type of the right-hand side of the assignmentprotected void recordBits(TreePath path)
path
- protected void scanDef(Tree tree)
tree
- the definition being scannedprotected void scanStat(StatementTree tree)
tree
- the statement being scannedprotected void scanStats(List<? extends StatementTree> trees)
trees
- the statements being scannedprotected void scanCond(ExpressionTree tree)
tree
- the condition being scannedprotected ST copyState(ST in)
protected void scanExpr(ExpressionTree tree)
tree
- the expression being scannedpublic Void visitClass(ClassTree node, Void p)
visitClass
in interface TreeVisitor<Void,Void>
visitClass
in class TreeScanner<Void,Void>
public Void visitImport(ImportTree tree, Void p)
visitImport
in interface TreeVisitor<Void,Void>
visitImport
in class TreeScanner<Void,Void>
public Void visitTypeCast(TypeCastTree node, Void p)
visitTypeCast
in interface TreeVisitor<Void,Void>
visitTypeCast
in class TreeScanner<Void,Void>
public Void visitAnnotation(AnnotationTree tree, Void p)
visitAnnotation
in interface TreeVisitor<Void,Void>
visitAnnotation
in class TreeScanner<Void,Void>
public Void visitIdentifier(IdentifierTree node, Void p)
visitIdentifier
in interface TreeVisitor<Void,Void>
visitIdentifier
in class TreeScanner<Void,Void>
public Void visitMemberSelect(MemberSelectTree node, Void p)
visitMemberSelect
in interface TreeVisitor<Void,Void>
visitMemberSelect
in class TreeScanner<Void,Void>
public Void visitVariable(VariableTree node, Void p)
visitVariable
in interface TreeVisitor<Void,Void>
visitVariable
in class TreeScanner<Void,Void>
public Void visitAssignment(AssignmentTree node, Void p)
visitAssignment
in interface TreeVisitor<Void,Void>
visitAssignment
in class TreeScanner<Void,Void>
public Void visitCompoundAssignment(CompoundAssignmentTree node, Void p)
visitCompoundAssignment
in interface TreeVisitor<Void,Void>
visitCompoundAssignment
in class TreeScanner<Void,Void>
protected static boolean containsKey(Tree tree, Collection<String> keys)
protected static boolean inferFromAssert(AssertTree node, SourceChecker checker)
public Void visitAssert(AssertTree node, Void p)
visitAssert
in interface TreeVisitor<Void,Void>
visitAssert
in class TreeScanner<Void,Void>
public Void visitIf(IfTree node, Void p)
visitIf
in interface TreeVisitor<Void,Void>
visitIf
in class TreeScanner<Void,Void>
public Void visitConditionalExpression(ConditionalExpressionTree node, Void p)
visitConditionalExpression
in interface TreeVisitor<Void,Void>
visitConditionalExpression
in class TreeScanner<Void,Void>
public Void visitWhileLoop(WhileLoopTree node, Void p)
visitWhileLoop
in interface TreeVisitor<Void,Void>
visitWhileLoop
in class TreeScanner<Void,Void>
public Void visitDoWhileLoop(DoWhileLoopTree node, Void p)
visitDoWhileLoop
in interface TreeVisitor<Void,Void>
visitDoWhileLoop
in class TreeScanner<Void,Void>
public Void visitForLoop(ForLoopTree node, Void p)
visitForLoop
in interface TreeVisitor<Void,Void>
visitForLoop
in class TreeScanner<Void,Void>
public Void visitEnhancedForLoop(EnhancedForLoopTree node, Void p)
visitEnhancedForLoop
in interface TreeVisitor<Void,Void>
visitEnhancedForLoop
in class TreeScanner<Void,Void>
public Void visitBreak(BreakTree node, Void p)
visitBreak
in interface TreeVisitor<Void,Void>
visitBreak
in class TreeScanner<Void,Void>
public Void visitContinue(ContinueTree node, Void p)
visitContinue
in interface TreeVisitor<Void,Void>
visitContinue
in class TreeScanner<Void,Void>
public Void visitReturn(ReturnTree node, Void p)
visitReturn
in interface TreeVisitor<Void,Void>
visitReturn
in class TreeScanner<Void,Void>
public Void visitThrow(ThrowTree node, Void p)
visitThrow
in interface TreeVisitor<Void,Void>
visitThrow
in class TreeScanner<Void,Void>
public Void visitTry(TryTree node, Void p)
visitTry
in interface TreeVisitor<Void,Void>
visitTry
in class TreeScanner<Void,Void>
public Void visitMethodInvocation(MethodInvocationTree node, Void p)
visitMethodInvocation
in interface TreeVisitor<Void,Void>
visitMethodInvocation
in class TreeScanner<Void,Void>
protected abstract void clearOnCall(@Nullable MethodTree enclMeth, ExecutableElement method)
enclMeth
- The method within which "method" is called.
Might be null if the invocation is in a field initializer.method
- The invoked method.public Void visitBlock(BlockTree node, Void p)
visitBlock
in interface TreeVisitor<Void,Void>
visitBlock
in class TreeScanner<Void,Void>
public Void visitMethod(MethodTree node, Void p)
visitMethod
in interface TreeVisitor<Void,Void>
visitMethod
in class TreeScanner<Void,Void>
public void visitMethodEndCallback(MethodTree node)
node
- public Void visitArrayAccess(ArrayAccessTree node, Void p)
visitArrayAccess
in interface TreeVisitor<Void,Void>
visitArrayAccess
in class TreeScanner<Void,Void>
protected boolean varDefHasAnnotation(@Nullable MethodTree enclMeth, AnnotationMirror annotation, Element var)
enclMeth
- the method within which the check happens;
null e.g. in field initializersannotation
- the annotation to check forvar
- the variable to checkprotected static final boolean isNonFinalField(Element element)