Closure JS hookup

Review by: cromwellian@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10778 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/PrecompileTaskArgProcessor.java b/dev/core/src/com/google/gwt/dev/PrecompileTaskArgProcessor.java
index 04be766..5f13163 100644
--- a/dev/core/src/com/google/gwt/dev/PrecompileTaskArgProcessor.java
+++ b/dev/core/src/com/google/gwt/dev/PrecompileTaskArgProcessor.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2011 Google Inc.
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
  * the License at
- * 
+ *
  * http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -28,6 +28,7 @@
 import com.google.gwt.dev.util.arg.ArgHandlerDraftCompile;
 import com.google.gwt.dev.util.arg.ArgHandlerDumpSignatures;
 import com.google.gwt.dev.util.arg.ArgHandlerEnableAssertions;
+import com.google.gwt.dev.util.arg.ArgHandlerEnableClosureCompiler;
 import com.google.gwt.dev.util.arg.ArgHandlerGenDir;
 import com.google.gwt.dev.util.arg.ArgHandlerMaxPermsPerPrecompile;
 import com.google.gwt.dev.util.arg.ArgHandlerOptimize;
@@ -60,6 +61,7 @@
     registerHandler(new ArgHandlerStrict(options));
     registerHandler(new ArgHandlerCompilerMetrics(options));
     registerHandler(new ArgHandlerDisableSoycHtml(options));
+    registerHandler(new ArgHandlerEnableClosureCompiler(options));
   }
 
   @Override
diff --git a/dev/core/src/com/google/gwt/dev/PrecompileTaskOptionsImpl.java b/dev/core/src/com/google/gwt/dev/PrecompileTaskOptionsImpl.java
index 7abf8b5..1fea930 100644
--- a/dev/core/src/com/google/gwt/dev/PrecompileTaskOptionsImpl.java
+++ b/dev/core/src/com/google/gwt/dev/PrecompileTaskOptionsImpl.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2011 Google Inc.
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
  * the License at
- * 
+ *
  * http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -84,6 +84,11 @@
   }
 
   @Override
+  public boolean isClosureCompilerEnabled() {
+    return jjsOptions.isClosureCompilerEnabled();
+  }
+
+  @Override
   public boolean isCompilerMetricsEnabled() {
     return jjsOptions.isCompilerMetricsEnabled();
   }
@@ -158,6 +163,11 @@
   }
 
   @Override
+  public void setClosureCompilerEnabled(boolean enabled) {
+    jjsOptions.setClosureCompilerEnabled(enabled);
+  }
+
+  @Override
   public void setCompilerMetricsEnabled(boolean enabled) {
     jjsOptions.setCompilerMetricsEnabled(enabled);
   }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JJSOptions.java b/dev/core/src/com/google/gwt/dev/jjs/JJSOptions.java
index fc13cde..3162e5e 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JJSOptions.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JJSOptions.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2008 Google Inc.
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
  * the License at
- * 
+ *
  * http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -19,6 +19,7 @@
 import com.google.gwt.dev.util.arg.OptionDisableCastChecking;
 import com.google.gwt.dev.util.arg.OptionDisableClassMetadata;
 import com.google.gwt.dev.util.arg.OptionEnableAssertions;
+import com.google.gwt.dev.util.arg.OptionEnableClosureCompiler;
 import com.google.gwt.dev.util.arg.OptionOptimize;
 import com.google.gwt.dev.util.arg.OptionOptimizePrecompile;
 import com.google.gwt.dev.util.arg.OptionRunAsyncEnabled;
@@ -34,6 +35,7 @@
 public interface JJSOptions extends OptionOptimize, OptionAggressivelyOptimize,
     OptionDisableClassMetadata, OptionDisableCastChecking, OptionEnableAssertions,
     OptionRunAsyncEnabled, OptionScriptStyle, OptionSoycEnabled, OptionSoycDetailed,
-    OptionOptimizePrecompile, OptionStrict, OptionSoycHtmlDisabled {
+    OptionOptimizePrecompile, OptionStrict, OptionSoycHtmlDisabled,
+    OptionEnableClosureCompiler {
 
 }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JJSOptionsImpl.java b/dev/core/src/com/google/gwt/dev/jjs/JJSOptionsImpl.java
index d3abb04..c1695bb 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JJSOptionsImpl.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JJSOptionsImpl.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2008 Google Inc.
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
  * the License at
- * 
+ *
  * http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -37,6 +37,7 @@
   private boolean soycExtra = false;
   private boolean soycHtmlDisabled = false;
   private boolean strict = false;
+  private boolean closureCompilerEnabled;
 
   public JJSOptionsImpl() {
   }
@@ -58,6 +59,7 @@
     setSoycExtra(other.isSoycExtra());
     setSoycHtmlDisabled(other.isSoycHtmlDisabled());
     setStrict(other.isStrict());
+    setClosureCompilerEnabled(other.isClosureCompilerEnabled());
   }
 
   @Override
@@ -86,6 +88,11 @@
   }
 
   @Override
+  public boolean isClosureCompilerEnabled() {
+    return this.closureCompilerEnabled;
+  }
+
+  @Override
   public boolean isCompilerMetricsEnabled() {
     return compilerMetricsEnabled;
   }
@@ -118,7 +125,7 @@
   public boolean isSoycExtra() {
     return soycExtra;
   }
-  
+
   @Override
   public boolean isSoycHtmlDisabled() {
     return soycHtmlDisabled;
@@ -145,6 +152,11 @@
   }
 
   @Override
+  public void setClosureCompilerEnabled(boolean enabled) {
+    this.closureCompilerEnabled = enabled;
+  }
+
+  @Override
   public void setCompilerMetricsEnabled(boolean enabled) {
     this.compilerMetricsEnabled = enabled;
   }
@@ -183,7 +195,7 @@
   public void setSoycExtra(boolean enabled) {
     soycExtra = enabled;
   }
-  
+
   @Override
   public void setSoycHtmlDisabled(boolean disabled) {
     soycHtmlDisabled = disabled;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
index c0bf87c..9fcc051 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2008 Google Inc.
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
  * the License at
- * 
+ *
  * http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -101,6 +101,7 @@
 import com.google.gwt.dev.jjs.impl.TypeTightener;
 import com.google.gwt.dev.jjs.impl.UnifyAst;
 import com.google.gwt.dev.jjs.impl.gflow.DataflowOptimizer;
+import com.google.gwt.dev.js.ClosureJsRunner;
 import com.google.gwt.dev.js.EvalFunctionsAtTopScope;
 import com.google.gwt.dev.js.JsBreakUpLargeVarStatements;
 import com.google.gwt.dev.js.JsCoerceIntShift;
@@ -190,26 +191,32 @@
       this.statementRanges = statementRanges;
     }
 
+    @Override
     public void addArtifacts(Collection<? extends Artifact<?>> newArtifacts) {
       this.artifacts.addAll(newArtifacts);
     }
 
+    @Override
     public ArtifactSet getArtifacts() {
       return artifacts;
     }
 
+    @Override
     public byte[][] getJs() {
       return js;
     }
 
+    @Override
     public Permutation getPermutation() {
       return permutation;
     }
 
+    @Override
     public byte[] getSerializedSymbolMap() {
       return serializedSymbolMap;
     }
 
+    @Override
     public StatementRanges[] getStatementRanges() {
       return statementRanges;
     }
@@ -233,7 +240,7 @@
 
   /**
    * Compiles a particular permutation, based on a precompiled unified AST.
-   * 
+   *
    * @param logger the logger to use
    * @param unifiedAst the result of a
    *          {@link #precompile(TreeLogger, ModuleDef, RebindPermutationOracle, String[], String[], JJSOptions, boolean, PrecompilationMetricsArtifact)}
@@ -334,7 +341,7 @@
 
       /*
        * Work around Safari 5 bug by rewriting a >> b as ~~a >> b.
-       * 
+       *
        * No shifts may be generated after this point.
        */
       JsCoerceIntShift.exec(jsProgram, logger, propertyOracles);
@@ -423,7 +430,8 @@
       PermutationResult toReturn =
           new PermutationResultImpl(js, permutation, makeSymbolMap(symbolTable, jsProgram), ranges);
       CompilationMetricsArtifact compilationMetrics = null;
-      if (options.isCompilerMetricsEnabled()) {
+      // TODO: enable this when ClosureCompiler is enabled
+      if (!options.isClosureCompilerEnabled() && options.isCompilerMetricsEnabled()) {
         compilationMetrics = new CompilationMetricsArtifact(permutation.getId());
         compilationMetrics.setCompileElapsedMilliseconds(System.currentTimeMillis()
             - startTimeMilliseconds);
@@ -434,12 +442,17 @@
         toReturn.addArtifacts(Lists.create(unifiedAst.getModuleMetrics(), unifiedAst
             .getPrecompilationMetrics(), compilationMetrics));
       }
-      toReturn.addArtifacts(makeSoycArtifacts(logger, permutationId, jprogram, js, sizeBreakdowns,
-          options.isSoycExtra() ? sourceInfoMaps : null, dependencies, jjsmap, obfuscateMap,
-          unifiedAst.getModuleMetrics(), unifiedAst.getPrecompilationMetrics(), compilationMetrics,
-          options.isSoycHtmlDisabled()));
 
-      if (isSourceMapsEnabled) {
+      // TODO: enable this when ClosureCompiler is enabled
+      if (!options.isClosureCompilerEnabled()) {
+        toReturn.addArtifacts(makeSoycArtifacts(logger, permutationId, jprogram, js, sizeBreakdowns,
+            options.isSoycExtra() ? sourceInfoMaps : null, dependencies, jjsmap, obfuscateMap,
+            unifiedAst.getModuleMetrics(), unifiedAst.getPrecompilationMetrics(), compilationMetrics,
+            options.isSoycHtmlDisabled()));
+      }
+
+      // TODO: enable this when ClosureCompiler is enabled
+      if (!options.isClosureCompilerEnabled() && isSourceMapsEnabled) {
         logger.log(TreeLogger.INFO, "Source Maps Enabled");
         toReturn.addArtifacts(SourceMapRecorder.makeSourceMapArtifacts(sourceInfoMaps,
             permutationId));
@@ -490,7 +503,7 @@
 
   /**
    * Performs a precompilation, returning a unified AST.
-   * 
+   *
    * @param logger the logger to use
    * @param module the module to compile
    * @param rpo the RebindPermutationOracle
@@ -612,7 +625,7 @@
 
       /*
        * 4) Possibly optimize some.
-       * 
+       *
        * Don't optimize early if this is a draft compile, or if there's only one
        * permutation.
        */
@@ -804,7 +817,7 @@
 
       /*
        * Enum ordinalization.
-       * 
+       *
        * TODO(jbrosenberg): graduate this out of the 'isAggressivelyOptimize'
        * block, over time.
        */
@@ -956,7 +969,7 @@
   /**
    * Generate JavaScript code from the given JavaScript ASTs. Also produces
    * information about that transformation.
-   * 
+   *
    * @param options The options this compiler instance is running with
    * @param jsProgram The AST to convert to source code
    * @param jjsMap A map between the JavaScript AST and the Java AST it came
@@ -976,6 +989,14 @@
       SizeBreakdown[] sizeBreakdowns,
       List<Map<Range, SourceInfo>> sourceInfoMaps,
       boolean splitBlocks, boolean sourceMapsEnabled) {
+
+    boolean useClosureCompiler = options.isClosureCompilerEnabled();
+    if (useClosureCompiler) {
+      ClosureJsRunner runner = new ClosureJsRunner();
+      runner.compile(jsProgram, js, options.getOutput());
+      return;
+    }
+
     for (int i = 0; i < js.length; i++) {
       DefaultTextOutput out = new DefaultTextOutput(options.getOutput().shouldMinimize());
       JsSourceGenerationVisitorWithSizeBreakdown v;
@@ -1036,7 +1057,7 @@
 
   /**
    * This method can be used to fetch the list of referenced classs.
-   * 
+   *
    * This method is intended to support compiler metrics in the precompile
    * phase.
    */
@@ -1164,7 +1185,7 @@
 
   /**
    * Create a variable assignment to invoke a call to the statistics collector.
-   * 
+   *
    * <pre>
    * Stats.isStatsAvailable() &&
    *   Stats.onModuleStart("mainClassName");
diff --git a/dev/core/src/com/google/gwt/dev/js/ClosureJsAst.java b/dev/core/src/com/google/gwt/dev/js/ClosureJsAst.java
new file mode 100644
index 0000000..0a437b0
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/js/ClosureJsAst.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.dev.js;
+
+import com.google.gwt.thirdparty.guava.common.base.Preconditions;
+import com.google.gwt.thirdparty.javascript.jscomp.AbstractCompiler;
+import com.google.gwt.thirdparty.javascript.jscomp.SourceAst;
+import com.google.gwt.thirdparty.javascript.jscomp.SourceFile;
+import com.google.gwt.thirdparty.javascript.rhino.InputId;
+import com.google.gwt.thirdparty.javascript.rhino.Node;
+
+/**
+ * Maps the JavaScript AST to a Closure Compiler input source.
+ */
+public class ClosureJsAst implements SourceAst {
+
+  private static final long serialVersionUID = 1L;
+
+  /*
+   * Root node of internal JS Compiler AST which represents the same source. In order to get the
+   * tree, getAstRoot() has to be called.
+   */
+  private Node root;
+  private final InputId inputId;
+
+  public ClosureJsAst(InputId inputId, Node root) {
+    Preconditions.checkNotNull(root);
+    this.inputId = inputId;
+    this.root = root;
+  }
+
+  @Override
+  public void clearAst() {
+    root = null;
+  }
+
+  @Override
+  public Node getAstRoot(AbstractCompiler compiler) {
+    return root;
+  }
+
+  @Override
+  public InputId getInputId() {
+    return inputId;
+  }
+
+  @Override
+  public SourceFile getSourceFile() {
+    return null;
+  }
+
+  public String getSourceName() {
+    return null;
+  }
+
+  @Override
+  public void setSourceFile(SourceFile file) {
+    throw new UnsupportedOperationException(
+        "ClosureJsAst cannot be associated with a SourceFile instance.");
+  }
+}
diff --git a/dev/core/src/com/google/gwt/dev/js/ClosureJsAstTranslator.java b/dev/core/src/com/google/gwt/dev/js/ClosureJsAstTranslator.java
new file mode 100644
index 0000000..54d1c46
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/js/ClosureJsAstTranslator.java
@@ -0,0 +1,823 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.js;
+
+import com.google.gwt.dev.jjs.HasSourceInfo;
+import com.google.gwt.dev.jjs.SourceInfo;
+import com.google.gwt.dev.js.ast.HasName;
+import com.google.gwt.dev.js.ast.JsArrayAccess;
+import com.google.gwt.dev.js.ast.JsArrayLiteral;
+import com.google.gwt.dev.js.ast.JsBinaryOperation;
+import com.google.gwt.dev.js.ast.JsBinaryOperator;
+import com.google.gwt.dev.js.ast.JsBlock;
+import com.google.gwt.dev.js.ast.JsBooleanLiteral;
+import com.google.gwt.dev.js.ast.JsBreak;
+import com.google.gwt.dev.js.ast.JsCase;
+import com.google.gwt.dev.js.ast.JsCatch;
+import com.google.gwt.dev.js.ast.JsConditional;
+import com.google.gwt.dev.js.ast.JsContinue;
+import com.google.gwt.dev.js.ast.JsDebugger;
+import com.google.gwt.dev.js.ast.JsDefault;
+import com.google.gwt.dev.js.ast.JsDoWhile;
+import com.google.gwt.dev.js.ast.JsEmpty;
+import com.google.gwt.dev.js.ast.JsExprStmt;
+import com.google.gwt.dev.js.ast.JsExpression;
+import com.google.gwt.dev.js.ast.JsFor;
+import com.google.gwt.dev.js.ast.JsForIn;
+import com.google.gwt.dev.js.ast.JsFunction;
+import com.google.gwt.dev.js.ast.JsIf;
+import com.google.gwt.dev.js.ast.JsInvocation;
+import com.google.gwt.dev.js.ast.JsLabel;
+import com.google.gwt.dev.js.ast.JsName;
+import com.google.gwt.dev.js.ast.JsNameOf;
+import com.google.gwt.dev.js.ast.JsNameRef;
+import com.google.gwt.dev.js.ast.JsNew;
+import com.google.gwt.dev.js.ast.JsNode;
+import com.google.gwt.dev.js.ast.JsNullLiteral;
+import com.google.gwt.dev.js.ast.JsNumberLiteral;
+import com.google.gwt.dev.js.ast.JsObjectLiteral;
+import com.google.gwt.dev.js.ast.JsParameter;
+import com.google.gwt.dev.js.ast.JsPostfixOperation;
+import com.google.gwt.dev.js.ast.JsPrefixOperation;
+import com.google.gwt.dev.js.ast.JsProgram;
+import com.google.gwt.dev.js.ast.JsProgramFragment;
+import com.google.gwt.dev.js.ast.JsPropertyInitializer;
+import com.google.gwt.dev.js.ast.JsRegExp;
+import com.google.gwt.dev.js.ast.JsReturn;
+import com.google.gwt.dev.js.ast.JsSeedIdOf;
+import com.google.gwt.dev.js.ast.JsStatement;
+import com.google.gwt.dev.js.ast.JsStringLiteral;
+import com.google.gwt.dev.js.ast.JsSwitch;
+import com.google.gwt.dev.js.ast.JsSwitchMember;
+import com.google.gwt.dev.js.ast.JsThisRef;
+import com.google.gwt.dev.js.ast.JsThrow;
+import com.google.gwt.dev.js.ast.JsTry;
+import com.google.gwt.dev.js.ast.JsUnaryOperator;
+import com.google.gwt.dev.js.ast.JsVars;
+import com.google.gwt.dev.js.ast.JsVars.JsVar;
+import com.google.gwt.dev.js.ast.JsWhile;
+import com.google.gwt.dev.js.ast.NodeKind;
+import com.google.gwt.thirdparty.guava.common.base.Preconditions;
+import com.google.gwt.thirdparty.guava.common.collect.Sets;
+import com.google.gwt.thirdparty.javascript.jscomp.AstValidator;
+import com.google.gwt.thirdparty.javascript.rhino.IR;
+import com.google.gwt.thirdparty.javascript.rhino.InputId;
+import com.google.gwt.thirdparty.javascript.rhino.Node;
+import com.google.gwt.thirdparty.javascript.rhino.Token;
+import com.google.gwt.thirdparty.javascript.rhino.jstype.SimpleSourceFile;
+import com.google.gwt.thirdparty.javascript.rhino.jstype.StaticSourceFile;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Translate a Dart JS AST to a Closure Compiler AST.
+ */
+public class ClosureJsAstTranslator {
+  private static String getStringValue(double value) {
+    long longValue = (long) value;
+
+    // Return "1" instead of "1.0"
+    if (longValue == value) {
+      return Long.toString(longValue);
+    } else {
+      return Double.toString(value);
+    }
+  }
+
+  private final Map<String, StaticSourceFile> sourceCache = new HashMap<String, StaticSourceFile>();
+
+  private final boolean validate;
+  private final Set<String> globalVars = Sets.newHashSet();
+  private final Set<String> externalProperties = Sets.newHashSet();
+
+  private final Set<String> externalVars = Sets.newHashSet();
+
+  private final JsProgram program;
+
+  ClosureJsAstTranslator(boolean validate, JsProgram program) {
+    this.program = program;
+    this.validate = validate;
+  }
+
+  public Node translate(JsProgramFragment fragment, InputId inputId, String source) {
+    Node script = IR.script();
+    script.putBooleanProp(Node.SYNTHETIC_BLOCK_PROP, true);
+    script.setInputId(inputId);
+    script.putProp(Node.SOURCENAME_PROP, source);
+    script.setStaticSourceFile(getClosureSourceFile(source));
+    for (JsStatement s : fragment.getGlobalBlock().getStatements()) {
+      script.addChildToBack(transform(s));
+    }
+    // Validate the structural integrity of the AST.
+    if (validate) {
+      new AstValidator().validateScript(script);
+    }
+    return script;
+  }
+
+  Set<String> getExternalPropertyReferences() {
+    return externalProperties;
+  }
+
+  Set<String> getExternalVariableReferences() {
+    return externalVars;
+  }
+
+  Set<String> getGlobalVariableNames() {
+    return globalVars;
+  }
+
+  private Node applyOriginalName(Node n, JsNode x) {
+    /*
+     * if (x instanceof HasSymbol) { Symbol symbol = ((HasSymbol)x).getSymbol(); if (symbol != null)
+     * { String originalName = symbol.getOriginalSymbolName(); n.putProp(Node.ORIGINALNAME_PROP,
+     * originalName); } }
+     */
+    return n;
+  }
+
+  private Node applySourceInfo(Node n, HasSourceInfo srcNode) {
+    if (n != null && srcNode != null) {
+      SourceInfo info = srcNode.getSourceInfo();
+      if (info != null && info.getFileName() != null) {
+        n.setStaticSourceFile(getClosureSourceFile(info.getFileName()));
+        n.setLineno(info.getStartLine());
+        n.setCharno(0);
+      }
+    }
+    return n;
+  }
+
+  private StaticSourceFile getClosureSourceFile(String source) {
+    StaticSourceFile closureSourceFile = sourceCache.get(source);
+    if (closureSourceFile == null) {
+      closureSourceFile = new SimpleSourceFile(source, false);
+      sourceCache.put(source, closureSourceFile);
+    }
+    return closureSourceFile;
+  }
+
+  private String getName(JsName name) {
+    return name.getShortIdent();
+  }
+
+  private String getName(JsNameRef name) {
+    return name.getShortIdent();
+  }
+
+  private Node getNameNodeFor(HasName hasName) {
+    Node n = IR.name(getName(hasName.getName()));
+    applyOriginalName(n, (JsNode) hasName);
+    return applySourceInfo(n, (HasSourceInfo) hasName);
+  }
+
+  private int getTokenForOp(JsBinaryOperator op) {
+    switch (op) {
+      case MUL:
+        return Token.MUL;
+      case DIV:
+        return Token.DIV;
+      case MOD:
+        return Token.MOD;
+      case ADD:
+        return Token.ADD;
+      case SUB:
+        return Token.SUB;
+      case SHL:
+        return Token.LSH;
+      case SHR:
+        return Token.RSH;
+      case SHRU:
+        return Token.URSH;
+      case LT:
+        return Token.LT;
+      case LTE:
+        return Token.LE;
+      case GT:
+        return Token.GT;
+      case GTE:
+        return Token.GE;
+      case INSTANCEOF:
+        return Token.INSTANCEOF;
+      case INOP:
+        return Token.IN;
+      case EQ:
+        return Token.EQ;
+      case NEQ:
+        return Token.NE;
+      case REF_EQ:
+        return Token.SHEQ;
+      case REF_NEQ:
+        return Token.SHNE;
+      case BIT_AND:
+        return Token.BITAND;
+      case BIT_XOR:
+        return Token.BITXOR;
+      case BIT_OR:
+        return Token.BITOR;
+      case AND:
+        return Token.AND;
+      case OR:
+        return Token.OR;
+      case ASG:
+        return Token.ASSIGN;
+      case ASG_ADD:
+        return Token.ASSIGN_ADD;
+      case ASG_SUB:
+        return Token.ASSIGN_SUB;
+      case ASG_MUL:
+        return Token.ASSIGN_MUL;
+      case ASG_DIV:
+        return Token.ASSIGN_DIV;
+      case ASG_MOD:
+        return Token.ASSIGN_MOD;
+      case ASG_SHL:
+        return Token.ASSIGN_LSH;
+      case ASG_SHR:
+        return Token.ASSIGN_RSH;
+      case ASG_SHRU:
+        return Token.ASSIGN_URSH;
+      case ASG_BIT_AND:
+        return Token.ASSIGN_BITAND;
+      case ASG_BIT_OR:
+        return Token.ASSIGN_BITOR;
+      case ASG_BIT_XOR:
+        return Token.ASSIGN_BITXOR;
+      case COMMA:
+        return Token.COMMA;
+    }
+    return 0;
+  }
+
+  private int getTokenForOp(JsUnaryOperator op) {
+    switch (op) {
+      case BIT_NOT:
+        return Token.BITNOT;
+      case DEC:
+        return Token.DEC;
+      case DELETE:
+        return Token.DELPROP;
+      case INC:
+        return Token.INC;
+      case NEG:
+        return Token.NEG;
+      case POS:
+        return Token.POS;
+      case NOT:
+        return Token.NOT;
+      case TYPEOF:
+        return Token.TYPEOF;
+      case VOID:
+        return Token.VOID;
+    }
+    throw new IllegalStateException();
+  }
+
+  private Node transform(JsArrayAccess x) {
+    Node n = IR.getelem(transform(x.getArrayExpr()), transform(x.getIndexExpr()));
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsArrayLiteral x) {
+    Node n = IR.arraylit();
+    for (Object element : x.getExpressions()) {
+      JsExpression arg = (JsExpression) element;
+      n.addChildToBack(transform(arg));
+    }
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsBinaryOperation x) {
+    JsBinaryOperator op = x.getOperator();
+    Node n = new Node(getTokenForOp(op), transform(x.getArg1()), transform(x.getArg2()));
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsBlock x) {
+    Node n = IR.block();
+    for (JsStatement s : x.getStatements()) {
+      n.addChildToBack(transform(s));
+    }
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsBooleanLiteral x) {
+    Node n = x.getValue() ? IR.trueNode() : IR.falseNode();
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsBreak x) {
+    Node n;
+    JsNameRef label = x.getLabel();
+    if (label == null) {
+      n = IR.breakNode();
+    } else {
+      n = IR.breakNode(transformLabel(label));
+    }
+
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsCase x) {
+    Node expr = transform(x.getCaseExpr());
+    Node body = IR.block();
+    body.putBooleanProp(Node.SYNTHETIC_BLOCK_PROP, true);
+    applySourceInfo(body, x);
+
+    for (Object element : x.getStmts()) {
+      JsStatement stmt = (JsStatement) element;
+      body.addChildToBack(transform(stmt));
+    }
+
+    Node n = IR.caseNode(expr, body);
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsCatch x) {
+    Node n = IR.catchNode(transformName(x.getParameter().getName()), transform(x.getBody()));
+    Preconditions.checkState(x.getCondition() == null);
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsConditional x) {
+    Node n =
+        IR.hook(transform(x.getTestExpression()), transform(x.getThenExpression()), transform(x
+            .getElseExpression()));
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsContinue x) {
+    Node n;
+    JsNameRef label = x.getLabel();
+    if (label == null) {
+      n = IR.continueNode();
+    } else {
+      n = IR.continueNode(transformLabel(label));
+    }
+
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsDebugger x) {
+    Node n = new Node(Token.DEBUGGER);
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsDefault x) {
+    Node body = IR.block();
+    body.putBooleanProp(Node.SYNTHETIC_BLOCK_PROP, true);
+    applySourceInfo(body, x);
+
+    for (Object element : x.getStmts()) {
+      JsStatement stmt = (JsStatement) element;
+      body.addChildToBack(transform(stmt));
+    }
+    Node n = IR.defaultCase(body);
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsDoWhile x) {
+    Node n = IR.doNode(transformBody(x.getBody(), x), transform(x.getCondition()));
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsEmpty x) {
+    return IR.empty();
+  }
+
+  private Node transform(JsExpression x) {
+    assert x != null;
+    switch (x.getKind()) {
+      case ARRAY:
+        return transform((JsArrayLiteral) x);
+      case ARRAY_ACCESS:
+        return transform((JsArrayAccess) x);
+      case BINARY_OP:
+        return transform((JsBinaryOperation) x);
+      case CONDITIONAL:
+        return transform((JsConditional) x);
+      case INVOKE:
+        return transform((JsInvocation) x);
+      case FUNCTION:
+        return transform((JsFunction) x);
+      case OBJECT:
+        return transform((JsObjectLiteral) x);
+      case BOOLEAN:
+        return transform((JsBooleanLiteral) x);
+      case NULL:
+        return transform((JsNullLiteral) x);
+      case NUMBER:
+        return transform((JsNumberLiteral) x);
+      case REGEXP:
+        return transform((JsRegExp) x);
+      case STRING:
+        return transform((JsStringLiteral) x);
+      case THIS:
+        return transform((JsThisRef) x);
+      case NAME_OF:
+        return transform((JsNameOf) x);
+      case SEED_ID_OF:
+        return transform((JsSeedIdOf) x);
+      case NAME_REF:
+        return transform((JsNameRef) x);
+      case NEW:
+        return transform((JsNew) x);
+      case POSTFIX_OP:
+        return transform((JsPostfixOperation) x);
+      case PREFIX_OP:
+        return transform((JsPrefixOperation) x);
+      default:
+        throw new IllegalStateException("Unexpected expression type: "
+            + x.getClass().getSimpleName());
+    }
+  }
+
+  private Node transform(JsExprStmt x) {
+    // The GWT JS AST doesn't produce function declarations, instead
+    // they are expressions statements:
+    Node expr = transform(x.getExpression());
+    if (!expr.isFunction()) {
+      return IR.exprResult(expr);
+    } else {
+      return expr;
+    }
+  }
+
+  private Node transform(JsFor x) {
+    // The init expressions or var decl.
+    //
+    Node init;
+    if (x.getInitExpr() != null) {
+      init = transform(x.getInitExpr());
+    } else if (x.getInitVars() != null) {
+      init = transform(x.getInitVars());
+    } else {
+      init = IR.empty();
+    }
+
+    // The loop test.
+    //
+    Node cond;
+    if (x.getCondition() != null) {
+      cond = transform(x.getCondition());
+    } else {
+      cond = IR.empty();
+    }
+
+    // The incr expression.
+    //
+    Node incr;
+    if (x.getIncrExpr() != null) {
+      incr = transform(x.getIncrExpr());
+    } else {
+      incr = IR.empty();
+    }
+
+    Node body = transformBody(x.getBody(), x);
+    Node n = IR.forNode(init, cond, incr, body);
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsForIn x) {
+    Node valueExpr;
+    if (x.getIterVarName() != null) {
+      valueExpr = new Node(Token.VAR, transformName(x.getIterVarName()));
+    } else {
+      // Just a name ref.
+      //
+      valueExpr = transform(x.getIterExpr());
+    }
+
+    Node n = IR.forIn(valueExpr, transform(x.getObjExpr()), transformBody(x.getBody(), x));
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsFunction x) {
+    Node name;
+    if (x.getName() != null) {
+      name = getNameNodeFor(x);
+    } else {
+      name = IR.name("");
+    }
+    applySourceInfo(name, x);
+
+    Node params = IR.paramList();
+    for (Object element : x.getParameters()) {
+      JsParameter param = (JsParameter) element;
+      params.addChildToBack(transform(param));
+    }
+    applySourceInfo(params, x);
+
+    Node n = IR.function(name, params, transform(x.getBody()));
+    if (name.getString().isEmpty()) {
+      n.putProp(Node.ORIGINALNAME_PROP, "");
+    } else {
+      applyOriginalName(n, x);
+    }
+
+    /*
+     * if (x.isConstructor()) { JSDocInfoBuilder builder = new JSDocInfoBuilder(false);
+     * builder.recordConstructor(); n.setJSDocInfo(builder.build(n)); }
+     */
+
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsIf x) {
+    Node n = IR.ifNode(transform(x.getIfExpr()), transformBody(x.getThenStmt(), x));
+    if (x.getElseStmt() != null) {
+      n.addChildToBack(transformBody(x.getElseStmt(), x));
+    }
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsInvocation x) {
+    Node n = IR.call(transform(x.getQualifier()));
+    for (Object element : x.getArguments()) {
+      JsExpression arg = (JsExpression) element;
+      n.addChildToBack(transform(arg));
+    }
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsLabel x) {
+    Node n = IR.label(transformLabel(x.getName()), transform(x.getStmt()));
+
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsNameOf x) {
+    Node n = transformName(x.getName().getShortIdent(), x);
+    applyOriginalName(n, x);
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsNameRef x) {
+    Node n;
+    JsName name = x.getName();
+    boolean isExternal = name == null || !name.isObfuscatable();
+    if (x.getQualifier() != null) {
+      n = IR.getprop(transform(x.getQualifier()), transformNameAsString(x.getShortIdent(), x));
+      if (isExternal) {
+        this.externalProperties.add(x.getShortIdent());
+      }
+    } else {
+      n = transformName(x.getShortIdent(), x);
+      if (isExternal) {
+        this.externalVars.add(x.getShortIdent());
+      } else if (name.getEnclosing() == program.getScope()) {
+        this.globalVars.add(x.getShortIdent());
+      }
+    }
+    applyOriginalName(n, x);
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsNew x) {
+    Node n = IR.newNode(transform(x.getConstructorExpression()));
+    for (Object element : x.getArguments()) {
+      JsExpression arg = (JsExpression) element;
+      n.addChildToBack(transform(arg));
+    }
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsNullLiteral x) {
+    return IR.nullNode();
+  }
+
+  private Node transform(JsNumberLiteral x) {
+    return IR.number(x.getValue());
+  }
+
+  private Node transform(JsObjectLiteral x) {
+    Node n = IR.objectlit();
+
+    for (Object element : x.getPropertyInitializers()) {
+      JsPropertyInitializer propInit = (JsPropertyInitializer) element;
+      Node key;
+      if (propInit.getLabelExpr().getKind() == NodeKind.NUMBER) {
+        key = transformNumberAsString((JsNumberLiteral) propInit.getLabelExpr());
+        key.putBooleanProp(Node.QUOTED_PROP, true);
+      } else if (propInit.getLabelExpr().getKind() == NodeKind.NAME_REF) {
+        key =
+            transformNameAsString(((JsNameRef) propInit.getLabelExpr()).getShortIdent(), propInit
+                .getLabelExpr());
+      } else {
+        key = transform(propInit.getLabelExpr());
+      }
+      Preconditions.checkState(key.isString(), key);
+      n.addChildToBack(IR.propdef(key, transform(propInit.getValueExpr())));
+    }
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsParameter x) {
+    return getNameNodeFor(x);
+  }
+
+  private Node transform(JsPostfixOperation x) {
+    Node n = new Node(getTokenForOp(x.getOperator()), transform(x.getArg()));
+    n.putBooleanProp(Node.INCRDECR_PROP, true);
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsPrefixOperation x) {
+    Node n = new Node(getTokenForOp(x.getOperator()), transform(x.getArg()));
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsRegExp x) {
+    String flags = x.getFlags();
+    Node n =
+        IR.regexp(Node.newString(x.getPattern()), Node.newString(flags != null ? x.getFlags() : ""));
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsReturn x) {
+    Node n = IR.returnNode();
+    JsExpression result = x.getExpr();
+    if (result != null) {
+      n.addChildToBack(transform(x.getExpr()));
+    }
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsSeedIdOf x) {
+    Node n = Node.newNumber(x.getSeedId());
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsStatement x) {
+    switch (x.getKind()) {
+      case BLOCK:
+        return transform((JsBlock) x);
+      case BREAK:
+        return transform((JsBreak) x);
+      case CONTINUE:
+        return transform((JsContinue) x);
+      case DEBUGGER:
+        return transform((JsDebugger) x);
+      case DO:
+        return transform((JsDoWhile) x);
+      case EMPTY:
+        return transform((JsEmpty) x);
+      case EXPR_STMT:
+        return transform((JsExprStmt) x);
+      case FOR:
+        return transform((JsFor) x);
+      case FOR_IN:
+        return transform((JsForIn) x);
+      case IF:
+        return transform((JsIf) x);
+      case LABEL:
+        return transform((JsLabel) x);
+      case RETURN:
+        return transform((JsReturn) x);
+      case SWITCH:
+        return transform((JsSwitch) x);
+      case THROW:
+        return transform((JsThrow) x);
+      case TRY:
+        return transform((JsTry) x);
+      case VARS:
+        return transform((JsVars) x);
+      case WHILE:
+        return transform((JsWhile) x);
+      default:
+        throw new IllegalStateException("Unexpected statement type: "
+            + x.getClass().getSimpleName());
+    }
+  }
+
+  private Node transform(JsStringLiteral x) {
+    return IR.string(x.getValue());
+  }
+
+  private Node transform(JsSwitch x) {
+    Node n = IR.switchNode(transform(x.getExpr()));
+    for (JsSwitchMember member : x.getCases()) {
+      n.addChildToBack(transform(member));
+    }
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsSwitchMember x) {
+    switch (x.getKind()) {
+      case CASE:
+        return transform((JsCase) x);
+      case DEFAULT:
+        return transform((JsDefault) x);
+      default:
+        throw new IllegalStateException("Unexpected switch member type: "
+            + x.getClass().getSimpleName());
+    }
+  }
+
+  private Node transform(JsThisRef x) {
+    Node n = new Node(Token.THIS);
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsThrow x) {
+    Node n = IR.throwNode(transform(x.getExpr()));
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsTry x) {
+    Node n = new Node(Token.TRY, transform(x.getTryBlock()));
+
+    Node catches = new Node(Token.BLOCK);
+    for (JsCatch catchBlock : x.getCatches()) {
+      catches.addChildToBack(transform(catchBlock));
+    }
+    n.addChildToBack(catches);
+
+    JsBlock finallyBlock = x.getFinallyBlock();
+    if (finallyBlock != null) {
+      n.addChildToBack(transform(finallyBlock));
+    }
+
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsVar x) {
+    Node n = getNameNodeFor(x);
+    JsExpression initExpr = x.getInitExpr();
+    if (initExpr != null) {
+      n.addChildToBack(transform(initExpr));
+    }
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsVars x) {
+    Node n = new Node(Token.VAR);
+    for (JsVar var : x) {
+      n.addChildToBack(transform(var));
+    }
+    return applySourceInfo(n, x);
+  }
+
+  private Node transform(JsWhile x) {
+    Node n =
+        IR.forNode(IR.empty(), transform(x.getCondition()), IR.empty(), transformBody(x.getBody(),
+            x));
+    return applySourceInfo(n, x);
+  }
+
+  private Node transformBody(JsStatement x, HasSourceInfo parent) {
+    Node n = transform(x);
+    if (!n.isBlock()) {
+      Node stmt = n;
+      n = IR.block();
+      if (!stmt.isEmpty()) {
+        n.addChildToBack(stmt);
+      }
+      applySourceInfo(n, parent);
+    }
+    return n;
+  }
+
+  private Node transformLabel(JsName label) {
+    Node n = IR.labelName(getName(label));
+    return applySourceInfo(n, label.getStaticRef());
+  }
+
+  private Node transformLabel(JsNameRef label) {
+    Node n = IR.labelName(getName(label));
+    return applySourceInfo(n, label);
+  }
+
+  private Node transformName(JsName name) {
+    Node n = IR.name(getName(name));
+    return applySourceInfo(n, name.getStaticRef());
+  }
+
+  private Node transformName(String name, HasSourceInfo info) {
+    Node n = IR.name(name);
+    return applySourceInfo(n, info);
+  }
+
+  private Node transformNameAsString(String name, HasSourceInfo info) {
+    Node n = IR.string(name);
+    return applySourceInfo(n, info);
+  }
+
+  private Node transformNumberAsString(JsNumberLiteral literalNode) {
+    Node irNode = Node.newString(getStringValue(literalNode.getValue()));
+    return irNode;
+  }
+}
diff --git a/dev/core/src/com/google/gwt/dev/js/ClosureJsRunner.java b/dev/core/src/com/google/gwt/dev/js/ClosureJsRunner.java
new file mode 100644
index 0000000..2bef925
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/js/ClosureJsRunner.java
@@ -0,0 +1,350 @@
+/*
+ * Copyright 2011 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.dev.js;
+
+import com.google.gwt.dev.jjs.JsOutputOption;
+import com.google.gwt.dev.js.ast.JsProgram;
+import com.google.gwt.dev.js.ast.JsProgramFragment;
+import com.google.gwt.thirdparty.guava.common.base.Preconditions;
+import com.google.gwt.thirdparty.guava.common.base.Throwables;
+import com.google.gwt.thirdparty.guava.common.collect.ImmutableList;
+import com.google.gwt.thirdparty.guava.common.collect.Lists;
+import com.google.gwt.thirdparty.guava.common.collect.Maps;
+import com.google.gwt.thirdparty.guava.common.collect.Sets;
+import com.google.gwt.thirdparty.guava.common.io.LimitInputStream;
+import com.google.gwt.thirdparty.javascript.jscomp.CheckLevel;
+import com.google.gwt.thirdparty.javascript.jscomp.Compiler;
+import com.google.gwt.thirdparty.javascript.jscomp.CompilerInput;
+import com.google.gwt.thirdparty.javascript.jscomp.CompilerOptions;
+import com.google.gwt.thirdparty.javascript.jscomp.CompilerOptions.Reach;
+import com.google.gwt.thirdparty.javascript.jscomp.DiagnosticGroups;
+import com.google.gwt.thirdparty.javascript.jscomp.JSError;
+import com.google.gwt.thirdparty.javascript.jscomp.JSModule;
+import com.google.gwt.thirdparty.javascript.jscomp.JSSourceFile;
+import com.google.gwt.thirdparty.javascript.jscomp.PropertyRenamingPolicy;
+import com.google.gwt.thirdparty.javascript.jscomp.Result;
+import com.google.gwt.thirdparty.javascript.jscomp.SourceAst;
+import com.google.gwt.thirdparty.javascript.jscomp.VariableMap;
+import com.google.gwt.thirdparty.javascript.jscomp.VariableRenamingPolicy;
+import com.google.gwt.thirdparty.javascript.jscomp.WarningLevel;
+import com.google.gwt.thirdparty.javascript.rhino.InputId;
+import com.google.gwt.thirdparty.javascript.rhino.Node;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+/**
+ * A wrapper to simplify the interactions to the Closure Compiler
+ */
+public class ClosureJsRunner {
+  // The externs expected in externs.zip, in sorted order.
+  private static final List<String> DEFAULT_EXTERNS_NAMES = ImmutableList.of(
+      // JS externs
+      "es3.js",
+      "es5.js",
+
+      // Event APIs
+      "w3c_event.js", "w3c_event3.js",
+      "gecko_event.js",
+      "ie_event.js",
+      "webkit_event.js",
+
+      // DOM apis
+      "w3c_dom1.js", "w3c_dom2.js", "w3c_dom3.js",
+      "gecko_dom.js",
+      "ie_dom.js",
+      "webkit_dom.js",
+
+      // CSS apis
+      "w3c_css.js",
+      "gecko_css.js",
+      "ie_css.js",
+      "webkit_css.js",
+
+      // Top-level namespaces
+      "google.js",
+
+      "deprecated.js", "fileapi.js", "flash.js", "gears_symbols.js", "gears_types.js",
+      "gecko_xml.js", "html5.js", "ie_vml.js", "iphone.js", "webstorage.js", "w3c_anim_timing.js",
+      "w3c_css3d.js", "w3c_elementtraversal.js", "w3c_geolocation.js", "w3c_indexeddb.js",
+      "w3c_navigation_timing.js", "w3c_range.js", "w3c_selectors.js", "w3c_xml.js", "window.js",
+      "webkit_notifications.js", "webgl.js");
+
+  /**
+   * @return a mutable list
+   * @throws IOException
+   */
+  public static List<JSSourceFile> getDefaultExterns() throws IOException {
+    Class<ClosureJsRunner> clazz = ClosureJsRunner.class;
+    InputStream input = clazz.getResourceAsStream("/com/google/javascript/jscomp/externs.zip");
+    if (input == null) {
+      /*
+       * HACK - the open source version of the closure compiler maps the resource into a different
+       * location.
+       */
+      input = clazz.getResourceAsStream("/externs.zip");
+    }
+    ZipInputStream zip = new ZipInputStream(input);
+    Map<String, JSSourceFile> externsMap = Maps.newHashMap();
+    for (ZipEntry entry = null; (entry = zip.getNextEntry()) != null;) {
+      BufferedInputStream entryStream =
+          new BufferedInputStream(new LimitInputStream(zip, entry.getSize()));
+      externsMap.put(entry.getName(), JSSourceFile.fromInputStream(
+      // Give the files an odd prefix, so that they do not conflict
+      // with the user's files.
+          "externs.zip//" + entry.getName(), entryStream));
+    }
+
+    Preconditions.checkState(externsMap.keySet().equals(Sets.newHashSet(DEFAULT_EXTERNS_NAMES)),
+        "Externs zip must match our hard-coded list of externs.");
+
+    // Order matters, so the resources must be added to the result list
+    // in the expected order.
+    List<JSSourceFile> externs = Lists.newArrayList();
+    for (String key : DEFAULT_EXTERNS_NAMES) {
+      externs.add(externsMap.get(key));
+    }
+
+    return externs;
+  }
+
+  private Compiler compiler = null;
+  private Set<String> externalProps = Sets.newHashSet();
+  private Set<String> externalVars = Sets.newHashSet();
+
+  private Set<String> globalVars = Sets.newHashSet();
+
+  private final boolean validate = true;
+
+  public ClosureJsRunner() {
+  }
+
+  public void compile(JsProgram program, String[] js, JsOutputOption jsOutputOption) {
+    CompilerOptions options = getClosureCompilerOptions(jsOutputOption);
+    // Turn off Closure Compiler logging
+    Logger.getLogger("com.google.gwt.thirdparty.javascript.jscomp").setLevel(Level.OFF);
+
+    // Create a fresh compiler instance.
+    compiler = new Compiler();
+
+    // Translate the ASTs and build the modules
+    List<JSModule> modules = createClosureModules(program);
+
+    // Build the externs based on what we discovered building the modules.
+    List<JSSourceFile> externs = getClosureCompilerExterns();
+
+    Result result = compiler.compileModules(externs, modules, options);
+    if (result.success) {
+      int fragments = program.getFragmentCount();
+      for (int i = 0; i < fragments; i++) {
+        int module = mapFragmentIndexToModuleIndex(fragments, i);
+        js[i] = compiler.toSource(modules.get(module));
+      }
+    } else {
+      for (JSError error : result.errors) {
+        System.err.println("error optimizing:" + error.toString());
+        throw new RuntimeException(error.description);
+      }
+    }
+  }
+
+  protected List<JSSourceFile> getDefaultExternsList() {
+    List<JSSourceFile> defaultExterns;
+    try {
+      defaultExterns = getDefaultExterns();
+      return defaultExterns;
+    } catch (IOException e) {
+      Throwables.propagate(e);
+      return null;
+    }
+  }
+
+  private CompilerInput createClosureJsAst(JsProgram program, JsProgramFragment fragment,
+      String source) {
+    String inputName = source;
+    InputId inputId = new InputId(inputName);
+    ClosureJsAstTranslator translator = new ClosureJsAstTranslator(validate, program);
+    Node root = translator.translate(fragment, inputId, source);
+    globalVars.addAll(translator.getGlobalVariableNames());
+    externalProps.addAll(translator.getExternalPropertyReferences());
+    externalVars.addAll(translator.getExternalVariableReferences());
+    SourceAst sourceAst = new ClosureJsAst(inputId, root);
+    CompilerInput input = new CompilerInput(sourceAst, false);
+    return input;
+  }
+
+  private JSModule createClosureModule(JsProgram program, JsProgramFragment fragment, String source) {
+    JSModule module = new JSModule(source);
+    module.add(createClosureJsAst(program, fragment, source));
+    return module;
+  }
+
+  private List<JSModule> createClosureModules(JsProgram program) {
+    int fragments = program.getFragmentCount();
+    JSModule[] modules = new JSModule[fragments];
+
+    for (int i = 0; i < fragments; i++) {
+      modules[mapFragmentIndexToModuleIndex(fragments, i)] =
+          createClosureModule(program, program.getFragment(i), "module" + i);
+    }
+    if (fragments > 1) {
+      //
+      // The fragments are expected in a specific order:
+      // init, split-1, split-2, ...,
+      // where the leftovers are dependent on the init module
+      // and the split modules are dependent on the leftovers
+      JSModule init = modules[0];
+      JSModule leftovers = modules[1];
+      leftovers.addDependency(init);
+      for (int i = 2; i < modules.length; i++) {
+        Preconditions.checkNotNull(modules[i], "Module: ", i);
+        modules[i].addDependency(leftovers);
+      }
+    }
+    modules[0].add(JSSourceFile.fromCode("hack", "window['gwtOnLoad'] = gwtOnLoad;\n"));
+
+    return Arrays.asList(modules);
+  }
+
+  private List<JSSourceFile> getClosureCompilerExterns() {
+    List<JSSourceFile> externs = getDefaultExternsList();
+    externs.add(JSSourceFile.fromCode("gwt_externs",
+
+    "var gwtOnLoad;\n" + "var $entry;\n" + "    var $gwt_version;\n" + "    var $wnd;\n"
+        + "    var $doc;\n" + "    var $moduleName\n" + "    var $moduleBase;\n"
+        + "    var $strongName;\n" + "    var $stats;\n" + "    var $sessionId;\n"
+        + "    window.prototype.__gwtStatsEvent;\n" + "    window.prototype.__gwtStatsSessionId;\n"
+        + "    window.prototype.moduleName;\n" + "    window.prototype.sessionId;\n"
+        + "    window.prototype.subSystem;\n" + "    window.prototype.evtGroup;\n"
+        + "    window.prototype.millis;\n" + "    window.prototype.type;\n"
+        + "    window.prototype.$h;\n" + "\n"));
+
+    // Generate externs
+    String generatedExterns = "var gwt_externs;\n";
+    for (String prop : this.externalProps) {
+      generatedExterns += "gwt_externs." + prop + ";\n";
+    }
+
+    for (String var : this.externalVars) {
+      generatedExterns += "var " + var + ";\n";
+    }
+
+    externs.add(JSSourceFile.fromCode("gwt_generated_externs", generatedExterns));
+
+    return externs;
+  }
+
+  private CompilerOptions getClosureCompilerOptions(JsOutputOption jsOutputOption) {
+    CompilerOptions options = new CompilerOptions();
+    WarningLevel.QUIET.setOptionsForWarningLevel(options);
+
+    // Basically, use CompilationLevel.ADVANCED_OPTIMIZATIONS:
+
+    // Build an identity map of variable names to prevent GWT names from
+    // being renamed while allowing new global variables to be renamed.
+    HashMap<String, String> varNames = new HashMap<String, String>();
+    for (String var : globalVars) {
+      varNames.put(var, var);
+    }
+    options.inputVariableMapSerialized = VariableMap.fromMap(varNames).toBytes();
+    if (jsOutputOption == JsOutputOption.OBFUSCATED) {
+      options.setRenamingPolicy(VariableRenamingPolicy.ALL, PropertyRenamingPolicy.OFF);
+      options.prettyPrint = false;
+      // This can help debug renaming policy changes.
+      // options.generatePseudoNames = true;
+    } else {
+      options.setRenamingPolicy(VariableRenamingPolicy.OFF, PropertyRenamingPolicy.OFF);
+      options.prettyPrint = true;
+    }
+
+    // All the safe optimizations.
+    options.closurePass = true;
+    options.foldConstants = true;
+    options.coalesceVariableNames = true;
+    options.deadAssignmentElimination = true;
+    options.extractPrototypeMemberDeclarations = true;
+    options.collapseVariableDeclarations = true;
+    options.convertToDottedProperties = true;
+    options.rewriteFunctionExpressions = true;
+    options.labelRenaming = true;
+    options.removeDeadCode = true;
+    options.optimizeArgumentsArray = true;
+    options.collapseObjectLiterals = true;
+    options.setShadowVariables(true);
+
+    // All the advance optimizations.
+    options.reserveRawExports = true;
+    options.removeUnusedPrototypeProperties = true;
+    options.collapseAnonymousFunctions = true;
+    options.smartNameRemoval = true; // ?
+    options.inlineConstantVars = true;
+    options.setInlineFunctions(Reach.ALL);
+    options.inlineGetters = true;
+    options.setInlineVariables(Reach.ALL);
+    options.flowSensitiveInlineVariables = true;
+    options.computeFunctionSideEffects = true;
+    // Remove unused vars also removes unused functions.
+    options.setRemoveUnusedVariable(Reach.ALL);
+    options.optimizeParameters = true;
+    options.optimizeReturns = true;
+    options.optimizeCalls = true;
+
+    // Maybe turn these off as well
+    options.collapseProperties = true; // ?
+    options.crossModuleCodeMotion = true; // ?
+    options.crossModuleMethodMotion = true; // ?
+    options.devirtualizePrototypeMethods = true; // ?
+
+    // Advanced optimization, disabled
+    options.setRemoveClosureAsserts(false);
+    options.aliasKeywords = false;
+    options.removeUnusedPrototypePropertiesInExterns = false;
+    options.checkGlobalThisLevel = CheckLevel.OFF;
+    options.rewriteFunctionExpressions = false; // Performance hit
+
+    // Kindly tell the user that they have JsDocs that we don't understand.
+    options.setWarningLevel(DiagnosticGroups.NON_STANDARD_JSDOC, CheckLevel.OFF);
+
+    return options;
+  }
+
+  private int mapFragmentIndexToModuleIndex(int fragments, int index) {
+    //
+    // The fragments are expected in a specific order:
+    // init, split-1, split-2, ...,
+    // where the leftovers are dependent on the init module
+    // and the split modules are dependent on the leftovers
+    //
+    // However, Closure Compiler modules must be in dependency order
+    //
+    if (index == 0) {
+      return 0;
+    } else if (index == fragments - 1) {
+      return 1;
+    } else {
+      return index + 1;
+    }
+  }
+}
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/CanBooleanEval.java b/dev/core/src/com/google/gwt/dev/js/ast/CanBooleanEval.java
index b42b3ee..2ce408d 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/CanBooleanEval.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/CanBooleanEval.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/HasArguments.java b/dev/core/src/com/google/gwt/dev/js/ast/HasArguments.java
index 8e4122f..c58477e 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/HasArguments.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/HasArguments.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2007 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/HasCondition.java b/dev/core/src/com/google/gwt/dev/js/ast/HasCondition.java
index fd21feb..2d49acf 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/HasCondition.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/HasCondition.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2007 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/HasName.java b/dev/core/src/com/google/gwt/dev/js/ast/HasName.java
index 86853a1..86273cb 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/HasName.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/HasName.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2007 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsArrayAccess.java b/dev/core/src/com/google/gwt/dev/js/ast/JsArrayAccess.java
index 5ab9e27..368a591 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsArrayAccess.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsArrayAccess.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -30,8 +28,7 @@
     super(sourceInfo);
   }
 
-  public JsArrayAccess(SourceInfo sourceInfo, JsExpression arrayExpr,
-      JsExpression indexExpr) {
+  public JsArrayAccess(SourceInfo sourceInfo, JsExpression arrayExpr, JsExpression indexExpr) {
     super(sourceInfo);
     this.arrayExpr = arrayExpr;
     this.indexExpr = indexExpr;
@@ -46,6 +43,11 @@
   }
 
   @Override
+  public NodeKind getKind() {
+    return NodeKind.ARRAY_ACCESS;
+  }
+
+  @Override
   public boolean hasSideEffects() {
     return arrayExpr.hasSideEffects() || indexExpr.hasSideEffects();
   }
@@ -68,6 +70,7 @@
     this.indexExpr = indexExpr;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       arrayExpr = v.accept(arrayExpr);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsArrayLiteral.java b/dev/core/src/com/google/gwt/dev/js/ast/JsArrayLiteral.java
index 8c83b23..dc04ee0 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsArrayLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsArrayLiteral.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -36,6 +34,11 @@
   }
 
   @Override
+  public NodeKind getKind() {
+    return NodeKind.ARRAY;
+  }
+
+  @Override
   public boolean hasSideEffects() {
     for (JsExpression expr : exprs) {
       if (expr.hasSideEffects()) {
@@ -45,10 +48,12 @@
     return false;
   }
 
+  @Override
   public boolean isBooleanFalse() {
     return false;
   }
 
+  @Override
   public boolean isBooleanTrue() {
     return true;
   }
@@ -63,6 +68,7 @@
     return false;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       v.acceptWithInsertRemove(exprs);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsBinaryOperation.java b/dev/core/src/com/google/gwt/dev/js/ast/JsBinaryOperation.java
index 6018e3a..2cfb1d7 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsBinaryOperation.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsBinaryOperation.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -32,8 +30,8 @@
     this(sourceInfo, op, null, null);
   }
 
-  public JsBinaryOperation(SourceInfo sourceInfo, JsBinaryOperator op,
-      JsExpression arg1, JsExpression arg2) {
+  public JsBinaryOperation(SourceInfo sourceInfo, JsBinaryOperator op, JsExpression arg1,
+      JsExpression arg2) {
     super(sourceInfo);
     this.op = op;
     this.arg1 = arg1;
@@ -48,6 +46,11 @@
     return arg2;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.BINARY_OP;
+  }
+
   public JsBinaryOperator getOperator() {
     return op;
   }
@@ -104,6 +107,7 @@
     this.arg2 = arg2;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       if (op.isAssignment()) {
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsBinaryOperator.java b/dev/core/src/com/google/gwt/dev/js/ast/JsBinaryOperator.java
index 5cac60d..36c4689 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsBinaryOperator.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsBinaryOperator.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -21,30 +19,25 @@
 public enum JsBinaryOperator implements JsOperator {
 
   /*
-   * Precedence indices from "JavaScript - The Definitive Guide" 4th Edition
-   * (page 57)
+   * Precedence indices from "JavaScript - The Definitive Guide" 4th Edition (page 57)
    * 
    * 
-   * Precedence 15 is for really important things that have their own AST
-   * classes.
+   * Precedence 15 is for really important things that have their own AST classes.
    * 
    * Precedence 14 is for unary operators.
    */
 
-  MUL("*", 13, LEFT | INFIX), DIV("/", 13, LEFT | INFIX), MOD("%", 13, LEFT
-      | INFIX),
+  MUL("*", 13, LEFT | INFIX), DIV("/", 13, LEFT | INFIX), MOD("%", 13, LEFT | INFIX),
 
   ADD("+", 12, LEFT | INFIX), SUB("-", 12, LEFT | INFIX),
 
-  SHL("<<", 11, LEFT | INFIX), SHR(">>", 11, LEFT | INFIX), SHRU(">>>", 11,
-      LEFT | INFIX),
+  SHL("<<", 11, LEFT | INFIX), SHR(">>", 11, LEFT | INFIX), SHRU(">>>", 11, LEFT | INFIX),
 
-  LT("<", 10, LEFT | INFIX), LTE("<=", 10, LEFT | INFIX), GT(">", 10, LEFT
-      | INFIX), GTE(">=", 10, LEFT | INFIX), INSTANCEOF("instanceof", 10, LEFT
-      | INFIX), INOP("in", 10, LEFT | INFIX),
+  LT("<", 10, LEFT | INFIX), LTE("<=", 10, LEFT | INFIX), GT(">", 10, LEFT | INFIX), GTE(">=", 10,
+      LEFT | INFIX), INSTANCEOF("instanceof", 10, LEFT | INFIX), INOP("in", 10, LEFT | INFIX),
 
-  EQ("==", 9, LEFT | INFIX), NEQ("!=", 9, LEFT | INFIX), REF_EQ("===", 9, LEFT
-      | INFIX), REF_NEQ("!==", 9, LEFT | INFIX),
+  EQ("==", 9, LEFT | INFIX), NEQ("!=", 9, LEFT | INFIX), REF_EQ("===", 9, LEFT | INFIX), REF_NEQ(
+      "!==", 9, LEFT | INFIX),
 
   BIT_AND("&", 8, LEFT | INFIX),
 
@@ -59,10 +52,10 @@
   // Precedence 3 is for the condition operator.
 
   // These assignment operators are right-associative.
-  ASG("=", 2, INFIX), ASG_ADD("+=", 2, INFIX), ASG_SUB("-=", 2, INFIX), ASG_MUL(
-      "*=", 2, INFIX), ASG_DIV("/=", 2, INFIX), ASG_MOD("%=", 2, INFIX), ASG_SHL(
-      "<<=", 2, INFIX), ASG_SHR(">>=", 2, INFIX), ASG_SHRU(">>>=", 2, INFIX), ASG_BIT_AND(
-      "&=", 2, INFIX), ASG_BIT_OR("|=", 2, INFIX), ASG_BIT_XOR("^=", 2, INFIX),
+  ASG("=", 2, INFIX), ASG_ADD("+=", 2, INFIX), ASG_SUB("-=", 2, INFIX), ASG_MUL("*=", 2, INFIX), ASG_DIV(
+      "/=", 2, INFIX), ASG_MOD("%=", 2, INFIX), ASG_SHL("<<=", 2, INFIX), ASG_SHR(">>=", 2, INFIX), ASG_SHRU(
+      ">>>=", 2, INFIX), ASG_BIT_AND("&=", 2, INFIX), ASG_BIT_OR("|=", 2, INFIX), ASG_BIT_XOR("^=",
+      2, INFIX),
 
   COMMA(",", 1, LEFT | INFIX);
 
@@ -78,42 +71,49 @@
     this.mask = mask;
   }
 
+  @Override
   public int getPrecedence() {
     return precedence;
   }
 
+  @Override
   public String getSymbol() {
     return symbol;
   }
 
   public boolean isAssignment() {
     /*
-     * Beware, flaky! Maybe I should have added Yet Another Field to
-     * BinaryOperator?
+     * Beware, flaky! Maybe I should have added Yet Another Field to BinaryOperator?
      */
     return (getPrecedence() == ASG.getPrecedence());
   }
 
+  @Override
   public boolean isKeyword() {
     return this == INSTANCEOF || this == INOP;
   }
 
+  @Override
   public boolean isLeftAssociative() {
     return (mask & LEFT) != 0;
   }
 
+  @Override
   public boolean isPrecedenceLessThan(JsOperator other) {
     return precedence < other.getPrecedence();
   }
 
+  @Override
   public boolean isValidInfix() {
     return (mask & INFIX) != 0;
   }
 
+  @Override
   public boolean isValidPostfix() {
     return (mask & POSTFIX) != 0;
   }
 
+  @Override
   public boolean isValidPrefix() {
     return (mask & PREFIX) != 0;
   }
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsBlock.java b/dev/core/src/com/google/gwt/dev/js/ast/JsBlock.java
index e7de0ed..fc95ff4 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsBlock.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsBlock.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -31,6 +29,11 @@
     super(sourceInfo);
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.BLOCK;
+  }
+
   public List<JsStatement> getStatements() {
     return stmts;
   }
@@ -39,6 +42,7 @@
     return false;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       v.acceptWithInsertRemove(stmts);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsBooleanLiteral.java b/dev/core/src/com/google/gwt/dev/js/ast/JsBooleanLiteral.java
index 24fc9c1..9545e0b 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsBooleanLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsBooleanLiteral.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -23,11 +21,9 @@
  */
 public final class JsBooleanLiteral extends JsValueLiteral {
 
-  public static final JsBooleanLiteral FALSE = new JsBooleanLiteral(
-      SourceOrigin.UNKNOWN, false);
+  public static final JsBooleanLiteral FALSE = new JsBooleanLiteral(SourceOrigin.UNKNOWN, false);
 
-  public static final JsBooleanLiteral TRUE = new JsBooleanLiteral(
-      SourceOrigin.UNKNOWN, true);
+  public static final JsBooleanLiteral TRUE = new JsBooleanLiteral(SourceOrigin.UNKNOWN, true);
 
   public static JsBooleanLiteral get(boolean value) {
     return value ? TRUE : FALSE;
@@ -40,14 +36,21 @@
     this.value = value;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.BOOLEAN;
+  }
+
   public boolean getValue() {
     return value;
   }
 
+  @Override
   public boolean isBooleanFalse() {
     return value == false;
   }
 
+  @Override
   public boolean isBooleanTrue() {
     return value == true;
   }
@@ -62,6 +65,7 @@
     return false;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     v.visit(this, ctx);
     v.endVisit(this, ctx);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsBreak.java b/dev/core/src/com/google/gwt/dev/js/ast/JsBreak.java
index 17e7d1b..804db5f 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsBreak.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsBreak.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -33,10 +31,16 @@
     this.label = label;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.BREAK;
+  }
+
   public JsNameRef getLabel() {
     return label;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       if (label != null) {
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsCase.java b/dev/core/src/com/google/gwt/dev/js/ast/JsCase.java
index b7e267e..a6c8490 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsCase.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsCase.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -32,10 +30,16 @@
     return caseExpr;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.CASE;
+  }
+
   public void setCaseExpr(JsExpression caseExpr) {
     this.caseExpr = caseExpr;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       caseExpr = v.accept(caseExpr);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsCatch.java b/dev/core/src/com/google/gwt/dev/js/ast/JsCatch.java
index 5a932cd..ae24484 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsCatch.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsCatch.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -41,10 +39,16 @@
     return body;
   }
 
+  @Override
   public JsExpression getCondition() {
     return condition;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.BREAK;
+  }
+
   public JsParameter getParameter() {
     return param;
   }
@@ -57,10 +61,12 @@
     this.body = body;
   }
 
+  @Override
   public void setCondition(JsExpression condition) {
     this.condition = condition;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       param = v.accept(param);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsCatchScope.java b/dev/core/src/com/google/gwt/dev/js/ast/JsCatchScope.java
index 542d398..fdfba9d 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsCatchScope.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsCatchScope.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2007 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -19,8 +17,8 @@
 import java.util.Iterator;
 
 /**
- * A special scope used only for catch blocks. It only holds a single symbol:
- * the catch argument's name.
+ * A special scope used only for catch blocks. It only holds a single symbol: the catch argument's
+ * name.
  */
 public class JsCatchScope extends JsNestingScope {
 
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsConditional.java b/dev/core/src/com/google/gwt/dev/js/ast/JsConditional.java
index 2d2c213..454fe8c 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsConditional.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsConditional.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -32,8 +30,8 @@
     super(sourceInfo);
   }
 
-  public JsConditional(SourceInfo sourceInfo, JsExpression testExpr,
-      JsExpression thenExpr, JsExpression elseExpr) {
+  public JsConditional(SourceInfo sourceInfo, JsExpression testExpr, JsExpression thenExpr,
+      JsExpression elseExpr) {
     super(sourceInfo);
     this.testExpr = testExpr;
     this.thenExpr = thenExpr;
@@ -44,6 +42,11 @@
     return elseExpr;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.CONDITIONAL;
+  }
+
   public JsExpression getTestExpression() {
     return testExpr;
   }
@@ -54,8 +57,7 @@
 
   @Override
   public boolean hasSideEffects() {
-    return testExpr.hasSideEffects() || thenExpr.hasSideEffects()
-        || elseExpr.hasSideEffects();
+    return testExpr.hasSideEffects() || thenExpr.hasSideEffects() || elseExpr.hasSideEffects();
   }
 
   @Override
@@ -80,6 +82,7 @@
     this.thenExpr = thenExpr;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       testExpr = v.accept(testExpr);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsContext.java b/dev/core/src/com/google/gwt/dev/js/ast/JsContext.java
index 503538d..ddb1d2c 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsContext.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsContext.java
@@ -1,24 +1,21 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
 
 /**
- * The context in which a JsNode visitation occurs. This represents the set of
- * possible operations a JsVisitor subclass can perform on the currently visited
- * node.
+ * The context in which a JsNode visitation occurs. This represents the set of possible operations a
+ * JsVisitor subclass can perform on the currently visited node.
  */
 public interface JsContext {
 
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsContinue.java b/dev/core/src/com/google/gwt/dev/js/ast/JsContinue.java
index 2e7490f..ad030a7 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsContinue.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsContinue.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -33,10 +31,16 @@
     this.label = label;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.CONTINUE;
+  }
+
   public JsNameRef getLabel() {
     return label;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       if (label != null) {
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsDebugger.java b/dev/core/src/com/google/gwt/dev/js/ast/JsDebugger.java
index 1cef5a7..2c65e11 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsDebugger.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsDebugger.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -26,9 +24,14 @@
     super(sourceInfo);
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.DEBUGGER;
+  }
+
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     v.visit(this, ctx);
     v.endVisit(this, ctx);
   }
-
 }
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsDefault.java b/dev/core/src/com/google/gwt/dev/js/ast/JsDefault.java
index f81ddf4..06dc3eb 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsDefault.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsDefault.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -26,6 +24,12 @@
     super(sourceInfo);
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.DEFAULT;
+  }
+
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       v.acceptWithInsertRemove(stmts);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsDoWhile.java b/dev/core/src/com/google/gwt/dev/js/ast/JsDoWhile.java
index 3c75fdb..03e65c6 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsDoWhile.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsDoWhile.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -30,8 +28,7 @@
     super(sourceInfo);
   }
 
-  public JsDoWhile(SourceInfo sourceInfo, JsExpression condition,
-      JsStatement body) {
+  public JsDoWhile(SourceInfo sourceInfo, JsExpression condition, JsStatement body) {
     super(sourceInfo);
     this.condition = condition;
     this.body = body;
@@ -45,6 +42,11 @@
     return condition;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.DO;
+  }
+
   public void setBody(JsStatement body) {
     this.body = body;
   }
@@ -53,6 +55,7 @@
     this.condition = condition;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       body = v.accept(body);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsEmpty.java b/dev/core/src/com/google/gwt/dev/js/ast/JsEmpty.java
index 4727008..b122f7c 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsEmpty.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsEmpty.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -26,9 +24,14 @@
     super(sourceInfo);
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.EMPTY;
+  }
+
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     v.visit(this, ctx);
     v.endVisit(this, ctx);
   }
-
 }
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsExprStmt.java b/dev/core/src/com/google/gwt/dev/js/ast/JsExprStmt.java
index 9bdd74d..154ee69 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsExprStmt.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsExprStmt.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -33,6 +31,12 @@
     return expr;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.EXPR_STMT;
+  }
+
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       expr = v.accept(expr);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsExpression.java b/dev/core/src/com/google/gwt/dev/js/ast/JsExpression.java
index 83d5cda..c79373c 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsExpression.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsExpression.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -42,9 +40,8 @@
   public abstract boolean isDefinitelyNull();
 
   /**
-   * Determines whether or not this expression is a leaf, such as a
-   * {@link JsNameRef}, {@link JsBooleanLiteral}, and so on. Leaf expressions
-   * never need to be parenthesized.
+   * Determines whether or not this expression is a leaf, such as a {@link JsNameRef},
+   * {@link JsBooleanLiteral}, and so on. Leaf expressions never need to be parenthesized.
    */
   public boolean isLeaf() {
     // Conservatively say that it isn't a leaf.
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsFor.java b/dev/core/src/com/google/gwt/dev/js/ast/JsFor.java
index 2703d0f..f2c21da 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsFor.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsFor.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -18,15 +16,14 @@
 import com.google.gwt.dev.jjs.SourceInfo;
 
 /**
- * A <code>for</code> statement. If specified at all, the initializer part is
- * either a declaration of one or more variables, in which case
- * {@link #getInitVars()} is used, or an expression, in which case
- * {@link #getInitExpr()} is used. In the latter case, the comma operator is
- * often used to create a compound expression.
+ * A <code>for</code> statement. If specified at all, the initializer part is either a declaration
+ * of one or more variables, in which case {@link #getInitVars()} is used, or an expression, in
+ * which case {@link #getInitExpr()} is used. In the latter case, the comma operator is often used
+ * to create a compound expression.
  * 
  * <p>
- * Note that any of the parts of the <code>for</code> loop header can be
- * <code>null</code>, although the body will never be null.
+ * Note that any of the parts of the <code>for</code> loop header can be <code>null</code>, although
+ * the body will never be null.
  */
 public class JsFor extends JsStatement {
 
@@ -64,6 +61,11 @@
     return initVars;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.FOR;
+  }
+
   public void setBody(JsStatement body) {
     this.body = body;
   }
@@ -84,6 +86,7 @@
     this.initVars = initVars;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       assert (!(initExpr != null && initVars != null));
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsForIn.java b/dev/core/src/com/google/gwt/dev/js/ast/JsForIn.java
index c73a56e..c829f46 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsForIn.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsForIn.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -52,6 +50,11 @@
     return iterVarName;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.FOR_IN;
+  }
+
   public JsExpression getObjExpr() {
     return objExpr;
   }
@@ -68,6 +71,7 @@
     this.objExpr = objExpr;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       if (iterExpr != null) {
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsFunction.java b/dev/core/src/com/google/gwt/dev/js/ast/JsFunction.java
index 74f211f..b4b4454 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsFunction.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsFunction.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -60,8 +58,7 @@
   /**
    * Creates a named function, possibly derived from Java source.
    */
-  public JsFunction(SourceInfo sourceInfo, JsScope parent, JsName name,
-      boolean fromJava) {
+  public JsFunction(SourceInfo sourceInfo, JsScope parent, JsName name, boolean fromJava) {
     super(sourceInfo);
     assert (parent != null);
     this.fromJava = fromJava;
@@ -76,9 +73,8 @@
   }
 
   /**
-   * If true, this indicates that only the first invocation of the function will
-   * have any effects. Subsequent invocations may be considered to be no-op
-   * calls whose return value is ignored.
+   * If true, this indicates that only the first invocation of the function will have any effects.
+   * Subsequent invocations may be considered to be no-op calls whose return value is ignored.
    */
   public boolean getExecuteOnce() {
     return executeOnce;
@@ -88,6 +84,12 @@
     return impliedExecute;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.FUNCTION;
+  }
+
+  @Override
   public JsName getName() {
     return name;
   }
@@ -110,10 +112,12 @@
     return artificiallyRescued;
   }
 
+  @Override
   public boolean isBooleanFalse() {
     return false;
   }
 
+  @Override
   public boolean isBooleanTrue() {
     return true;
   }
@@ -165,6 +169,7 @@
     this.trace = true;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     String before = null;
     if (trace && v instanceof JsModVisitor) {
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsGlobalBlock.java b/dev/core/src/com/google/gwt/dev/js/ast/JsGlobalBlock.java
index f6dfb25..d087132 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsGlobalBlock.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsGlobalBlock.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsIf.java b/dev/core/src/com/google/gwt/dev/js/ast/JsIf.java
index 7f4bdfd..b7c2f58 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsIf.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsIf.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -32,8 +30,7 @@
     super(sourceInfo);
   }
 
-  public JsIf(SourceInfo sourceInfo, JsExpression ifExpr, JsStatement thenStmt,
-      JsStatement elseStmt) {
+  public JsIf(SourceInfo sourceInfo, JsExpression ifExpr, JsStatement thenStmt, JsStatement elseStmt) {
     super(sourceInfo);
     this.ifExpr = ifExpr;
     this.thenStmt = thenStmt;
@@ -48,6 +45,11 @@
     return ifExpr;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.IF;
+  }
+
   public JsStatement getThenStmt() {
     return thenStmt;
   }
@@ -64,6 +66,7 @@
     this.thenStmt = thenStmt;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       ifExpr = v.accept(ifExpr);
@@ -77,10 +80,8 @@
 
   @Override
   public boolean unconditionalControlBreak() {
-    boolean thenBreaks = thenStmt != null
-        && thenStmt.unconditionalControlBreak();
-    boolean elseBreaks = elseStmt != null
-        && elseStmt.unconditionalControlBreak();
+    boolean thenBreaks = thenStmt != null && thenStmt.unconditionalControlBreak();
+    boolean elseBreaks = elseStmt != null && elseStmt.unconditionalControlBreak();
     if (thenBreaks && elseBreaks) {
       // both branches have an unconditional break
       return true;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsInvocation.java b/dev/core/src/com/google/gwt/dev/js/ast/JsInvocation.java
index 2a7bd56..213f853 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsInvocation.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsInvocation.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -33,10 +31,16 @@
     super(sourceInfo);
   }
 
+  @Override
   public List<JsExpression> getArguments() {
     return args;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.INVOKE;
+  }
+
   public JsExpression getQualifier() {
     return qualifier;
   }
@@ -60,6 +64,7 @@
     this.qualifier = qualifier;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       qualifier = v.accept(qualifier);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsLabel.java b/dev/core/src/com/google/gwt/dev/js/ast/JsLabel.java
index 85a8fb7..ca0a920 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsLabel.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsLabel.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -31,6 +29,12 @@
     this.label = label;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.LABEL;
+  }
+
+  @Override
   public JsName getName() {
     return label;
   }
@@ -43,6 +47,7 @@
     this.stmt = stmt;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       stmt = v.accept(stmt);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsLiteral.java b/dev/core/src/com/google/gwt/dev/js/ast/JsLiteral.java
index 6fc345d..9fdb8ce 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsLiteral.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsModVisitor.java b/dev/core/src/com/google/gwt/dev/js/ast/JsModVisitor.java
index 4577c96..fe78950 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsModVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsModVisitor.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -31,36 +29,43 @@
     private boolean removed;
     private boolean replaced;
 
+    @Override
     public boolean canInsert() {
       return true;
     }
 
+    @Override
     public boolean canRemove() {
       return true;
     }
 
+    @Override
     public void insertAfter(JsVisitable node) {
       checkRemoved();
       collection.add(index + 1, (T) node);
       didChange = true;
     }
 
+    @Override
     public void insertBefore(JsVisitable node) {
       checkRemoved();
       collection.add(index++, (T) node);
       didChange = true;
     }
 
+    @Override
     public boolean isLvalue() {
       return false;
     }
 
+    @Override
     public void removeMe() {
       checkState();
       collection.remove(index--);
       didChange = removed = true;
     }
 
+    @Override
     public void replaceMe(JsVisitable node) {
       checkState();
       checkReplacement(collection.get(index), node);
@@ -102,30 +107,37 @@
     private T node;
     private boolean replaced;
 
+    @Override
     public boolean canInsert() {
       return false;
     }
 
+    @Override
     public boolean canRemove() {
       return false;
     }
 
+    @Override
     public void insertAfter(JsVisitable node) {
       throw new UnsupportedOperationException();
     }
 
+    @Override
     public void insertBefore(JsVisitable node) {
       throw new UnsupportedOperationException();
     }
 
+    @Override
     public boolean isLvalue() {
       return false;
     }
 
+    @Override
     public void removeMe() {
       throw new UnsupportedOperationException();
     }
 
+    @Override
     public void replaceMe(JsVisitable node) {
       if (replaced) {
         throw new InternalCompilerException("Node was already replaced");
@@ -143,14 +155,12 @@
     }
   }
 
-  protected static void checkReplacement(JsVisitable origNode,
-      JsVisitable newNode) {
+  protected static void checkReplacement(JsVisitable origNode, JsVisitable newNode) {
     if (newNode == null) {
       throw new InternalCompilerException("Cannot replace with null");
     }
     if (newNode == origNode) {
-      throw new InternalCompilerException(
-          "The replacement is the same as the original");
+      throw new InternalCompilerException("The replacement is the same as the original");
     }
   }
 
@@ -183,8 +193,7 @@
   }
 
   @Override
-  protected <T extends JsVisitable> void doAcceptWithInsertRemove(
-      List<T> collection) {
+  protected <T extends JsVisitable> void doAcceptWithInsertRemove(List<T> collection) {
     new ListContext<T>().traverse(collection);
   }
 
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsName.java b/dev/core/src/com/google/gwt/dev/js/ast/JsName.java
index 2c224d4..460b53e 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsName.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsName.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsNameOf.java b/dev/core/src/com/google/gwt/dev/js/ast/JsNameOf.java
index 27d7e67..74439f0 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsNameOf.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsNameOf.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2009 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -23,13 +21,18 @@
 public class JsNameOf extends JsExpression {
   private final JsName name;
 
+  public JsNameOf(SourceInfo info, HasName node) {
+    this(info, node.getName());
+  }
+
   public JsNameOf(SourceInfo info, JsName name) {
     super(info);
     this.name = name;
   }
 
-  public JsNameOf(SourceInfo info, HasName node) {
-    this(info, node.getName());
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.NAME_OF;
   }
 
   public JsName getName() {
@@ -52,6 +55,7 @@
     return false;
   }
 
+  @Override
   public void traverse(JsVisitor visitor, JsContext ctx) {
     if (visitor.visit(this, ctx)) {
     }
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsNameRef.java b/dev/core/src/com/google/gwt/dev/js/ast/JsNameRef.java
index c1e51c3..1845feb 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsNameRef.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsNameRef.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -21,8 +19,7 @@
 /**
  * Represents a JavaScript expression that references a name.
  */
-public final class JsNameRef extends JsExpression implements CanBooleanEval,
-    HasName {
+public final class JsNameRef extends JsExpression implements CanBooleanEval, HasName {
 
   private String ident;
   private JsName name;
@@ -42,6 +39,12 @@
     return (name == null) ? ident : name.getIdent();
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.NAME_REF;
+  }
+
+  @Override
   public JsName getName() {
     return name;
   }
@@ -66,10 +69,12 @@
     return qualifier.hasSideEffects();
   }
 
+  @Override
   public boolean isBooleanFalse() {
     return isDefinitelyNull();
   }
 
+  @Override
   public boolean isBooleanTrue() {
     return false;
   }
@@ -107,6 +112,7 @@
     this.qualifier = qualifier;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       if (qualifier != null) {
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsNestingScope.java b/dev/core/src/com/google/gwt/dev/js/ast/JsNestingScope.java
index 7c148e7..ce8ade3 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsNestingScope.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsNestingScope.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2011 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -25,8 +23,7 @@
 public abstract class JsNestingScope extends JsScope {
 
   /**
-   * Transient because children will add themselves to the parent after
-   * deserialization.
+   * Transient because children will add themselves to the parent after deserialization.
    */
   private transient List<JsScope> children = Lists.create();
 
@@ -51,8 +48,7 @@
   }
 
   /**
-   * Returns the parent scope of this scope, or <code>null</code> if this is the
-   * root scope.
+   * Returns the parent scope of this scope, or <code>null</code> if this is the root scope.
    */
   @Override
   public final JsScope getParent() {
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsNew.java b/dev/core/src/com/google/gwt/dev/js/ast/JsNew.java
index 6bed072..f229988 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsNew.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsNew.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -34,6 +32,7 @@
     this.ctorExpr = ctorExpr;
   }
 
+  @Override
   public List<JsExpression> getArguments() {
     return args;
   }
@@ -43,6 +42,11 @@
   }
 
   @Override
+  public NodeKind getKind() {
+    return NodeKind.NEW;
+  }
+
+  @Override
   public boolean hasSideEffects() {
     return true;
   }
@@ -59,6 +63,7 @@
     return false;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       ctorExpr = v.accept(ctorExpr);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsNode.java b/dev/core/src/com/google/gwt/dev/js/ast/JsNode.java
index d1837cd..30b93fc 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsNode.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsNode.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -26,8 +24,7 @@
 /**
  * Base class for all JS AST elements.
  */
-public abstract class JsNode implements JsVisitable, HasSourceInfo,
-    Serializable {
+public abstract class JsNode implements JsVisitable, HasSourceInfo, Serializable {
 
   private SourceInfo sourceInfo;
 
@@ -36,6 +33,9 @@
     this.sourceInfo = sourceInfo;
   }
 
+  public abstract NodeKind getKind();
+
+  @Override
   public SourceInfo getSourceInfo() {
     return sourceInfo;
   }
@@ -53,15 +53,13 @@
   }
 
   /**
-   * Returns a source code representation of the node using short or long
-   * identifiers.
+   * Returns a source code representation of the node using short or long identifiers.
    * 
    * @param useLongIdents if true, emit all identifiers in long form
    */
   public final String toSource(boolean useLongIdents) {
     DefaultTextOutput out = new DefaultTextOutput(false);
-    JsSourceGenerationVisitor v = new JsSourceGenerationVisitor(out,
-        useLongIdents);
+    JsSourceGenerationVisitor v = new JsSourceGenerationVisitor(out, useLongIdents);
     v.accept(this);
     return out.toString();
   }
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsNormalScope.java b/dev/core/src/com/google/gwt/dev/js/ast/JsNormalScope.java
index c27a734..3e54ee6 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsNormalScope.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsNormalScope.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2011 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -57,8 +55,7 @@
   }
 
   /**
-   * Attempts to find the name object for the specified ident, searching in this
-   * scope only.
+   * Attempts to find the name object for the specified ident, searching in this scope only.
    * 
    * @return <code>null</code> if the identifier has no associated name
    */
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsNullLiteral.java b/dev/core/src/com/google/gwt/dev/js/ast/JsNullLiteral.java
index 2774635..5661f72 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsNullLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsNullLiteral.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -23,17 +21,23 @@
  */
 public final class JsNullLiteral extends JsValueLiteral {
 
-  public static final JsNullLiteral INSTANCE = new JsNullLiteral(
-      SourceOrigin.UNKNOWN);
+  public static final JsNullLiteral INSTANCE = new JsNullLiteral(SourceOrigin.UNKNOWN);
 
   private JsNullLiteral(SourceInfo sourceInfo) {
     super(sourceInfo);
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.NULL;
+  }
+
+  @Override
   public boolean isBooleanFalse() {
     return true;
   }
 
+  @Override
   public boolean isBooleanTrue() {
     return false;
   }
@@ -48,14 +52,15 @@
     return true;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     v.visit(this, ctx);
     v.endVisit(this, ctx);
   }
 
   /**
-   * Note, if this ever becomes not-a-singleton, we'll need to check the
-   * SourceInfo == SourceOrigin.UNKNOWN.
+   * Note, if this ever becomes not-a-singleton, we'll need to check the SourceInfo ==
+   * SourceOrigin.UNKNOWN.
    */
   private Object readResolve() {
     return INSTANCE;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsNumberLiteral.java b/dev/core/src/com/google/gwt/dev/js/ast/JsNumberLiteral.java
index df3508c..abf88e4 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsNumberLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsNumberLiteral.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -29,14 +27,21 @@
     this.value = value;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.NUMBER;
+  }
+
   public double getValue() {
     return value;
   }
 
+  @Override
   public boolean isBooleanFalse() {
     return value == 0.0;
   }
 
+  @Override
   public boolean isBooleanTrue() {
     return value != 0.0;
   }
@@ -51,6 +56,7 @@
     return false;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     v.visit(this, ctx);
     v.endVisit(this, ctx);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsObjectLiteral.java b/dev/core/src/com/google/gwt/dev/js/ast/JsObjectLiteral.java
index 3b3fcfc..e7e12e6 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsObjectLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsObjectLiteral.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -31,6 +29,11 @@
     super(sourceInfo);
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.OBJECT;
+  }
+
   public List<JsPropertyInitializer> getPropertyInitializers() {
     return props;
   }
@@ -45,10 +48,12 @@
     return false;
   }
 
+  @Override
   public boolean isBooleanFalse() {
     return false;
   }
 
+  @Override
   public boolean isBooleanTrue() {
     return true;
   }
@@ -63,6 +68,7 @@
     return false;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       v.acceptWithInsertRemove(props);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsOperator.java b/dev/core/src/com/google/gwt/dev/js/ast/JsOperator.java
index 543b6c5..d321f85 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsOperator.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsOperator.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -40,5 +38,6 @@
 
   boolean isValidPrefix();
 
+  @Override
   String toString();
 }
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsParameter.java b/dev/core/src/com/google/gwt/dev/js/ast/JsParameter.java
index 603b3e4..e0f8575 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsParameter.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsParameter.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -30,10 +28,17 @@
     name.setStaticRef(this);
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.PARAMETER;
+  }
+
+  @Override
   public JsName getName() {
     return name;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     v.visit(this, ctx);
     v.endVisit(this, ctx);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsPostfixOperation.java b/dev/core/src/com/google/gwt/dev/js/ast/JsPostfixOperation.java
index 648bf15..c25ff93 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsPostfixOperation.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsPostfixOperation.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -26,12 +24,16 @@
     this(sourceInfo, op, null);
   }
 
-  public JsPostfixOperation(SourceInfo sourceInfo, JsUnaryOperator op,
-      JsExpression arg) {
+  public JsPostfixOperation(SourceInfo sourceInfo, JsUnaryOperator op, JsExpression arg) {
     super(sourceInfo, op, arg);
   }
 
   @Override
+  public NodeKind getKind() {
+    return NodeKind.POSTFIX_OP;
+  }
+
+  @Override
   public boolean isDefinitelyNotNull() {
     return true;
   }
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsPrefixOperation.java b/dev/core/src/com/google/gwt/dev/js/ast/JsPrefixOperation.java
index bc813db..14fe16e 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsPrefixOperation.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsPrefixOperation.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -20,33 +18,36 @@
 /**
  * A JavaScript prefix operation.
  */
-public final class JsPrefixOperation extends JsUnaryOperation implements
-    CanBooleanEval {
+public final class JsPrefixOperation extends JsUnaryOperation implements CanBooleanEval {
 
   public JsPrefixOperation(SourceInfo sourceInfo, JsUnaryOperator op) {
     this(sourceInfo, op, null);
   }
 
-  public JsPrefixOperation(SourceInfo sourceInfo, JsUnaryOperator op,
-      JsExpression arg) {
+  public JsPrefixOperation(SourceInfo sourceInfo, JsUnaryOperator op, JsExpression arg) {
     super(sourceInfo, op, arg);
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.PREFIX_OP;
+  }
+
+  @Override
   public boolean isBooleanFalse() {
     if (getOperator() == JsUnaryOperator.VOID) {
       return true;
     }
-    if (getOperator() == JsUnaryOperator.NOT
-        && getArg() instanceof CanBooleanEval) {
+    if (getOperator() == JsUnaryOperator.NOT && getArg() instanceof CanBooleanEval) {
       CanBooleanEval eval = (CanBooleanEval) getArg();
       return eval.isBooleanTrue();
     }
     return false;
   }
 
+  @Override
   public boolean isBooleanTrue() {
-    if (getOperator() == JsUnaryOperator.NOT
-        && getArg() instanceof CanBooleanEval) {
+    if (getOperator() == JsUnaryOperator.NOT && getArg() instanceof CanBooleanEval) {
       CanBooleanEval eval = (CanBooleanEval) getArg();
       return eval.isBooleanFalse();
     }
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsProgram.java b/dev/core/src/com/google/gwt/dev/js/ast/JsProgram.java
index db4358d..a1805bb 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsProgram.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsProgram.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -44,15 +42,9 @@
 
   /**
    * Constructs a JavaScript program object.
-   * 
-   * @param soycEnabled Controls whether or not SourceInfo nodes created via the
-   *          JsProgram will record descendant information. Enabling this
-   *          feature will collect extra data during the compilation cycle, but
-   *          at a cost of memory and object allocations.
    */
   public JsProgram(CorrelationFactory correlator) {
-    super(correlator.makeSourceInfo(SourceOrigin.create(0,
-        JsProgram.class.getName())));
+    super(correlator.makeSourceInfo(SourceOrigin.create(0, JsProgram.class.getName())));
 
     this.correlator = correlator;
 
@@ -61,10 +53,8 @@
     setFragmentCount(1);
   }
 
-  public SourceInfo createSourceInfo(int startPos, int endPos, int startLine,
-      String fileName) {
-    return correlator.makeSourceInfo(SourceOrigin.create(startPos, endPos,
-        startLine, fileName));
+  public SourceInfo createSourceInfo(int startPos, int endPos, int startLine, String fileName) {
+    return correlator.makeSourceInfo(SourceOrigin.create(startPos, endPos, startLine, fileName));
   }
 
   public SourceInfo createSourceInfo(int lineNumber, String location) {
@@ -75,6 +65,13 @@
     return createSourceInfo(0, caller.getName());
   }
 
+  public JsProgramFragment getFragment(int fragment) {
+    if (fragment < 0 || fragment >= fragments.length) {
+      throw new IllegalArgumentException("Invalid fragment: " + fragment);
+    }
+    return fragments[fragment];
+  }
+
   public JsBlock getFragmentBlock(int fragment) {
     if (fragment < 0 || fragment >= fragments.length) {
       throw new IllegalArgumentException("Invalid fragment: " + fragment);
@@ -97,13 +94,17 @@
     return indexedFunctions.get(name);
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.PROGRAM;
+  }
+
   public JsScope getObjectScope() {
     return objectScope;
   }
 
   /**
-   * Gets the top level scope. This is the scope of all the statements in the
-   * main program.
+   * Gets the top level scope. This is the scope of all the statements in the main program.
    */
   public JsScope getScope() {
     return topScope;
@@ -112,8 +113,7 @@
   public void setFragmentCount(int fragments) {
     this.fragments = new JsProgramFragment[fragments];
     for (int i = 0; i < fragments; i++) {
-      this.fragments[i] = new JsProgramFragment(
-          createSourceInfoSynthetic(JsProgram.class));
+      this.fragments[i] = new JsProgramFragment(createSourceInfoSynthetic(JsProgram.class));
     }
   }
 
@@ -122,6 +122,7 @@
     this.indexedFunctions.putAll(indexedFunctions);
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       for (JsProgramFragment fragment : fragments) {
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsProgramFragment.java b/dev/core/src/com/google/gwt/dev/js/ast/JsProgramFragment.java
index 703a5f0..5591e70 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsProgramFragment.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsProgramFragment.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -32,11 +30,16 @@
     return globalBlock;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.PROGRAM_FRAGMENT;
+  }
+
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       v.accept(globalBlock);
     }
     v.endVisit(this, ctx);
   }
-
 }
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsPropertyInitializer.java b/dev/core/src/com/google/gwt/dev/js/ast/JsPropertyInitializer.java
index 23033a6..ae67b25 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsPropertyInitializer.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsPropertyInitializer.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -30,13 +28,17 @@
     super(sourceInfo);
   }
 
-  public JsPropertyInitializer(SourceInfo sourceInfo, JsExpression labelExpr,
-      JsExpression valueExpr) {
+  public JsPropertyInitializer(SourceInfo sourceInfo, JsExpression labelExpr, JsExpression valueExpr) {
     super(sourceInfo);
     this.labelExpr = labelExpr;
     this.valueExpr = valueExpr;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.PROPERTY_INIT;
+  }
+
   public JsExpression getLabelExpr() {
     return labelExpr;
   }
@@ -57,6 +59,7 @@
     this.valueExpr = valueExpr;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       labelExpr = v.accept(labelExpr);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsRegExp.java b/dev/core/src/com/google/gwt/dev/js/ast/JsRegExp.java
index 49579a3..76b2589 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsRegExp.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsRegExp.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -34,14 +32,21 @@
     return flags;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.REGEXP;
+  }
+
   public String getPattern() {
     return pattern;
   }
 
+  @Override
   public boolean isBooleanFalse() {
     return false;
   }
 
+  @Override
   public boolean isBooleanTrue() {
     return true;
   }
@@ -64,6 +69,7 @@
     this.pattern = re;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     v.visit(this, ctx);
     v.endVisit(this, ctx);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsReturn.java b/dev/core/src/com/google/gwt/dev/js/ast/JsReturn.java
index 9571619..04a94ec 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsReturn.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsReturn.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -37,10 +35,16 @@
     return expr;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.RETURN;
+  }
+
   public void setExpr(JsExpression expr) {
     this.expr = expr;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       if (expr != null) {
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsRootName.java b/dev/core/src/com/google/gwt/dev/js/ast/JsRootName.java
index d32582a..9f70e10 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsRootName.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsRootName.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2011 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsRootScope.java b/dev/core/src/com/google/gwt/dev/js/ast/JsRootScope.java
index 2589bfd..3ceb8be 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsRootScope.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsRootScope.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2007 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -25,8 +23,8 @@
 import java.util.Map;
 
 /**
- * The root scope is the parent of every scope, it contains a list of browser
- * built-in identifiers that we should recognize and never obfuscate into.
+ * The root scope is the parent of every scope, it contains a list of browser built-in identifiers
+ * that we should recognize and never obfuscate into.
  */
 public final class JsRootScope extends JsScope {
   /*
@@ -41,7 +39,7 @@
 
   public static final JsRootScope INSTANCE;
 
-  private static final String[] COMMON_BUILTINS = new String[]{
+  private static final String[] COMMON_BUILTINS = new String[] {
       // 15.1.1 Value Properties of the Global Object
       "NaN",
       "Infinity",
@@ -241,7 +239,7 @@
       "oncanplaythrough",
       "onended",
       "onprogress",
-      
+
       // extra window methods
       "uneval",
 
@@ -314,29 +312,24 @@
       // that don't ensure GWT's window != $wnd, document != $doc, etc.
       // Taken from the Rhino book, pg 715
       "Anchor", "Applet", "Attr", "Canvas", "CanvasGradient", "CanvasPattern",
-      "CanvasRenderingContext2D", "CDATASection", "CharacterData", "Comment",
-      "CSS2Properties", "CSSRule", "CSSStyleSheet", "Document",
-      "DocumentFragment", "DocumentType", "DOMException", "DOMImplementation",
-      "DOMParser", "Element", "Event", "ExternalInterface", "FlashPlayer",
-      "Form", "Frame", "History", "HTMLCollection", "HTMLDocument",
-      "HTMLElement", "IFrame", "Image", "Input", "JSObject", "KeyEvent",
-      "Link", "Location", "MimeType", "MouseEvent", "Navigator", "Node",
-      "NodeList", "Option", "Plugin", "ProcessingInstruction", "Range",
-      "RangeException", "Screen", "Select", "Table", "TableCell", "TableRow",
-      "TableSelection", "Text", "TextArea", "UIEvent", "Window",
-      "XMLHttpRequest", "XMLSerializer", "XPathException", "XPathResult",
-      "XSLTProcessor",
+      "CanvasRenderingContext2D", "CDATASection", "CharacterData", "Comment", "CSS2Properties",
+      "CSSRule", "CSSStyleSheet", "Document", "DocumentFragment", "DocumentType", "DOMException",
+      "DOMImplementation", "DOMParser", "Element", "Event", "ExternalInterface", "FlashPlayer",
+      "Form", "Frame", "History", "HTMLCollection", "HTMLDocument", "HTMLElement", "IFrame",
+      "Image", "Input", "JSObject", "KeyEvent", "Link", "Location", "MimeType", "MouseEvent",
+      "Navigator", "Node", "NodeList", "Option", "Plugin", "ProcessingInstruction", "Range",
+      "RangeException", "Screen", "Select", "Table", "TableCell", "TableRow", "TableSelection",
+      "Text", "TextArea", "UIEvent", "Window", "XMLHttpRequest", "XMLSerializer", "XPathException",
+      "XPathResult", "XSLTProcessor",
 
       /*
-       * These keywords trigger the loading of the java-plugin. For the
-       * next-generation plugin, this results in starting a new Java process.
+       * These keywords trigger the loading of the java-plugin. For the next-generation plugin, this
+       * results in starting a new Java process.
        */
-      "java", "Packages", "netscape", "sun", "JavaObject", "JavaClass",
-      "JavaArray", "JavaMember",
+      "java", "Packages", "netscape", "sun", "JavaObject", "JavaClass", "JavaArray", "JavaMember",
 
       // GWT-defined identifiers
-      "$wnd", "$doc", "$moduleName", "$moduleBase", "$gwt_version",
-      "$sessionId",
+      "$wnd", "$doc", "$moduleName", "$moduleBase", "$gwt_version", "$sessionId",
 
       // Identifiers used by JsStackEmulator; later set to obfuscatable
       "$stack", "$stackDepth", "$location",
@@ -387,8 +380,7 @@
 
   @Override
   protected JsName doCreateName(String ident, String shortIdent) {
-    throw new UnsupportedOperationException(
-        "Cannot create new names in the root scope");
+    throw new UnsupportedOperationException("Cannot create new names in the root scope");
   }
 
   @Override
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsScope.java b/dev/core/src/com/google/gwt/dev/js/ast/JsScope.java
index a1ff03c..269d7db 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsScope.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsScope.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -23,29 +21,25 @@
 import java.util.List;
 
 /**
- * A scope is a factory for creating and allocating
- * {@link com.google.gwt.dev.js.ast.JsName}s. A JavaScript AST is built in terms
- * of abstract name objects without worrying about obfuscation,
+ * A scope is a factory for creating and allocating {@link com.google.gwt.dev.js.ast.JsName}s. A
+ * JavaScript AST is built in terms of abstract name objects without worrying about obfuscation,
  * keyword/identifier blacklisting, and so on.
  * 
  * <p>
  * 
- * Scopes are associated with {@link com.google.gwt.dev.js.ast.JsFunction}s, but
- * the two are not equivalent. Functions <i>have</i> scopes, but a scope does
- * not necessarily have an associated Function. Examples of this include the
- * {@link com.google.gwt.dev.js.ast.JsRootScope} and synthetic scopes that might
- * be created by a client.
+ * Scopes are associated with {@link com.google.gwt.dev.js.ast.JsFunction}s, but the two are not
+ * equivalent. Functions <i>have</i> scopes, but a scope does not necessarily have an associated
+ * Function. Examples of this include the {@link com.google.gwt.dev.js.ast.JsRootScope} and
+ * synthetic scopes that might be created by a client.
  * 
  * <p>
  * 
- * Scopes can have parents to provide constraints when allocating actual
- * identifiers for names. Specifically, names in child scopes are chosen such
- * that they do not conflict with names in their parent scopes. The ultimate
- * parent is usually the global scope (see
- * {@link com.google.gwt.dev.js.ast.JsProgram#getGlobalScope()}), but parentless
- * scopes are useful for managing names that are always accessed with a
- * qualifier and could therefore never be confused with the global scope
- * hierarchy.
+ * Scopes can have parents to provide constraints when allocating actual identifiers for names.
+ * Specifically, names in child scopes are chosen such that they do not conflict with names in their
+ * parent scopes. The ultimate parent is usually the global scope (see
+ * {@link com.google.gwt.dev.js.ast.JsProgram#getGlobalScope()}), but parentless scopes are useful
+ * for managing names that are always accessed with a qualifier and could therefore never be
+ * confused with the global scope hierarchy.
  */
 public abstract class JsScope implements Serializable {
 
@@ -66,8 +60,7 @@
   }
 
   /**
-   * Gets a name object associated with the specified ident in this scope,
-   * creating it if necessary.
+   * Gets a name object associated with the specified ident in this scope, creating it if necessary.
    * 
    * @param ident An identifier that is unique within this scope.
    */
@@ -81,13 +74,12 @@
   }
 
   /**
-   * Gets a name object associated with the specified ident in this scope,
-   * creating it if necessary.
+   * Gets a name object associated with the specified ident in this scope, creating it if necessary.
    * 
    * @param ident An identifier that is unique within this scope.
    * @param shortIdent A "pretty" name that does not have to be unique.
-   * @throws IllegalArgumentException if ident already exists in this scope but
-   *           the requested short name does not match the existing short name.
+   * @throws IllegalArgumentException if ident already exists in this scope but the requested short
+   *           name does not match the existing short name.
    */
   public final JsName declareName(String ident, String shortIdent) {
     ident = maybeMangleKeyword(ident);
@@ -96,8 +88,8 @@
     if (name != null) {
       if (!name.getShortIdent().equals(shortIdent)) {
         throw new IllegalArgumentException("Requested short name " + shortIdent
-            + " conflicts with preexisting short name " + name.getShortIdent()
-            + " for identifier " + ident);
+            + " conflicts with preexisting short name " + name.getShortIdent() + " for identifier "
+            + ident);
       }
       return name;
     }
@@ -105,8 +97,8 @@
   }
 
   /**
-   * Attempts to find the name object for the specified ident, searching in this
-   * scope, and if not found, in the parent scopes.
+   * Attempts to find the name object for the specified ident, searching in this scope, and if not
+   * found, in the parent scopes.
    * 
    * @return <code>null</code> if the identifier has no associated name
    */
@@ -120,8 +112,8 @@
   }
 
   /**
-   * Attempts to find an unobfuscatable name object for the specified ident,
-   * searching in this scope, and if not found, in the parent scopes.
+   * Attempts to find an unobfuscatable name object for the specified ident, searching in this
+   * scope, and if not found, in the parent scopes.
    * 
    * @return <code>null</code> if the identifier has no associated name
    */
@@ -148,8 +140,7 @@
   public abstract List<JsScope> getChildren();
 
   /**
-   * Returns the parent scope of this scope, or <code>null</code> if this is the
-   * root scope.
+   * Returns the parent scope of this scope, or <code>null</code> if this is the root scope.
    */
   public abstract JsScope getParent();
 
@@ -170,8 +161,7 @@
   protected abstract JsName doCreateName(String ident, String shortIdent);
 
   /**
-   * Attempts to find the name object for the specified ident, searching in this
-   * scope only.
+   * Attempts to find the name object for the specified ident, searching in this scope only.
    * 
    * @return <code>null</code> if the identifier has no associated name
    */
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsSeedIdOf.java b/dev/core/src/com/google/gwt/dev/js/ast/JsSeedIdOf.java
index e7c1778..01cd160 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsSeedIdOf.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsSeedIdOf.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2011 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -29,10 +27,16 @@
     this.seedId = seedId;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.SEED_ID_OF;
+  }
+
   public int getSeedId() {
     return seedId;
   }
 
+  @Override
   public void traverse(JsVisitor visitor, JsContext ctx) {
     if (visitor.visit(this, ctx)) {
     }
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsStatement.java b/dev/core/src/com/google/gwt/dev/js/ast/JsStatement.java
index 6691c76..c0a91eb 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsStatement.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsStatement.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -27,8 +25,7 @@
   }
 
   /**
-   * Returns true if this statement definitely causes an abrupt change in flow
-   * control.
+   * Returns true if this statement definitely causes an abrupt change in flow control.
    */
   public boolean unconditionalControlBreak() {
     return false;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsStringLiteral.java b/dev/core/src/com/google/gwt/dev/js/ast/JsStringLiteral.java
index 7eba50f..d5738c7 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsStringLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsStringLiteral.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -30,14 +28,21 @@
     this.value = StringInterner.get().intern(value);
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.STRING;
+  }
+
   public String getValue() {
     return value;
   }
 
+  @Override
   public boolean isBooleanFalse() {
     return value.length() == 0;
   }
 
+  @Override
   public boolean isBooleanTrue() {
     return value.length() != 0;
   }
@@ -52,6 +57,7 @@
     return false;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     v.visit(this, ctx);
     v.endVisit(this, ctx);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsSuperVisitor.java b/dev/core/src/com/google/gwt/dev/js/ast/JsSuperVisitor.java
index 231437f..f5d1c44 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsSuperVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsSuperVisitor.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -18,9 +16,9 @@
 import com.google.gwt.dev.js.ast.JsVars.JsVar;
 
 /**
- * A visitor that walks up the type hierarchy. By default, if a subclass has no
- * specific override for a concrete node type, this visitor will call a
- * visit/endVisit for its super class, and so on up the type heirarchy.
+ * A visitor that walks up the type hierarchy. By default, if a subclass has no specific override
+ * for a concrete node type, this visitor will call a visit/endVisit for its super class, and so on
+ * up the type heirarchy.
  */
 public class JsSuperVisitor extends JsVisitor {
 
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsSwitch.java b/dev/core/src/com/google/gwt/dev/js/ast/JsSwitch.java
index 16341ab..748dd77 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsSwitch.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsSwitch.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -41,10 +39,16 @@
     return expr;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.SWITCH;
+  }
+
   public void setExpr(JsExpression expr) {
     this.expr = expr;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       expr = v.accept(expr);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsSwitchMember.java b/dev/core/src/com/google/gwt/dev/js/ast/JsSwitchMember.java
index 113901d..a856fe8 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsSwitchMember.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsSwitchMember.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsThisRef.java b/dev/core/src/com/google/gwt/dev/js/ast/JsThisRef.java
index 3f4ed82..99b6ff8 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsThisRef.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsThisRef.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -26,10 +24,17 @@
     super(sourceInfo);
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.THIS;
+  }
+
+  @Override
   public boolean isBooleanFalse() {
     return false;
   }
 
+  @Override
   public boolean isBooleanTrue() {
     return true;
   }
@@ -37,9 +42,8 @@
   @Override
   public boolean isDefinitelyNotNull() {
     /*
-     * You'd think that you could get a null this via function.call/apply, but
-     * in fact you can't: they just make this be the window object instead. So
-     * it really can't ever be null.
+     * You'd think that you could get a null this via function.call/apply, but in fact you can't:
+     * they just make this be the window object instead. So it really can't ever be null.
      */
     return true;
   }
@@ -49,6 +53,7 @@
     return false;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     v.visit(this, ctx);
     v.endVisit(this, ctx);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsThrow.java b/dev/core/src/com/google/gwt/dev/js/ast/JsThrow.java
index 6b45f97..3944b0b 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsThrow.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsThrow.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -37,10 +35,16 @@
     return expr;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.THROW;
+  }
+
   public void setExpr(JsExpression expr) {
     this.expr = expr;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       expr = v.accept(expr);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsTry.java b/dev/core/src/com/google/gwt/dev/js/ast/JsTry.java
index 35ca695..9d1dbe3 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsTry.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsTry.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -43,6 +41,11 @@
     return finallyBlock;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.TRY;
+  }
+
   public JsBlock getTryBlock() {
     return tryBlock;
   }
@@ -55,6 +58,7 @@
     tryBlock = block;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       tryBlock = v.accept(tryBlock);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsUnaryOperation.java b/dev/core/src/com/google/gwt/dev/js/ast/JsUnaryOperation.java
index bf323ce..571b714 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsUnaryOperation.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsUnaryOperation.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -30,8 +28,7 @@
     this(sourceInfo, op, null);
   }
 
-  public JsUnaryOperation(SourceInfo sourceInfo, JsUnaryOperator op,
-      JsExpression arg) {
+  public JsUnaryOperation(SourceInfo sourceInfo, JsUnaryOperator op, JsExpression arg) {
     super(sourceInfo);
     this.op = op;
     this.arg = arg;
@@ -54,11 +51,12 @@
     this.arg = arg;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (op.isModifying()) {
       /*
-       * The delete operator is practically like an assignment of undefined, so
-       * for practical purposes we're treating it as an lvalue.
+       * The delete operator is practically like an assignment of undefined, so for practical
+       * purposes we're treating it as an lvalue.
        */
       arg = v.acceptLvalue(arg);
     } else {
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsUnaryOperator.java b/dev/core/src/com/google/gwt/dev/js/ast/JsUnaryOperator.java
index 454a1df..0c0ea4e 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsUnaryOperator.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsUnaryOperator.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -20,14 +18,12 @@
  */
 public enum JsUnaryOperator implements JsOperator {
   /*
-   * Precedence indices from "JavaScript - The Definitive Guide" 4th Edition
-   * (page 57)
+   * Precedence indices from "JavaScript - The Definitive Guide" 4th Edition (page 57)
    */
 
-  BIT_NOT("~", 14, PREFIX), DEC("--", 14, POSTFIX | PREFIX), DELETE("delete",
-      14, PREFIX), INC("++", 14, POSTFIX | PREFIX), NEG("-", 14, PREFIX), POS(
-      "+", 14, PREFIX), NOT("!", 14, PREFIX), TYPEOF("typeof", 14, PREFIX), VOID(
-      "void", 14, PREFIX);
+  BIT_NOT("~", 14, PREFIX), DEC("--", 14, POSTFIX | PREFIX), DELETE("delete", 14, PREFIX), INC(
+      "++", 14, POSTFIX | PREFIX), NEG("-", 14, PREFIX), POS("+", 14, PREFIX), NOT("!", 14, PREFIX), TYPEOF(
+      "typeof", 14, PREFIX), VOID("void", 14, PREFIX);
 
   private final int mask;
 
@@ -41,18 +37,22 @@
     this.mask = mask;
   }
 
+  @Override
   public int getPrecedence() {
     return precedence;
   }
 
+  @Override
   public String getSymbol() {
     return symbol;
   }
 
+  @Override
   public boolean isKeyword() {
     return this == DELETE || this == TYPEOF || this == VOID;
   }
 
+  @Override
   public boolean isLeftAssociative() {
     return (mask & LEFT) != 0;
   }
@@ -61,18 +61,22 @@
     return this == DEC || this == INC || this == DELETE;
   }
 
+  @Override
   public boolean isPrecedenceLessThan(JsOperator other) {
     return precedence < other.getPrecedence();
   }
 
+  @Override
   public boolean isValidInfix() {
     return (mask & INFIX) != 0;
   }
 
+  @Override
   public boolean isValidPostfix() {
     return (mask & POSTFIX) != 0;
   }
 
+  @Override
   public boolean isValidPrefix() {
     return (mask & PREFIX) != 0;
   }
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsValueLiteral.java b/dev/core/src/com/google/gwt/dev/js/ast/JsValueLiteral.java
index ba6dcd3..fac9228 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsValueLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsValueLiteral.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsVars.java b/dev/core/src/com/google/gwt/dev/js/ast/JsVars.java
index 2e55e33..6fdb3cd 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsVars.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsVars.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -44,6 +42,12 @@
       return initExpr;
     }
 
+    @Override
+    public NodeKind getKind() {
+      return NodeKind.VAR;
+    }
+
+    @Override
     public JsName getName() {
       return name;
     }
@@ -52,6 +56,7 @@
       this.initExpr = initExpr;
     }
 
+    @Override
     public void traverse(JsVisitor v, JsContext ctx) {
       if (v.visit(this, ctx)) {
         if (initExpr != null) {
@@ -72,6 +77,11 @@
     vars.add(var);
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.VARS;
+  }
+
   public int getNumVars() {
     return vars.size();
   }
@@ -81,10 +91,12 @@
   }
 
   // Iterator returns JsVar objects
+  @Override
   public Iterator<JsVar> iterator() {
     return vars.iterator();
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       v.acceptWithInsertRemove(vars);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsVisitable.java b/dev/core/src/com/google/gwt/dev/js/ast/JsVisitable.java
index cd37d2f..4d55475 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsVisitable.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsVisitable.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2007 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsVisitor.java b/dev/core/src/com/google/gwt/dev/js/ast/JsVisitor.java
index 142e462..ba5396c 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsVisitor.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -30,30 +28,37 @@
 
   protected static final JsContext LVALUE_CONTEXT = new JsContext() {
 
+    @Override
     public boolean canInsert() {
       return false;
     }
 
+    @Override
     public boolean canRemove() {
       return false;
     }
 
+    @Override
     public void insertAfter(JsVisitable node) {
       throw new UnsupportedOperationException();
     }
 
+    @Override
     public void insertBefore(JsVisitable node) {
       throw new UnsupportedOperationException();
     }
 
+    @Override
     public boolean isLvalue() {
       return true;
     }
 
+    @Override
     public void removeMe() {
       throw new UnsupportedOperationException();
     }
 
+    @Override
     public void replaceMe(JsVisitable node) {
       throw new UnsupportedOperationException();
     }
@@ -61,30 +66,37 @@
 
   protected static final JsContext UNMODIFIABLE_CONTEXT = new JsContext() {
 
+    @Override
     public boolean canInsert() {
       return false;
     }
 
+    @Override
     public boolean canRemove() {
       return false;
     }
 
+    @Override
     public void insertAfter(JsVisitable node) {
       throw new UnsupportedOperationException();
     }
 
+    @Override
     public void insertBefore(JsVisitable node) {
       throw new UnsupportedOperationException();
     }
 
+    @Override
     public boolean isLvalue() {
       return false;
     }
 
+    @Override
     public void removeMe() {
       throw new UnsupportedOperationException();
     }
 
+    @Override
     public void replaceMe(JsVisitable node) {
       throw new UnsupportedOperationException();
     }
@@ -105,8 +117,7 @@
     return doAcceptLvalue(expr);
   }
 
-  public final <T extends JsVisitable> void acceptWithInsertRemove(
-      List<T> collection) {
+  public final <T extends JsVisitable> void acceptWithInsertRemove(List<T> collection) {
     doAcceptWithInsertRemove(collection);
   }
 
@@ -439,8 +450,7 @@
     return expr;
   }
 
-  protected <T extends JsVisitable> void doAcceptWithInsertRemove(
-      List<T> collection) {
+  protected <T extends JsVisitable> void doAcceptWithInsertRemove(List<T> collection) {
     for (Iterator<T> it = collection.iterator(); it.hasNext();) {
       doTraverse(it.next(), UNMODIFIABLE_CONTEXT);
     }
@@ -454,8 +464,7 @@
     }
   }
 
-  private InternalCompilerException translateException(JsVisitable node,
-      Throwable e) {
+  private InternalCompilerException translateException(JsVisitable node, Throwable e) {
     if (e instanceof VirtualMachineError) {
       // Always rethrow VM errors (an attempt to wrap may fail).
       throw (VirtualMachineError) e;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsWhile.java b/dev/core/src/com/google/gwt/dev/js/ast/JsWhile.java
index af2b9d0..d1d6afb 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsWhile.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsWhile.java
@@ -1,16 +1,14 @@
 /*
  * Copyright 2008 Google Inc.
  * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
 package com.google.gwt.dev.js.ast;
@@ -44,6 +42,11 @@
     return condition;
   }
 
+  @Override
+  public NodeKind getKind() {
+    return NodeKind.WHILE;
+  }
+
   public void setBody(JsStatement body) {
     this.body = body;
   }
@@ -52,6 +55,7 @@
     this.condition = condition;
   }
 
+  @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
       condition = v.accept(condition);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/NodeKind.java b/dev/core/src/com/google/gwt/dev/js/ast/NodeKind.java
new file mode 100644
index 0000000..85b3095
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/js/ast/NodeKind.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.dev.js.ast;
+
+/**
+ * NodeKind used to simplify direct AST iteration.
+ */
+public enum NodeKind {
+  ARRAY_ACCESS, ARRAY, BINARY_OP, BLOCK, BOOLEAN, BREAK, CASE, CATCH, CONDITIONAL, CONTINUE, DEBUGGER, DEFAULT, DO, EMPTY, EXPR_STMT, FOR, FOR_IN, FUNCTION, IF, INVOKE, LABEL, NAME_REF, NAME_OF, NEW, NULL, NUMBER, OBJECT, PARAMETER, POSTFIX_OP, PREFIX_OP, PROGRAM, PROGRAM_FRAGMENT, PROPERTY_INIT, REGEXP, RETURN, SEED_ID_OF, STRING, SWITCH, THIS, THROW, TRY, VARS, VAR, WHILE
+}
diff --git a/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerEnableClosureCompiler.java b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerEnableClosureCompiler.java
new file mode 100644
index 0000000..206cccd
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerEnableClosureCompiler.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.util.arg;
+
+import com.google.gwt.util.tools.ArgHandlerFlag;
+
+/**
+ * An ArgHandler to provide the -enableClosureCompiler flag.
+ */
+public class ArgHandlerEnableClosureCompiler extends ArgHandlerFlag {
+
+  private final OptionEnableClosureCompiler option;
+
+  public ArgHandlerEnableClosureCompiler(OptionEnableClosureCompiler option) {
+    this.option = option;
+  }
+
+  @Override
+  public String getPurpose() {
+    return "EXPERIMENTAL: Enables Closure Compiler optimizations";
+  }
+
+  @Override
+  public String getTag() {
+    return "-XenableClosureCompiler";
+  }
+
+  @Override
+  public boolean setFlag() {
+    option.setClosureCompilerEnabled(true);
+    return true;
+  }
+}
diff --git a/dev/core/src/com/google/gwt/dev/util/arg/OptionEnableClosureCompiler.java b/dev/core/src/com/google/gwt/dev/util/arg/OptionEnableClosureCompiler.java
new file mode 100644
index 0000000..77649db
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/util/arg/OptionEnableClosureCompiler.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.util.arg;
+
+/**
+ * Encapsulates a compiler option to enable Closure Compiler optimizations.
+ */
+public interface OptionEnableClosureCompiler {
+  boolean isClosureCompilerEnabled();
+
+  void setClosureCompilerEnabled(boolean enabled);
+}