Refactor SOYC to produce artifacts more directly.

Patch by: spoon
Review by: me



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@6498 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/CompilationAnalysis.java b/dev/core/src/com/google/gwt/core/ext/linker/CompilationAnalysis.java
deleted file mode 100644
index 982499a..0000000
--- a/dev/core/src/com/google/gwt/core/ext/linker/CompilationAnalysis.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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.core.ext.linker;
-
-import com.google.gwt.core.ext.Linker;
-import com.google.gwt.core.ext.linker.impl.StandardCompilationAnalysis.SoycArtifact;
-
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Represents analysis data for a CompilationResult.
- */
-public abstract class CompilationAnalysis extends Artifact<CompilationAnalysis> {
-
-  protected CompilationAnalysis(Class<? extends Linker> linkerType) {
-    super(linkerType);
-  }
-
-  /**
-   * @return a file of dependencies
-   */
-  public abstract EmittedArtifact getDepFile();
-
-  /**
-   * @return a file with detailed story information
-   */
-  public abstract EmittedArtifact getDetailedStoriesFile();
-
-  /**
-   * Files containing the HTML dashboard.
-   */
-
-  public abstract List<SoycArtifact> getReportFiles();
-
-  /**
-   * @return a file of size maps
-   */
-  public abstract EmittedArtifact getSizeMapsFile();
-
-  /**
-   * @return a file of split points
-   */
-  public abstract EmittedArtifact getSplitPointsFile();
-
-  @Override
-  public final int hashCode() {
-    int code = 37;
-    for (EmittedArtifact file : allFiles()) {
-      if (file == null) {
-        code = code * 17 + 37;
-      } else {
-        code = code * 17 + file.getPartialPath().hashCode();
-      }
-    }
-    return code;
-  }
-
-  @Override
-  protected final int compareToComparableArtifact(CompilationAnalysis o) {
-    LinkedList<EmittedArtifact> myFiles = new LinkedList<EmittedArtifact>(
-        allFiles());
-    LinkedList<EmittedArtifact> otherFiles = new LinkedList<EmittedArtifact>(
-        o.allFiles());
-
-    while (!myFiles.isEmpty()) {
-      if (otherFiles.isEmpty()) {
-        return 1;
-      }
-
-      EmittedArtifact myFile = myFiles.removeFirst();
-      EmittedArtifact otherFile = otherFiles.removeFirst();
-      if (myFile == null && otherFile == null) {
-        continue;
-      }
-      if (myFile == null && otherFile != null) {
-        return -1;
-      }
-      if (myFile != null && otherFile == null) {
-        return 1;
-      }
-      assert myFile != null;
-      assert otherFile != null;
-
-      int fileCompare = myFile.getPartialPath().compareTo(
-          otherFile.getPartialPath());
-      if (fileCompare != 0) {
-        return fileCompare;
-      }
-    }
-
-    if (!otherFiles.isEmpty()) {
-      return -1;
-    }
-
-    return 0;
-  }
-
-  @Override
-  protected final Class<CompilationAnalysis> getComparableArtifactType() {
-    return CompilationAnalysis.class;
-  }
-
-  private List<EmittedArtifact> allFiles() {
-    List<EmittedArtifact> files = new ArrayList<EmittedArtifact>();
-    files.add(getSplitPointsFile());
-    files.add(getDepFile());
-    files.add(getSizeMapsFile());
-    files.add(getDetailedStoriesFile());
-    files.addAll(getReportFiles());
-    return files;
-  }
-}
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardCompilationAnalysis.java b/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardCompilationAnalysis.java
deleted file mode 100644
index 327c5ba..0000000
--- a/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardCompilationAnalysis.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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.core.ext.linker.impl;
-
-import com.google.gwt.core.ext.linker.CompilationAnalysis;
-import com.google.gwt.core.ext.linker.SyntheticArtifact;
-import com.google.gwt.core.linker.SoycReportLinker;
-
-import java.util.List;
-
-/**
- * An implementation of CompilationAnalysis. This class transforms SourceInfos
- * and related data into an API suitable for public consumption via the Linker
- * API.
- */
-public class StandardCompilationAnalysis extends CompilationAnalysis {
-
-  /**
-   * A SOYC artifact. The existence of this class is an implementation detail.
-   */
-  public static class SoycArtifact extends SyntheticArtifact {
-    public SoycArtifact(String partialPath, byte[] bytes) {
-      super(SoycReportLinker.class, partialPath, bytes);
-      setPrivate(true);
-    }
-  }
-
-  /**
-   * File containing method-level control-flow dependencies (corresponding to
-   * the current report).
-   */
-  private SoycArtifact depFile;
-
-  /**
-   * File containing detailed story information.
-   */
-  private SoycArtifact detailedStoriesFile;
-
-  /**
-   * Files containing the HTML dashboard.
-   */
-  private List<SoycArtifact> reportFiles;
-
-  /**
-   * File containing size maps.
-   */
-  private SoycArtifact sizeMapsFile;
-
-  /**
-   * File containing split points.
-   */
-  private SoycArtifact splitPointsFile;
-
-  /**
-   * Constructed by PermutationCompiler.
-   */
-  public StandardCompilationAnalysis(SoycArtifact dependencies,
-      SoycArtifact sizeMaps, SoycArtifact splitPoints,
-      SoycArtifact detailedStories, List<SoycArtifact> reportFiles) {
-    super(StandardLinkerContext.class);
-    this.depFile = dependencies;
-    this.sizeMapsFile = sizeMaps;
-    this.splitPointsFile = splitPoints;
-    this.detailedStoriesFile = detailedStories;
-    this.reportFiles = reportFiles;
-  }
-
-  @Override
-  public SoycArtifact getDepFile() {
-    return depFile;
-  }
-
-  @Override
-  public SoycArtifact getDetailedStoriesFile() {
-    return detailedStoriesFile;
-  }
-
-  @Override
-  public List<SoycArtifact> getReportFiles() {
-    return reportFiles;
-  }
-
-  @Override
-  public SoycArtifact getSizeMapsFile() {
-    return sizeMapsFile;
-  }
-
-  @Override
-  public SoycArtifact getSplitPointsFile() {
-    return splitPointsFile;
-  }
-}
diff --git a/dev/core/src/com/google/gwt/core/ext/soyc/package-info.java b/dev/core/src/com/google/gwt/core/ext/soyc/package-info.java
index 5cb0045..50693fb 100644
--- a/dev/core/src/com/google/gwt/core/ext/soyc/package-info.java
+++ b/dev/core/src/com/google/gwt/core/ext/soyc/package-info.java
@@ -16,8 +16,8 @@
 
 /**
  * This package contains interfaces that provide access to
- * "Story of Your Compile" information. When the compiler is run with analysis
- * turned on, these types are available to Linkers via
- * {@link com.google.gwt.core.ext.linker.CompilationAnalysis} artifacts.
+ * "Story of Your Compile" information. When the compiler is run with detailed
+ * analysis turned on, these types are available via XML files in the extras
+ * output.
  */
 package com.google.gwt.core.ext.soyc;
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/core/linker/SoycReportLinker.java b/dev/core/src/com/google/gwt/core/linker/SoycReportLinker.java
index 2f63ff1..2843250 100644
--- a/dev/core/src/com/google/gwt/core/linker/SoycReportLinker.java
+++ b/dev/core/src/com/google/gwt/core/linker/SoycReportLinker.java
@@ -23,8 +23,8 @@
 import com.google.gwt.core.ext.linker.CompilationResult;

 import com.google.gwt.core.ext.linker.LinkerOrder;

 import com.google.gwt.core.ext.linker.SelectionProperty;

+import com.google.gwt.core.ext.linker.SyntheticArtifact;

 import com.google.gwt.core.ext.linker.LinkerOrder.Order;

-import com.google.gwt.core.ext.linker.impl.StandardCompilationAnalysis;

 import com.google.gwt.soyc.SoycDashboard;

 import com.google.gwt.soyc.io.ArtifactsOutputDirectory;

 

@@ -33,7 +33,7 @@
 import java.util.TreeMap;

 

 /**

- * Converts SOYC report files into emitted private artifacts.

+ * Generates the top-level report files for a compile report.

  */

 @LinkerOrder(Order.POST)

 public class SoycReportLinker extends Linker {

@@ -46,38 +46,22 @@
   @Override

   public ArtifactSet link(TreeLogger logger, LinkerContext context,

       ArtifactSet artifacts) throws UnableToCompleteException {

+    if (!includesReports(artifacts)) {

+      return artifacts;

+    }

+

     ArtifactSet results = new ArtifactSet(artifacts);

-    boolean foundReports = false;

 

-    for (StandardCompilationAnalysis soycFiles : artifacts.find(StandardCompilationAnalysis.class)) {

-      if (soycFiles.getDepFile() != null) {

-        results.add(soycFiles.getDepFile());

-      }

-      if (soycFiles.getSizeMapsFile() != null) {

-        results.add(soycFiles.getSizeMapsFile());

-      }

-      if (soycFiles.getDetailedStoriesFile() != null) {

-        results.add(soycFiles.getDetailedStoriesFile());

-      }

-      results.add(soycFiles.getSplitPointsFile());

-      if (!soycFiles.getReportFiles().isEmpty()) {

-        results.addAll(soycFiles.getReportFiles());

-        foundReports = true;

-      }

+    // Run the final step of the dashboard to generate top-level files.

+    ArtifactsOutputDirectory out = new ArtifactsOutputDirectory();

+    try {

+      new SoycDashboard(out).generateCrossPermutationFiles(extractPermutationDescriptions(artifacts));

+    } catch (IOException e) {

+      logger.log(TreeLogger.ERROR,

+          "Error while generating a Story of Your Compile", e);

     }

+    results.addAll(out.getArtifacts());

 

-    if (foundReports) {

-      // run the final step of the dashboard to generate top-level files

-      ArtifactsOutputDirectory out = new ArtifactsOutputDirectory();

-      try {

-        new SoycDashboard(out).generateCrossPermutationFiles(extractPermutationDescriptions(artifacts));

-      } catch (IOException e) {

-        logger.log(TreeLogger.ERROR,

-            "Error while generating a Story of Your Compile", e);

-        e.printStackTrace();

-      }

-      results.addAll(out.getArtifacts());

-    }

     return results;

   }

 

@@ -98,4 +82,14 @@
 

     return permDescriptions;

   }

+

+  private boolean includesReports(ArtifactSet artifacts) {

+    for (SyntheticArtifact art : artifacts.find(SyntheticArtifact.class)) {

+      if (art.getPartialPath().startsWith(

+          ArtifactsOutputDirectory.COMPILE_REPORT_DIRECTORY + "/")) {

+        return true;

+      }

+    }

+    return false;

+  }

 }

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 a6d177d..99d34a3 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -19,18 +19,19 @@
 import com.google.gwt.core.ext.SelectionProperty;
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.linker.Artifact;
 import com.google.gwt.core.ext.linker.ArtifactSet;
 import com.google.gwt.core.ext.linker.EmittedArtifact;
 import com.google.gwt.core.ext.linker.StatementRanges;
 import com.google.gwt.core.ext.linker.SymbolData;
-import com.google.gwt.core.ext.linker.impl.StandardCompilationAnalysis;
+import com.google.gwt.core.ext.linker.SyntheticArtifact;
 import com.google.gwt.core.ext.linker.impl.StandardSymbolData;
-import com.google.gwt.core.ext.linker.impl.StandardCompilationAnalysis.SoycArtifact;
 import com.google.gwt.core.ext.soyc.Range;
 import com.google.gwt.core.ext.soyc.impl.DependencyRecorder;
 import com.google.gwt.core.ext.soyc.impl.SizeMapRecorder;
 import com.google.gwt.core.ext.soyc.impl.SplitPointRecorder;
 import com.google.gwt.core.ext.soyc.impl.StoryRecorder;
+import com.google.gwt.core.linker.SoycReportLinker;
 import com.google.gwt.dev.cfg.ModuleDef;
 import com.google.gwt.dev.jdt.RebindPermutationOracle;
 import com.google.gwt.dev.jdt.WebModeCompilerFrontEnd;
@@ -111,7 +112,6 @@
 import com.google.gwt.dev.util.PerfLogger;
 import com.google.gwt.dev.util.TextOutput;
 import com.google.gwt.dev.util.Util;
-import com.google.gwt.dev.util.collect.Lists;
 import com.google.gwt.dev.util.collect.Maps;
 import com.google.gwt.soyc.SoycDashboard;
 import com.google.gwt.soyc.io.ArtifactsOutputDirectory;
@@ -128,6 +128,7 @@
 import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -290,7 +291,7 @@
       JsStackEmulator.exec(jsProgram, propertyOracles);
 
       // (10) Split up the program into fragments
-      SoycArtifact dependencies = null;
+      SyntheticArtifact dependencies = null;
       if (options.isAggressivelyOptimize() && options.isRunAsyncEnabled()) {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         CodeSplitter.exec(logger, jprogram, jsProgram, map,
@@ -299,8 +300,8 @@
           recordNonSplitDependencies(jprogram, baos);
         }
         if (baos.size() > 0) {
-          dependencies = new SoycArtifact("dependencies" + permutationId
-              + ".xml.gz", baos.toByteArray());
+          dependencies = new SyntheticArtifact(SoycReportLinker.class,
+              "dependencies" + permutationId + ".xml.gz", baos.toByteArray());
         }
       }
 
@@ -357,9 +358,9 @@
 
       PermutationResult toReturn = new PermutationResultImpl(js,
           makeSymbolMap(symbolTable), ranges, permutationId);
-      toReturn.getArtifacts().add(
-          makeSoycArtifact(logger, permutationId, jprogram, js, sizeBreakdowns,
-              sourceInfoMaps, dependencies, map, obfuscateMap));
+      toReturn.getArtifacts().addAll(
+          makeSoycArtifacts(logger, permutationId, jprogram, js,
+              sizeBreakdowns, sourceInfoMaps, dependencies, map, obfuscateMap));
 
       logger.log(TreeLogger.TRACE, "Permutation took "
           + (System.currentTimeMillis() - permStart) + " ms");
@@ -938,32 +939,36 @@
     }
   }
 
-  private static StandardCompilationAnalysis makeSoycArtifact(
+  private static Collection<? extends Artifact<?>> makeSoycArtifacts(
       TreeLogger logger, int permutationId, JProgram jprogram, String[] js,
       SizeBreakdown[] sizeBreakdowns,
-      List<Map<Range, SourceInfo>> sourceInfoMaps, SoycArtifact dependencies,
-      JavaToJavaScriptMap jjsmap, Map<JsName, String> obfuscateMap)
-      throws IOException, UnableToCompleteException {
+      List<Map<Range, SourceInfo>> sourceInfoMaps,
+      SyntheticArtifact dependencies, JavaToJavaScriptMap jjsmap,
+      Map<JsName, String> obfuscateMap) throws IOException,
+      UnableToCompleteException {
+    List<Artifact<?>> soycArtifacts = new ArrayList<Artifact<?>>();
+
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
 
     PerfLogger.start("Recording compile report output");
 
     PerfLogger.start("Record split points");
     SplitPointRecorder.recordSplitPoints(jprogram, baos, logger);
-    SoycArtifact splitPoints = new SoycArtifact("splitPoints" + permutationId
-        + ".xml.gz", baos.toByteArray());
+    SyntheticArtifact splitPoints = new SyntheticArtifact(
+        SoycReportLinker.class, "splitPoints" + permutationId + ".xml.gz",
+        baos.toByteArray());
+    soycArtifacts.add(splitPoints);
     PerfLogger.end();
 
-    SoycArtifact sizeMaps = null;
-    SoycArtifact detailedStories = null;
-
+    SyntheticArtifact sizeMaps = null;
     if (sizeBreakdowns != null) {
       PerfLogger.start("Record size map");
       baos.reset();
       SizeMapRecorder.recordMap(logger, baos, sizeBreakdowns, jjsmap,
           obfuscateMap);
-      sizeMaps = new SoycArtifact("stories" + permutationId + ".xml.gz",
-          baos.toByteArray());
+      sizeMaps = new SyntheticArtifact(SoycReportLinker.class, "stories"
+          + permutationId + ".xml.gz", baos.toByteArray());
+      soycArtifacts.add(sizeMaps);
       PerfLogger.end();
     }
 
@@ -971,14 +976,17 @@
       PerfLogger.start("Record detailed stories");
       baos.reset();
       StoryRecorder.recordStories(logger, baos, sourceInfoMaps, js);
-      detailedStories = new SoycArtifact("detailedStories" + permutationId
-          + ".xml.gz", baos.toByteArray());
+      soycArtifacts.add(new SyntheticArtifact(SoycReportLinker.class,
+          "detailedStories" + permutationId + ".xml.gz", baos.toByteArray()));
       PerfLogger.end();
     }
 
+    if (dependencies != null) {
+      soycArtifacts.add(dependencies);
+    }
+
     PerfLogger.end();
 
-    List<SoycArtifact> reportArtifacts = Lists.create();
     if (sizeBreakdowns != null) {
       PerfLogger.start("Generating compile report");
       ArtifactsOutputDirectory outDir = new ArtifactsOutputDirectory();
@@ -1002,12 +1010,11 @@
             e);
       }
       dashboard.generateForOnePermutation();
-      reportArtifacts = outDir.getArtifacts();
+      soycArtifacts.addAll(outDir.getArtifacts());
       PerfLogger.end();
     }
 
-    return new StandardCompilationAnalysis(dependencies, sizeMaps, splitPoints,
-        detailedStories, reportArtifacts);
+    return soycArtifacts;
   }
 
   /**
diff --git a/dev/core/src/com/google/gwt/soyc/io/ArtifactsOutputDirectory.java b/dev/core/src/com/google/gwt/soyc/io/ArtifactsOutputDirectory.java
index fb774b7..1b34036 100644
--- a/dev/core/src/com/google/gwt/soyc/io/ArtifactsOutputDirectory.java
+++ b/dev/core/src/com/google/gwt/soyc/io/ArtifactsOutputDirectory.java
@@ -15,7 +15,8 @@
  */
 package com.google.gwt.soyc.io;
 
-import com.google.gwt.core.ext.linker.impl.StandardCompilationAnalysis.SoycArtifact;
+import com.google.gwt.core.ext.linker.SyntheticArtifact;
+import com.google.gwt.core.linker.SoycReportLinker;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -28,13 +29,13 @@
  * artifacts.
  */
 public class ArtifactsOutputDirectory implements OutputDirectory {
+  public static final String COMPILE_REPORT_DIRECTORY = "compile-report";
+
   /**
    * An in-memory output stream. When it is closed, its contents are saved to an
    * artifact.
    */
   private class OutputStreamForArtifact extends OutputStream {
-    private static final String OUTPUT_DIRECTORY_NAME = "compile-report";
-
     private ByteArrayOutputStream baos = new ByteArrayOutputStream();
     private boolean closed = false;
     private final String path;
@@ -47,8 +48,9 @@
     public void close() {
       if (!closed) {
         closed = true;
-        SoycArtifact newArtifact = new SoycArtifact(OUTPUT_DIRECTORY_NAME + "/"
-            + path, baos.toByteArray());
+        SyntheticArtifact newArtifact = new SyntheticArtifact(
+            SoycReportLinker.class, COMPILE_REPORT_DIRECTORY + "/" + path,
+            baos.toByteArray());
         newArtifact.setPrivate(false);
         artifacts.add(newArtifact);
         baos = null;
@@ -71,12 +73,12 @@
     }
   }
 
-  private List<SoycArtifact> artifacts = new ArrayList<SoycArtifact>();
+  private List<SyntheticArtifact> artifacts = new ArrayList<SyntheticArtifact>();
 
   /**
    * Return the list of artifacts that have been written so far.
    */
-  public List<SoycArtifact> getArtifacts() {
+  public List<SyntheticArtifact> getArtifacts() {
     return artifacts;
   }