if (nodes.size() < 2) {
return null;
}
final ControlFlowNode conditionNode = firstOrDefault(
nodes,
new Predicate<ControlFlowNode>() {
@Override
public boolean test(final ControlFlowNode n) {
return n.getType() == ControlFlowNodeType.LoopCondition;
}
}
);
if (conditionNode == null) {
return null;
}
final List<ControlFlowNode> bodyNodes = new ArrayList<>();
for (final ControlFlowEdge edge : conditionNode.getIncoming()) {
final ControlFlowNode from = edge.getFrom();
final Statement statement = from.getPreviousStatement();
if (statement != null && body.isAncestorOf(statement)) {
bodyNodes.add(from);
}
}
if (bodyNodes.size() != 1) {
return null;
}
final Set<Statement> incoming = new LinkedHashSet<>();
final Set<ControlFlowEdge> visited = new HashSet<>();
final ArrayDeque<ControlFlowEdge> agenda = new ArrayDeque<>();
agenda.addAll(conditionNode.getIncoming());
visited.addAll(conditionNode.getIncoming());
while (!agenda.isEmpty()) {
final ControlFlowEdge edge = agenda.removeFirst();
final ControlFlowNode from = edge.getFrom();
if (from == null) {
continue;
}
if (edge.getType() == ControlFlowEdgeType.Jump) {
final Statement jump = from.getNextStatement();
if (jump.getPreviousStatement() != null) {
incoming.add(jump.getPreviousStatement());
}
else {
incoming.add(jump);
}
continue;
}
final Statement previousStatement = from.getPreviousStatement();
if (previousStatement == null) {
continue;
}
if (from.getType() == ControlFlowNodeType.EndNode) {
if (previousStatement instanceof TryCatchStatement) {
incoming.add(previousStatement);
continue;
}
if (previousStatement instanceof BlockStatement || hasNestedBlocks(previousStatement)) {
for (final ControlFlowEdge e : from.getIncoming()) {
if (visited.add(e)) {
agenda.addLast(e);
}
}
}