Make DexSplitter not warn on main dex list classes missing from the application

R8 would already have complained about this, and we explicitly allow classes in features that will be fused in by play store

Bug: 120845002
Change-Id: I0c934f1332ec47e44e634ad89f00fbf25c240863
diff --git a/src/main/java/com/android/tools/r8/DexSplitterHelper.java b/src/main/java/com/android/tools/r8/DexSplitterHelper.java
index f78912f..27c564a 100644
--- a/src/main/java/com/android/tools/r8/DexSplitterHelper.java
+++ b/src/main/java/com/android/tools/r8/DexSplitterHelper.java
@@ -58,6 +58,7 @@
     InternalOptions options = command.getInternalOptions();
     options.enableDesugaring = false;
     options.enableMainDexListCheck = false;
+    options.ignoreMainDexMissingClasses = true;
     options.minimalMainDex = false;
     options.enableMinification = false;
     options.enableInlining = false;
diff --git a/src/main/java/com/android/tools/r8/dex/VirtualFile.java b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
index 0e62775..0d12915 100644
--- a/src/main/java/com/android/tools/r8/dex/VirtualFile.java
+++ b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
@@ -307,11 +307,13 @@
             mainDexFile.addClass(programClass);
             classes.remove(programClass);
           } else {
-            options.reporter.warning(
-                new StringDiagnostic(
-                    "Application does not contain `"
-                        + type.toSourceString()
-                        + "` as referenced in main-dex-list."));
+            if (!options.ignoreMainDexMissingClasses) {
+              options.reporter.warning(
+                  new StringDiagnostic(
+                      "Application does not contain `"
+                          + type.toSourceString()
+                          + "` as referenced in main-dex-list."));
+            }
           }
           mainDexFile.commitTransaction();
         }
diff --git a/src/main/java/com/android/tools/r8/dexsplitter/DexSplitter.java b/src/main/java/com/android/tools/r8/dexsplitter/DexSplitter.java
index 9062ae7..4b89d9e 100644
--- a/src/main/java/com/android/tools/r8/dexsplitter/DexSplitter.java
+++ b/src/main/java/com/android/tools/r8/dexsplitter/DexSplitter.java
@@ -86,7 +86,7 @@
 
   @Keep
   public static final class Options {
-    private final DiagnosticsHandler diagnosticsHandler = new DiagnosticsHandler() {};
+    private final DiagnosticsHandler diagnosticsHandler;
     private List<String> inputArchives = new ArrayList<>();
     private List<FeatureJar> featureJars = new ArrayList<>();
     private List<String> baseJars = new ArrayList<>();
@@ -97,6 +97,14 @@
     private String mainDexList;
     private boolean splitNonClassResources = false;
 
+    public Options() {
+      this(new DiagnosticsHandler() {});
+    }
+
+    public Options(DiagnosticsHandler diagnosticsHandler) {
+      this.diagnosticsHandler = diagnosticsHandler;
+    }
+
     public DiagnosticsHandler getDiagnosticsHandler() {
       return diagnosticsHandler;
     }
@@ -293,7 +301,9 @@
       throw new AbortException();
     }
 
-    D8Command.Builder builder = D8Command.builder();
+    D8Command.Builder builder = D8Command.builder(options.diagnosticsHandler);
+
+
     for (String s : options.inputArchives) {
       builder.addProgramFiles(Paths.get(s));
     }
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 a35100e..a5854b6 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -147,6 +147,10 @@
   // Throw exception if there is a warning about invalid debug info.
   public boolean invalidDebugInfoFatal = false;
 
+  // When dexsplitting we ignore main dex classes missing in the application. These will be
+  // fused together by play store when shipped for pre-L devices.
+  public boolean ignoreMainDexMissingClasses = false;
+
   // Hidden marker for classes.dex
   private boolean hasMarker = false;
   private Marker marker;
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
index ff948aa..5103951 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -226,14 +226,15 @@
   @Test
   public void everyThirdClassInMainWithDexSplitter() throws Throwable {
     List<String> featureMappings = new ArrayList<>();
+    List<String> inFeatureMapping = new ArrayList<>();
 
     ImmutableList.Builder<String> mainDexBuilder = ImmutableList.builder();
     for (int i = 0; i < MANY_CLASSES.size(); i++) {
       String clazz = MANY_CLASSES.get(i);
       // Write the first 2 classes into the split.
-      if (i < 2) {
+      if (i < 10) {
         featureMappings.add(clazz + ":feature1");
-        continue;
+        inFeatureMapping.add(clazz);
       }
       if (i % 3 == 0) {
         mainDexBuilder.add(clazz);
@@ -246,19 +247,20 @@
     FileUtils.writeTextFile(mainDexFile, ListUtils.map(mainDexList, MainDexListTests::typeToEntry));
     Path output = temp.getRoot().toPath().resolve("split_output");
     Files.createDirectories(output);
-
-    Options options = new Options();
+    TestDiagnosticsHandler diagnosticsHandler = new TestDiagnosticsHandler();
+    Options options = new Options(diagnosticsHandler);
     options.addInputArchive(getManyClassesMultiDexAppPath().toString());
     options.setFeatureSplitMapping(featureSplitMapping.toString());
     options.setOutput(output.toString());
     options.setMainDexList(mainDexFile.toString());
     DexSplitter.run(options);
+    assertEquals(0, diagnosticsHandler.numberOfErrorsAndWarnings());
     Path baseDir = output.resolve("base");
     CodeInspector inspector =
         new CodeInspector(
             AndroidApp.builder().addProgramFiles(baseDir.resolve("classes.dex")).build());
     for (String clazz : mainDexList) {
-      if (!inspector.clazz(clazz).isPresent()) {
+      if (!inspector.clazz(clazz).isPresent() && !inFeatureMapping.contains(clazz)) {
         failedToFindClassInExpectedFile(baseDir, clazz);
       }
     }
@@ -923,10 +925,20 @@
   private class TestDiagnosticsHandler implements DiagnosticsHandler {
 
     public List<Diagnostic> errors = new ArrayList<>();
+    public List<Diagnostic> warnings = new ArrayList<>();
+
+    public int numberOfErrorsAndWarnings() {
+      return errors.size() + warnings.size();
+    }
 
     @Override
     public void error(Diagnostic error) {
       errors.add(error);
     }
+
+    @Override
+    public void warning(Diagnostic warning) {
+      warnings.add(warning);
+    }
   }
 }