public class ControlFlowUtil
extends java.lang.Object
Modifier and Type | Class and Description |
---|---|
static class |
ControlFlowUtil.ControlFlowEdge |
static class |
ControlFlowUtil.VariableInfo |
Modifier and Type | Field and Description |
---|---|
static java.lang.Class<? extends PsiStatement>[] |
DEFAULT_EXIT_STATEMENTS_CLASSES |
static int |
NORMAL_COMPLETION_REASON |
Constructor and Description |
---|
ControlFlowUtil() |
Modifier and Type | Method and Description |
---|---|
static boolean |
areVariablesUnmodifiedAtLocations(ControlFlow flow,
int startOffset,
int endOffset,
java.util.Set<? extends PsiVariable> variables,
java.lang.Iterable<? extends PsiElement> locations)
Check that in the
flow between startOffset and endOffset there are no writes
to the variables or these writes aren't observable at the locations . |
static boolean |
canCompleteNormally(ControlFlow flow,
int startOffset,
int endOffset)
returns true iff exists control flow path completing normally, i.e.
|
static boolean |
collectOuterLocals(java.util.List<? super PsiVariable> array,
PsiElement scope,
PsiElement member,
PsiElement targetClassMember)
Checks possibility of extracting code fragment outside containing anonymous (local) class.
|
static PsiElement |
findCodeFragment(PsiElement element) |
static java.util.Collection<PsiStatement> |
findExitPointsAndStatements(ControlFlow flow,
int start,
int end,
IntArrayList exitPoints,
java.lang.Class<? extends PsiStatement>... classesFilter) |
static PsiReferenceExpression |
findSingleReadOccurrence(ControlFlow flow,
PsiElement element,
PsiVariable variable)
If the variable occurs only once in the element and it's read access return that occurrence
|
static int |
getCompletionReasons(ControlFlow flow,
int offset,
int endOffset)
return reasons.normalCompletion when block can complete normally
reasons.returnCalled when block can complete abruptly because of return statement executed
|
static java.util.List<ControlFlowUtil.ControlFlowEdge> |
getEdges(ControlFlow flow,
int start)
Returns control flow edges which are potentially reachable from start instruction
|
static java.util.Collection<ControlFlowUtil.VariableInfo> |
getInitializedTwice(ControlFlow flow) |
static java.util.Collection<ControlFlowUtil.VariableInfo> |
getInitializedTwice(ControlFlow flow,
int startOffset,
int endOffset) |
static java.util.List<PsiVariable> |
getInputVariables(ControlFlow flow,
int start,
int end) |
static int |
getMinDefinitelyReachedOffset(ControlFlow flow,
int sourceOffset,
java.util.List<? extends PsiElement> references) |
static PsiVariable [] |
getOutputVariables(ControlFlow flow,
int start,
int end,
int [] exitPoints) |
static java.util.List<PsiReferenceExpression> |
getReadBeforeWrite(ControlFlow flow) |
static java.util.List<PsiReferenceExpression> |
getReadBeforeWriteLocals(ControlFlow flow) |
static java.util.List<PsiVariable> |
getSSAVariables(ControlFlow flow) |
static java.util.List<PsiVariable> |
getSSAVariables(ControlFlow flow,
int from,
int to,
boolean reportVarsIfNonInitializingPathExists) |
static PsiElement |
getUnreachableStatement(ControlFlow flow) |
static java.util.List<PsiVariable> |
getUsedVariables(ControlFlow flow,
int start,
int end) |
static boolean[] |
getVariablePossiblyUnassignedOffsets(PsiVariable variable,
ControlFlow flow)
Returns offsets starting from which the variable could be unassigned
|
static java.util.Map<PsiElement,PsiVariable> |
getWritesBeforeReads(ControlFlow flow,
java.util.Set<? extends PsiVariable> writeVars,
java.util.Set<? extends PsiVariable> readVars,
int stopPoint)
Find locations of writes of variables from writeVars that happened before one of reads of variables from readVars.
|
static java.util.Collection<PsiVariable> |
getWrittenVariables(ControlFlow flow,
int start,
int end,
boolean ignoreNotReachingWrites) |
static void |
getWrittenVariables(ControlFlow flow,
int start,
int end,
boolean ignoreNotReachingWrites,
java.util.Collection<? super PsiVariable> set) |
static boolean |
hasObservableThrowExitPoints(ControlFlow flow,
int flowStart,
int flowEnd,
PsiElement [] elements,
PsiElement enclosingCodeFragment)
Detect throw instructions which might affect observable control flow via side effects with local variables.
|
static boolean |
isDominator(ControlFlow flow,
int maybeDominator,
int target)
Returns true of instruction at given offset is a dominator for target instruction (that is: execution from flow start to
the target always goes through given offset).
|
static boolean |
isInstructionReachable(ControlFlow flow,
int instructionOffset,
int startOffset) |
static boolean |
isValueUsedWithoutVisitingStop(ControlFlow flow,
int start,
int stop,
PsiVariable variable)
Returns true if the value the variable has at start is later referenced without going through stop instruction
|
static boolean |
isVariableAccess(ControlFlow flow,
int offset,
PsiVariable variable)
Checks if the control flow instruction at given offset accesses (reads or writes) given variable
|
static boolean |
isVariableAssignedInLoop(PsiReferenceExpression expression,
PsiElement resolved) |
static boolean |
isVariableDefinitelyAssigned(PsiVariable variable,
ControlFlow flow) |
static boolean |
isVariableDefinitelyNotAssigned(PsiVariable variable,
ControlFlow flow) |
static boolean |
isVariableReadInFinally(ControlFlow flow,
PsiElement startElement,
PsiElement enclosingCodeFragment,
PsiVariable variable) |
static boolean |
isVariableUsed(ControlFlow flow,
int start,
int end,
PsiVariable variable) |
static boolean |
needVariableValueAt(PsiVariable variable,
ControlFlow flow,
int offset) |
static boolean |
processReturns(ControlFlow flow,
ReturnStatementsVisitor afterVisitor) |
static boolean |
returnPresent(ControlFlow flow) |
static boolean |
returnPresentBetween(ControlFlow flow,
int startOffset,
int endOffset) |
public static final java.lang.Class<? extends PsiStatement>[] DEFAULT_EXIT_STATEMENTS_CLASSES
public static final int NORMAL_COMPLETION_REASON
public static java.util.List<PsiVariable> getSSAVariables(ControlFlow flow)
public static java.util.List<PsiVariable> getSSAVariables(ControlFlow flow, int from, int to, boolean reportVarsIfNonInitializingPathExists)
public static boolean needVariableValueAt(PsiVariable variable, ControlFlow flow, int offset)
public static java.util.Collection<PsiVariable> getWrittenVariables(ControlFlow flow, int start, int end, boolean ignoreNotReachingWrites)
public static void getWrittenVariables(ControlFlow flow, int start, int end, boolean ignoreNotReachingWrites, java.util.Collection<? super PsiVariable> set)
public static java.util.List<PsiVariable> getUsedVariables(ControlFlow flow, int start, int end)
public static boolean isVariableUsed(ControlFlow flow, int start, int end, PsiVariable variable)
public static PsiReferenceExpression findSingleReadOccurrence(ControlFlow flow, PsiElement element, PsiVariable variable)
public static boolean isVariableReadInFinally(ControlFlow flow, PsiElement startElement, PsiElement enclosingCodeFragment, PsiVariable variable)
public static java.util.List<PsiVariable> getInputVariables(ControlFlow flow, int start, int end)
public static PsiVariable [] getOutputVariables(ControlFlow flow, int start, int end, int [] exitPoints)
@SafeVarargs public static java.util.Collection<PsiStatement> findExitPointsAndStatements(ControlFlow flow, int start, int end, IntArrayList exitPoints, java.lang.Class<? extends PsiStatement>... classesFilter)
public static boolean hasObservableThrowExitPoints(ControlFlow flow, int flowStart, int flowEnd, PsiElement [] elements, PsiElement enclosingCodeFragment)
{ // --- start of theOuterBlock --- Status status = STARTED; try { // --- start of theTryBlock --- status = PREPARING; doPrepare(); // may throw exception status = WORKING; doWork(); // may throw exception status = FINISHED; } // --- end of theTryBlock --- catch (Exception e) { LOG.error("Failed when " + status, e); // can get PREPARING or WORKING here } if (status == FINISHED) LOG.info("Finished"); // can get PREPARING or WORKING here in the case of exception } // --- end of theOuterBlock ---In the example above
hasObservableThrowExitPoints(theTryBlock) == true
,
because the resulting value of the "status" variable depends on the exceptions being thrown.
In the same example hasObservableThrowExitPoints(theOuterBlock) == false
,
because no outgoing variables here depend on the exceptions being thrown.public static PsiElement findCodeFragment(PsiElement element)
public static boolean collectOuterLocals(java.util.List<? super PsiVariable> array, PsiElement scope, PsiElement member, PsiElement targetClassMember)
array
- Vector to collect variables to be passed as additional parametersscope
- scope to be scanned (part of code fragment to be extracted)member
- member containing the code to be extractedtargetClassMember
- member in target class containing code fragmentpublic static boolean returnPresent(ControlFlow flow)
public static boolean processReturns(ControlFlow flow, ReturnStatementsVisitor afterVisitor) throws IncorrectOperationException
IncorrectOperationException
public static boolean returnPresentBetween(ControlFlow flow, int startOffset, int endOffset)
public static boolean canCompleteNormally(ControlFlow flow, int startOffset, int endOffset)
public static PsiElement getUnreachableStatement(ControlFlow flow)
public static boolean isDominator(ControlFlow flow, int maybeDominator, int target)
flow
- control flow to analyzemaybeDominator
- a dominator candidate offsettarget
- a target instruction offsetpublic static boolean isVariableDefinitelyAssigned(PsiVariable variable, ControlFlow flow)
public static boolean[] getVariablePossiblyUnassignedOffsets(PsiVariable variable, ControlFlow flow)
variable
- variable to checkflow
- control flowpublic static boolean isVariableDefinitelyNotAssigned(PsiVariable variable, ControlFlow flow)
public static boolean isValueUsedWithoutVisitingStop(ControlFlow flow, int start, int stop, PsiVariable variable)
flow
- ControlFlow to analyzestart
- the point at which variable value is createdstop
- the stop-pointvariable
- the variable to examinepublic static boolean isVariableAccess(ControlFlow flow, int offset, PsiVariable variable)
flow
- control flowoffset
- offset inside given control flowvariable
- a variable the access to which is to be checkedpublic static java.util.List<ControlFlowUtil.ControlFlowEdge> getEdges(ControlFlow flow, int start)
flow
- control flow to analyzestart
- starting instruction offsetpublic static int getMinDefinitelyReachedOffset(ControlFlow flow, int sourceOffset, java.util.List<? extends PsiElement> references)
public static java.util.List<PsiReferenceExpression> getReadBeforeWriteLocals(ControlFlow flow)
public static java.util.List<PsiReferenceExpression> getReadBeforeWrite(ControlFlow flow)
public static int getCompletionReasons(ControlFlow flow, int offset, int endOffset)
public static java.util.Collection<ControlFlowUtil.VariableInfo> getInitializedTwice(ControlFlow flow)
public static java.util.Collection<ControlFlowUtil.VariableInfo> getInitializedTwice(ControlFlow flow, int startOffset, int endOffset)
public static java.util.Map<PsiElement,PsiVariable> getWritesBeforeReads(ControlFlow flow, java.util.Set<? extends PsiVariable> writeVars, java.util.Set<? extends PsiVariable> readVars, int stopPoint)
stopPoint
- point until which reads are consideredpublic static boolean isInstructionReachable(ControlFlow flow, int instructionOffset, int startOffset)
public static boolean isVariableAssignedInLoop(PsiReferenceExpression expression, PsiElement resolved)
public static boolean areVariablesUnmodifiedAtLocations(ControlFlow flow, int startOffset, int endOffset, java.util.Set<? extends PsiVariable> variables, java.lang.Iterable<? extends PsiElement> locations)
flow
between startOffset
and endOffset
there are no writes
to the variables
or these writes aren't observable at the locations
.