Merge "Add settings.gradle if not present in app folder"
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 4d79275..065ad10 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -628,9 +628,7 @@
NamingLens namingLens;
if (options.enableMinification) {
timing.begin("Minification");
- namingLens =
- new Minifier(appView.appInfo().withLiveness(), rootSet, desugaredCallSites, options)
- .run(timing);
+ namingLens = new Minifier(appView.withLiveness(), rootSet, desugaredCallSites).run(timing);
timing.end();
} else {
namingLens = NamingLens.getIdentityLens();
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 bc81538..b59b79b 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
@@ -9,6 +9,7 @@
import static com.android.tools.r8.utils.DescriptorUtils.getDescriptorFromClassBinaryName;
import static com.android.tools.r8.utils.DescriptorUtils.getPackageBinaryNameFromJavaType;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexClass;
@@ -50,6 +51,7 @@
class ClassNameMinifier {
+ private final AppView<AppInfoWithLiveness> appView;
private final AppInfoWithLiveness appInfo;
private final Reporter reporter;
private final PackageObfuscationMode packageObfuscationMode;
@@ -74,11 +76,10 @@
private final GenericSignatureParser<DexType> genericSignatureParser =
new GenericSignatureParser<>(genericSignatureRewriter);
- ClassNameMinifier(
- AppInfoWithLiveness appInfo,
- RootSet rootSet,
- InternalOptions options) {
- this.appInfo = appInfo;
+ ClassNameMinifier(AppView<AppInfoWithLiveness> appView, RootSet rootSet) {
+ this.appView = appView;
+ this.appInfo = appView.appInfo();
+ InternalOptions options = appView.options();
this.reporter = options.reporter;
this.packageObfuscationMode = options.getProguardConfiguration().getPackageObfuscationMode();
this.isAccessModificationAllowed =
@@ -546,6 +547,7 @@
@Override
public DexType parsedTypeName(String name) {
DexType type = appInfo.dexItemFactory.createType(getDescriptorFromClassBinaryName(name));
+ type = appView.graphLense().lookupType(type);
DexString renamedDescriptor = renaming.getOrDefault(type, type.descriptor);
renamedSignature.append(getClassBinaryNameFromDescriptor(renamedDescriptor.toString()));
return type;
@@ -564,6 +566,7 @@
String enclosingRenamedBinaryName =
getClassBinaryNameFromDescriptor(
renaming.getOrDefault(enclosingType, enclosingType.descriptor).toString());
+ type = appView.graphLense().lookupType(type);
DexString renamedDescriptor = renaming.get(type);
if (renamedDescriptor != null) {
// Pick the renamed inner class from the fully renamed binary name.
diff --git a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
index be339b6..e2127dd 100644
--- a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexField;
@@ -10,7 +11,6 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
-import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
@@ -19,8 +19,8 @@
class FieldNameMinifier extends MemberNameMinifier<DexField, DexType> {
- FieldNameMinifier(AppInfoWithLiveness appInfo, RootSet rootSet, InternalOptions options) {
- super(appInfo, rootSet, options);
+ FieldNameMinifier(AppView<AppInfoWithLiveness> appView, RootSet rootSet) {
+ super(appView, rootSet);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
index 419bfbb..53957e4 100644
--- a/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CachedHashValueDexItem;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
@@ -18,6 +19,7 @@
abstract class MemberNameMinifier<MemberType, StateType extends CachedHashValueDexItem> {
+ protected final AppView<AppInfoWithLiveness> appView;
protected final AppInfoWithLiveness appInfo;
protected final RootSet rootSet;
protected final InternalOptions options;
@@ -34,10 +36,11 @@
// which is useful for debugging.
private final BiMap<DexType, NamingState<StateType, ?>> states = HashBiMap.create();
- MemberNameMinifier(AppInfoWithLiveness appInfo, RootSet rootSet, InternalOptions options) {
- this.appInfo = appInfo;
+ MemberNameMinifier(AppView<AppInfoWithLiveness> appView, RootSet rootSet) {
+ this.appView = appView;
+ this.appInfo = appView.appInfo();
this.rootSet = rootSet;
- this.options = options;
+ this.options = appView.options();
this.dictionary = options.getProguardConfiguration().getObfuscationDictionary();
this.useUniqueMemberNames = options.getProguardConfiguration().isUseUniqueClassMemberNames();
this.overloadAggressively =
diff --git a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
index 8864271..2cd8712 100644
--- a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -91,11 +92,8 @@
private final FrontierState frontierState = new FrontierState();
- MethodNameMinifier(
- AppInfoWithLiveness appInfo,
- RootSet rootSet,
- InternalOptions options) {
- super(appInfo, rootSet, options);
+ MethodNameMinifier(AppView<AppInfoWithLiveness> appView, RootSet rootSet) {
+ super(appView, rootSet);
equivalence =
overloadAggressively
? MethodSignatureEquivalence.get()
diff --git a/src/main/java/com/android/tools/r8/naming/Minifier.java b/src/main/java/com/android/tools/r8/naming/Minifier.java
index 5333125..7f389a4 100644
--- a/src/main/java/com/android/tools/r8/naming/Minifier.java
+++ b/src/main/java/com/android/tools/r8/naming/Minifier.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.naming;
import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -24,6 +25,7 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.ImmutableMap;
+import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
@@ -35,26 +37,27 @@
static final char INNER_CLASS_SEPARATOR = '$';
+ private final AppView<AppInfoWithLiveness> appView;
private final AppInfoWithLiveness appInfo;
private final RootSet rootSet;
private final Set<DexCallSite> desugaredCallSites;
private final InternalOptions options;
public Minifier(
- AppInfoWithLiveness appInfo,
+ AppView<AppInfoWithLiveness> appView,
RootSet rootSet,
- Set<DexCallSite> desugaredCallSites,
- InternalOptions options) {
- this.appInfo = appInfo;
+ Set<DexCallSite> desugaredCallSites) {
+ this.appView = appView;
+ this.appInfo = appView.appInfo();
this.rootSet = rootSet;
this.desugaredCallSites = desugaredCallSites;
- this.options = options;
+ this.options = appView.options();
}
public NamingLens run(Timing timing) {
assert options.enableMinification;
timing.begin("MinifyClasses");
- ClassNameMinifier classNameMinifier = new ClassNameMinifier(appInfo, rootSet, options);
+ ClassNameMinifier classNameMinifier = new ClassNameMinifier(appView, rootSet);
ClassRenaming classRenaming = classNameMinifier.computeRenaming(timing);
timing.end();
@@ -64,16 +67,14 @@
timing.begin("MinifyMethods");
MethodRenaming methodRenaming =
- new MethodNameMinifier(appInfo, rootSet, options)
- .computeRenaming(desugaredCallSites, timing);
+ new MethodNameMinifier(appView, rootSet).computeRenaming(desugaredCallSites, timing);
timing.end();
assert new MinifiedRenaming(classRenaming, methodRenaming, FieldRenaming.empty(), appInfo)
.verifyNoCollisions(appInfo.classes(), appInfo.dexItemFactory);
timing.begin("MinifyFields");
- FieldRenaming fieldRenaming =
- new FieldNameMinifier(appInfo, rootSet, options).computeRenaming(timing);
+ FieldRenaming fieldRenaming = new FieldNameMinifier(appView, rootSet).computeRenaming(timing);
timing.end();
NamingLens lens = new MinifiedRenaming(classRenaming, methodRenaming, fieldRenaming, appInfo);
@@ -86,11 +87,13 @@
return lens;
}
- private static class MinifiedRenaming extends NamingLens {
+ static class MinifiedRenaming extends NamingLens {
private final AppInfo appInfo;
private final Map<String, String> packageRenaming;
private final Map<DexItem, DexString> renaming = new IdentityHashMap<>();
+ // This set is only used for asserting no duplicated names.
+ private final Map<DexString, DexType> renamedTypesForVerification;
private MinifiedRenaming(
ClassRenaming classRenaming,
@@ -103,6 +106,10 @@
renaming.putAll(methodRenaming.renaming);
renaming.putAll(methodRenaming.callSiteRenaming);
renaming.putAll(fieldRenaming.renaming);
+ renamedTypesForVerification = new HashMap<>();
+ for (Map.Entry<DexType, DexString> entry : classRenaming.classRenaming.entrySet()) {
+ renamedTypesForVerification.put(entry.getValue(), entry.getKey());
+ }
}
@Override
@@ -112,7 +119,18 @@
@Override
public DexString lookupDescriptor(DexType type) {
- return renaming.getOrDefault(type, type.descriptor);
+ DexString dexString = renaming.get(type);
+ if (dexString != null) {
+ return dexString;
+ }
+ assert type.isPrimitiveType()
+ || type.isVoidType()
+ || !renamedTypesForVerification.containsKey(type.descriptor)
+ : "Duplicate minified type '"
+ + type.descriptor
+ + "' already mapped for: "
+ + renamedTypesForVerification.get(type.descriptor);
+ return type.descriptor;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardTypeMatcher.java b/src/main/java/com/android/tools/r8/shaking/ProguardTypeMatcher.java
index dc8925a..a59a08c 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardTypeMatcher.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardTypeMatcher.java
@@ -386,24 +386,43 @@
wildcard = wildcards.get(wildcardIndex);
assert wildcard.isPattern();
wildcardPattern = wildcard.asPattern();
+
boolean includeSeparators = pattern.length() > (i + 1) && pattern.charAt(i + 1) == '*';
- int nextPatternIndex = i + (includeSeparators ? 2 : 1);
- // Fast cases for the common case where a pattern ends with '**' or '*'.
+ boolean includeAll = pattern.length() > (i + 2) && pattern.charAt(i + 2) == '*';
+ int nextPatternIndex = i + 1;
+ if (includeAll) {
+ nextPatternIndex += 2;
+ } else if (includeSeparators) {
+ nextPatternIndex += 1;
+ }
+
+ // Fast cases for the common case where a pattern ends with '*', '**', or '***'.
if (nextPatternIndex == pattern.length()) {
- wildcardPattern.setCaptured(name.substring(nameIndex, name.length()));
+ wildcardPattern.setCaptured(name.substring(nameIndex));
+ if (includeAll) {
+ return true;
+ }
if (includeSeparators) {
return kind == ClassOrType.CLASS || !isArrayType(name);
}
boolean hasSeparators = containsSeparatorsStartingAt(name, nameIndex);
return !hasSeparators && (kind == ClassOrType.CLASS || !isArrayType(name));
}
+
// Match the rest of the pattern against the (non-empty) rest of the class name.
for (int nextNameIndex = nameIndex; nextNameIndex < name.length(); nextNameIndex++) {
wildcardPattern.setCaptured(name.substring(nameIndex, nextNameIndex));
- if (!includeSeparators && name.charAt(nextNameIndex) == '.') {
- return matchClassOrTypeNameImpl(
- pattern, nextPatternIndex, name, nextNameIndex, wildcards, wildcardIndex + 1,
- kind);
+ if (!includeSeparators) {
+ if (name.charAt(nextNameIndex) == '.') {
+ return matchClassOrTypeNameImpl(
+ pattern,
+ nextPatternIndex,
+ name,
+ nextNameIndex,
+ wildcards,
+ wildcardIndex + 1,
+ kind);
+ }
}
if (kind == ClassOrType.TYPE && name.charAt(nextNameIndex) == '[') {
return matchClassOrTypeNameImpl(
@@ -416,11 +435,12 @@
return true;
}
}
- // Finally, check the case where the '*' or '**' eats all of the class name.
- wildcardPattern.setCaptured(name.substring(nameIndex, name.length()));
+
+ // Finally, check the case where the '*', '**', or '***' eats all of the class name.
+ wildcardPattern.setCaptured(name.substring(nameIndex));
return matchClassOrTypeNameImpl(
- pattern, nextPatternIndex, name, name.length(), wildcards, wildcardIndex + 1,
- kind);
+ pattern, nextPatternIndex, name, name.length(), wildcards, wildcardIndex + 1, kind);
+
case '?':
wildcard = wildcards.get(wildcardIndex);
assert wildcard.isPattern();
@@ -432,6 +452,7 @@
nameIndex++;
wildcardIndex++;
break;
+
case '<':
wildcard = wildcards.get(wildcardIndex);
assert wildcard.isBackReference();
@@ -446,6 +467,7 @@
wildcardIndex++;
i = pattern.indexOf(">", i);
break;
+
default:
if (nameIndex == name.length() || patternChar != name.charAt(nameIndex++)) {
return false;
diff --git a/src/test/java/com/android/tools/r8/naming/MinifierTest.java b/src/test/java/com/android/tools/r8/naming/MinifierTest.java
index 473ca53..adf74ce 100644
--- a/src/test/java/com/android/tools/r8/naming/MinifierTest.java
+++ b/src/test/java/com/android/tools/r8/naming/MinifierTest.java
@@ -3,13 +3,16 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;
+import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.fail;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.naming.Minifier.MinifiedRenaming;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Timing;
import java.nio.file.Paths;
@@ -40,6 +43,25 @@
inspection.accept(dexItemFactory, naming);
}
+ @Test
+ public void ensureClassesAddedToRenamingOrNoClashTest() throws Exception {
+ MinifiedRenaming naming =
+ (MinifiedRenaming) runMinifier(ListUtils.map(keepRulesFiles, Paths::get));
+ // Create a type that exists.
+ String existingType = "La/c;";
+ DexType d = dexItemFactory.createType(existingType);
+ try {
+ naming.lookupDescriptor(d);
+ } catch (AssertionError ae) {
+ assertTrue(
+ ae.getMessage()
+ .startsWith(
+ "Duplicate minified type '" + existingType + "' already mapped for: naming001."));
+ return;
+ }
+ fail("Should have thrown an error.");
+ }
+
@Parameters(name = "test: {0} keep: {1}")
public static Collection<Object[]> data() {
List<String> tests = Arrays.asList("naming001");
diff --git a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
index 7b6052a..4dcb52f 100644
--- a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
+++ b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.shaking.Enqueuer;
+import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.shaking.ProguardConfiguration;
import com.android.tools.r8.shaking.RootSetBuilder;
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
@@ -74,9 +75,12 @@
new RootSetBuilder(appView, program, configuration.getRules(), options).run(executor);
Enqueuer enqueuer = new Enqueuer(appView, options, null, options.forceProguardCompatibility);
- AppInfoWithSubtyping appInfo =
+ AppInfoWithLiveness appInfo =
enqueuer.traceApplication(rootSet, configuration.getDontWarnPatterns(), executor, timing);
- return new Minifier(appInfo.withLiveness(), rootSet, Collections.emptySet(), options)
+ return new Minifier(
+ new AppView<>(appInfo, GraphLense.getIdentityLense(), options),
+ rootSet,
+ Collections.emptySet())
.run(timing);
}
diff --git a/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java b/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java
index 32e8e4d..659a8fc 100644
--- a/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java
+++ b/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java
@@ -7,20 +7,21 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
import static org.hamcrest.CoreMatchers.allOf;
-import static org.hamcrest.CoreMatchers.anyOf;
-import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
+import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.graph.DexAnnotationElement;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.DexValue.DexValueArray;
import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.AnnotationSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
@@ -28,7 +29,7 @@
public class B124357885Test extends TestBase {
- private void checkSignatureAnnotation(AnnotationSubject signature) {
+ private void checkSignatureAnnotation(CodeInspector inspector, AnnotationSubject signature) {
DexAnnotationElement[] elements = signature.getAnnotation().elements;
assertEquals(1, elements.length);
assertEquals("value", elements[0].name.toString());
@@ -39,20 +40,22 @@
assertTrue(value instanceof DexValueString);
builder.append(((DexValueString) value).value);
}
- // TODO(124357885): This should be the minified name for FooImpl instead of Foo.
- String fooDescriptor = DescriptorUtils.javaTypeToDescriptor(Foo.class.getTypeName());
+ String fooImplFinalDescriptor =
+ DescriptorUtils.javaTypeToDescriptor(inspector.clazz(FooImpl.class).getFinalName());
StringBuilder expected =
new StringBuilder()
.append("()")
- .append(fooDescriptor.substring(0, fooDescriptor.length() - 1)) // Remove the ;.
+ // Remove the final ; from the descriptor to add the generic type.
+ .append(fooImplFinalDescriptor.substring(0, fooImplFinalDescriptor.length() - 1))
.append("<Ljava/lang/String;>")
- .append(";"); // Add the ; here.
+ // Add the ; after the generic type.
+ .append(";");
assertEquals(expected.toString(), builder.toString());
}
@Test
public void test() throws Exception {
- testForR8(Backend.DEX)
+ R8TestCompileResult compileResult = testForR8(Backend.DEX)
.addProgramClasses(Main.class, Service.class, Foo.class, FooImpl.class)
.addKeepMainRule(Main.class)
.addKeepRules("-keepattributes Signature,InnerClasses,EnclosingMethod")
@@ -66,17 +69,14 @@
assertEquals(1, inspector.clazz(Service.class).allMethods().size());
MethodSubject fooList = inspector.clazz(Service.class).allMethods().get(0);
AnnotationSubject signature = fooList.annotation("dalvik.annotation.Signature");
- checkSignatureAnnotation(signature);
- })
- .run(Main.class)
- .assertFailureWithErrorThatMatches(
- anyOf(
- containsString(
- "java.lang.ClassNotFoundException: "
- + "Didn't find class \"com.android.tools.r8.naming.b124357885.Foo\""),
- containsString(
- "java.lang.NoClassDefFoundError: "
- + "com/android/tools/r8/naming/b124357885/Foo")));
+ checkSignatureAnnotation(inspector, signature);
+ });
+
+ String fooImplFinalName = compileResult.inspector().clazz(FooImpl.class).getFinalName();
+
+ compileResult
+ .run(Main.class)
+ .assertSuccessWithOutput(StringUtils.lines(fooImplFinalName, fooImplFinalName));
}
}
@@ -89,7 +89,7 @@
// Convince R8 we only use subtypes to get class merging of Foo into FooImpl.
Foo<String> foo = new FooImpl<>();
- System.out.println(foo);
+ System.out.println(foo.getClass().getTypeName());
}
}
diff --git a/src/test/java/com/android/tools/r8/proguard/rules/ProguardMatchAllRuleWithPrefixTest.java b/src/test/java/com/android/tools/r8/proguard/rules/ProguardMatchAllRuleWithPrefixTest.java
new file mode 100644
index 0000000..d5f456b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/proguard/rules/ProguardMatchAllRuleWithPrefixTest.java
@@ -0,0 +1,59 @@
+// Copyright (c) 2019, 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.proguard.rules;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.junit.Assert.assertThat;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+
+/** Regression test for b/124584385. */
+public class ProguardMatchAllRuleWithPrefixTest extends TestBase {
+
+ @Test
+ public void test() throws Exception {
+ CodeInspector inspector =
+ testForR8(Backend.DEX)
+ .addProgramClasses(TestClass.class)
+ .addKeepRules(
+ "-keep,allowobfuscation class com.android.tools.r8.*** {",
+ " com.android.tools.r8.*** methodA();",
+ " com.android.tools.r8.***Class methodB();",
+ " com.android.tools.r8.***[] methodC();",
+ " com.android.tools.r8.***Class[] methodD();",
+ "}")
+ .compile()
+ .inspector();
+
+ ClassSubject classSubject = inspector.clazz(TestClass.class);
+ assertThat(classSubject, isPresent());
+ assertThat(classSubject.uniqueMethodWithName("methodA"), isPresent());
+ assertThat(classSubject.uniqueMethodWithName("methodB"), isPresent());
+ assertThat(classSubject.uniqueMethodWithName("methodC"), isPresent());
+ assertThat(classSubject.uniqueMethodWithName("methodD"), isPresent());
+ }
+
+ static class TestClass {
+
+ TestClass methodA() {
+ return new TestClass();
+ }
+
+ TestClass methodB() {
+ return new TestClass();
+ }
+
+ TestClass[] methodC() {
+ return new TestClass[0];
+ }
+
+ TestClass[] methodD() {
+ return new TestClass[0];
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
index aa083da..f585226 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -321,6 +321,14 @@
return obfuscatedTypeName != null ? obfuscatedTypeName : originalTypeName;
}
+ String getOriginalTypeName(String minifiedTypeName) {
+ String originalTypeName = null;
+ if (mapping != null) {
+ originalTypeName = mapType(obfuscatedToOriginalMapping, minifiedTypeName);
+ }
+ return originalTypeName != null ? originalTypeName : minifiedTypeName;
+ }
+
InstructionSubject createInstructionSubject(Instruction instruction) {
DexInstructionSubject dexInst = new DexInstructionSubject(instruction);
if (dexInst.isInvoke()) {
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
index 6581a47..dd7cd85 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
@@ -143,18 +143,14 @@
// X method(X) -> a
//
// whereas the final signature is for X.a is "a (a)"
- String[] OriginalParameters = new String[signature.parameters.length];
- for (int i = 0; i < OriginalParameters.length; i++) {
- String obfuscated = signature.parameters[i];
- String original = codeInspector.obfuscatedToOriginalMapping.get(obfuscated);
- OriginalParameters[i] = original != null ? original : obfuscated;
+ String[] originalParameters = new String[signature.parameters.length];
+ for (int i = 0; i < originalParameters.length; i++) {
+ originalParameters[i] = codeInspector.getOriginalTypeName(signature.parameters[i]);
}
- String obfuscatedReturnType = signature.type;
- String originalReturnType = codeInspector.obfuscatedToOriginalMapping.get(obfuscatedReturnType);
- String returnType = originalReturnType != null ? originalReturnType : obfuscatedReturnType;
+ String returnType = codeInspector.getOriginalTypeName(signature.type);
MethodSignature lookupSignature =
- new MethodSignature(signature.name, returnType, OriginalParameters);
+ new MethodSignature(signature.name, returnType, originalParameters);
MemberNaming memberNaming = clazz.naming.lookup(lookupSignature);
return memberNaming != null ? (MethodSignature) memberNaming.getOriginalSignature() : signature;