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) {