Merge "Remove empty failures list from DebugTestBase"
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 5b28e78..c6fcc22 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -45,6 +45,7 @@
 import com.android.tools.r8.utils.CfgPrinter;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.StringDiagnostic;
 import com.android.tools.r8.utils.ThreadUtils;
 import com.android.tools.r8.utils.Timing;
 import com.google.common.io.ByteStreams;
@@ -206,11 +207,11 @@
         missingClasses = filterMissingClasses(
             missingClasses, options.proguardConfiguration.getDontWarnPatterns());
         if (!missingClasses.isEmpty()) {
-          System.err.println();
-          System.err.println("WARNING, some classes are missing:");
-          missingClasses.forEach(clazz -> {
-            System.err.println(" - " + clazz.toSourceString());
-          });
+          missingClasses.forEach(
+              clazz -> {
+                options.diagnosticsHandler.warning(
+                    new StringDiagnostic("Missing class: " + clazz.toSourceString()));
+              });
           if (!options.ignoreMissingClasses) {
             throw new CompilationError(
                 "Shrinking can't be performed because some library classes are missing.");
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 752c66b..61e1022 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -144,9 +144,9 @@
       } else if (!options.canUseMultidex()
           && options.mainDexKeepRules.isEmpty()
           && application.mainDexList.isEmpty()) {
-        distributor = new VirtualFile.MonoDexDistributor(this);
+        distributor = new VirtualFile.MonoDexDistributor(this, options);
       } else {
-        distributor = new VirtualFile.FillFilesDistributor(this, options.minimalMainDex);
+        distributor = new VirtualFile.FillFilesDistributor(this, options);
       }
       Map<Integer, VirtualFile> newFiles = distributor.run();
 
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 eeb5023..34ec68c 100644
--- a/src/main/java/com/android/tools/r8/dex/VirtualFile.java
+++ b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
@@ -23,6 +23,8 @@
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.StringDiagnostic;
 import com.google.common.collect.Iterators;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
@@ -267,9 +269,11 @@
     protected Set<DexProgramClass> classes;
     protected Map<DexProgramClass, String> originalNames;
     protected final VirtualFile mainDexFile;
+    protected final InternalOptions options;
 
-    DistributorBase(ApplicationWriter writer) {
+    DistributorBase(ApplicationWriter writer, InternalOptions options) {
       super(writer);
+      this.options = options;
 
       // Create the primary dex file. The distribution will add more if needed.
       mainDexFile = new VirtualFile(0, writer.namingLens);
@@ -293,10 +297,11 @@
             mainDexFile.addClass(programClass);
             classes.remove(programClass);
           } else {
-            System.out.println(
-                "WARNING: Application does not contain `"
-                    + type.toSourceString()
-                    + "` as referenced in main-dex-list.");
+            options.diagnosticsHandler.warning(
+                new StringDiagnostic(
+                    "Application does not contain `"
+                        + type.toSourceString()
+                        + "` as referenced in main-dex-list."));
           }
           mainDexFile.commitTransaction();
         }
@@ -338,12 +343,10 @@
   }
 
   public static class FillFilesDistributor extends DistributorBase {
-    boolean minimalMainDex;
     private final FillStrategy fillStrategy;
 
-    FillFilesDistributor(ApplicationWriter writer, boolean minimalMainDex) {
-      super(writer);
-      this.minimalMainDex = minimalMainDex;
+    FillFilesDistributor(ApplicationWriter writer, InternalOptions options) {
+      super(writer, options);
       this.fillStrategy = FillStrategy.FILL_MAX;
     }
 
@@ -357,7 +360,7 @@
       }
 
       Map<Integer, VirtualFile> filesForDistribution = nameToFileMap;
-      if (minimalMainDex && !mainDexFile.isEmpty()) {
+      if (options.minimalMainDex && !mainDexFile.isEmpty()) {
         assert !nameToFileMap.get(0).isEmpty();
         // The main dex file is filtered out, so create ensure at least one file for the remaining
         // classes
@@ -378,8 +381,8 @@
   }
 
   public static class MonoDexDistributor extends DistributorBase {
-    MonoDexDistributor(ApplicationWriter writer) {
-      super(writer);
+    MonoDexDistributor(ApplicationWriter writer, InternalOptions options) {
+      super(writer, options);
     }
 
     @Override
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
index 2560fd6..239f9bc 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
@@ -45,6 +45,7 @@
     private Path classObfuscationDictionary;
     private Path packageObfuscationDictionary;
     private boolean useUniqueClassMemberNames;
+    private boolean keepParameterNames;
 
     private Builder(DexItemFactory dexItemFactory) {
       this.dexItemFactory = dexItemFactory;
@@ -164,6 +165,14 @@
       return useUniqueClassMemberNames;
     }
 
+    public void setKeepParameterNames(boolean keepParameterNames) {
+      this.keepParameterNames = keepParameterNames;
+    }
+
+    boolean isKeepParameterNames() {
+      return keepParameterNames;
+    }
+
     public ProguardConfiguration build() {
       return new ProguardConfiguration(
           dexItemFactory,
@@ -191,7 +200,8 @@
           DictionaryReader.readAllNames(obfuscationDictionary),
           DictionaryReader.readAllNames(classObfuscationDictionary),
           DictionaryReader.readAllNames(packageObfuscationDictionary),
-          useUniqueClassMemberNames);
+          useUniqueClassMemberNames,
+          keepParameterNames);
     }
   }
 
@@ -221,6 +231,7 @@
   private final ImmutableList<String> classObfuscationDictionary;
   private final ImmutableList<String> packageObfuscationDictionary;
   private boolean useUniqueClassMemberNames;
+  private boolean keepParameterNames;
 
   private ProguardConfiguration(
       DexItemFactory factory,
@@ -248,7 +259,8 @@
       ImmutableList<String> obfuscationDictionary,
       ImmutableList<String> classObfuscationDictionary,
       ImmutableList<String> packageObfuscationDictionary,
-      boolean useUniqueClassMemberNames) {
+      boolean useUniqueClassMemberNames,
+      boolean keepParameterNames) {
     this.dexItemFactory = factory;
     this.injars = ImmutableList.copyOf(injars);
     this.libraryjars = ImmutableList.copyOf(libraryjars);
@@ -275,6 +287,7 @@
     this.classObfuscationDictionary = classObfuscationDictionary;
     this.packageObfuscationDictionary = packageObfuscationDictionary;
     this.useUniqueClassMemberNames = useUniqueClassMemberNames;
+    this.keepParameterNames = keepParameterNames;
   }
 
   /**
@@ -388,6 +401,10 @@
     return useUniqueClassMemberNames;
   }
 
+  public boolean isKeepParameterNames() {
+    return keepParameterNames;
+  }
+
   public static ProguardConfiguration defaultConfiguration(DexItemFactory dexItemFactory) {
     return new DefaultProguardConfiguration(dexItemFactory);
   }
@@ -420,7 +437,8 @@
           ImmutableList.of()    /* obfuscationDictionary */,
           ImmutableList.of()    /* classObfuscationDictionary */,
           ImmutableList.of()    /* packageObfuscationDictionary */,
-          false                 /* useUniqueClassMemberNames*/);
+          false                 /* useUniqueClassMemberNames*/,
+          false                 /* keepParameterNames */);
     }
 
     @Override
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
index 4784387..08a7eca 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -85,6 +85,13 @@
       throw new ProguardRuleParserException("-useuniqueulassmembernames is not supported");
     }
 
+    if (configurationBuilder.isKeepParameterNames()
+        && configurationBuilder.isObfuscating()) {
+      // The flag -keepparameternames has only effect when minifying, so ignore it if we
+      // are not.
+      throw new ProguardRuleParserException("-keepparameternames is not supported");
+    }
+
     return configurationBuilder.build();
   }
 
@@ -156,6 +163,8 @@
       } else if (acceptString("keeppackagenames")) {
         ProguardKeepPackageNamesRule rule = parseKeepPackageNamesRule();
         configurationBuilder.addRule(rule);
+      } else if (acceptString("keepparameternames")) {
+        configurationBuilder.setKeepParameterNames(true);
       } else if (acceptString("checkdiscard")) {
         ProguardCheckDiscardRule rule = parseCheckDiscardRule();
         configurationBuilder.addRule(rule);
diff --git a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
index 9f19536..3f44025 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -680,4 +680,40 @@
     config = parser.getConfig();
     assertTrue(config.isUseUniqueClassMemberNames());
   }
+
+  @Test
+  public void parseKeepParameterNames() throws Exception {
+    try {
+      ProguardConfigurationParser parser = new ProguardConfigurationParser(new DexItemFactory());
+      parser.parse(new ProguardConfigurationSourceStrings(ImmutableList.of(
+          "-keepparameternames"
+      )));
+      parser.getConfig();
+      fail();
+    } catch (ProguardRuleParserException e) {
+      System.out.println(e);
+      assertTrue(e.getMessage().contains("-keepparameternames is not supported"));
+    }
+  }
+
+  @Test
+  public void parseKeepParameterNamesWithoutMinification() throws Exception {
+    ProguardConfigurationParser parser = new ProguardConfigurationParser(new DexItemFactory());
+    parser.parse(new ProguardConfigurationSourceStrings(ImmutableList.of(
+        "-keepparameternames",
+        "-dontobfuscate"
+    )));
+    ProguardConfiguration config = parser.getConfig();
+    assertTrue(config.isKeepParameterNames());
+
+    parser = new ProguardConfigurationParser(new DexItemFactory());
+    parser.parse(new ProguardConfigurationSourceStrings(ImmutableList.of(
+        "-keepparameternames"
+    )));
+    parser.parse(new ProguardConfigurationSourceStrings(ImmutableList.of(
+        "-dontobfuscate"
+    )));
+    config = parser.getConfig();
+    assertTrue(config.isKeepParameterNames());
+  }
 }