- Minor code gen optimization: no longer prints CRLFs into generated output on Windows in obfuscated mode (just LF).
- In non-obfuscated mode, all compiler output uses appropriate platform text line endings (CRLF on Windows)
- TextOutputOnPrintWriter renamed to DefaultTextOutput 
- Simplified interface to DefaultTextOutput to remove a lot of duplicate code.
- Removed unncessary flushing in DefaultTextOutput; possible due to interface change.
- Removed mostly duplicate TextOutputOnCharArray; everything uses DefaultTextOutput now.

Suggested by: fredsa
Review by: bruce


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@953 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/GWTCompiler.java b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
index 7c63b9a..bdda80b 100644
--- a/dev/core/src/com/google/gwt/dev/GWTCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
@@ -36,6 +36,7 @@
 import com.google.gwt.dev.jdt.WebModeCompilerFrontEnd;
 import com.google.gwt.dev.jjs.JavaToJavaScriptCompiler;
 import com.google.gwt.dev.shell.StandardRebindOracle;
+import com.google.gwt.dev.util.DefaultTextOutput;
 import com.google.gwt.dev.util.SelectionScriptGenerator;
 import com.google.gwt.dev.util.Util;
 import com.google.gwt.dev.util.arg.ArgHandlerGenDir;
@@ -441,78 +442,92 @@
   }
 
   private String getHtmlPrefix() {
-    StringBuffer sb = new StringBuffer();
-
-    sb.append("<html>\n");
+    DefaultTextOutput out = new DefaultTextOutput(obfuscate);
+    out.print("<html>");
+    out.newlineOpt();
 
     // Setup the well-known variables.
     //
-    sb.append("<head><script>\n");
-    sb.append("var $wnd = parent;\n");
-    sb.append("var $doc = $wnd.document;\n");
-    sb.append("var $moduleName = \"" + moduleName + "\";\n");
-    sb.append("</script></head>\n");
-    sb.append("<body>\n");
+    out.print("<head><script>");
+    out.newlineOpt();
+    out.print("var $wnd = parent;");
+    out.newlineOpt();
+    out.print("var $doc = $wnd.document;");
+    out.newlineOpt();
+    out.print("var $moduleName = \"" + moduleName + "\";");
+    out.newlineOpt();
+    out.print("</script></head>");
+    out.newlineOpt();
+    out.print("<body>");
+    out.newlineOpt();
 
     // A nice message in case someone opens the file directly.
     //
-    sb.append("<font face='arial' size='-1'>This script is part of module</font>\n");
-    sb.append("<code>");
-    sb.append(module.getName());
-    sb.append("</code>\n");
+    out.print("<font face='arial' size='-1'>This script is part of module</font>");
+    out.newlineOpt();
+    out.print("<code>");
+    out.print(module.getName());
+    out.print("</code>");
+    out.newlineOpt();
 
     // Begin a script block inside the body. It's commented out so that the
     // browser won't mistake strings containing "<script>" for actual script.
-    sb.append("<script><!--\n");
-
-    String s = sb.toString();
-    return s;
+    out.print("<script><!--");
+    out.newline();
+    return out.toString();
   }
 
   private String getHtmlSuffix() {
-    StringBuffer sb = new StringBuffer();
+    DefaultTextOutput out = new DefaultTextOutput(obfuscate);
     String moduleFunction = module.getName().replace('.', '_');
 
     // Generate the call to tell the bootstrap code that we're ready to go.
-    sb.append("\n");
-    sb.append("if ($wnd." + moduleFunction + ") $wnd." + moduleFunction
-        + ".onScriptLoad();\n");
-    sb.append("--></script></body></html>\n");
+    out.newlineOpt();
+    out.print("if ($wnd." + moduleFunction + ") $wnd." + moduleFunction
+        + ".onScriptLoad();");
+    out.newline();
+    out.print("--></script></body></html>");
+    out.newlineOpt();
 
-    String s = sb.toString();
-    return s;
+    return out.toString();
   }
 
   private String getJsPrefix() {
-    StringBuffer sb = new StringBuffer();
+    DefaultTextOutput out = new DefaultTextOutput(obfuscate);
 
-    sb.append("(function(){\n");
+    out.print("(function(){");
+    out.newlineOpt();
 
     // Setup the well-known variables.
     //
-    sb.append("var $wnd = parent;\n");
-    sb.append("var $doc = $wnd.document;\n");
-    sb.append("var $moduleName = \"" + moduleName + "\";\n");
+    out.print("var $wnd = parent;");
+    out.newlineOpt();
+    out.print("var $doc = $wnd.document;");
+    out.newlineOpt();
+    out.print("var $moduleName = \"" + moduleName + "\";");
+    out.newlineOpt();
 
-    String s = sb.toString();
-    return s;
+    return out.toString();
   }
 
   private String getJsSuffix() {
-    StringBuffer sb = new StringBuffer();
+    DefaultTextOutput out = new DefaultTextOutput(obfuscate);
     String moduleFunction = module.getName().replace('.', '_');
 
     // Generate the call to tell the bootstrap code that we're ready to go.
-    sb.append("\n");
-    sb.append("if (" + moduleFunction + ") {\n");
-    sb.append("  var __gwt_initHandlers = " + moduleFunction
-        + ".__gwt_initHandlers;\n");
-    sb.append("  " + moduleFunction + ".onScriptLoad(gwtOnLoad);\n");
-    sb.append("}\n");
-    sb.append("})();\n");
+    out.newlineOpt();
+    out.print("if (" + moduleFunction + ") {");
+    out.newlineOpt();
+    out.print("  var __gwt_initHandlers = " + moduleFunction
+        + ".__gwt_initHandlers;");
+    out.print("  " + moduleFunction + ".onScriptLoad(gwtOnLoad);");
+    out.newlineOpt();
+    out.print("}");
+    out.newlineOpt();
+    out.print("})();");
+    out.newlineOpt();
 
-    String s = sb.toString();
-    return s;
+    return out.toString();
   }
 
   /**
@@ -706,7 +721,7 @@
   private boolean run() {
     // Set any platform specific system properties.
     BootStrapPlatform.setSystemProperties();
-    
+
     if (useGuiLogger) {
       // Initialize a tree logger window.
       DetachedTreeLoggerWindow loggerWindow = DetachedTreeLoggerWindow.getInstance(
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 517029e..476b023 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -56,7 +56,7 @@
 import com.google.gwt.dev.js.JsSymbolResolver;
 import com.google.gwt.dev.js.JsVerboseNamer;
 import com.google.gwt.dev.js.ast.JsProgram;
-import com.google.gwt.dev.util.TextOutputOnPrintWriter;
+import com.google.gwt.dev.util.DefaultTextOutput;
 import com.google.gwt.dev.util.Util;
 
 import org.eclipse.jdt.core.compiler.IProblem;
@@ -64,8 +64,6 @@
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 
-import java.io.PrintWriter;
-import java.io.StringWriter;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -401,13 +399,10 @@
         JsVerboseNamer.exec(jsProgram);
       }
 
-      StringWriter sw = new StringWriter();
-      PrintWriter pw = new PrintWriter(sw, true);
-      TextOutputOnPrintWriter out = new TextOutputOnPrintWriter(pw, obfuscate);
+      DefaultTextOutput out = new DefaultTextOutput(obfuscate);
       JsSourceGenerationVisitor v = new JsSourceGenerationVisitor(out);
       v.accept(jsProgram);
-
-      return sw.toString();
+      return out.toString();
     } catch (UnableToCompleteException e) {
       // just rethrow
       throw e;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JNode.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JNode.java
index 6822888..b8c9ba0 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JNode.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JNode.java
@@ -19,7 +19,7 @@
 import com.google.gwt.dev.jjs.SourceInfo;
 import com.google.gwt.dev.jjs.impl.SourceGenerationVisitor;
 import com.google.gwt.dev.jjs.impl.ToStringGenerationVisitor;
-import com.google.gwt.dev.util.TextOutputOnCharArray;
+import com.google.gwt.dev.util.DefaultTextOutput;
 
 /**
  * Base class for all visitable AST nodes.
@@ -45,17 +45,17 @@
 
   // Causes source generation to delegate to the one visitor
   public final String toSource() {
-    TextOutputOnCharArray p = new TextOutputOnCharArray(false);
-    SourceGenerationVisitor v = new SourceGenerationVisitor(p);
+    DefaultTextOutput out = new DefaultTextOutput(false);
+    SourceGenerationVisitor v = new SourceGenerationVisitor(out);
     v.accept(this);
-    return new String(p.getText());
+    return out.toString();
   }
 
   // Causes source generation to delegate to the one visitor
   public final String toString() {
-    TextOutputOnCharArray p = new TextOutputOnCharArray(false);
-    ToStringGenerationVisitor v = new ToStringGenerationVisitor(p);
+    DefaultTextOutput out = new DefaultTextOutput(false);
+    ToStringGenerationVisitor v = new ToStringGenerationVisitor(out);
     v.accept(this);
-    return new String(p.getText());
+    return out.toString();
   }
 }
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 87799fa..9182255 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
@@ -19,7 +19,7 @@
 import com.google.gwt.dev.jjs.SourceInfo;
 import com.google.gwt.dev.js.JsSourceGenerationVisitor;
 import com.google.gwt.dev.js.JsToStringGenerationVisitor;
-import com.google.gwt.dev.util.TextOutputOnCharArray;
+import com.google.gwt.dev.util.DefaultTextOutput;
 
 /**
  * Base class for all JS AST elements.
@@ -30,20 +30,20 @@
     // TODO: make this real
     return null;
   }
-  
+
   // Causes source generation to delegate to the one visitor
   public final String toSource() {
-    TextOutputOnCharArray p = new TextOutputOnCharArray(false);
-    JsSourceGenerationVisitor v = new JsSourceGenerationVisitor(p);
+    DefaultTextOutput out = new DefaultTextOutput(false);
+    JsSourceGenerationVisitor v = new JsSourceGenerationVisitor(out);
     v.accept(this);
-    return new String(p.getText());
+    return out.toString();
   }
 
   // Causes source generation to delegate to the one visitor
   public final String toString() {
-    TextOutputOnCharArray p = new TextOutputOnCharArray(false);
-    JsToStringGenerationVisitor v = new JsToStringGenerationVisitor(p);
+    DefaultTextOutput out = new DefaultTextOutput(false);
+    JsToStringGenerationVisitor v = new JsToStringGenerationVisitor(out);
     v.accept(this);
-    return new String(p.getText());
+    return out.toString();
   }
 }
diff --git a/dev/core/src/com/google/gwt/dev/util/TextOutputOnPrintWriter.java b/dev/core/src/com/google/gwt/dev/util/DefaultTextOutput.java
similarity index 82%
rename from dev/core/src/com/google/gwt/dev/util/TextOutputOnPrintWriter.java
rename to dev/core/src/com/google/gwt/dev/util/DefaultTextOutput.java
index 14fb6df..5f469e6 100644
--- a/dev/core/src/com/google/gwt/dev/util/TextOutputOnPrintWriter.java
+++ b/dev/core/src/com/google/gwt/dev/util/DefaultTextOutput.java
@@ -16,29 +16,26 @@
 package com.google.gwt.dev.util;
 
 import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.Arrays;
 
 /**
  * Adapts {@link TextOutput} to a print writer.
  */
-public final class TextOutputOnPrintWriter implements TextOutput {
+public final class DefaultTextOutput implements TextOutput {
 
   private final boolean compact;
   private int identLevel = 0;
-  private int indentGranularity;
+  private int indentGranularity = 2;
   private char[][] indents = new char[][] {new char[0]};
   private boolean justNewlined;
   private final PrintWriter p;
+  private final StringWriter sw;
 
-  public TextOutputOnPrintWriter(PrintWriter writer, boolean compact) {
-    this(writer, compact, 2);
-  }
-
-  public TextOutputOnPrintWriter(PrintWriter writer, boolean compact,
-      int indentGranularity) {
-    this.indentGranularity = indentGranularity;
+  public DefaultTextOutput(boolean compact) {
     this.compact = compact;
-    p = writer;
+    sw = new StringWriter();
+    p = new PrintWriter(sw, false);
   }
 
   public void indentIn() {
@@ -54,41 +51,42 @@
       indents = newIndents;
     }
   }
-
+  
   public void indentOut() {
     --identLevel;
   }
 
   public void newline() {
-    p.println();
+    if (compact) {
+      p.print('\n');
+    } else {
+      p.println();
+    }
     justNewlined = true;
   }
 
   public void newlineOpt() {
     if (!compact) {
       p.println();
+      justNewlined = true;
     }
-    justNewlined = true;
   }
 
   public void print(char c) {
     maybeIndent();
     p.print(c);
-    p.flush();
     justNewlined = false;
   }
 
   public void print(char[] s) {
     maybeIndent();
     p.print(s);
-    p.flush();
     justNewlined = false;
   }
 
   public void print(String s) {
     maybeIndent();
     p.print(s);
-    p.flush();
     justNewlined = false;
   }
 
@@ -96,7 +94,6 @@
     if (!compact) {
       maybeIndent();
       p.print(c);
-      p.flush();
     }
   }
 
@@ -104,7 +101,6 @@
     if (!compact) {
       maybeIndent();
       p.print(s);
-      p.flush();
     }
   }
 
@@ -112,10 +108,14 @@
     if (!compact) {
       maybeIndent();
       p.print(s);
-      p.flush();
     }
   }
 
+  public String toString() {
+    p.flush();
+    return sw.toString();
+  }
+
   private void maybeIndent() {
     if (justNewlined && !compact) {
       p.print(indents[identLevel]);
diff --git a/dev/core/src/com/google/gwt/dev/util/Jsni.java b/dev/core/src/com/google/gwt/dev/util/Jsni.java
index 1f43e86..99d7781 100644
--- a/dev/core/src/com/google/gwt/dev/util/Jsni.java
+++ b/dev/core/src/com/google/gwt/dev/util/Jsni.java
@@ -380,11 +380,10 @@
    * JSNI idents have been replaced with legal JavaScript for hosted mode.
    */
   private static String generateJavaScriptForHostedMode(JsNode node) {
-    TextOutputOnCharArray tooca = new TextOutputOnCharArray(false);
-    JsSourceGenWithJsniIdentFixup vi = new JsSourceGenWithJsniIdentFixup(tooca);
+    DefaultTextOutput out = new DefaultTextOutput(false);
+    JsSourceGenWithJsniIdentFixup vi = new JsSourceGenWithJsniIdentFixup(out);
     vi.accept(node);
-    char[] source = tooca.getText();
-    return String.valueOf(source);
+    return out.toString();
   }
 
 }
diff --git a/dev/core/src/com/google/gwt/dev/util/SelectionScriptGenerator.java b/dev/core/src/com/google/gwt/dev/util/SelectionScriptGenerator.java
index 4114381..3ba7fe7 100644
--- a/dev/core/src/com/google/gwt/dev/util/SelectionScriptGenerator.java
+++ b/dev/core/src/com/google/gwt/dev/util/SelectionScriptGenerator.java
@@ -216,12 +216,10 @@
           JsVerboseNamer.exec(jsProgram);
         }
 
-        StringWriter sw = new StringWriter();
-        PrintWriter pw = new PrintWriter(sw, true);
-        TextOutputOnPrintWriter out = new TextOutputOnPrintWriter(pw, obfuscate);
+        DefaultTextOutput out = new DefaultTextOutput(obfuscate);
         JsSourceGenerationVisitor v = new JsSourceGenerationVisitor(out);
         v.accept(jsProgram);
-        return sw.toString();
+        return out.toString();
       }
     } catch (IOException e) {
       throw new RuntimeException("Error processing selection script template.",
diff --git a/dev/core/src/com/google/gwt/dev/util/TextOutputOnCharArray.java b/dev/core/src/com/google/gwt/dev/util/TextOutputOnCharArray.java
deleted file mode 100644
index 2376b2c..0000000
--- a/dev/core/src/com/google/gwt/dev/util/TextOutputOnCharArray.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright 2006 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;
-
-import java.io.CharArrayWriter;
-import java.io.PrintWriter;
-import java.util.Arrays;
-
-/**
- * Implements {@link TextOutput} on top of a character array.
- */
-public class TextOutputOnCharArray implements TextOutput {
-
-  private final CharArrayWriter charArrayWriter;
-  private final boolean compact;
-  private int indent = 0;
-  private int indentGranularity;
-  private char[][] indents = new char[][] {new char[0]};
-  private boolean justNewlined;
-  private final PrintWriter p;
-
-  public TextOutputOnCharArray(boolean compact) {
-    indentGranularity = 2;
-    charArrayWriter = new CharArrayWriter(50 * 1024);
-    p = new PrintWriter(charArrayWriter);
-    this.compact = compact;
-  }
-
-  public int getIndent() {
-    return indent;
-  }
-
-  public char[] getText() {
-    return charArrayWriter.toCharArray();
-  }
-
-  public void indentIn() {
-    ++indent;
-    if (indent >= indents.length) {
-      // Cache a new level of indentation string.
-      //
-      char[] newIndentLevel = new char[indent * indentGranularity];
-      Arrays.fill(newIndentLevel, ' ');
-      char[][] newIndents = new char[indents.length + 1][];
-      System.arraycopy(indents, 0, newIndents, 0, indents.length);
-      newIndents[indent] = newIndentLevel;
-      indents = newIndents;
-    }
-  }
-
-  public void indentOut() {
-    --indent;
-  }
-
-  public void newline() {
-    p.print('\n');
-    // TODO: remove flush calls
-    p.flush();
-    justNewlined = true;
-  }
-
-  public void newlineOpt() {
-    if (!compact) {
-      p.print('\n');
-      // TODO: remove flush calls
-      p.flush();
-    }
-    justNewlined = true;
-  }
-
-  public void print(char c) {
-    maybeIndent();
-    p.print(c);
-    // TODO: remove flush calls
-    p.flush();
-    justNewlined = false;
-  }
-
-  public void print(char[] s) {
-    maybeIndent();
-    p.print(s);
-    // TODO: remove flush calls
-    p.flush();
-    justNewlined = false;
-  }
-
-  public void print(String s) {
-    maybeIndent();
-    p.print(s);
-    // TODO: remove flush calls
-    p.flush();
-    justNewlined = false;
-  }
-
-  public void printOpt(char c) {
-    if (!compact) {
-      maybeIndent();
-      p.print(c);
-      // TODO: remove flush calls
-      p.flush();
-    }
-  }
-
-  public void printOpt(char[] s) {
-    if (!compact) {
-      maybeIndent();
-      p.print(s);
-      // TODO: remove flush calls
-      p.flush();
-    }
-  }
-
-  public void printOpt(String s) {
-    if (!compact) {
-      maybeIndent();
-      p.print(s);
-      // TODO: remove flush calls
-      p.flush();
-    }
-  }
-
-  public void setIndent(int indent) {
-    this.indent = indent;
-  }
-
-  private void maybeIndent() {
-    if (justNewlined && !compact) {
-      p.print(indents[indent]);
-      // TODO: remove flush calls
-      p.flush();
-      justNewlined = false;
-    }
-  }
-}