Skip to content

Commit

Permalink
Remove unnecessary fallthrough case labels
Browse files Browse the repository at this point in the history
eg.
switch('foo') {
  case 'foo':
  case 'bar':
    alert();
}

becomes

alert();

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=163541301
  • Loading branch information
Dominator008 authored and blickly committed Jul 31, 2017
1 parent a5b8c5f commit 27401f0
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 27 deletions.
30 changes: 24 additions & 6 deletions src/com/google/javascript/jscomp/PeepholeRemoveDeadCode.java
Expand Up @@ -374,7 +374,10 @@ private Node tryOptimizeSwitch(Node n) {

// Generally, it is unsafe to remove other cases when the default case is not the last one.
if (defaultCase == null || n.getLastChild().isDefaultCase()) {
Node cond = n.getFirstChild(), prev = null, next = null, cur;
Node cond = n.getFirstChild();
Node prev = null;
Node next = null;
Node cur;

for (cur = cond.getNext(); cur != null; cur = next) {
next = cur.getNext();
Expand Down Expand Up @@ -404,18 +407,33 @@ private Node tryOptimizeSwitch(Node n) {
removeCase(n, cur);
}
}
if (caseMatches != TernaryValue.UNKNOWN) {
Node block, lastStm;
if (cur != null && caseMatches == TernaryValue.TRUE) {
// Skip cases until you find one whose last stm is a removable break
Node matchingCase = cur;
Node matchingCaseBlock = matchingCase.getLastChild();
while (cur != null) {
block = cur.getLastChild();
lastStm = block.getLastChild();
cur = cur.getNext();
Node block = cur.getLastChild();
Node lastStm = block.getLastChild();
boolean isLastStmRemovableBreak = false;
if (lastStm != null && isExit(lastStm)) {
removeIfUnnamedBreak(lastStm);
isLastStmRemovableBreak = true;
}
next = cur.getNext();
// Remove the fallthrough case labels
if (cur != matchingCase) {
while (block.hasChildren()) {
matchingCaseBlock.addChildToBack(block.getFirstChild().detach());
}
cur.detach();
reportCodeChange();
}
cur = next;
if (isLastStmRemovableBreak) {
break;
}
}

// Remove any remaining cases
for (; cur != null; cur = next) {
next = cur.getNext();
Expand Down
81 changes: 60 additions & 21 deletions test/com/google/javascript/jscomp/PeepholeRemoveDeadCodeTest.java
Expand Up @@ -407,22 +407,39 @@ public void testOptimizeSwitch() {
" break;\n" +
"}",
"");
foldSame("switch ('fallThru') {\n" +
"case 'fallThru':\n" +
" if (foo(123) > 0) {\n" +
" foobar(1);\n" +
" break;\n" +
" }\n" +
" foobar(2);\n" +
"case 'bar':\n" +
" bar();\n" +
"}");
foldSame("switch ('fallThru') {\n" +
"case 'fallThru':\n" +
" foo();\n" +
"case 'bar':\n" +
" bar();\n" +
"}");
fold(
LINE_JOINER.join(
"switch ('fallThru') {",
"case 'fallThru':",
" if (foo(123) > 0) {",
" foobar(1);",
" break;",
" }",
" foobar(2);",
"case 'bar':",
" bar();",
"}"),
LINE_JOINER.join(
"switch ('fallThru') {",
"case 'fallThru':",
" if (foo(123) > 0) {",
" foobar(1);",
" break;",
" }",
" foobar(2);",
" bar();",
"}"));
fold(
LINE_JOINER.join(
"switch ('fallThru') {",
"case 'fallThru':",
" foo();",
"case 'bar':",
" bar();",
"}"),
LINE_JOINER.join(
"foo();",
"bar();"));
fold(
LINE_JOINER.join(
"switch ('hasDefaultCase') {",
Expand Down Expand Up @@ -496,11 +513,14 @@ public void testOptimizeSwitch() {
"case '\\u000B':\n" +
" foo();\n" +
"}");
foldSame("switch ('empty') {\n" +
"case 'empty':\n" +
"case 'foo':\n" +
" foo();\n" +
"}");
fold(
LINE_JOINER.join(
"switch ('empty') {",
"case 'empty':",
"case 'foo':",
" foo();",
"}"),
"foo()");

fold(
LINE_JOINER.join(
Expand Down Expand Up @@ -547,6 +567,25 @@ public void testOptimizeSwitch2() {
"outer: {f(); break outer;}");
}

public void testOptimizeSwitch3() {
fold(
LINE_JOINER.join(
"switch (1) {",
" case 1:",
" case 2:",
" case 3: {",
" break;",
" }",
" case 4:",
" case 5:",
" case 6:",
" default:",
" fail('Should not get here');",
" break;",
"}"),
"");
}

public void testOptimizeSwitchWithLabellessBreak() {
test(
LINE_JOINER.join(
Expand Down

0 comments on commit 27401f0

Please sign in to comment.