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 {