Make CodeServer force next recompile after clearing cache.

When navigating to the CodeServer web page (http://localhost:9876/), the
clean button will clear caches, but does not force the next recompile.
If no changes were made to your module, the next compile will say
"skipped compile because no input files have changed."

If you're cleaning the caches, it's presumably because you're having
some issues — in which case serving up the previous compile doesn't make
much sense. This forces you to make some arbitrary change to your module
to force the recompile.

Using the clean button should always force the next recompile.

Closes #9293 on GitHub

Change-Id: I55f599900ea8f2e9752862c00a2bc255dae894c1
diff --git a/dev/codeserver/java/com/google/gwt/dev/codeserver/JobRunner.java b/dev/codeserver/java/com/google/gwt/dev/codeserver/JobRunner.java
index f7b2e45..265446b 100644
--- a/dev/codeserver/java/com/google/gwt/dev/codeserver/JobRunner.java
+++ b/dev/codeserver/java/com/google/gwt/dev/codeserver/JobRunner.java
@@ -48,10 +48,10 @@
   /**
    * Submits a cleaner job to be executed. (Waits for completion.)
    */
-  void clean(TreeLogger logger) throws ExecutionException {
+  void clean(final TreeLogger logger, final OutboxTable outboxTable) throws ExecutionException {
     try {
       TreeLogger branch = logger.branch(TreeLogger.INFO, "Cleaning disk caches.");
-      executor.submit(new CleanerJob(branch)).get();
+      executor.submit(new CleanerJob(branch, outboxTable)).get();
     } catch (InterruptedException e) {
       // Allow the JVM to shutdown.
     }
@@ -114,17 +114,20 @@
   }
 
   /**
-   * A callable for clearing both unit and minimalRebuild caches.
+   * A callable for clearing both unit and minimalRebuild caches. It also forces the next recompile
+   * even if no input files have changed.
    * <p>
    * By packaging it as a callable and running it in the ExecutorService any danger of clearing
    * caches at the same time as an active compile job is avoided.
    */
   private class CleanerJob implements Callable<Void> {
 
+    private final OutboxTable outboxTable;
     private TreeLogger logger;
 
-    public CleanerJob(TreeLogger logger) {
+    public CleanerJob(final TreeLogger logger, final OutboxTable outboxTable) {
       this.logger = logger;
+      this.outboxTable = outboxTable;
     }
 
     @Override
@@ -132,6 +135,7 @@
       long beforeMs = System.nanoTime() / 1000000L;
       minimalRebuildCacheManager.deleteCaches();
       UnitCacheSingleton.clearCache();
+      outboxTable.forceNextRecompileAll();
       long afterMs = System.nanoTime() / 1000000L;
       logger.log(TreeLogger.INFO, String.format("Cleaned in %sms.", (afterMs - beforeMs)));
       return null;
diff --git a/dev/codeserver/java/com/google/gwt/dev/codeserver/Outbox.java b/dev/codeserver/java/com/google/gwt/dev/codeserver/Outbox.java
index a744d93..2640e18 100644
--- a/dev/codeserver/java/com/google/gwt/dev/codeserver/Outbox.java
+++ b/dev/codeserver/java/com/google/gwt/dev/codeserver/Outbox.java
@@ -66,6 +66,13 @@
   }
 
   /**
+   * Forces the next recompile even if no input files have changed.
+   */
+  void forceNextRecompile() {
+    recompiler.forceNextRecompile();
+  }
+
+  /**
    * A unique id for this outbox. (This should be treated as an opaque string.)
    */
   String getId() {
diff --git a/dev/codeserver/java/com/google/gwt/dev/codeserver/OutboxTable.java b/dev/codeserver/java/com/google/gwt/dev/codeserver/OutboxTable.java
index 220a487..f48cc17 100644
--- a/dev/codeserver/java/com/google/gwt/dev/codeserver/OutboxTable.java
+++ b/dev/codeserver/java/com/google/gwt/dev/codeserver/OutboxTable.java
@@ -81,6 +81,12 @@
     }
   }
 
+  void forceNextRecompileAll() {
+    for (Outbox box: outboxes.values()) {
+      box.forceNextRecompile();
+    }
+  }
+
   /**
    * Given the name of a policy file, searches all the boxes for a file with that name.
    * Returns null if not found.
diff --git a/dev/codeserver/java/com/google/gwt/dev/codeserver/Recompiler.java b/dev/codeserver/java/com/google/gwt/dev/codeserver/Recompiler.java
index f407e25..3e8c7a0 100644
--- a/dev/codeserver/java/com/google/gwt/dev/codeserver/Recompiler.java
+++ b/dev/codeserver/java/com/google/gwt/dev/codeserver/Recompiler.java
@@ -100,6 +100,13 @@
   }
 
   /**
+   * Forces the next recompile even if no input files have changed.
+   */
+  void forceNextRecompile() {
+    previousInputSummary = null;
+  }
+
+  /**
    * Compiles the first time, while Super Dev Mode is starting up.
    * Either this method or {@link #initWithoutPrecompile} should be called first.
    */
@@ -336,7 +343,7 @@
       return true;
     }
     // Force a recompile if we don't succeed.
-    previousInputSummary = null;
+    forceNextRecompile();
 
     job.onProgress("Compiling");
 
diff --git a/dev/codeserver/java/com/google/gwt/dev/codeserver/WebServer.java b/dev/codeserver/java/com/google/gwt/dev/codeserver/WebServer.java
index 930ef4f..7af168f 100644
--- a/dev/codeserver/java/com/google/gwt/dev/codeserver/WebServer.java
+++ b/dev/codeserver/java/com/google/gwt/dev/codeserver/WebServer.java
@@ -232,7 +232,7 @@
     if (target.startsWith("/clean")) {
       JsonObject json = null;
       try {
-        runner.clean(logger);
+        runner.clean(logger, outboxes);
         json = jsonExporter.exportOk("Cleaned disk caches.");
       } catch (ExecutionException e) {
         json = jsonExporter.exportError(e.getMessage());