Cleanup Proguard map supplier

Change-Id: Ibac49a3fcd5a22f05bd96d712a284bb3dcbad180
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index 3c132e0..ea07dfc 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -250,7 +250,7 @@
                 GraphLense.getIdentityLense(),
                 NamingLens.getIdentityLens(),
                 null)
-            .write(options.getClassFileConsumer(), executor);
+            .write(options.getClassFileConsumer());
       } else {
         NamingLens namingLens;
         DexApplication finalApp = app;
diff --git a/src/main/java/com/android/tools/r8/GenerateLintFiles.java b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
index bf55656..7d5b31e 100644
--- a/src/main/java/com/android/tools/r8/GenerateLintFiles.java
+++ b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
@@ -37,7 +37,6 @@
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.Reporter;
-import com.android.tools.r8.utils.ThreadUtils;
 import com.android.tools.r8.utils.Timing;
 import com.google.common.collect.Sets;
 import java.io.File;
@@ -326,7 +325,7 @@
     ClassFileConsumer consumer =
         new ClassFileConsumer.ArchiveConsumer(
             lintFile(compilationApiLevel, minApiLevel, FileUtils.JAR_EXTENSION));
-    writer.write(consumer, ThreadUtils.getExecutorService(options));
+    writer.write(consumer);
     consumer.finished(options.reporter);
   }
 
diff --git a/src/main/java/com/android/tools/r8/L8.java b/src/main/java/com/android/tools/r8/L8.java
index 50a4a70..cf9684c 100644
--- a/src/main/java/com/android/tools/r8/L8.java
+++ b/src/main/java/com/android/tools/r8/L8.java
@@ -136,7 +136,7 @@
               GraphLense.getIdentityLense(),
               PrefixRewritingNamingLens.createPrefixRewritingNamingLens(appView),
               null)
-          .write(options.getClassFileConsumer(), executor);
+          .write(options.getClassFileConsumer());
       options.printWarnings();
     } catch (ExecutionException e) {
       throw unwrapExecutionException(e);
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index b03172f..e82c7eb 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -212,7 +212,7 @@
       if (options.isGeneratingClassFiles()) {
         new CfApplicationWriter(
                 application, appView, options, marker, graphLense, namingLens, proguardMapSupplier)
-            .write(options.getClassFileConsumer(), executorService);
+            .write(options.getClassFileConsumer());
       } else {
         new ApplicationWriter(
                 application,
@@ -789,8 +789,6 @@
         namingLens = NamingLens.getIdentityLens();
       }
 
-      ProguardMapSupplier proguardMapSupplier;
-
       timing.begin("Line number remapping");
       // When line number optimization is turned off the identity mapping for line numbers is
       // used. We still run the line number optimizer to collect line numbers and inline frame
@@ -798,7 +796,6 @@
       ClassNameMapper classNameMapper =
           LineNumberOptimizer.run(appView, application, inputApp, namingLens);
       timing.end();
-      proguardMapSupplier = ProguardMapSupplier.fromClassNameMapper(classNameMapper, options);
 
       // If a method filter is present don't produce output since the application is likely partial.
       if (options.hasMethodsFilter()) {
@@ -849,7 +846,7 @@
           appView.initClassLens(),
           PrefixRewritingNamingLens.createPrefixRewritingNamingLens(appView, namingLens),
           options,
-          proguardMapSupplier);
+          ProguardMapSupplier.create(classNameMapper, options));
 
       options.printWarnings();
     } catch (ExecutionException e) {
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index 79b4362..8ee86f3 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -38,9 +38,9 @@
 import com.android.tools.r8.graph.InnerClassAttribute;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
 import com.android.tools.r8.graph.ParameterAnnotationsList;
-import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.naming.ProguardMapSupplier;
+import com.android.tools.r8.naming.ProguardMapSupplier.ProguardMapId;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.ExceptionUtils;
@@ -230,17 +230,17 @@
 
   public void write(ExecutorService executorService) throws IOException, ExecutionException {
     application.timing.begin("DexApplication.write");
-    ProguardMapSupplier.ProguardMapAndId proguardMapAndId = null;
+    ProguardMapId proguardMapId = null;
     if (proguardMapSupplier != null && options.proguardMapConsumer != null) {
-      proguardMapAndId = proguardMapSupplier.getProguardMapAndId();
+      proguardMapId = proguardMapSupplier.writeProguardMap();
     }
 
     // If we do have a map then we're called from R8. In that case we have exactly one marker.
-    assert proguardMapAndId == null || (markers != null && markers.size() == 1);
+    assert proguardMapId == null || (markers != null && markers.size() == 1);
 
     if (markers != null && !markers.isEmpty()) {
-      if (proguardMapAndId != null) {
-        markers.get(0).setPgMapId(proguardMapAndId.id);
+      if (proguardMapId != null) {
+        markers.get(0).setPgMapId(proguardMapId.get());
       }
       markerStrings = new ArrayList<>(markers.size());
       for (Marker marker : markers) {
@@ -338,13 +338,7 @@
       // Fail if there are pending errors, e.g., the program consumers may have reported errors.
       options.reporter.failIfPendingErrors();
       // Supply info to all additional resource consumers.
-      supplyAdditionalConsumers(
-          application,
-          appView,
-          graphLense,
-          namingLens,
-          options,
-          proguardMapAndId == null ? null : proguardMapAndId.map);
+      supplyAdditionalConsumers(application, appView, graphLense, namingLens, options);
     } finally {
       application.timing.end();
     }
@@ -355,20 +349,13 @@
       AppView<?> appView,
       GraphLense graphLense,
       NamingLens namingLens,
-      InternalOptions options,
-      String proguardMapContent) {
+      InternalOptions options) {
     if (options.configurationConsumer != null) {
       ExceptionUtils.withConsumeResourceHandler(
           options.reporter, options.configurationConsumer,
           options.getProguardConfiguration().getParsedConfiguration());
       ExceptionUtils.withFinishedResourceHandler(options.reporter, options.configurationConsumer);
     }
-    if (proguardMapContent != null) {
-      assert validateProguardMapParses(proguardMapContent);
-      ExceptionUtils.withConsumeResourceHandler(
-          options.reporter, options.proguardMapConsumer, proguardMapContent);
-      ExceptionUtils.withFinishedResourceHandler(options.reporter, options.proguardMapConsumer);
-    }
     if (options.mainDexListConsumer != null) {
       ExceptionUtils.withConsumeResourceHandler(
           options.reporter, options.mainDexListConsumer, writeMainDexList(application, namingLens));
@@ -465,16 +452,6 @@
     }
   }
 
-  private static boolean validateProguardMapParses(String content) {
-    try {
-      ClassNameMapper.mapperFromString(content);
-    } catch (IOException e) {
-      e.printStackTrace();
-      return false;
-    }
-    return true;
-  }
-
   private void insertAttributeAnnotations() {
     // Convert inner-class attributes to DEX annotations
     for (DexProgramClass clazz : application.classes()) {
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index 1112e9c..9f51daa 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -41,7 +41,6 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.Optional;
-import java.util.concurrent.ExecutorService;
 import org.objectweb.asm.AnnotationVisitor;
 import org.objectweb.asm.ClassReader;
 import org.objectweb.asm.ClassWriter;
@@ -89,22 +88,18 @@
     this.proguardMapSupplier = proguardMapSupplier;
   }
 
-  public void write(ClassFileConsumer consumer, ExecutorService executor) {
+  public void write(ClassFileConsumer consumer) {
     application.timing.begin("CfApplicationWriter.write");
     try {
-      writeApplication(consumer, executor);
+      writeApplication(consumer);
     } finally {
       application.timing.end();
     }
   }
 
-  private void writeApplication(ClassFileConsumer consumer, ExecutorService executor) {
-    ProguardMapSupplier.ProguardMapAndId proguardMapAndId = null;
+  private void writeApplication(ClassFileConsumer consumer) {
     if (proguardMapSupplier != null && options.proguardMapConsumer != null) {
-      proguardMapAndId = proguardMapSupplier.getProguardMapAndId();
-      if (proguardMapAndId != null) {
-        marker.setPgMapId(proguardMapAndId.id);
-      }
+      marker.setPgMapId(proguardMapSupplier.writeProguardMap().get());
     }
     Optional<String> markerString =
         marker.isRelocator() ? Optional.empty() : Optional.of(marker.toString());
@@ -118,12 +113,7 @@
       }
     }
     ApplicationWriter.supplyAdditionalConsumers(
-        application,
-        appView,
-        graphLense,
-        namingLens,
-        options,
-        proguardMapAndId == null ? null : proguardMapAndId.map);
+        application, appView, graphLense, namingLens, options);
   }
 
   private void writeClass(
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java b/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
index e45b97b..4472714 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
@@ -178,6 +178,10 @@
     return classNameMappings.get(obfuscatedName);
   }
 
+  public boolean isEmpty() {
+    return classNameMappings.isEmpty();
+  }
+
   public void write(Writer writer) throws IOException {
     // Sort classes by their original name such that the generated Proguard map is deterministic
     // (and easy to navigate manually).
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapSupplier.java b/src/main/java/com/android/tools/r8/naming/ProguardMapSupplier.java
index 0cee87f..d5b915b 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapSupplier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapSupplier.java
@@ -4,15 +4,13 @@
 package com.android.tools.r8.naming;
 
 import com.android.tools.r8.Version;
-import com.android.tools.r8.graph.DexApplication;
+import com.android.tools.r8.utils.Box;
+import com.android.tools.r8.utils.ExceptionUtils;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.VersionProperties;
 import com.google.common.hash.Hasher;
 import com.google.common.hash.Hashing;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.Writer;
 
 public class ProguardMapSupplier {
 
@@ -25,58 +23,56 @@
 
   public static int PG_MAP_ID_LENGTH = 7;
 
-  public static ProguardMapSupplier fromClassNameMapper(
-      ClassNameMapper classNameMapper, InternalOptions options) {
-    return new ProguardMapSupplier(true, classNameMapper, null, null, options);
-  }
-
-  public static ProguardMapSupplier fromNamingLens(
-      NamingLens namingLens, DexApplication dexApplication, InternalOptions options) {
-    return new ProguardMapSupplier(false, null, namingLens, dexApplication, options);
-  }
-
-  public static class ProguardMapAndId {
-    public final String map;
-    public final String id;
-
-    ProguardMapAndId(String map, String id) {
-      assert map != null && id != null;
-      this.map = map;
-      this.id = id;
+  // Truncated murmur hash of the non-whitespace codepoints of the Proguard map (excluding the
+  // marker).
+  public static class ProguardMapId extends Box<String> {
+    private ProguardMapId(String id) {
+      super(id);
+      assert id != null;
+      assert id.length() == PG_MAP_ID_LENGTH;
     }
   }
 
-  public ProguardMapSupplier(
-      boolean useClassNameMapper,
-      ClassNameMapper classNameMapper,
-      NamingLens namingLens,
-      DexApplication application,
-      InternalOptions options) {
-    this.useClassNameMapper = useClassNameMapper;
-    this.classNameMapper = classNameMapper;
-    this.namingLens = namingLens;
-    this.application = application;
-    this.minApiLevel = options.isGeneratingClassFiles() ? null : options.minApiLevel;
-  }
-
-  private final boolean useClassNameMapper;
   private final ClassNameMapper classNameMapper;
-  private final NamingLens namingLens;
-  private final DexApplication application;
-  private final Integer minApiLevel;
+  private final InternalOptions options;
 
-  public ProguardMapAndId getProguardMapAndId() {
-    String body = getBody();
-    if (body == null || body.trim().length() == 0) {
-      return null;
-    }
-    // Algorithm:
-    // Hash of the non-whitespace codepoints of the input string.
+  public ProguardMapSupplier(ClassNameMapper classNameMapper, InternalOptions options) {
+    this.classNameMapper = classNameMapper;
+    this.options = options;
+  }
+
+  public static ProguardMapSupplier create(
+      ClassNameMapper classNameMapper, InternalOptions options) {
+    return classNameMapper.isEmpty() ? null : new ProguardMapSupplier(classNameMapper, options);
+  }
+
+  public ProguardMapId writeProguardMap() {
+    String body = classNameMapper.toString();
+    assert body != null;
+    assert !body.trim().isEmpty();
+    ProguardMapId id = computeProguardMapId(body);
+    StringBuilder builder = new StringBuilder();
+    writeMarker(builder, id);
+    writeBody(builder, body);
+    String proguardMapContent = builder.toString();
+    assert validateProguardMapParses(proguardMapContent);
+    ExceptionUtils.withConsumeResourceHandler(
+        options.reporter, options.proguardMapConsumer, proguardMapContent);
+    ExceptionUtils.withFinishedResourceHandler(options.reporter, options.proguardMapConsumer);
+    return id;
+  }
+
+  private ProguardMapId computeProguardMapId(String body) {
     Hasher hasher = Hashing.murmur3_32().newHasher();
     body.codePoints().filter(c -> !Character.isWhitespace(c)).forEach(hasher::putInt);
-    String proguardMapId = hasher.hash().toString().substring(0, PG_MAP_ID_LENGTH);
+    return new ProguardMapId(hasher.hash().toString().substring(0, PG_MAP_ID_LENGTH));
+  }
 
-    StringBuilder builder = new StringBuilder();
+  private void writeBody(StringBuilder builder, String body) {
+    builder.append(body);
+  }
+
+  private void writeMarker(StringBuilder builder, ProguardMapId id) {
     builder.append(
         "# "
             + MARKER_KEY_COMPILER
@@ -88,44 +84,25 @@
             + ": "
             + Version.LABEL
             + "\n");
-    if (minApiLevel != null) {
-      builder.append("# " + MARKER_KEY_MIN_API + ": " + minApiLevel + "\n");
+    if (options.isGeneratingDex()) {
+      builder.append("# " + MARKER_KEY_MIN_API + ": " + options.minApiLevel + "\n");
     }
     if (Version.isDevelopmentVersion()) {
       builder.append(
           "# " + MARKER_KEY_COMPILER_HASH + ": " + VersionProperties.INSTANCE.getSha() + "\n");
     }
-    builder.append("# " + MARKER_KEY_PG_MAP_ID + ": " + proguardMapId + "\n");
+    builder.append("# " + MARKER_KEY_PG_MAP_ID + ": " + id.get() + "\n");
     // Turn off linting of the mapping file in some build systems.
     builder.append("# common_typos_disable" + "\n");
-    builder.append(body);
-
-    return new ProguardMapAndId(builder.toString(), proguardMapId);
   }
 
-  private String getBody() {
-    if (useClassNameMapper) {
-      assert classNameMapper != null;
-      return classNameMapper.toString();
+  private static boolean validateProguardMapParses(String content) {
+    try {
+      ClassNameMapper.mapperFromString(content);
+    } catch (IOException e) {
+      e.printStackTrace();
+      return false;
     }
-    assert namingLens != null && application != null;
-    // TODO(herhut): Should writing of the proguard-map file be split like this?
-    if (!namingLens.isIdentityLens()) {
-      StringBuilder map = new StringBuilder();
-      new MinifiedNameMapPrinter(application, namingLens).write(map);
-      return map.toString();
-    }
-    if (application.getProguardMap() != null) {
-      ByteArrayOutputStream bytes = new ByteArrayOutputStream();
-      Writer writer = new PrintWriter(bytes);
-      try {
-        application.getProguardMap().write(writer);
-        writer.flush();
-      } catch (IOException e) {
-        throw new RuntimeException("IOException while creating Proguard-map output: " + e);
-      }
-      return bytes.toString();
-    }
-    return null;
+    return true;
   }
 }
diff --git a/src/main/java/com/android/tools/r8/relocator/Relocator.java b/src/main/java/com/android/tools/r8/relocator/Relocator.java
index 4d6165b..5c3d003 100644
--- a/src/main/java/com/android/tools/r8/relocator/Relocator.java
+++ b/src/main/java/com/android/tools/r8/relocator/Relocator.java
@@ -116,7 +116,7 @@
               GraphLense.getIdentityLense(),
               PrefixRewritingNamingLens.createPrefixRewritingNamingLens(appView),
               null)
-          .write(command.getConsumer(), executor);
+          .write(command.getConsumer());
       options.printWarnings();
     } catch (ExecutionException e) {
       throw unwrapExecutionException(e);