More if-statment optimizations in JsStaticEval.
Adds two extra optimizations:
- Empty, but present else statements are pruned:
if (x) {doSomething();} else {} -> if (x) {doSomething();}
- If statements with empty "then" conditions are inverted:
if (x) {} else {doSomething()} -> if (!x) {doSomething();}
Patch by: mmastrac
Review by: me
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5536 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java b/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
index 01bf4c2..91e3af7 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
@@ -35,6 +35,7 @@
import com.google.gwt.dev.js.ast.JsPrefixOperation;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsStatement;
+import com.google.gwt.dev.js.ast.JsUnaryOperation;
import com.google.gwt.dev.js.ast.JsUnaryOperator;
import com.google.gwt.dev.js.ast.JsValueLiteral;
import com.google.gwt.dev.js.ast.JsVars;
@@ -348,8 +349,37 @@
block.getStatements().add(decls);
}
ctx.replaceMe(accept(block));
- } else if (isEmpty(thenStmt) && isEmpty(elseStmt)) {
- ctx.replaceMe(expr.makeStmt());
+ } else {
+ boolean thenIsEmpty = isEmpty(thenStmt);
+ boolean elseIsEmpty = isEmpty(elseStmt);
+
+ if (thenIsEmpty && elseIsEmpty) {
+ ctx.replaceMe(expr.makeStmt());
+ } else if (thenIsEmpty && !elseIsEmpty) {
+ /*
+ * If the then block is blank, but the else statement has statements,
+ * invert the test
+ */
+ sourceInfo = x.getSourceInfo().makeChild(StaticEvalVisitor.class,
+ "Simplified if with empty then statement");
+
+ JsUnaryOperation negatedOperation = new JsPrefixOperation(sourceInfo,
+ JsUnaryOperator.NOT, x.getIfExpr());
+ JsIf newIf = new JsIf(sourceInfo, negatedOperation, elseStmt, null);
+
+ ctx.replaceMe(accept(newIf));
+ } else if (elseIsEmpty && elseStmt != null) {
+ /*
+ * If the else statement is present but has no effective statements,
+ * prune it
+ */
+ sourceInfo = x.getSourceInfo().makeChild(StaticEvalVisitor.class,
+ "Pruned empty else statement");
+
+ JsIf newIf = new JsIf(sourceInfo, x.getIfExpr(), thenStmt, null);
+
+ ctx.replaceMe(accept(newIf));
+ }
}
}
diff --git a/dev/core/test/com/google/gwt/dev/js/JsStaticEvalTest.java b/dev/core/test/com/google/gwt/dev/js/JsStaticEvalTest.java
index 3e9a97e..ff19020 100644
--- a/dev/core/test/com/google/gwt/dev/js/JsStaticEvalTest.java
+++ b/dev/core/test/com/google/gwt/dev/js/JsStaticEvalTest.java
@@ -29,20 +29,36 @@
public class JsStaticEvalTest extends TestCase {
+ public void testIfWithEmptyThen() throws Exception {
+ assertEquals("a();", optimize("if (a()) { }"));
+ }
+
+ public void testIfWithEmptyThenAndElse() throws Exception {
+ assertEquals("if(!a()){b()}", optimize("if (a()) { } else { b(); }"));
+ }
+
+ public void testIfWithEmptyThenAndEmptyElse() throws Exception {
+ assertEquals("a();", optimize("if (a()) { } else { }"));
+ }
+
+ public void testIfWithThenAndEmptyElse() throws Exception {
+ assertEquals("if(a()){b()}", optimize("if (a()) { b() } else { }"));
+ }
+
public void testLiteralEqNull() throws Exception {
- assertTrue(optimize("alert('test' == null)").equals("alert(false);"));
+ assertEquals("alert(false);", optimize("alert('test' == null)"));
}
public void testLiteralNeNull() throws Exception {
- assertTrue(optimize("alert('test' != null)").equals("alert(true);"));
+ assertEquals("alert(true);", optimize("alert('test' != null)"));
}
public void testNullEqNull() throws Exception {
- assertTrue(optimize("alert(null == null)").equals("alert(true);"));
+ assertEquals("alert(true);", optimize("alert(null == null)"));
}
public void testNullNeNull() throws Exception {
- assertTrue(optimize("alert(null != null)").equals("alert(false);"));
+ assertEquals("alert(false);", optimize("alert(null != null)"));
}
private String optimize(String js) throws Exception {