1) Util.maybeDumpSource() has structured error output now (which makes testing easier) and insists on a typeName.
2) TypeOracleBuilder fixed to provide that typeName.
3) TypeOracleTestingUtils factored out of JSORestrictionsTest to make generic utility methods.
4) JSORestrictionsTest now uses UnitTestTreeLogger rather than handrolled logger.

Patch by: spoon, scottb (pair prog)


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2216 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jdt/TypeOracleBuilder.java b/dev/core/src/com/google/gwt/dev/jdt/TypeOracleBuilder.java
index 77592a6..48b2ac4 100644
--- a/dev/core/src/com/google/gwt/dev/jdt/TypeOracleBuilder.java
+++ b/dev/core/src/com/google/gwt/dev/jdt/TypeOracleBuilder.java
@@ -420,7 +420,8 @@
 
         String fileName = CharOperation.charToString(cud.getFileName());
         char[] source = cud.compilationResult.compilationUnit.getContents();
-        Util.maybeDumpSource(logger, fileName, source, null);
+        Util.maybeDumpSource(logger, fileName, source,
+            String.valueOf(cud.getMainTypeName()));
         logger.log(TreeLogger.TRACE, "Removing problematic compilation unit '"
             + fileName + "'", null);
       }
diff --git a/dev/core/src/com/google/gwt/dev/util/Util.java b/dev/core/src/com/google/gwt/dev/util/Util.java
index 42d2baa..42bfaf4 100644
--- a/dev/core/src/com/google/gwt/dev/util/Util.java
+++ b/dev/core/src/com/google/gwt/dev/util/Util.java
@@ -541,37 +541,35 @@
   /**
    * Give the developer a chance to see the in-memory source that failed.
    */
-  public static String maybeDumpSource(TreeLogger logger, String location,
-      char[] source, String optionalTypeName) {
+  public static void maybeDumpSource(TreeLogger logger, String location,
+      char[] source, String typeName) {
 
     if (isCompilationUnitOnDisk(location)) {
       // Don't write another copy.
-      //
-      return null;
+      return;
+    }
+
+    TreeLogger branch = logger.branch(TreeLogger.ERROR,
+        "Compilation problem due to '" + location + "'", null);
+    if (!branch.isLoggable(TreeLogger.INFO)) {
+      // Don't bother dumping source if they can't see the related message.
+      return;
     }
 
     File tmpSrc;
     Throwable caught = null;
     try {
-      String prefix = "gen";
-      if (optionalTypeName != null) {
-        prefix = optionalTypeName;
-      }
-      tmpSrc = File.createTempFile(prefix, ".java");
+      tmpSrc = File.createTempFile(typeName, ".java");
       writeCharsAsFile(logger, tmpSrc, source);
       String dumpPath = tmpSrc.getAbsolutePath();
-      logger.log(TreeLogger.ERROR, "Compilation problem due to '" + location
-          + "'; see snapshot " + dumpPath, null);
-      return dumpPath;
+      branch.log(TreeLogger.INFO, "See snapshot: " + dumpPath, null);
+      return;
     } catch (IOException e) {
       caught = e;
     } catch (UnableToCompleteException e) {
       caught = e;
     }
-    logger.log(TreeLogger.ERROR,
-        "Compilation problem due to in-memory source '" + location
-            + "', but unable to dump to disk", caught);
-    return null;
+    branch.log(TreeLogger.INFO, "Unable to dump source to disk", caught);
   }
 
   public static byte[] readFileAsBytes(File file) {
diff --git a/dev/core/test/com/google/gwt/dev/jdt/JSORestrictionsTest.java b/dev/core/test/com/google/gwt/dev/jdt/JSORestrictionsTest.java
index 24da3e1..b4c8cde 100644
--- a/dev/core/test/com/google/gwt/dev/jdt/JSORestrictionsTest.java
+++ b/dev/core/test/com/google/gwt/dev/jdt/JSORestrictionsTest.java
@@ -17,8 +17,7 @@
 
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.dev.jdt.StaticCompilationUnitProvider;
-import com.google.gwt.dev.jdt.TypeOracleBuilder;
+import com.google.gwt.dev.util.UnitTestTreeLogger;
 
 import junit.framework.TestCase;
 
@@ -148,50 +147,6 @@
         + JSORestrictionsChecker.ERR_OVERRIDDEN_METHOD);
   }
 
-  private void addStandardCups(TypeOracleBuilder builder)
-      throws UnableToCompleteException {
-    StringBuffer code = new StringBuffer();
-    code.append("package java.lang;\n");
-    code.append("public class Object {\n");
-    code.append("  public String toString() { return \"Object\"; }\n");
-    code.append("  public Object clone() { return this; } ");
-    code.append("}\n");
-
-    StaticCompilationUnitProvider objectCup = new StaticCompilationUnitProvider(
-        "java.lang", "Object", code.toString().toCharArray());
-
-    code.setLength(0);
-    code.append("package java.lang;\n");
-    code.append("public final class String {\n");
-    code.append("  public int length() { return 0; }\n");
-    code.append("}\n");
-
-    StaticCompilationUnitProvider stringCup = new StaticCompilationUnitProvider(
-        "java.lang", "String", code.toString().toCharArray());
-
-    code.setLength(0);
-    code.append("package java.lang;\n");
-    code.append("public interface Serializable { }\n");
-
-    StaticCompilationUnitProvider serializableCup = new StaticCompilationUnitProvider(
-        "java.lang", "Serializable", code.toString().toCharArray());
-
-    code.setLength(0);
-    code.append("package com.google.gwt.core.client;\n");
-    code.append("public class JavaScriptObject {\n");
-    code.append("  protected JavaScriptObject() { }\n");
-    code.append("}\n");
-
-    StaticCompilationUnitProvider jsoCup = new StaticCompilationUnitProvider(
-        "com.google.gwt.core.client", "JavaScriptObject",
-        code.toString().toCharArray());
-
-    builder.addCompilationUnit(objectCup);
-    builder.addCompilationUnit(stringCup);
-    builder.addCompilationUnit(serializableCup);
-    builder.addCompilationUnit(jsoCup);
-  }
-
   /**
    * Test that when compiling buggyCode, the TypeOracleBuilder emits
    * expectedError somewhere in its output. The code should define a class named
@@ -199,35 +154,14 @@
    */
   private void shouldGenerateError(CharSequence buggyCode,
       final String expectedError) throws UnableToCompleteException {
-    TypeOracleBuilder builder = new TypeOracleBuilder();
-    addStandardCups(builder);
-
-    StaticCompilationUnitProvider buggyCup = new StaticCompilationUnitProvider(
-        "", "Buggy", buggyCode.toString().toCharArray());
-    builder.addCompilationUnit(buggyCup);
-
-    final boolean[] gotExpectedError = new boolean[1];
-
-    TreeLogger testLogger = new TreeLogger() {
-      public TreeLogger branch(Type type, String msg, Throwable caught) {
-        return this;
-      }
-
-      public boolean isLoggable(Type type) {
-        return type == ERROR;
-      }
-
-      public void log(Type type, String msg, Throwable caught) {
-        if (type == ERROR && msg.startsWith("Line ")) {
-          assertEquals(null, caught);
-          assertEquals(expectedError, msg);
-          gotExpectedError[0] = true;
-        }
-      }
-    };
-
-    builder.build(testLogger);
-    assertTrue("Failed to get expected error: '" + expectedError + "'",
-        gotExpectedError[0]);
+    UnitTestTreeLogger.Builder builder = new UnitTestTreeLogger.Builder();
+    builder.setLowestLogLevel(TreeLogger.ERROR);
+    builder.expectError("Errors in \'transient source for Buggy\'", null);
+    builder.expectError(expectedError, null);
+    builder.expectError(
+        "Compilation problem due to \'transient source for Buggy\'", null);
+    UnitTestTreeLogger logger = builder.createLogger();
+    TypeOracleTestingUtils.buildTypeOracleForCode("Buggy", buggyCode, logger);
+    logger.assertCorrectLogEntries();
   }
 }
diff --git a/dev/core/test/com/google/gwt/dev/jdt/TypeOracleTestingUtils.java b/dev/core/test/com/google/gwt/dev/jdt/TypeOracleTestingUtils.java
new file mode 100644
index 0000000..a3263b0
--- /dev/null
+++ b/dev/core/test/com/google/gwt/dev/jdt/TypeOracleTestingUtils.java
@@ -0,0 +1,104 @@
+/*
+ * 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.jdt;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+
+/**
+ * Utilities for tests that build a type oracle and watch for errors.
+ * 
+ */
+public class TypeOracleTestingUtils {
+
+  public static void addCup(TypeOracleBuilder builder, String typeName,
+      CharSequence code) throws UnableToCompleteException {
+    String packageName;
+    String className;
+    int pos = typeName.lastIndexOf('.');
+    if (pos >= 0) {
+      packageName = typeName.substring(0, pos);
+      className = typeName.substring(pos + 1);
+    } else {
+      packageName = "";
+      className = typeName;
+    }
+    StaticCompilationUnitProvider cup = new StaticCompilationUnitProvider(
+        packageName, className, code.toString().toCharArray());
+    builder.addCompilationUnit(cup);
+  }
+
+  /**
+   * Add compilation units for basic classes like Object and String.
+   */
+  public static void addStandardCups(TypeOracleBuilder builder)
+      throws UnableToCompleteException {
+    {
+      StringBuffer code = new StringBuffer();
+      code.append("package java.lang;\n");
+      code.append("public class Object {\n");
+      code.append("  public String toString() { return \"Object\"; }\n");
+      code.append("  public Object clone() { return this; } ");
+      code.append("}\n");
+      addCup(builder, "java.lang.Object", code);
+    }
+    {
+      StringBuffer code = new StringBuffer();
+      code.append("package java.lang;\n");
+      code.append("public final class String {\n");
+      code.append("  public int length() { return 0; }\n");
+      code.append("}\n");
+      addCup(builder, "java.lang.String", code);
+    }
+    {
+      StringBuffer code = new StringBuffer();
+      code.append("package java.lang;\n");
+      code.append("public interface Serializable { }\n");
+      addCup(builder, "java.lang.Serializable", code);
+    }
+    {
+      StringBuffer code = new StringBuffer();
+      code.append("package java.lang;\n");
+      code.append("public @interface SuppressWarnings {\n");
+      code.append("  String[] value();\n");
+      code.append("}\n");
+      addCup(builder, "java.lang.SuppressWarnings", code);
+    }
+    {
+      StringBuffer code = new StringBuffer();
+      code.append("package java.lang.annotation;\n");
+      code.append("public interface Annotation {\n");
+      code.append("}\n");
+      addCup(builder, "java.lang.annotation.Annotation", code);
+    }
+    {
+      StringBuffer code = new StringBuffer();
+      code.append("package com.google.gwt.core.client;\n");
+      code.append("public class JavaScriptObject {\n");
+      code.append("  protected JavaScriptObject() { }\n");
+      code.append("}\n");
+      addCup(builder, "com.google.gwt.core.client.JavaScriptObject", code);
+    }
+  }
+
+  public static void buildTypeOracleForCode(String typeName, CharSequence code,
+      TreeLogger testLogger) throws UnableToCompleteException {
+    TypeOracleBuilder builder = new TypeOracleBuilder();
+    addStandardCups(builder);
+    addCup(builder, typeName, code);
+    builder.build(testLogger);
+  }
+}