Support multiple -dontwarn and -adaptclassstrings lines

Before only the last of these lines had effect.

Bug: 67836745
Change-Id: I6206211405e93b3b419af6e6b2b517a546749dc8
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index ae6326e..5255fc5 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -30,8 +30,7 @@
 import com.android.tools.r8.shaking.DiscardedChecker;
 import com.android.tools.r8.shaking.Enqueuer;
 import com.android.tools.r8.shaking.MainDexListBuilder;
-import com.android.tools.r8.shaking.ProguardClassNameList;
-import com.android.tools.r8.shaking.ProguardTypeMatcher.MatchSpecificType;
+import com.android.tools.r8.shaking.ProguardClassFilter;
 import com.android.tools.r8.shaking.ReasonPrinter;
 import com.android.tools.r8.shaking.RootSetBuilder;
 import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
@@ -147,15 +146,9 @@
   }
 
   private Set<DexType> filterMissingClasses(Set<DexType> missingClasses,
-      ProguardClassNameList dontWarnPatterns) {
+      ProguardClassFilter dontWarnPatterns) {
     Set<DexType> result = new HashSet<>(missingClasses);
-    dontWarnPatterns.forEachTypeMatcher(matcher -> {
-      if (matcher instanceof MatchSpecificType) {
-        result.remove(((MatchSpecificType) matcher).type);
-      } else {
-        result.removeIf(matcher::matches);
-      }
-    });
+    dontWarnPatterns.filterOutMatches(result);
     return result;
   }
 
diff --git a/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java b/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java
index fe0ff72..552516d 100644
--- a/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java
@@ -12,19 +12,19 @@
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexValue.DexValueString;
-import com.android.tools.r8.shaking.ProguardClassNameList;
+import com.android.tools.r8.shaking.ProguardClassFilter;
 import com.android.tools.r8.utils.DescriptorUtils;
 import java.util.Map;
 
 class IdentifierMinifier {
 
   private final AppInfo appInfo;
-  private final ProguardClassNameList adaptClassStrings;
+  private final ProguardClassFilter adaptClassStrings;
   private final NamingLens lens;
 
   IdentifierMinifier(
       AppInfo appInfo,
-      ProguardClassNameList adaptClassStrings,
+      ProguardClassFilter adaptClassStrings,
       NamingLens lens) {
     this.appInfo = appInfo;
     this.adaptClassStrings = adaptClassStrings;
@@ -32,7 +32,7 @@
   }
 
   void run() {
-    if (adaptClassStrings.size() != 0) {
+    if (!adaptClassStrings.isEmpty()) {
       handleAdaptClassStrings();
     }
     // TODO(b/36799092): Handle influx of string literals from call sites to annotated members.
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardClassFilter.java b/src/main/java/com/android/tools/r8/shaking/ProguardClassFilter.java
new file mode 100644
index 0000000..939dca3
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardClassFilter.java
@@ -0,0 +1,64 @@
+// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.shaking;
+
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.shaking.ProguardTypeMatcher.MatchSpecificType;
+import com.google.common.collect.ImmutableList;
+import java.util.Set;
+
+public class ProguardClassFilter {
+  private final ImmutableList<ProguardClassNameList> patterns;
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableList.Builder<ProguardClassNameList> patterns = ImmutableList.builder();
+
+    private Builder() {
+    }
+
+    public Builder addPattern(ProguardClassNameList pattern) {
+      patterns.add(pattern);
+      return this;
+    }
+
+    ProguardClassFilter build() {
+      return new ProguardClassFilter(patterns.build());
+    }
+  }
+
+  private ProguardClassFilter(ImmutableList<ProguardClassNameList> patterns) {
+    this.patterns = patterns;
+  }
+
+  public boolean isEmpty() {
+    return patterns.size() == 0;
+  }
+
+  public boolean matches(DexType type) {
+    for (ProguardClassNameList pattern : patterns) {
+      if (pattern.matches(type)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public void filterOutMatches(Set<DexType> types) {
+    for (ProguardClassNameList pattern : patterns) {
+      pattern.forEachTypeMatcher(matcher -> {
+        if (matcher instanceof MatchSpecificType) {
+          assert matcher.getSpecificType() != null;
+          types.remove(matcher.getSpecificType());
+        } else {
+          types.removeIf(matcher::matches);
+        }
+      });
+    }
+  }
+}
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 dc800a3..3251c04 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
@@ -34,7 +34,7 @@
     private boolean verbose;
     private String renameSourceFileAttribute;
     private final List<String> keepAttributePatterns = new ArrayList<>();
-    private ProguardClassNameList dontWarnPatterns;
+    private ProguardClassFilter.Builder dontWarnPatterns = ProguardClassFilter.builder();
     protected final List<ProguardConfigurationRule> rules = new ArrayList<>();
     private final DexItemFactory dexItemFactory;
     private boolean printSeeds;
@@ -44,8 +44,7 @@
     private Path packageObfuscationDictionary;
     private boolean useUniqueClassMemberNames;
     private boolean keepParameterNames;
-    private ProguardClassNameList adaptClassStrings = ProguardClassNameList.emptyList();
-
+    private ProguardClassFilter.Builder adaptClassStrings = ProguardClassFilter.builder();
     private Builder(DexItemFactory dexItemFactory) {
       this.dexItemFactory = dexItemFactory;
       resetProguardDefaults();
@@ -69,7 +68,7 @@
       verbose = false;
       renameSourceFileAttribute = null;
       keepAttributePatterns.clear();
-      dontWarnPatterns = ProguardClassNameList.emptyList();
+      dontWarnPatterns = ProguardClassFilter.builder();
       rules.clear();
       printSeeds = false;
       seedFile = null;
@@ -78,6 +77,7 @@
       packageObfuscationDictionary = null;
       useUniqueClassMemberNames = false;
       keepParameterNames = false;
+      adaptClassStrings = ProguardClassFilter.builder();
     }
 
     public void addInjars(List<FilteredClassPath> injars) {
@@ -162,8 +162,8 @@
       this.rules.add(rule);
     }
 
-    public void setDontWarnPatterns(ProguardClassNameList patterns) {
-      dontWarnPatterns = patterns;
+    public void addDontWarnPattern(ProguardClassNameList pattern) {
+      dontWarnPatterns.addPattern(pattern);
     }
 
     public void setSeedFile(Path seedFile) {
@@ -202,8 +202,8 @@
       return keepParameterNames;
     }
 
-    public void setAdaptClassStrings(ProguardClassNameList adaptClassStrings) {
-      this.adaptClassStrings = adaptClassStrings;
+    public void addAdaptClassStringsPattern(ProguardClassNameList pattern) {
+      adaptClassStrings.addPattern(pattern);
     }
 
     public ProguardConfiguration build() throws CompilationException {
@@ -226,7 +226,7 @@
           verbose,
           renameSourceFileAttribute,
           keepAttributePatterns,
-          dontWarnPatterns,
+          dontWarnPatterns.build(),
           rules,
           printSeeds,
           seedFile,
@@ -235,7 +235,7 @@
           DictionaryReader.readAllNames(packageObfuscationDictionary),
           useUniqueClassMemberNames,
           keepParameterNames,
-          adaptClassStrings);
+          adaptClassStrings.build());
     }
   }
 
@@ -257,7 +257,7 @@
   private final boolean verbose;
   private final String renameSourceFileAttribute;
   private final ImmutableList<String> keepAttributesPatterns;
-  private final ProguardClassNameList dontWarnPatterns;
+  private final ProguardClassFilter dontWarnPatterns;
   protected final ImmutableList<ProguardConfigurationRule> rules;
   private final boolean printSeeds;
   private final Path seedFile;
@@ -266,7 +266,7 @@
   private final ImmutableList<String> packageObfuscationDictionary;
   private boolean useUniqueClassMemberNames;
   private boolean keepParameterNames;
-  private final ProguardClassNameList adaptClassStrings;
+  private final ProguardClassFilter adaptClassStrings;
 
   private ProguardConfiguration(
       DexItemFactory factory,
@@ -287,7 +287,7 @@
       boolean verbose,
       String renameSourceFileAttribute,
       List<String> keepAttributesPatterns,
-      ProguardClassNameList dontWarnPatterns,
+      ProguardClassFilter dontWarnPatterns,
       List<ProguardConfigurationRule> rules,
       boolean printSeeds,
       Path seedFile,
@@ -296,7 +296,7 @@
       ImmutableList<String> packageObfuscationDictionary,
       boolean useUniqueClassMemberNames,
       boolean keepParameterNames,
-      ProguardClassNameList adaptClassStrings) {
+      ProguardClassFilter adaptClassStrings) {
     this.dexItemFactory = factory;
     this.injars = ImmutableList.copyOf(injars);
     this.libraryjars = ImmutableList.copyOf(libraryjars);
@@ -419,7 +419,7 @@
     return keepAttributesPatterns;
   }
 
-  public ProguardClassNameList getDontWarnPatterns() {
+  public ProguardClassFilter getDontWarnPatterns() {
     return dontWarnPatterns;
   }
 
@@ -447,7 +447,7 @@
     return keepParameterNames;
   }
 
-  public ProguardClassNameList getAdaptClassStrings() {
+  public ProguardClassFilter getAdaptClassStrings() {
     return adaptClassStrings;
   }
 
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 ef63e40..40b7598 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -76,6 +76,7 @@
       DexItemFactory dexItemFactory, DiagnosticsHandler diagnosticsHandler) {
     this.dexItemFactory = dexItemFactory;
     configurationBuilder = ProguardConfiguration.builder(dexItemFactory);
+
     this.diagnosticsHandler = diagnosticsHandler;
   }
 
@@ -212,9 +213,9 @@
         configurationBuilder.setIgnoreWarnings(true);
       } else if (acceptString("dontwarn")) {
         if (isOptionalArgumentGiven()) {
-          configurationBuilder.setDontWarnPatterns(parseClassNames());
+          configurationBuilder.addDontWarnPattern(parseClassNames());
         } else {
-          configurationBuilder.setDontWarnPatterns(
+          configurationBuilder.addDontWarnPattern(
               ProguardClassNameList.singletonList(ProguardTypeMatcher.defaultAllMatcher()));
         }
       } else if (acceptString("repackageclasses")) {
@@ -292,9 +293,9 @@
       } else if (acceptString("adaptclassstrings")) {
         skipWhitespace();
         if (isOptionalArgumentGiven()) {
-          configurationBuilder.setAdaptClassStrings(parseClassNames());
+          configurationBuilder.addAdaptClassStringsPattern(parseClassNames());
         } else {
-          configurationBuilder.setAdaptClassStrings(
+          configurationBuilder.addAdaptClassStringsPattern(
               ProguardClassNameList.singletonList(ProguardTypeMatcher.defaultAllMatcher()));
         }
       } else if (acceptString("identifiernamestring")) {
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 00777fa..7912a9d 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -167,6 +167,25 @@
   }
 
   @Test
+  public void testDontWarnMultiple() throws Exception {
+    DexItemFactory dexItemFactory = new DexItemFactory();
+    ProguardConfigurationParser parser =
+        new ProguardConfigurationParser(dexItemFactory, diagnosticsHandler);
+    List<String> configuration1 = ImmutableList.of("-dontwarn foo.**, bar.**");
+    List<String> configuration2 = ImmutableList.of("-dontwarn foo.**", "-dontwarn bar.**");
+    for (List<String> configuration : ImmutableList.of(configuration1, configuration2)) {
+      parser.parse(createConfigurationForTesting(configuration));
+      ProguardConfiguration config = parser.getConfig();
+      assertTrue(
+          config.getDontWarnPatterns().matches(dexItemFactory.createType("Lfoo/Bar;")));
+      assertTrue(
+          config.getDontWarnPatterns().matches(dexItemFactory.createType("Lfoo/bar7Bar;")));
+      assertTrue(
+          config.getDontWarnPatterns().matches(dexItemFactory.createType("Lbar/Foo;")));
+    }
+  }
+
+  @Test
   public void testDontWarnAllExplicitly() throws Exception {
     DexItemFactory dexItemFactory = new DexItemFactory();
     ProguardConfigurationParser parser =
@@ -360,6 +379,26 @@
   }
 
   @Test
+  public void testAdaptClassStringsMultiple() throws Exception {
+    DexItemFactory dexItemFactory = new DexItemFactory();
+    ProguardConfigurationParser parser =
+        new ProguardConfigurationParser(dexItemFactory, diagnosticsHandler);
+    List<String> configuration1 = ImmutableList.of("-adaptclassstrings foo.**, bar.**");
+    List<String> configuration2 =
+        ImmutableList.of("-adaptclassstrings foo.**", "-adaptclassstrings bar.**");
+    for (List<String> configuration : ImmutableList.of(configuration1, configuration2)) {
+      parser.parse(createConfigurationForTesting(configuration));
+      ProguardConfiguration config = parser.getConfig();
+      assertTrue(
+          config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoo/Bar;")));
+      assertTrue(
+          config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoo/bar7Bar;")));
+      assertTrue(
+          config.getAdaptClassStrings().matches(dexItemFactory.createType("Lbar/Foo;")));
+    }
+  }
+
+  @Test
   public void testAdaptClassStringsAllExplicitly() throws Exception {
     DexItemFactory dexItemFactory = new DexItemFactory();
     ProguardConfigurationParser parser =
diff --git a/src/test/java/com/android/tools/r8/shaking/ProguardNameMatchingTest.java b/src/test/java/com/android/tools/r8/shaking/ProguardNameMatchingTest.java
index 2737971..d8c43c9 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardNameMatchingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardNameMatchingTest.java
@@ -9,6 +9,9 @@
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.shaking.ProguardTypeMatcher.ClassOrType;
 import com.android.tools.r8.utils.DescriptorUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.Arrays;
+import java.util.List;
 import org.junit.Test;
 
 public class ProguardNameMatchingTest {
@@ -24,12 +27,20 @@
   }
 
   private static boolean matchClassName(String className, String... patterns) {
-    ProguardClassNameList.Builder builder = ProguardClassNameList.builder();
-    for (String pattern : patterns) {
-      boolean isNegated = pattern.startsWith("!");
-      String actualPattern = isNegated ? pattern.substring(1) : pattern;
-      builder.addClassName(isNegated,
-          ProguardTypeMatcher.create(actualPattern, ClassOrType.CLASS, dexItemFactory));
+    return matchClassName(className, ImmutableList.of(Arrays.asList(patterns)));
+  }
+
+  private static boolean matchClassName(String className, List<List<String>> patternsList) {
+    ProguardClassFilter.Builder builder = ProguardClassFilter.builder();
+    for (List<String> patterns : patternsList) {
+      ProguardClassNameList.Builder listBuilder = ProguardClassNameList.builder();
+      for (String pattern : patterns) {
+        boolean isNegated = pattern.startsWith("!");
+        String actualPattern = isNegated ? pattern.substring(1) : pattern;
+        listBuilder.addClassName(isNegated,
+            ProguardTypeMatcher.create(actualPattern, ClassOrType.CLASS, dexItemFactory));
+      }
+      builder.addPattern(listBuilder.build());
     }
     return builder.build()
         .matches(dexItemFactory.createType(DescriptorUtils.javaTypeToDescriptor(className)));
@@ -65,6 +76,18 @@
 
     assertTrue(matchClassName("boobar", "!foobar", "*bar"));
     assertFalse(matchClassName("foobar", "!foobar", "*bar"));
+
+    assertFalse(matchClassName("foo", "!boo"));
+    assertFalse(matchClassName("foo", "baz,!boo"));
+
+    assertFalse(matchClassName("boo", "!boo", "**"));
+    assertTrue(matchClassName("boo", "**", "!boo"));
+    assertTrue(matchClassName("boo",
+        ImmutableList.of(ImmutableList.of("!boo"), ImmutableList.of("**"))));
+
+    assertFalse(matchClassName("boofoo", "!boo*,*foo,boofoo"));
+    assertTrue(matchClassName("boofoo",
+        ImmutableList.of(ImmutableList.of("!boo*,*foo"), ImmutableList.of("boofoo"))));
   }
 
   private void assertMatchesBasicTypes(String pattern) {