Skip to content

Commit

Permalink
Handle multiple case expressions
Browse files Browse the repository at this point in the history
As a side effect, fall throughs now go to the next block, not the next case expression
  • Loading branch information
Mr-Pine committed Apr 5, 2024
1 parent 30b0f04 commit af64a20
Showing 1 changed file with 35 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
import spoon.reflect.visitor.CtAbstractVisitor;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
Expand Down Expand Up @@ -390,7 +391,12 @@ public <T> void visitCtBinaryOperator(CtBinaryOperator<T> operator) {

}

private <R> void travelStatementList(List<CtStatement> statements) {
/**
* Add a list of statements as a block to the current CFG.
* @param statements The list of statements
* @return The start node of the block
*/
private ControlFlowNode travelStatementList(List<CtStatement> statements) {
ControlFlowNode begin = new ControlFlowNode(null, result, BranchKind.BLOCK_BEGIN);
tryAddEdge(lastNode, begin);
lastNode = begin;
Expand All @@ -402,6 +408,7 @@ private <R> void travelStatementList(List<CtStatement> statements) {
ControlFlowNode end = new ControlFlowNode(null, result, BranchKind.BLOCK_END);
tryAddEdge(lastNode, end);
lastNode = end;
return begin;
}

@Override
Expand Down Expand Up @@ -774,14 +781,34 @@ public <S> void visitCtSwitch(CtSwitch<S> switchStatement) {

//Visit Case
registerStatementLabel(caseStatement);
ControlFlowNode cn = new ControlFlowNode(caseStatement.getCaseExpression(), result, BranchKind.STATEMENT);
hasDefaultCase |= caseStatement.getCaseExpressions().isEmpty();
tryAddEdge(lastNode, cn);
if (lastNode != switchNode) {
tryAddEdge(switchNode, cn);
var caseExpressions = caseStatement.getCaseExpressions();
ArrayList<ControlFlowNode> caseExpressionNodes = new ArrayList<>();
for (CtExpression<?> expression: caseExpressions) {
ControlFlowNode caseNode = new ControlFlowNode(expression, result, BranchKind.STATEMENT);
caseExpressionNodes.add(caseNode);
tryAddEdge(switchNode, caseNode);
}

if (caseExpressionNodes.isEmpty()) {
hasDefaultCase = true;
ControlFlowNode defaultNode = new ControlFlowNode(null, result, BranchKind.STATEMENT);
caseExpressionNodes.add(defaultNode);
tryAddEdge(switchNode, defaultNode);
}

ControlFlowNode fallThroughEnd = null;
if(lastNode != switchNode) {
fallThroughEnd = lastNode;
}
lastNode = cn;
travelStatementList(caseStatement.getStatements());
lastNode = null;

ControlFlowNode blockStart = travelStatementList(caseStatement.getStatements());
tryAddEdge(fallThroughEnd, blockStart);

for (ControlFlowNode expressionNode : caseExpressionNodes) {
tryAddEdge(expressionNode, blockStart);
}

if (lastNode.getStatement() instanceof CtBreak) {
lastNode = switchNode;
}
Expand Down

0 comments on commit af64a20

Please sign in to comment.