Merge "Enable errorprone check to ensure hashCode is implemented."
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/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 7eff6fa..5b3cfb5 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -477,7 +477,6 @@
internal.useDiscardedChecker = useDiscardedChecker();
assert !internal.ignoreMissingClasses;
internal.ignoreMissingClasses = ignoreMissingClasses;
- internal.keepAttributes.applyPatterns(proguardConfiguration.getKeepAttributesPatterns());
internal.ignoreMissingClasses |= proguardConfiguration.isIgnoreWarnings();
assert !internal.verbose;
internal.mainDexKeepRules = mainDexKeepRules;
diff --git a/src/main/java/com/android/tools/r8/dex/DexFileReader.java b/src/main/java/com/android/tools/r8/dex/DexFileReader.java
index 8175834..770afdf 100644
--- a/src/main/java/com/android/tools/r8/dex/DexFileReader.java
+++ b/src/main/java/com/android/tools/r8/dex/DexFileReader.java
@@ -53,6 +53,7 @@
import com.android.tools.r8.graph.OffsetToObjectMapping;
import com.android.tools.r8.logging.Log;
import com.android.tools.r8.utils.ProgramResource.Kind;
+import it.unimi.dsi.fastutil.ints.Int2IntArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.io.ByteArrayOutputStream;
@@ -62,7 +63,6 @@
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Hashtable;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -751,7 +751,7 @@
file.getUshort(); // Skip padding ushort
}
if (triesSize > 0) {
- Hashtable<Integer, Integer> handlerMap = new Hashtable<>();
+ Int2IntArrayMap handlerMap = new Int2IntArrayMap();
// tries: try_item[tries_size].
for (int i = 0; i < triesSize; i++) {
int startAddr = file.getUint();
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java
index b1db651..dccf887 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -62,7 +62,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
-import java.util.Hashtable;
+import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
@@ -997,8 +997,8 @@
= createObject2IntMap();
private final Object2IntMap<DexProgramClass> classesWithData = createObject2IntMap();
private final Object2IntMap<DexEncodedArray> encodedArrays = createObject2IntMap();
- private final Hashtable<DexProgramClass, DexAnnotationDirectory> clazzToAnnotationDirectory
- = new Hashtable<>();
+ private final Map<DexProgramClass, DexAnnotationDirectory> clazzToAnnotationDirectory
+ = new HashMap<>();
private static <T> Object2IntMap<T> createObject2IntMap() {
Object2IntMap<T> result = new Object2IntLinkedOpenHashMap<>();
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
index 093442b..a2caf1d 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
@@ -8,7 +8,7 @@
import com.google.common.collect.Sets;
import java.util.Collections;
import java.util.HashSet;
-import java.util.Hashtable;
+import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
@@ -18,7 +18,7 @@
// Set of missing classes, discovered during subtypeMap computation.
private Set<DexType> missingClasses = Sets.newIdentityHashSet();
// Map from types to their subtypes.
- private final Hashtable<DexType, ImmutableSet<DexType>> subtypeMap = new Hashtable<>();
+ private final Map<DexType, ImmutableSet<DexType>> subtypeMap = new IdentityHashMap<>();
public AppInfoWithSubtyping(DexApplication application) {
super(application);
@@ -57,7 +57,7 @@
return subtypes == null ? ImmutableSet.of() : subtypes;
}
- private void populateSuperType(Hashtable<DexType, Set<DexType>> map, DexType superType,
+ private void populateSuperType(Map<DexType, Set<DexType>> map, DexType superType,
DexClass baseClass, Function<DexType, DexClass> definitions) {
if (superType != null) {
Set<DexType> set = map.computeIfAbsent(superType, ignore -> new HashSet<>());
@@ -68,7 +68,7 @@
}
}
- private void populateAllSuperTypes(Hashtable<DexType, Set<DexType>> map, DexType holder,
+ private void populateAllSuperTypes(Map<DexType, Set<DexType>> map, DexType holder,
DexClass baseClass, Function<DexType, DexClass> definitions) {
DexClass holderClass = definitions.apply(holder);
// Skip if no corresponding class is found.
@@ -98,7 +98,7 @@
private void populateSubtypeMap(DirectMappedDexApplication app, DexItemFactory dexItemFactory) {
dexItemFactory.clearSubtypeInformation();
dexItemFactory.objectType.tagAsSubtypeRoot();
- Hashtable<DexType, Set<DexType>> map = new Hashtable<>();
+ Map<DexType, Set<DexType>> map = new IdentityHashMap<>();
for (DexClass clazz : Iterables.<DexClass>concat(app.classes(), app.libraryClasses())) {
populateAllSuperTypes(map, clazz.type, clazz, app::definitionFor);
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index 9267f7d..6a2fcbf 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -17,11 +17,11 @@
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringUtils;
+import it.unimi.dsi.fastutil.ints.Int2IntMap;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@@ -359,7 +359,7 @@
this.handlerIndex = NO_INDEX;
}
- public void setHandlerIndex(Hashtable<Integer, Integer> map) {
+ public void setHandlerIndex(Int2IntMap map) {
handlerIndex = map.get(handlerOffset);
}
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java b/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
index 504cc4a..1360964 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
@@ -17,7 +17,7 @@
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
-import java.util.Hashtable;
+import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
@@ -26,7 +26,7 @@
private final ImmutableMap<String, ClassNaming> classNameMappings;
private ImmutableBiMap<String, String> nameMapping;
- private Hashtable<Signature, Signature> signatureMap = new Hashtable<>();
+ private Map<Signature, Signature> signatureMap = new HashMap<>();
ClassNameMapper(Map<String, ClassNaming> classNameMappings) {
this.classNameMappings = ImmutableMap.copyOf(classNameMappings);
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
index c5e62e2..39ca020 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
@@ -71,7 +71,7 @@
this.isAccessModificationAllowed = options.proguardConfiguration.isAccessModificationAllowed();
this.packageDictionary = options.proguardConfiguration.getPackageObfuscationDictionary();
this.classDictionary = options.proguardConfiguration.getClassObfuscationDictionary();
- this.keepInnerClassStructure = options.keepAttributes.signature;
+ this.keepInnerClassStructure = options.proguardConfiguration.getKeepAttributes().signature;
// Initialize top-level naming state.
topLevelState = new Namespace(
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/naming/SourceFileRewriter.java b/src/main/java/com/android/tools/r8/naming/SourceFileRewriter.java
index c10d0d7..3736008 100644
--- a/src/main/java/com/android/tools/r8/naming/SourceFileRewriter.java
+++ b/src/main/java/com/android/tools/r8/naming/SourceFileRewriter.java
@@ -31,7 +31,7 @@
public void run() {
String renameSourceFile = options.proguardConfiguration.getRenameSourceFileAttribute();
// Return early if a user wants to keep the current source file attribute as-is.
- if (renameSourceFile == null && options.keepAttributes.sourceFile) {
+ if (renameSourceFile == null && options.proguardConfiguration.getKeepAttributes().sourceFile) {
return;
}
// Now, the user wants either to remove source file attribute or to rename it.
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 824f1bd..1698f7a 100644
--- a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
@@ -13,7 +13,6 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.InternalOptions.KeepAttributeOptions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.function.Predicate;
@@ -21,14 +20,13 @@
public class AnnotationRemover {
private final AppInfoWithLiveness appInfo;
- private final KeepAttributeOptions keep;
+ private final ProguardKeepAttributes keep;
public AnnotationRemover(AppInfoWithLiveness appInfo, InternalOptions options) {
- this(appInfo, options.keepAttributes);
+ this(appInfo, options.proguardConfiguration.getKeepAttributes());
}
- public AnnotationRemover(AppInfoWithLiveness appInfo,
- KeepAttributeOptions keep) {
+ public AnnotationRemover(AppInfoWithLiveness appInfo, ProguardKeepAttributes keep) {
this.appInfo = appInfo;
this.keep = keep;
}
@@ -91,7 +89,7 @@
}
break;
case DexAnnotation.VISIBILITY_BUILD:
- if (!keep.runtimeInvisibleParamterAnnotations) {
+ if (!keep.runtimeInvisibleParameterAnnotations) {
return false;
}
break;
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..4a84321 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
@@ -6,7 +6,6 @@
import com.android.tools.r8.CompilationException;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.DictionaryReader;
-import com.android.tools.r8.utils.InternalOptions.KeepAttributeOptions;
import com.android.tools.r8.utils.InternalOptions.PackageObfuscationMode;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
@@ -34,7 +33,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 +43,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 +67,7 @@
verbose = false;
renameSourceFileAttribute = null;
keepAttributePatterns.clear();
- dontWarnPatterns = ProguardClassNameList.emptyList();
+ dontWarnPatterns = ProguardClassFilter.builder();
rules.clear();
printSeeds = false;
seedFile = null;
@@ -78,6 +76,7 @@
packageObfuscationDictionary = null;
useUniqueClassMemberNames = false;
keepParameterNames = false;
+ adaptClassStrings = ProguardClassFilter.builder();
}
public void addInjars(List<FilteredClassPath> injars) {
@@ -162,8 +161,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 +201,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 +225,7 @@
verbose,
renameSourceFileAttribute,
keepAttributePatterns,
- dontWarnPatterns,
+ dontWarnPatterns.build(),
rules,
printSeeds,
seedFile,
@@ -235,7 +234,7 @@
DictionaryReader.readAllNames(packageObfuscationDictionary),
useUniqueClassMemberNames,
keepParameterNames,
- adaptClassStrings);
+ adaptClassStrings.build());
}
}
@@ -256,8 +255,8 @@
private final Path applyMappingFile;
private final boolean verbose;
private final String renameSourceFileAttribute;
- private final ImmutableList<String> keepAttributesPatterns;
- private final ProguardClassNameList dontWarnPatterns;
+ private final ProguardKeepAttributes keepAttributes;
+ private final ProguardClassFilter dontWarnPatterns;
protected final ImmutableList<ProguardConfigurationRule> rules;
private final boolean printSeeds;
private final Path seedFile;
@@ -266,7 +265,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 +286,7 @@
boolean verbose,
String renameSourceFileAttribute,
List<String> keepAttributesPatterns,
- ProguardClassNameList dontWarnPatterns,
+ ProguardClassFilter dontWarnPatterns,
List<ProguardConfigurationRule> rules,
boolean printSeeds,
Path seedFile,
@@ -296,7 +295,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);
@@ -314,7 +313,7 @@
this.applyMappingFile = applyMappingFile;
this.verbose = verbose;
this.renameSourceFileAttribute = renameSourceFileAttribute;
- this.keepAttributesPatterns = ImmutableList.copyOf(keepAttributesPatterns);
+ this.keepAttributes = ProguardKeepAttributes.fromPatterns(keepAttributesPatterns);
this.dontWarnPatterns = dontWarnPatterns;
this.rules = ImmutableList.copyOf(rules);
this.printSeeds = printSeeds;
@@ -338,7 +337,7 @@
Builder builder = new Builder(dexItemFactory);
builder.setObfuscating(false);
builder.setShrinking(false);
- builder.addKeepAttributePatterns(KeepAttributeOptions.KEEP_ALL);
+ builder.addKeepAttributePatterns(ProguardKeepAttributes.KEEP_ALL);
builder.addRule(ProguardKeepRule.defaultKeepAllRule());
return builder;
}
@@ -415,11 +414,11 @@
return renameSourceFileAttribute;
}
- public ImmutableList<String> getKeepAttributesPatterns() {
- return keepAttributesPatterns;
+ public ProguardKeepAttributes getKeepAttributes() {
+ return keepAttributes;
}
- public ProguardClassNameList getDontWarnPatterns() {
+ public ProguardClassFilter getDontWarnPatterns() {
return dontWarnPatterns;
}
@@ -447,7 +446,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/main/java/com/android/tools/r8/shaking/ProguardKeepAttributes.java b/src/main/java/com/android/tools/r8/shaking/ProguardKeepAttributes.java
new file mode 100644
index 0000000..487a5b4
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardKeepAttributes.java
@@ -0,0 +1,182 @@
+// 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.errors.CompilationError;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+
+public class ProguardKeepAttributes {
+
+ public static final String SOURCE_FILE = "SourceFile";
+ public static final String SOURCE_DIR = "SourceDir";
+ public static final String INNER_CLASSES = "InnerClasses";
+ public static final String ENCLOSING_METHOD = "EnclosingMethod";
+ public static final String SIGNATURE = "Signature";
+ public static final String EXCEPTIONS = "Exceptions";
+ public static final String SOURCE_DEBUG_EXTENSION = "SourceDebugExtension";
+ public static final String RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations";
+ public static final String RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations";
+ public static final String RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS =
+ "RuntimeVisibleParameterAnnotations";
+ public static final String RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS =
+ "RuntimeInvisibleParameterAnnotations";
+ public static final String RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations";
+ public static final String RUNTIME_INVISIBLE_TYPE_ANNOTATIONS =
+ "RuntimeInvisibleTypeAnnotations";
+ public static final String ANNOTATION_DEFAULT = "AnnotationDefault";
+
+ public static final List<String> KEEP_ALL = ImmutableList.of("*");
+
+ public boolean sourceFile = false;
+ public boolean sourceDir = false;
+ public boolean innerClasses = false;
+ public boolean enclosingMethod = false;
+ public boolean signature = false;
+ public boolean exceptions = false;
+ public boolean sourceDebugExtension = false;
+ public boolean runtimeVisibleAnnotations = false;
+ public boolean runtimeInvisibleAnnotations = false;
+ public boolean runtimeVisibleParameterAnnotations = false;
+ public boolean runtimeInvisibleParameterAnnotations = false;
+ public boolean runtimeVisibleTypeAnnotations = false;
+ public boolean runtimeInvisibleTypeAnnotations = false;
+ public boolean annotationDefault = false;
+
+ private ProguardKeepAttributes() {
+ }
+
+ public static ProguardKeepAttributes filterOnlySignatures() {
+ ProguardKeepAttributes result = new ProguardKeepAttributes();
+ result.applyPatterns(KEEP_ALL);
+ result.signature = false;
+ return result;
+ }
+
+ /**
+ * Implements ProGuards attribute matching rules.
+ *
+ * @see <a href="https://www.guardsquare.com/en/proguard/manual/attributes">ProGuard manual</a>.
+ */
+ private boolean update(boolean previous, String text, List<String> patterns) {
+ for (String pattern : patterns) {
+ if (previous) {
+ return true;
+ }
+ if (pattern.charAt(0) == '!') {
+ if (matches(pattern, 1, text, 0)) {
+ break;
+ }
+ } else {
+ previous = matches(pattern, 0, text, 0);
+ }
+ }
+ return previous;
+ }
+
+ private boolean matches(String pattern, int patternPos, String text, int textPos) {
+ while (patternPos < pattern.length()) {
+ char next = pattern.charAt(patternPos++);
+ if (next == '*') {
+ while (textPos < text.length()) {
+ if (matches(pattern, patternPos, text, textPos++)) {
+ return true;
+ }
+ }
+ return patternPos >= pattern.length();
+ } else {
+ if (textPos >= text.length() || text.charAt(textPos) != next) {
+ return false;
+ }
+ textPos++;
+ }
+ }
+ return textPos == text.length();
+ }
+
+ public static ProguardKeepAttributes fromPatterns(List<String> patterns) {
+ ProguardKeepAttributes keepAttributes = new ProguardKeepAttributes();
+ keepAttributes.applyPatterns(patterns);
+ return keepAttributes;
+ }
+
+ public void applyPatterns(List<String> patterns) {
+ sourceFile = update(sourceFile, SOURCE_FILE, patterns);
+ sourceDir = update(sourceDir, SOURCE_DIR, patterns);
+ innerClasses = update(innerClasses, INNER_CLASSES, patterns);
+ enclosingMethod = update(enclosingMethod, ENCLOSING_METHOD, patterns);
+ signature = update(signature, SIGNATURE, patterns);
+ exceptions = update(exceptions, EXCEPTIONS, patterns);
+ sourceDebugExtension = update(sourceDebugExtension, SOURCE_DEBUG_EXTENSION, patterns);
+ runtimeVisibleAnnotations = update(runtimeVisibleAnnotations, RUNTIME_VISIBLE_ANNOTATIONS,
+ patterns);
+ runtimeInvisibleAnnotations = update(runtimeInvisibleAnnotations,
+ RUNTIME_INVISIBLE_ANNOTATIONS, patterns);
+ runtimeVisibleParameterAnnotations = update(runtimeVisibleParameterAnnotations,
+ RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, patterns);
+ runtimeInvisibleParameterAnnotations = update(runtimeInvisibleParameterAnnotations,
+ RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, patterns);
+ runtimeVisibleTypeAnnotations = update(runtimeVisibleTypeAnnotations,
+ RUNTIME_VISIBLE_TYPE_ANNOTATIONS, patterns);
+ runtimeInvisibleTypeAnnotations = update(runtimeInvisibleTypeAnnotations,
+ RUNTIME_INVISIBLE_TYPE_ANNOTATIONS, patterns);
+ annotationDefault = update(annotationDefault, ANNOTATION_DEFAULT, patterns);
+ }
+
+ public void ensureValid() {
+ if (innerClasses && !enclosingMethod) {
+ throw new CompilationError("Attribute InnerClasses requires EnclosingMethod attribute. "
+ + "Check -keepattributes directive.");
+ } else if (!innerClasses && enclosingMethod) {
+ throw new CompilationError("Attribute EnclosingMethod requires InnerClasses attribute. "
+ + "Check -keepattributes directive.");
+ } else if (signature && !innerClasses) {
+ throw new CompilationError("Attribute Signature requires InnerClasses attribute. Check "
+ + "-keepattributes directive.");
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof ProguardKeepAttributes)) {
+ return false;
+ }
+ ProguardKeepAttributes other = (ProguardKeepAttributes) o;
+ return this.sourceFile == other.sourceFile
+ && this.sourceDir == other.sourceDir
+ && this.innerClasses == other.innerClasses
+ && this.enclosingMethod == other.enclosingMethod
+ && this.signature == other.signature
+ && this.exceptions == other.exceptions
+ && this.sourceDebugExtension == other.sourceDebugExtension
+ && this.runtimeVisibleAnnotations == other.runtimeVisibleAnnotations
+ && this.runtimeInvisibleAnnotations == other.runtimeInvisibleAnnotations
+ && this.runtimeVisibleParameterAnnotations == other.runtimeVisibleParameterAnnotations
+ && this.runtimeInvisibleParameterAnnotations == other.runtimeInvisibleParameterAnnotations
+ && this.runtimeVisibleTypeAnnotations == other.runtimeVisibleTypeAnnotations
+ && this.runtimeInvisibleTypeAnnotations == other.runtimeInvisibleTypeAnnotations
+ && this.annotationDefault == other.annotationDefault;
+ }
+
+ @Override
+ public int hashCode() {
+ return (this.sourceFile ? 1 : 0)
+ + (this.sourceDir ? 1 << 1 : 0)
+ + (this.innerClasses ? 1 << 2 : 0)
+ + (this.enclosingMethod ? 1 << 3 : 0)
+ + (this.signature ? 1 << 4 : 0)
+ + (this.exceptions ? 1 << 5 : 0)
+ + (this.sourceDebugExtension ? 1 << 6 : 0)
+ + (this.runtimeVisibleAnnotations ? 1 << 7 : 0)
+ + (this.runtimeInvisibleAnnotations ? 1 << 8 : 0)
+ + (this.runtimeVisibleParameterAnnotations ? 1 << 9 : 0)
+ + (this.runtimeInvisibleParameterAnnotations ? 1 << 10 : 0)
+ + (this.runtimeVisibleTypeAnnotations ? 1 << 11 : 0)
+ + (this.runtimeInvisibleTypeAnnotations ? 1 << 12 : 0)
+ + (this.annotationDefault ? 1 << 13 : 0);
+ }
+}
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 8d7171f..75f89be 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -6,7 +6,6 @@
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.Resource.Origin;
import com.android.tools.r8.dex.Marker;
-import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.InvalidDebugInfoException;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
@@ -114,7 +113,6 @@
public boolean skipMinification = false;
public boolean disableAssertions = true;
public boolean debugKeepRules = false;
- public final KeepAttributeOptions keepAttributes = new KeepAttributeOptions();
public boolean allowParameterName = false;
public boolean debug = false;
@@ -282,132 +280,6 @@
public boolean invertConditionals = false;
}
- public static class KeepAttributeOptions {
-
- public static final String SOURCE_FILE = "SourceFile";
- public static final String SOURCE_DIR = "SourceDir";
- public static final String INNER_CLASSES = "InnerClasses";
- public static final String ENCLOSING_METHOD = "EnclosingMethod";
- public static final String SIGNATURE = "Signature";
- public static final String EXCEPTIONS = "Exceptions";
- public static final String SOURCE_DEBUG_EXTENSION = "SourceDebugExtension";
- public static final String RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations";
- public static final String RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations";
- public static final String RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS =
- "RuntimeVisibleParameterAnnotations";
- public static final String RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS =
- "RuntimeInvisibleParameterAnnotations";
- public static final String RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations";
- public static final String RUNTIME_INVISIBLE_TYPE_ANNOTATIONS =
- "RuntimeInvisibleTypeAnnotations";
- public static final String ANNOTATION_DEFAULT = "AnnotationDefault";
-
- public static final List<String> KEEP_ALL = ImmutableList.of("*");
-
- public boolean sourceFile = false;
- public boolean sourceDir = false;
- public boolean innerClasses = false;
- public boolean enclosingMethod = false;
- public boolean signature = false;
- public boolean exceptions = false;
- public boolean sourceDebugExtension = false;
- public boolean runtimeVisibleAnnotations = false;
- public boolean runtimeInvisibleAnnotations = false;
- public boolean runtimeVisibleParameterAnnotations = false;
- public boolean runtimeInvisibleParamterAnnotations = false;
- public boolean runtimeVisibleTypeAnnotations = false;
- public boolean runtimeInvisibleTypeAnnotations = false;
- public boolean annotationDefault = false;
-
- private KeepAttributeOptions() {
-
- }
-
- public static KeepAttributeOptions filterOnlySignatures() {
- KeepAttributeOptions result = new KeepAttributeOptions();
- result.applyPatterns(KEEP_ALL);
- result.signature = false;
- return result;
- }
-
- /**
- * Implements ProGuards attribute matching rules.
- *
- * @see <a href="https://www.guardsquare.com/en/proguard/manual/attributes">ProGuard manual</a>.
- */
- private boolean update(boolean previous, String text, List<String> patterns) {
- for (String pattern : patterns) {
- if (previous) {
- return true;
- }
- if (pattern.charAt(0) == '!') {
- if (matches(pattern, 1, text, 0)) {
- break;
- }
- } else {
- previous = matches(pattern, 0, text, 0);
- }
- }
- return previous;
- }
-
- private boolean matches(String pattern, int patternPos, String text, int textPos) {
- while (patternPos < pattern.length()) {
- char next = pattern.charAt(patternPos++);
- if (next == '*') {
- while (textPos < text.length()) {
- if (matches(pattern, patternPos, text, textPos++)) {
- return true;
- }
- }
- return patternPos >= pattern.length();
- } else {
- if (textPos >= text.length() || text.charAt(textPos) != next) {
- return false;
- }
- textPos++;
- }
- }
- return textPos == text.length();
- }
-
- public void applyPatterns(List<String> patterns) {
- sourceFile = update(sourceFile, SOURCE_FILE, patterns);
- sourceDir = update(sourceDir, SOURCE_DIR, patterns);
- innerClasses = update(innerClasses, INNER_CLASSES, patterns);
- enclosingMethod = update(enclosingMethod, ENCLOSING_METHOD, patterns);
- signature = update(signature, SIGNATURE, patterns);
- exceptions = update(exceptions, EXCEPTIONS, patterns);
- sourceDebugExtension = update(sourceDebugExtension, SOURCE_DEBUG_EXTENSION, patterns);
- runtimeVisibleAnnotations = update(runtimeVisibleAnnotations, RUNTIME_VISIBLE_ANNOTATIONS,
- patterns);
- runtimeInvisibleAnnotations = update(runtimeInvisibleAnnotations,
- RUNTIME_INVISIBLE_ANNOTATIONS, patterns);
- runtimeVisibleParameterAnnotations = update(runtimeVisibleParameterAnnotations,
- RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, patterns);
- runtimeInvisibleParamterAnnotations = update(runtimeInvisibleParamterAnnotations,
- RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, patterns);
- runtimeVisibleTypeAnnotations = update(runtimeVisibleTypeAnnotations,
- RUNTIME_VISIBLE_TYPE_ANNOTATIONS, patterns);
- runtimeInvisibleTypeAnnotations = update(runtimeInvisibleTypeAnnotations,
- RUNTIME_INVISIBLE_TYPE_ANNOTATIONS, patterns);
- annotationDefault = update(annotationDefault, ANNOTATION_DEFAULT, patterns);
- }
-
- public void ensureValid() {
- if (innerClasses && !enclosingMethod) {
- throw new CompilationError("Attribute InnerClasses requires EnclosingMethod attribute. "
- + "Check -keepattributes directive.");
- } else if (!innerClasses && enclosingMethod) {
- throw new CompilationError("Attribute EnclosingMethod requires InnerClasses attribute. "
- + "Check -keepattributes directive.");
- } else if (signature && !innerClasses) {
- throw new CompilationError("Attribute Signature requires InnerClasses attribute. Check "
- + "-keepattributes directive.");
- }
- }
- }
-
public boolean canUseInvokePolymorphicOnVarHandle() {
return minApiLevel >= AndroidApiLevel.P.getLevel();
}
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..6dc19aa 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -18,7 +18,6 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.utils.DefaultDiagnosticsHandler;
import com.android.tools.r8.utils.FileUtils;
-import com.android.tools.r8.utils.InternalOptions.KeepAttributeOptions;
import com.android.tools.r8.utils.InternalOptions.PackageObfuscationMode;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
@@ -167,6 +166,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 +378,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 =
@@ -777,8 +815,8 @@
parser.parse(createConfigurationForTesting(ImmutableList.of(config1, config2)));
ProguardConfiguration config = parser.getConfig();
assertEquals("PG", config.getRenameSourceFileAttribute());
- assertTrue(config.getKeepAttributesPatterns().contains(KeepAttributeOptions.SOURCE_FILE));
- assertTrue(config.getKeepAttributesPatterns().contains(KeepAttributeOptions.SOURCE_DIR));
+ assertTrue(config.getKeepAttributes().sourceFile);
+ assertTrue(config.getKeepAttributes().sourceDir);
}
@Test
@@ -790,14 +828,16 @@
parser.parse(createConfigurationForTesting(ImmutableList.of(config1, config2)));
ProguardConfiguration config = parser.getConfig();
assertEquals("", config.getRenameSourceFileAttribute());
- assertTrue(config.getKeepAttributesPatterns().contains(KeepAttributeOptions.SOURCE_FILE));
+ assertTrue(config.getKeepAttributes().sourceFile);
}
private void testKeepattributes(List<String> expected, String config) throws Exception {
ProguardConfigurationParser parser =
new ProguardConfigurationParser(new DexItemFactory(), diagnosticsHandler);
parser.parse(createConfigurationForTesting(ImmutableList.of(config)));
- assertEquals(expected, parser.getConfig().getKeepAttributesPatterns());
+ assertEquals(
+ ProguardKeepAttributes.fromPatterns(expected),
+ parser.getConfig().getKeepAttributes());
}
@Test
@@ -809,9 +849,11 @@
testKeepattributes(xxxYYY, "-keepattributes xxx , yyy");
testKeepattributes(xxxYYY, "-keepattributes xxx , yyy ");
testKeepattributes(xxxYYY, "-keepattributes xxx , yyy \n");
- String config = "-keepattributes Exceptions,InnerClasses,Signature,Deprecated,\n" +
- " SourceFile,LineNumberTable,*Annotation*,EnclosingMethod\n";
- List<String> expected = ImmutableList.of("Exceptions", "InnerClasses", "Signature", "Deprecated",
+ String config =
+ "-keepattributes Exceptions,InnerClasses,Signature,Deprecated,\n"
+ + " SourceFile,LineNumberTable,*Annotation*,EnclosingMethod\n";
+ List<String> expected = ImmutableList.of(
+ "Exceptions", "InnerClasses", "Signature", "Deprecated",
"SourceFile", "LineNumberTable", "*Annotation*", "EnclosingMethod");
testKeepattributes(expected, config);
}
@@ -850,7 +892,6 @@
parser.getConfig();
fail();
} catch (ProguardRuleParserException e) {
- System.out.println(e);
assertTrue(e.getMessage().contains("-keepparameternames is not supported"));
}
}
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) {