Clear annotations in L8

- Avoid hundreds of warnings in L8
- Fix reporting in L8 (same reporter)
- Add test APIs for L8

Bug: 134732760
Change-Id: Idd7c38bf75accb64fe732c18e58121fc467bcca7
diff --git a/src/main/java/com/android/tools/r8/L8.java b/src/main/java/com/android/tools/r8/L8.java
index d2b5fb3..40c45a6 100644
--- a/src/main/java/com/android/tools/r8/L8.java
+++ b/src/main/java/com/android/tools/r8/L8.java
@@ -14,6 +14,7 @@
 import com.android.tools.r8.ir.conversion.IRConverter;
 import com.android.tools.r8.jar.CfApplicationWriter;
 import com.android.tools.r8.naming.PrefixRewritingNamingLens;
+import com.android.tools.r8.shaking.AnnotationRemover;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.ExceptionUtils;
 import com.android.tools.r8.utils.InternalOptions;
@@ -34,21 +35,34 @@
    * @param command L8 command.
    */
   public static void run(L8Command command) throws CompilationFailedException {
-    ExecutorService executor =
-        ThreadUtils.getExecutorService(command.getInternalOptions().numberOfThreads);
+    runForTesting(
+        command.getInputApp(),
+        command.getInternalOptions(),
+        command.isShrinking(),
+        command.getD8Command(),
+        command.getR8Command());
+  }
+
+  static void runForTesting(
+      AndroidApp app,
+      InternalOptions options,
+      boolean shrink,
+      D8Command d8Command,
+      R8Command r8Command)
+      throws CompilationFailedException {
+    ExecutorService executor = ThreadUtils.getExecutorService(options);
     try {
       ExceptionUtils.withD8CompilationHandler(
-          command.getReporter(),
+          options.reporter,
           () -> {
-            desugar(command.getInputApp(), command.getInternalOptions(), executor);
+            desugar(app, options, executor);
           });
-      if (command.isShrinking()) {
-        command
-            .getReporter()
-            .warning(new StringDiagnostic("Shrinking of desugared library is work in progress."));
-        R8.run(command.getR8Command(), executor);
+      if (shrink) {
+        options.reporter.warning(
+            new StringDiagnostic("Shrinking of desugared library is work in progress."));
+        R8.run(r8Command, executor);
       } else {
-        D8.run(command.getD8Command(), executor);
+        D8.run(d8Command, executor);
       }
     } finally {
       executor.shutdown();
@@ -68,6 +82,9 @@
       AppView<?> appView = AppView.createForL8(appInfo, options);
       IRConverter converter = new IRConverter(appView, timing);
 
+      if (!options.testing.disableL8AnnotationRemoval) {
+        AnnotationRemover.clearAnnotations(appView);
+      }
       app = converter.convert(app, executor);
       assert appView.appInfo() == appInfo;
 
diff --git a/src/main/java/com/android/tools/r8/L8Command.java b/src/main/java/com/android/tools/r8/L8Command.java
index 93fa4fc..4933163 100644
--- a/src/main/java/com/android/tools/r8/L8Command.java
+++ b/src/main/java/com/android/tools/r8/L8Command.java
@@ -224,7 +224,7 @@
 
       if (isShrinking()) {
         R8Command.Builder r8Builder =
-            R8Command.builder()
+            R8Command.builder(getReporter())
                 .addProgramResourceProvider(desugaredLibrary)
                 .setMinApiLevel(getMinApiLevel())
                 // We disable minification in Core libraries since it breaks class initialization
@@ -245,7 +245,7 @@
         r8Command = r8Builder.makeCommand();
       } else {
         D8Command.Builder d8Builder =
-            D8Command.builder()
+            D8Command.builder(getReporter())
                 .addProgramResourceProvider(desugaredLibrary)
                 .setMinApiLevel(getMinApiLevel())
                 .setMode(getMode())
diff --git a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
index 67e945f..a96116b 100644
--- a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexAnnotation;
 import com.android.tools.r8.graph.DexAnnotationElement;
+import com.android.tools.r8.graph.DexAnnotationSet;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedAnnotation;
 import com.android.tools.r8.graph.DexEncodedField;
@@ -351,4 +352,16 @@
       clazz.clearInnerClasses();
     }
   }
+
+  public static void clearAnnotations(AppView<?> appView) {
+    for (DexProgramClass clazz : appView.appInfo().classes()) {
+      clazz.annotations = DexAnnotationSet.empty();
+      for (DexEncodedMethod method : clazz.methods()) {
+        method.annotations = DexAnnotationSet.empty();
+      }
+      for (DexEncodedField field : clazz.fields()) {
+        field.annotations = DexAnnotationSet.empty();
+      }
+    }
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 60d6b06..82963c9 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -1000,6 +1000,7 @@
 
     public boolean allowTypeErrors =
         !Version.isDev() || System.getProperty("com.android.tools.r8.allowTypeErrors") != null;
+    public boolean disableL8AnnotationRemoval = false;
     public boolean allowUnusedProguardConfigurationRules = true;
     public boolean reportUnusedProguardConfigurationRules = false;
     public boolean alwaysUsePessimisticRegisterAllocation = false;
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index f958a28..8b31384 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -1072,6 +1072,18 @@
     return compatSink.build();
   }
 
+  public static void runL8(L8Command command, Consumer<InternalOptions> optionsModifier)
+      throws CompilationFailedException {
+    InternalOptions internalOptions = command.getInternalOptions();
+    optionsModifier.accept(internalOptions);
+    L8.runForTesting(
+        command.getInputApp(),
+        internalOptions,
+        command.isShrinking(),
+        command.getD8Command(),
+        command.getR8Command());
+  }
+
   public static void addFilteredAndroidJar(BaseCommand.Builder builder, AndroidApiLevel apiLevel) {
     addFilteredAndroidJar(getAppBuilder(builder), apiLevel);
   }
@@ -1204,10 +1216,10 @@
     }
     if (classPath != null) {
       cmdline.add("-cp");
-      if (isWindows()){
-        cmdline.add(String.join(";",classPath));
+      if (isWindows()) {
+        cmdline.add(String.join(";", classPath));
       } else {
-        cmdline.add(String.join(":",classPath));
+        cmdline.add(String.join(":", classPath));
       }
     }
     cmdline.add("-d");
@@ -1434,8 +1446,11 @@
     assert headSha1 != null;
 
     return Files.createDirectories(
-         Paths.get(destDir.getAbsolutePath(), headSha1, testClassName, testName + "-" + String
-             .format("%03d", testOutputPathIndex)));
+        Paths.get(
+            destDir.getAbsolutePath(),
+            headSha1,
+            testClassName,
+            testName + "-" + String.format("%03d", testOutputPathIndex)));
   }
 
   private static List<File> unzipDexFilesArchive(File zipFile) throws IOException {
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java b/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java
index 3e13a86..ff0237f 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java
@@ -5,11 +5,12 @@
 package com.android.tools.r8.desugar.corelib;
 
 import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
 
-import com.android.tools.r8.L8;
 import com.android.tools.r8.L8Command;
 import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestDiagnosticMessagesImpl;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.origin.Origin;
@@ -59,9 +60,14 @@
       throws RuntimeException {
     // We wrap exceptions in a RuntimeException to call this from a lambda.
     try {
+      // If we compile extended library here, it means we use TestNG.
+      // TestNG requires annotations, hence we disable AnnotationRemoval.
+      // This implies that extra warning are generated if this is set.
+      boolean disableL8AnnotationRemovalForTesting = !additionalProgramFiles.isEmpty();
+      TestDiagnosticMessagesImpl diagnosticsHandler = new TestDiagnosticMessagesImpl();
       Path desugaredLib = temp.newFolder().toPath().resolve("desugar_jdk_libs_dex.zip");
       L8Command.Builder l8Builder =
-          L8Command.builder()
+          L8Command.builder(diagnosticsHandler)
               .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
               .addProgramFiles(ToolHelper.getDesugarJDKLibs())
               .addProgramFiles(additionalProgramFiles)
@@ -72,7 +78,23 @@
         l8Builder.addProguardConfiguration(
             Arrays.asList(keepRules.split(System.lineSeparator())), Origin.unknown());
       }
-      L8.run(l8Builder.build());
+      ToolHelper.runL8(
+          l8Builder.build(),
+          options -> {
+            if (disableL8AnnotationRemovalForTesting) {
+              options.testing.disableL8AnnotationRemoval = true;
+            }
+          });
+      if (!disableL8AnnotationRemovalForTesting) {
+        assertTrue(
+            diagnosticsHandler.getInfos().stream()
+                .noneMatch(
+                    string ->
+                        string
+                            .getDiagnosticMessage()
+                            .startsWith(
+                                "Invalid parameter counts in MethodParameter attributes.")));
+      }
       return desugaredLib;
     } catch (Exception e) {
       throw new RuntimeException(e);