Merge "Let MinifiedNameMapPrinter use StringBuilder"
diff --git a/src/main/java/com/android/tools/r8/errors/Unreachable.java b/src/main/java/com/android/tools/r8/errors/Unreachable.java
index 4b17eba..0eb71d2 100644
--- a/src/main/java/com/android/tools/r8/errors/Unreachable.java
+++ b/src/main/java/com/android/tools/r8/errors/Unreachable.java
@@ -14,4 +14,8 @@
   public Unreachable(String s) {
     super(s);
   }
+
+  public Unreachable(Throwable cause) {
+    super(cause);
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/naming/MemberNaming.java b/src/main/java/com/android/tools/r8/naming/MemberNaming.java
index 6fb166f..711672c 100644
--- a/src/main/java/com/android/tools/r8/naming/MemberNaming.java
+++ b/src/main/java/com/android/tools/r8/naming/MemberNaming.java
@@ -6,6 +6,7 @@
 import static com.android.tools.r8.utils.DescriptorUtils.javaTypeToDescriptor;
 
 import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
@@ -112,7 +113,8 @@
         write(writer);
         return writer.toString();
       } catch (IOException e) {
-        return e.toString();
+        // StringWriter is not throwing IOException
+        throw new Unreachable(e);
       }
     }
 
diff --git a/src/main/java/com/android/tools/r8/naming/MinifiedNameMapPrinter.java b/src/main/java/com/android/tools/r8/naming/MinifiedNameMapPrinter.java
index 5d34ca4..3ae9d06 100644
--- a/src/main/java/com/android/tools/r8/naming/MinifiedNameMapPrinter.java
+++ b/src/main/java/com/android/tools/r8/naming/MinifiedNameMapPrinter.java
@@ -14,11 +14,6 @@
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.google.common.collect.Sets;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
@@ -27,6 +22,7 @@
 
 public class MinifiedNameMapPrinter {
 
+  private static final String NEW_LINE = "\n";
   private final DexApplication application;
   private final NamingLens namingLens;
   private final Set<DexType> seenTypes = Sets.newIdentityHashSet();
@@ -42,13 +38,13 @@
     return copy;
   }
 
-  private void writeClass(DexProgramClass clazz, PrintStream out) {
+  private void writeClass(DexProgramClass clazz, StringBuilder out) {
     seenTypes.add(clazz.type);
     DexString descriptor = namingLens.lookupDescriptor(clazz.type);
-    out.print(DescriptorUtils.descriptorToJavaType(clazz.type.descriptor.toSourceString()));
-    out.print(" -> ");
-    out.print(DescriptorUtils.descriptorToJavaType(descriptor.toSourceString()));
-    out.println(":");
+    out.append(DescriptorUtils.descriptorToJavaType(clazz.type.descriptor.toSourceString()));
+    out.append(" -> ");
+    out.append(DescriptorUtils.descriptorToJavaType(descriptor.toSourceString()));
+    out.append(":").append(NEW_LINE);
     writeFields(sortedCopy(
         clazz.instanceFields(), Comparator.comparing(DexEncodedField::toSourceString)), out);
     writeFields(sortedCopy(
@@ -59,39 +55,39 @@
         clazz.virtualMethods(), Comparator.comparing(DexEncodedMethod::toSourceString)), out);
   }
 
-  private void writeType(DexType type, PrintStream out) {
+  private void writeType(DexType type, StringBuilder out) {
     if (type.isClassType() && seenTypes.add(type)) {
       DexString descriptor = namingLens.lookupDescriptor(type);
-      out.print(DescriptorUtils.descriptorToJavaType(type.descriptor.toSourceString()));
-      out.print(" -> ");
-      out.print(DescriptorUtils.descriptorToJavaType(descriptor.toSourceString()));
-      out.println(":");
+      out.append(DescriptorUtils.descriptorToJavaType(type.descriptor.toSourceString()));
+      out.append(" -> ");
+      out.append(DescriptorUtils.descriptorToJavaType(descriptor.toSourceString()));
+      out.append(":").append(NEW_LINE);
     }
   }
 
-  private void writeFields(DexEncodedField[] fields, PrintStream out) {
+  private void writeFields(DexEncodedField[] fields, StringBuilder out) {
     for (DexEncodedField encodedField : fields) {
       DexField field = encodedField.field;
       DexString renamed = namingLens.lookupName(field);
       if (renamed != field.name) {
-        out.print("    ");
-        out.print(field.type.toSourceString());
-        out.print(" ");
-        out.print(field.name.toSourceString());
-        out.print(" -> ");
-        out.println(renamed.toSourceString());
+        out.append("    ");
+        out.append(field.type.toSourceString());
+        out.append(" ");
+        out.append(field.name.toSourceString());
+        out.append(" -> ");
+        out.append(renamed.toSourceString()).append(NEW_LINE);
       }
     }
   }
 
-  private void writeMethod(MethodSignature signature, String renamed, PrintStream out) {
-    out.print("    ");
-    out.print(signature);
-    out.print(" -> ");
-    out.println(renamed);
+  private void writeMethod(MethodSignature signature, String renamed, StringBuilder out) {
+    out.append("    ");
+    out.append(signature.toString());
+    out.append(" -> ");
+    out.append(renamed).append(NEW_LINE);
   }
 
-  private void writeMethods(DexEncodedMethod[] methods, PrintStream out) {
+  private void writeMethods(DexEncodedMethod[] methods, StringBuilder out) {
     for (DexEncodedMethod encodedMethod : methods) {
       DexMethod method = encodedMethod.method;
       DexString renamed = namingLens.lookupName(method);
@@ -103,7 +99,7 @@
     }
   }
 
-  public void write(PrintStream out) {
+  public void write(StringBuilder out) {
     // First write out all classes that have been renamed.
     List<DexProgramClass> classes = new ArrayList<>(application.classes());
     classes.sort(Comparator.comparing(DexProgramClass::toSourceString));
@@ -111,11 +107,4 @@
     // Now write out all types only mentioned in descriptors that have been renamed.
     namingLens.forAllRenamedTypes(type -> writeType(type, out));
   }
-
-  public void write(Path destination) throws IOException {
-    PrintStream out = new PrintStream(Files.newOutputStream(destination), true,
-        StandardCharsets.UTF_8.name());
-    write(out);
-  }
-
 }
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 f394e76..3863c14 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapSupplier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapSupplier.java
@@ -6,7 +6,6 @@
 import com.android.tools.r8.graph.DexApplication;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.io.PrintStream;
 import java.io.PrintWriter;
 import java.io.Writer;
 
@@ -47,11 +46,9 @@
     assert namingLens != null && application != null;
     // TODO(herhut): Should writing of the proguard-map file be split like this?
     if (!namingLens.isIdentityLens()) {
-      ByteArrayOutputStream bytes = new ByteArrayOutputStream();
-      PrintStream stream = new PrintStream(bytes);
-      new MinifiedNameMapPrinter(application, namingLens).write(stream);
-      stream.flush();
-      return bytes.toString();
+      StringBuilder map = new StringBuilder();
+      new MinifiedNameMapPrinter(application, namingLens).write(map);
+      return map.toString();
     }
     if (application.getProguardMap() != null) {
       ByteArrayOutputStream bytes = new ByteArrayOutputStream();