// Eliminate unnecessary default statements.
// Having a default statement prevents other optimizations so aggressively
// optimize them out where possible.
boolean hasDefault = false;
for (int i = newChildren.size(); --i >= 1;) {
SwitchCase cs = (SwitchCase) newChildren.get(i);
if (!(cs instanceof DefaultCaseStmt)) { continue; }
Block body = cs.getBody();
if (body.children().isEmpty()) {
changed = true;
newChildren.remove(i);
} else if (isBlankBreak(body)) {
if (i != 1 || !exits(((SwitchCase) newChildren.get(i - 1)).getBody())) {
// Move the break into the preceding case.
SwitchCase prev = (SwitchCase) newChildren.get(i - 1);
newChildren.set(i - 1, withBody(prev, combine(prev.getBody(), body)));
changed = true;
}
newChildren.remove(i);
changed = true;
} else {
hasDefault = true;
}
}
// Eliminate unnecessary breaks
if (!hasDefault) {
for (int i = newChildren.size(); --i >= 1;) {
CaseStmt cs = (CaseStmt) newChildren.get(i);
Block body = cs.getBody();
if (!isBlankBreak(body)) { continue; }
if (cs.getCaseValue().simplifyForSideEffect() != null) { continue; }
if (i != 1) {
SwitchCase prev = (SwitchCase) newChildren.get(i - 1);
if (!exits(prev.getBody())) {
// Move the break into the preceding case.
newChildren.set(
i - 1, withBody(prev, combine(prev.getBody(), body)));
}
}
newChildren.remove(i);
changed = true;
}
}
// Eliminate duplicate cases
SwitchCase last = null;
for (int i = 1; i < newChildren.size(); ++i) {
SwitchCase cs = (SwitchCase) newChildren.get(i);
if (last != null && !last.getBody().children().isEmpty()
&& ParseTreeNodes.deepEquals(last.getBody(), cs.getBody())) {
newChildren.set(i - 1, withoutBody(last));
changed = true;
}
last = cs;
}
while (newChildren.size() > 1) {
int lastIndex = newChildren.size() - 1;
last = (SwitchCase) newChildren.get(lastIndex);
Block lastBody = last.getBody();
boolean changedOne = false;
if (!lastBody.children().isEmpty()) {
// Eliminate trailing break statement.
List<? extends Statement> stmts = lastBody.children();
int n = stmts.size();
if (n > 0 && isBlankBreak(stmts.get(n - 1))) {
stmts = stmts.subList(0, n - 1);
Block newBody = new Block(lastBody.getFilePosition(), stmts);
newChildren.set(newChildren.size() - 1, withBody(last, newBody));
changedOne = true;
}
} else if (isBlankBreak(lastBody)) {
// switch (...) { default: ... case foo: break; }
// => switch (...) { default: ... case foo: }
newChildren.set(lastIndex, withoutBody(last));
changedOne = true;
} else if (!hasDefault) {
CaseStmt cs = (CaseStmt) last; // OK since !hasDefault
// switch (...) { ... case 4: case 5: break; }
// => switch (...) { ... }
// We can eliminate cases entirely if there is no default since it
// will not change the set of values that default matches.
if (null == cs.getCaseValue().simplifyForSideEffect()) {
newChildren.remove(lastIndex);
changedOne = true;
}
}
if (changedOne) {