Reland "Experimental API for generating optimized line mapping with D8."

Bug: b/183125319
This reverts commit b63e56077626feeae062d079da0b8c68652fb40d.

Change-Id: I2c25ec23309126cdf989753f2f919c04f391ce26
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index acbd677..fe2ed57 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -146,6 +146,41 @@
     }
 
     /**
+     * Set a consumer for receiving the proguard-map content.
+     *
+     * <p>Note that when a proguard-map consumer is specified for a release build, the compiler will
+     * optimize the line-number information and obtaining a source-level stacktrace will require the
+     * use of a retrace tool exactly as is needed for programs built by R8.
+     *
+     * <p>Note that any subsequent call to this method or {@link #setProguardMapOutputPath} will
+     * override the previous setting.
+     *
+     * @param proguardMapConsumer Consumer to receive the content once produced.
+     */
+    @Override
+    public Builder setProguardMapConsumer(StringConsumer proguardMapConsumer) {
+      return super.setProguardMapConsumer(proguardMapConsumer);
+    }
+
+    /**
+     * Set an output destination to which proguard-map content should be written.
+     *
+     * <p>Note that when a proguard-map output is specified for a release build, the compiler will
+     * optimize the line-number information and obtaining a source-level stacktrace will require the
+     * use of a retrace tool exactly as is needed for programs built by R8.
+     *
+     * <p>This is a short-hand for setting a {@link StringConsumer.FileConsumer} using {@link
+     * #setProguardMapConsumer}. Note that any subsequent call to this method or {@link
+     * #setProguardMapConsumer} will override the previous setting.
+     *
+     * @param proguardMapOutput File-system path to write output at.
+     */
+    @Override
+    public Builder setProguardMapOutputPath(Path proguardMapOutput) {
+      return super.setProguardMapOutputPath(proguardMapOutput);
+    }
+
+    /**
      * Indicate if compilation is to intermediate results, i.e., intended for later merging.
      *
      * <p>When compiling to intermediate mode, the compiler will avoid sharing of synthetic items,
@@ -376,6 +411,7 @@
           getThreadCount(),
           getDumpInputFlags(),
           getMapIdProvider(),
+          proguardMapConsumer,
           factory);
     }
   }
@@ -392,6 +428,7 @@
   private final boolean enableMainDexListCheck;
   private final boolean minimalMainDex;
   private final ImmutableList<ProguardConfigurationRule> mainDexKeepRules;
+  private final StringConsumer proguardMapConsumer;
   private final DexItemFactory factory;
 
   public static Builder builder() {
@@ -460,6 +497,7 @@
       int threadCount,
       DumpInputFlags dumpInputFlags,
       MapIdProvider mapIdProvider,
+      StringConsumer proguardMapConsumer,
       DexItemFactory factory) {
     super(
         inputApp,
@@ -488,6 +526,7 @@
     this.enableMainDexListCheck = enableMainDexListCheck;
     this.minimalMainDex = minimalMainDex;
     this.mainDexKeepRules = mainDexKeepRules;
+    this.proguardMapConsumer = proguardMapConsumer;
     this.factory = factory;
   }
 
@@ -503,6 +542,7 @@
     enableMainDexListCheck = true;
     minimalMainDex = false;
     mainDexKeepRules = null;
+    proguardMapConsumer = null;
     factory = null;
   }
 
@@ -532,7 +572,11 @@
     internal.setGlobalSyntheticsConsumer(globalSyntheticsConsumer);
     internal.desugarGraphConsumer = desugarGraphConsumer;
     internal.mainDexKeepRules = mainDexKeepRules;
-    internal.lineNumberOptimization = LineNumberOptimization.OFF;
+    internal.proguardMapConsumer = proguardMapConsumer;
+    internal.lineNumberOptimization =
+        !internal.debug && proguardMapConsumer != null
+            ? LineNumberOptimization.ON
+            : LineNumberOptimization.OFF;
 
     // Assert and fixup defaults.
     assert !internal.isShrinking();
diff --git a/src/main/java/com/android/tools/r8/D8CommandParser.java b/src/main/java/com/android/tools/r8/D8CommandParser.java
index 9e729e0..719120f 100644
--- a/src/main/java/com/android/tools/r8/D8CommandParser.java
+++ b/src/main/java/com/android/tools/r8/D8CommandParser.java
@@ -30,6 +30,7 @@
           "--lib",
           "--classpath",
           "--pg-map",
+          "--pg-map-output",
           MIN_API_FLAG,
           "--main-dex-rules",
           "--main-dex-list",
@@ -131,6 +132,9 @@
                       + AndroidApiLevel.getDefault().getLevel()
                       + ".",
                   "  --pg-map <file>         # Use <file> as a mapping file for distribution.",
+                  // TODO(b/183125319): Add help info once supported.
+                  // "  --pg-map-output <file>  # Enable line optimization and output mapping to"
+                  //     +" <file>.",
                   "  --intermediate          # Compile an intermediate result intended for later",
                   "                          # merging.",
                   "  --file-per-class        # Produce a separate dex file per class.",
@@ -226,6 +230,8 @@
         outputMode = OutputMode.ClassFile;
       } else if (arg.equals("--pg-map")) {
         builder.setProguardInputMapFile(Paths.get(nextArg));
+      } else if (arg.equals("--pg-map-output")) {
+        builder.setProguardMapOutputPath(Paths.get(nextArg));
       } else if (arg.equals("--output")) {
         if (outputPath != null) {
           builder.error(
diff --git a/src/test/java/com/android/tools/r8/D8TestBuilder.java b/src/test/java/com/android/tools/r8/D8TestBuilder.java
index cf27d33..1ec4d18 100644
--- a/src/test/java/com/android/tools/r8/D8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/D8TestBuilder.java
@@ -123,13 +123,10 @@
     return self();
   }
 
-  // TODO(b/183125319): Make this the default as part of API support in D8.
   public D8TestBuilder internalEnableMappingOutput() {
     assert proguardMapOutputBuilder == null;
     proguardMapOutputBuilder = new StringBuilder();
-    // TODO(b/183125319): Use the API once supported in D8.
-    addOptionsModification(
-        o -> o.proguardMapConsumer = (s, h) -> proguardMapOutputBuilder.append(s));
+    getBuilder().setProguardMapConsumer((s, h) -> proguardMapOutputBuilder.append(s));
     return self();
   }
 }
diff --git a/src/test/java/com/android/tools/r8/debuginfo/EnsureNoDebugInfoEmittedForPcOnlyTestRunner.java b/src/test/java/com/android/tools/r8/debuginfo/EnsureNoDebugInfoEmittedForPcOnlyTestRunner.java
index a5e76eb..f3a22bf 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/EnsureNoDebugInfoEmittedForPcOnlyTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/EnsureNoDebugInfoEmittedForPcOnlyTestRunner.java
@@ -5,11 +5,10 @@
 package com.android.tools.r8.debuginfo;
 
 import static com.android.tools.r8.naming.retrace.StackTrace.isSameExceptForFileNameAndLineNumber;
-import static com.android.tools.r8.utils.InternalOptions.LineNumberOptimization.ON;
 import static junit.framework.TestCase.assertEquals;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.SourceFileEnvironment;
@@ -74,7 +73,6 @@
         .addProgramClasses(MAIN)
         .setMinApi(parameters.getApiLevel())
         .internalEnableMappingOutput()
-        // TODO(b/191038746): Enable LineNumberOptimization for release builds for DEX PC Output.
         .applyIf(
             apiLevelSupportsPcAndSourceFileOutput(),
             builder ->
@@ -92,7 +90,6 @@
                               return true;
                             }
                           };
-                      options.lineNumberOptimization = ON;
                     }))
         .run(parameters.getRuntime(), MAIN)
         .inspectFailure(
@@ -150,10 +147,7 @@
     List<DexDebugEntry> entries =
         new DexDebugEntryBuilder(main.getMethod(), inspector.getFactory()).build();
     Set<Integer> lines = entries.stream().map(e -> e.line).collect(Collectors.toSet());
-    // Check some of the lines in main are present (not 27 as it may be optimized out).
-    assertTrue(lines.contains(22));
-    assertTrue(lines.contains(23));
-    assertTrue(lines.contains(25));
+    assertFalse(lines.isEmpty());
   }
 
   private void checkExpectedStackTrace(StackTrace stackTrace) {
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceLambdaTest.java b/src/test/java/com/android/tools/r8/retrace/RetraceLambdaTest.java
index d68447d..e7b884c 100644
--- a/src/test/java/com/android/tools/r8/retrace/RetraceLambdaTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceLambdaTest.java
@@ -34,12 +34,6 @@
 
   private static final String JAVAC_LAMBDA_METHOD = "lambda$main$0";
 
-  // TODO(b/172014416): These should not be needed once fixed.
-  private static final String LAMBDA_BRIDGE_METHOD = "$r8$lambda$dX5OYTAgq4ijGUv_zaGoVsFINMs";
-  private static final String INTERNAL_LAMBDA_CLASS =
-      Main.class.getTypeName()
-          + "$$InternalSyntheticLambda$0$11a5d582ed94e937718cf3ed497d4d164b60dfa85d606466457007fade57dce8$0";
-
   @Parameters(name = "{0}")
   public static TestParametersCollection parameters() {
     return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();