Merge "Repackage all embedded libraries"
diff --git a/build.gradle b/build.gradle
index 42d8292..7a007d4 100644
--- a/build.gradle
+++ b/build.gradle
@@ -54,6 +54,12 @@
}
output.resourcesDir = 'build/classes/debugTestResourcesJava8'
}
+ debugTestResourcesKotlin {
+ java {
+ srcDirs = ['src/test/debugTestResourcesKotlin']
+ }
+ output.resourcesDir = 'build/classes/debugTestResourcesKotlin'
+ }
examples {
java {
srcDirs = ['src/test/examples', 'build/generated/source/proto/examples/javalite/' ]
@@ -130,6 +136,7 @@
supportLibs 'com.android.support:support-v4:25.4.0'
supportLibs 'junit:junit:4.12'
supportLibs 'com.android.support.test.espresso:espresso-core:3.0.0'
+ debugTestResourcesKotlinCompileOnly 'org.jetbrains.kotlin:kotlin-stdlib:1.1.3'
}
protobuf {
@@ -175,6 +182,7 @@
"jdwp-tests.tar.gz",
"jasmin.tar.gz",
"jctf.tar.gz",
+ "kotlin.tar.gz",
"android_cts_baseline.tar.gz",
],
// All dex-vms have a fixed OS of Linux, as they are only supported on Linux, and will be run in a Docker
@@ -534,11 +542,29 @@
from "build/test/debugTestResourcesJava8/classes"
include "**/*.class"
}
+ def kotlinResourcesDir = file("src/test/debugTestResourcesKotlin")
+ def kotlinHostJar = "debug_test_resources_kotlin.jar"
+ task "jar_debugTestResourcesKotlin"(type: Exec) {
+ if (OperatingSystem.current().isWindows()) {
+ executable file("third_party/kotlin/kotlinc/bin/kotlinc.bat")
+ } else {
+ executable file("third_party/kotlin/kotlinc/bin/kotlinc");
+ }
+ args "-include-runtime"
+ args "-d"
+ args "build/test/${kotlinHostJar}"
+ args fileTree(dir: kotlinResourcesDir, include: '**/*.kt')
+ }
dependsOn downloadDeps
dependsOn jar_debugTestResources
dependsOn jar_debugTestResourcesJava8
+ dependsOn jar_debugTestResourcesKotlin
}
+// Proto lite generated code yields warnings when compiling with javac.
+// We change the options passed to javac to ignore it.
+compileExamplesJava.options.compilerArgs = ["-Xlint:none"]
+
task buildExampleJars {
dependsOn downloadProguard
def examplesDir = file("src/test/examples")
diff --git a/src/main/java/com/android/tools/r8/BaseCommand.java b/src/main/java/com/android/tools/r8/BaseCommand.java
index 430624b..debe8a1 100644
--- a/src/main/java/com/android/tools/r8/BaseCommand.java
+++ b/src/main/java/com/android/tools/r8/BaseCommand.java
@@ -95,6 +95,9 @@
private CompilationMode mode;
private int minApiLevel = Constants.DEFAULT_ANDROID_API;
+ // Internal flag used by CompatDx to ignore dex files in archives.
+ protected boolean ignoreDexInArchive = false;
+
protected Builder(CompilationMode mode) {
this(AndroidApp.builder(), mode);
}
@@ -108,6 +111,7 @@
assert mode != null;
this.app = builder;
this.mode = mode;
+ app.setIgnoreDexInArchive(ignoreDexInArchive);
}
abstract B self();
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index 64a1a0e..cb8c170 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -36,7 +36,7 @@
private boolean intermediate = false;
- private Builder() {
+ protected Builder() {
super(CompilationMode.DEBUG);
}
diff --git a/src/main/java/com/android/tools/r8/compatdx/CompatDx.java b/src/main/java/com/android/tools/r8/compatdx/CompatDx.java
index 6750f4c..9bcf510 100644
--- a/src/main/java/com/android/tools/r8/compatdx/CompatDx.java
+++ b/src/main/java/com/android/tools/r8/compatdx/CompatDx.java
@@ -450,7 +450,7 @@
ExecutorService executor = ThreadUtils.getExecutorService(numberOfThreads);
D8Output result;
try {
- D8Command.Builder builder = D8Command.builder();
+ D8Command.Builder builder = new CompatDxCommandBuilder();
builder
.addProgramFiles(inputs)
.setMode(mode)
diff --git a/src/main/java/com/android/tools/r8/compatdx/CompatDxCommandBuilder.java b/src/main/java/com/android/tools/r8/compatdx/CompatDxCommandBuilder.java
new file mode 100644
index 0000000..ba9daec
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/compatdx/CompatDxCommandBuilder.java
@@ -0,0 +1,13 @@
+// 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.compatdx;
+
+import com.android.tools.r8.D8Command;
+
+public class CompatDxCommandBuilder extends D8Command.Builder {
+ CompatDxCommandBuilder() {
+ ignoreDexInArchive = true;
+ }
+}
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 32342fc..c1e8515 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
@@ -20,6 +20,7 @@
import com.android.tools.r8.naming.signature.GenericSignatureParser;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
+import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.PackageObfuscationMode;
import com.android.tools.r8.utils.StringUtils;
@@ -39,15 +40,16 @@
private final AppInfoWithLiveness appInfo;
private final RootSet rootSet;
private final PackageObfuscationMode packageObfuscationMode;
+ private final Set<String> usedPackagePrefixes = Sets.newHashSet();
private final Set<DexString> usedTypeNames = Sets.newIdentityHashSet();
private final Map<DexType, DexString> renaming = Maps.newIdentityHashMap();
- private final Map<String, ClassNamingState> states = new HashMap<>();
+ private final Map<String, Namespace> states = new HashMap<>();
private final ImmutableList<String> packageDictionary;
private final ImmutableList<String> classDictionary;
private final boolean keepInnerClassStructure;
- private final ClassNamingState topLevelState;
+ private final Namespace topLevelState;
private GenericSignatureRewriter genericSignatureRewriter = new GenericSignatureRewriter();
@@ -66,8 +68,8 @@
this.keepInnerClassStructure = options.attributeRemoval.signature;
// Initialize top-level naming state.
- topLevelState = new ClassNamingState(getPackageBinaryNameFromJavaType(
- options.proguardConfiguration.getPackagePrefix()));
+ topLevelState = new Namespace(
+ getPackageBinaryNameFromJavaType(options.proguardConfiguration.getPackagePrefix()));
states.computeIfAbsent("", k -> topLevelState);
}
@@ -144,6 +146,8 @@
*/
private void registerClassAsUsed(DexType type) {
renaming.put(type, type.descriptor);
+ registerPackagePrefixesAsUsed(
+ getParentPackagePrefix(getClassBinaryNameFromDescriptor(type.descriptor.toSourceString())));
usedTypeNames.add(type.descriptor);
if (keepInnerClassStructure) {
DexType outerClass = getOutClassForType(type);
@@ -156,6 +160,17 @@
}
}
+ /**
+ * Registers the given package prefix and all of parent packages as used.
+ */
+ private void registerPackagePrefixesAsUsed(String packagePrefix) {
+ String usedPrefix = packagePrefix;
+ while (usedPrefix.length() > 0) {
+ usedPackagePrefixes.add(usedPrefix);
+ usedPrefix = getParentPackagePrefix(usedPrefix);
+ }
+ }
+
private DexType getOutClassForType(DexType type) {
DexClass clazz = appInfo.definitionFor(type);
if (clazz == null) {
@@ -176,7 +191,7 @@
}
private DexString computeName(DexClass clazz) {
- ClassNamingState state = null;
+ Namespace state = null;
if (keepInnerClassStructure) {
// When keeping the nesting structure of inner classes, we have to insert the name
// of the outer class for the $ prefix.
@@ -186,22 +201,22 @@
}
}
if (state == null) {
- state = getStateFor(clazz);
+ state = getStateForClass(clazz);
}
return state.nextTypeName();
}
- private ClassNamingState getStateFor(DexClass clazz) {
+ private Namespace getStateForClass(DexClass clazz) {
String packageName = getPackageBinaryNameFromJavaType(clazz.type.getPackageDescriptor());
// Check whether the given class should be kept.
if (rootSet.keepPackageName.contains(clazz)) {
- return states.computeIfAbsent(packageName, ClassNamingState::new);
+ return states.computeIfAbsent(packageName, Namespace::new);
}
- ClassNamingState state = topLevelState;
+ Namespace state = topLevelState;
switch (packageObfuscationMode) {
case NONE:
- // TODO(b/36799686): general obfuscation.
- state = states.computeIfAbsent(packageName, ClassNamingState::new);
+ // For general obfuscation, rename all the involved package prefixes.
+ state = getStateForPackagePrefix(packageName);
break;
case REPACKAGE:
// For repackaging, all classes are repackaged to a single package.
@@ -210,16 +225,29 @@
case FLATTEN:
// For flattening, all packages are repackaged to a single package.
state = states.computeIfAbsent(packageName, k -> {
- String renamedPackageName =
- getClassBinaryNameFromDescriptor(topLevelState.nextSuggestedName());
- return new ClassNamingState(renamedPackageName);
+ String renamedPackagePrefix = topLevelState.nextPackagePrefix();
+ return new Namespace(renamedPackagePrefix);
});
break;
}
return state;
}
- private ClassNamingState getStateForOuterClass(DexType outer) {
+ private Namespace getStateForPackagePrefix(String prefix) {
+ return states.computeIfAbsent(prefix, k -> {
+ // Calculate the parent package prefix, e.g., La/b/c -> La/b
+ String parentPackage = getParentPackagePrefix(prefix);
+ // Create a state for parent package prefix, if necessary, in a recursive manner.
+ // That recursion should end when the parent package hits the top-level, "".
+ Namespace superState = getStateForPackagePrefix(parentPackage);
+ // From the super state, get a renamed package prefix for the current level.
+ String renamedPackagePrefix = superState.nextPackagePrefix();
+ // Create a new state, which corresponds to a new name space, for the current level.
+ return new Namespace(renamedPackagePrefix);
+ });
+ }
+
+ private Namespace getStateForOuterClass(DexType outer) {
String prefix = getClassBinaryNameFromDescriptor(outer.toDescriptorString());
return states.computeIfAbsent(prefix, k -> {
// Create a naming state with this classes renaming as prefix.
@@ -235,7 +263,7 @@
}
}
String binaryName = getClassBinaryNameFromDescriptor(renamed.toString());
- return new ClassNamingState(binaryName, "$");
+ return new Namespace(binaryName, "$");
});
}
@@ -256,46 +284,67 @@
}
}
- private class ClassNamingState {
+ private class Namespace {
private final char[] packagePrefix;
private int typeCounter = 1;
- private Iterator<String> dictionaryIterator;
+ private int packageCounter = 1;
+ private Iterator<String> packageDictionaryIterator;
+ private Iterator<String> classDictionaryIterator;
- ClassNamingState(String packageName) {
+ Namespace(String packageName) {
this(packageName, "/");
}
- ClassNamingState(String packageName, String separator) {
+ Namespace(String packageName, String separator) {
this.packagePrefix = ("L" + packageName
// L or La/b/ (or La/b/C$)
+ (packageName.isEmpty() ? "" : separator))
.toCharArray();
- // TODO(b/36799686): general obfuscation should use packageDictionary when renaming package.
- this.dictionaryIterator = classDictionary.iterator();
+ this.packageDictionaryIterator = packageDictionary.iterator();
+ this.classDictionaryIterator = classDictionary.iterator();
}
- public char[] getPackagePrefix() {
- return packagePrefix;
- }
-
- String nextSuggestedName() {
+ private String nextSuggestedNameForClass() {
StringBuilder nextName = new StringBuilder();
- if (dictionaryIterator.hasNext()) {
- nextName.append(packagePrefix).append(dictionaryIterator.next()).append(';');
+ if (classDictionaryIterator.hasNext()) {
+ nextName.append(packagePrefix).append(classDictionaryIterator.next()).append(';');
return nextName.toString();
} else {
return StringUtils.numberToIdentifier(packagePrefix, typeCounter++, true);
}
}
- private DexString nextTypeName() {
+ DexString nextTypeName() {
DexString candidate;
do {
- candidate = appInfo.dexItemFactory.createString(nextSuggestedName());
+ candidate = appInfo.dexItemFactory.createString(nextSuggestedNameForClass());
} while (usedTypeNames.contains(candidate));
return candidate;
}
+
+ private String nextSuggestedNameForSubpackage() {
+ StringBuilder nextName = new StringBuilder();
+ // Note that the differences between this method and the other variant for class renaming are
+ // 1) this one uses the different dictionary and counter,
+ // 2) this one does not append ';' at the end, and
+ // 3) this one removes 'L' at the beginning to make the return value a binary form.
+ if (packageDictionaryIterator.hasNext()) {
+ nextName.append(packagePrefix).append(packageDictionaryIterator.next());
+ } else {
+ nextName.append(StringUtils.numberToIdentifier(packagePrefix, packageCounter++, false));
+ }
+ return nextName.toString().substring(1);
+ }
+
+ String nextPackagePrefix() {
+ String candidate;
+ do {
+ candidate = nextSuggestedNameForSubpackage();
+ } while (usedPackagePrefixes.contains(candidate));
+ return candidate;
+ }
+
}
private class GenericSignatureRewriter implements GenericSignatureAction<DexType> {
@@ -355,4 +404,18 @@
// nothing to do
}
}
+
+ /**
+ * Compute parent package prefix from the given package prefix.
+ *
+ * @param packagePrefix i.e. "Ljava/lang"
+ * @return parent package prefix i.e. "Ljava"
+ */
+ static String getParentPackagePrefix(String packagePrefix) {
+ int i = packagePrefix.lastIndexOf(DescriptorUtils.DESCRIPTOR_PACKAGE_SEPARATOR);
+ if (i < 0) {
+ return "";
+ }
+ return packagePrefix.substring(0, i);
+ }
}
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 93c4dbb..e39faa0 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
@@ -25,7 +25,6 @@
private boolean allowAccessModification = false;
private boolean ignoreWarnings = false;
private boolean optimize = true;
- private int optimizationPasses = 1;
private boolean obfuscating = true;
private boolean shrinking = true;
private boolean printUsage = false;
@@ -81,11 +80,6 @@
this.optimize = optimize;
}
- public void setOptimizationPasses(int optimizationPasses) {
- // TODO(b/36800551): no-op until we have clear ideas about optimization passes.
- // this.optimizationPasses = optimizationPasses;
- }
-
public void setObfuscating(boolean obfuscate) {
this.obfuscating = obfuscate;
}
@@ -155,7 +149,6 @@
packagePrefix,
allowAccessModification,
ignoreWarnings,
- optimize ? optimizationPasses : 0,
obfuscating,
shrinking,
printUsage,
@@ -181,7 +174,6 @@
private final String packagePrefix;
private final boolean allowAccessModification;
private final boolean ignoreWarnings;
- private final int optimizationPasses;
private final boolean obfuscating;
private final boolean shrinking;
private final boolean printUsage;
@@ -206,7 +198,6 @@
String packagePrefix,
boolean allowAccessModification,
boolean ignoreWarnings,
- int optimizationPasses,
boolean obfuscating,
boolean shrinking,
boolean printUsage,
@@ -229,7 +220,6 @@
this.packagePrefix = packagePrefix;
this.allowAccessModification = allowAccessModification;
this.ignoreWarnings = ignoreWarnings;
- this.optimizationPasses = optimizationPasses;
this.obfuscating = obfuscating;
this.shrinking = shrinking;
this.printUsage = printUsage;
@@ -294,10 +284,6 @@
return ignoreWarnings;
}
- public int getOptimizationPasses() {
- return optimizationPasses;
- }
-
public boolean isObfuscating() {
return obfuscating;
}
@@ -356,7 +342,6 @@
"" /* package prefix */,
false /* allowAccessModification */,
false /* ignoreWarnings */,
- 1 /* optimizationPasses */,
false /* obfuscating */,
false /* shrinking */,
false /* printUsage */,
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 5b34221..4fb7357 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -163,7 +163,6 @@
if (expectedOptimizationPasses == null) {
throw parseError("Missing n of \"-optimizationpasses n\"");
}
- configurationBuilder.setOptimizationPasses(expectedOptimizationPasses);
warnIgnoringOptions("optimizationpasses");
} else if (acceptString("dontobfuscate")) {
configurationBuilder.setObfuscating(false);
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApp.java b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
index 006dc1a..97a3679 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -423,6 +423,7 @@
private List<Resource> mainDexListResources = new ArrayList<>();
private List<String> mainDexListClasses = new ArrayList<>();
private Resource mainDexListOutput;
+ private boolean ignoreDexInArchive = false;
// See AndroidApp::builder().
private Builder() {
@@ -671,6 +672,17 @@
}
/**
+ * Ignore dex resources in input archives.
+ *
+ * In some situations (e.g. AOSP framework build) the input archives include both class and
+ * dex resources. Setting this flag ignores the dex resources and reads the class resources
+ * only.
+ */
+ public void setIgnoreDexInArchive(boolean value) {
+ ignoreDexInArchive = value;
+ }
+
+ /**
* Build final AndroidApp.
*/
public AndroidApp build() {
@@ -697,7 +709,7 @@
} else if (isClassFile(file)) {
programResources.add(Resource.fromFile(Resource.Kind.CLASSFILE, file));
} else if (isArchive(file)) {
- programFileArchiveReaders.add(new ProgramFileArchiveReader(file));
+ programFileArchiveReaders.add(new ProgramFileArchiveReader(file, ignoreDexInArchive));
} else {
throw new CompilationError("Unsupported source file type for file: " + file);
}
diff --git a/src/main/java/com/android/tools/r8/utils/ProgramFileArchiveReader.java b/src/main/java/com/android/tools/r8/utils/ProgramFileArchiveReader.java
index 814ffd1..8341921 100644
--- a/src/main/java/com/android/tools/r8/utils/ProgramFileArchiveReader.java
+++ b/src/main/java/com/android/tools/r8/utils/ProgramFileArchiveReader.java
@@ -25,11 +25,13 @@
class ProgramFileArchiveReader {
private final Path archive;
+ private boolean ignoreDexInArchive;
private List<Resource> dexResources = null;
private List<Resource> classResources = null;
- ProgramFileArchiveReader(Path archive) {
+ ProgramFileArchiveReader(Path archive, boolean ignoreDexInArchive) {
this.archive = archive;
+ this.ignoreDexInArchive = ignoreDexInArchive;
}
private void readArchive() throws IOException {
@@ -41,9 +43,11 @@
while ((entry = stream.getNextEntry()) != null) {
Path name = Paths.get(entry.getName());
if (isDexFile(name)) {
- Resource resource =
- new OneShotByteResource(Resource.Kind.DEX, ByteStreams.toByteArray(stream), null);
- dexResources.add(resource);
+ if (!ignoreDexInArchive) {
+ Resource resource =
+ new OneShotByteResource(Resource.Kind.DEX, ByteStreams.toByteArray(stream), null);
+ dexResources.add(resource);
+ }
} else if (isClassFile(name)) {
String descriptor = PreloadedClassFileProvider.guessTypeDescriptor(name);
Resource resource = new OneShotByteResource(Resource.Kind.CLASSFILE,
diff --git a/src/test/debugTestResourcesKotlin/KotlinApp.kt b/src/test/debugTestResourcesKotlin/KotlinApp.kt
new file mode 100644
index 0000000..7c15337
--- /dev/null
+++ b/src/test/debugTestResourcesKotlin/KotlinApp.kt
@@ -0,0 +1,21 @@
+// 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.
+
+class KotlinApp {
+ companion object {
+ @JvmStatic fun main(args: Array<String>) {
+ println("Hello world!")
+ val instance = KotlinApp()
+ instance.processObject(instance, instance::printObject)
+ }
+ }
+
+ fun processObject(obj: Any, func: (Any) -> Unit) {
+ func(obj)
+ }
+
+ fun printObject(obj: Any) {
+ println(obj)
+ }
+}
\ No newline at end of file
diff --git a/src/test/examples/naming044/keep-rules-005.txt b/src/test/examples/naming044/keep-rules-005.txt
new file mode 100644
index 0000000..5583ccf
--- /dev/null
+++ b/src/test/examples/naming044/keep-rules-005.txt
@@ -0,0 +1,9 @@
+# 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.
+
+-allowaccessmodification
+
+-keep,allowobfuscation class * {
+ *;
+}
diff --git a/src/test/examples/naming101/a/a.java b/src/test/examples/naming101/a/a.java
new file mode 100644
index 0000000..261bfc3
--- /dev/null
+++ b/src/test/examples/naming101/a/a.java
@@ -0,0 +1,8 @@
+// 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 naming101.a;
+
+public class a {
+ static int f = 6;
+}
diff --git a/src/test/examples/naming101/a/b/c.java b/src/test/examples/naming101/a/b/c.java
new file mode 100644
index 0000000..b399bda
--- /dev/null
+++ b/src/test/examples/naming101/a/b/c.java
@@ -0,0 +1,8 @@
+// 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 naming101.a.b;
+
+public class c {
+ static boolean flag = true;
+}
diff --git a/src/test/examples/naming101/a/c.java b/src/test/examples/naming101/a/c.java
new file mode 100644
index 0000000..fbf890b
--- /dev/null
+++ b/src/test/examples/naming101/a/c.java
@@ -0,0 +1,10 @@
+// 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 naming101.a;
+
+public class c {
+ public static int a() {
+ return a.f;
+ }
+}
diff --git a/src/test/examples/naming101/b/a.java b/src/test/examples/naming101/b/a.java
new file mode 100644
index 0000000..c7eaa83
--- /dev/null
+++ b/src/test/examples/naming101/b/a.java
@@ -0,0 +1,8 @@
+// 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 naming101.b;
+
+public class a {
+ static boolean flag = false;
+}
diff --git a/src/test/examples/naming101/b/b.java b/src/test/examples/naming101/b/b.java
new file mode 100644
index 0000000..db21bd3
--- /dev/null
+++ b/src/test/examples/naming101/b/b.java
@@ -0,0 +1,10 @@
+// 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 naming101.b;
+
+public class b {
+ static boolean a() {
+ return a.flag;
+ }
+}
diff --git a/src/test/examples/naming101/c.java b/src/test/examples/naming101/c.java
new file mode 100644
index 0000000..7477024
--- /dev/null
+++ b/src/test/examples/naming101/c.java
@@ -0,0 +1,8 @@
+// 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 naming101;
+
+public class c {
+ static int i = 1;
+}
diff --git a/src/test/examples/naming101/d.java b/src/test/examples/naming101/d.java
new file mode 100644
index 0000000..3bb8131
--- /dev/null
+++ b/src/test/examples/naming101/d.java
@@ -0,0 +1,10 @@
+// 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 naming101;
+
+public class d {
+ static int c() {
+ return c.i;
+ }
+}
diff --git a/src/test/examples/naming101/keep-rules-001.txt b/src/test/examples/naming101/keep-rules-001.txt
new file mode 100644
index 0000000..a191b54
--- /dev/null
+++ b/src/test/examples/naming101/keep-rules-001.txt
@@ -0,0 +1,11 @@
+# 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.
+
+-allowaccessmodification
+
+-repackageclasses ''
+
+-keep,allowobfuscation class * {
+ *;
+}
diff --git a/src/test/examples/naming101/keep-rules-002.txt b/src/test/examples/naming101/keep-rules-002.txt
new file mode 100644
index 0000000..bbdde22
--- /dev/null
+++ b/src/test/examples/naming101/keep-rules-002.txt
@@ -0,0 +1,15 @@
+# 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.
+
+-allowaccessmodification
+
+-repackageclasses 'naming101.a'
+
+-keep public class **.a {
+ *;
+}
+
+-keep,allowobfuscation class * {
+ *;
+}
diff --git a/src/test/examples/naming101/keep-rules-003.txt b/src/test/examples/naming101/keep-rules-003.txt
new file mode 100644
index 0000000..10b2856
--- /dev/null
+++ b/src/test/examples/naming101/keep-rules-003.txt
@@ -0,0 +1,11 @@
+# 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.
+
+-allowaccessmodification
+
+-flattenpackagehierarchy ''
+
+-keep,allowobfuscation class * {
+ *;
+}
diff --git a/src/test/examples/naming101/keep-rules-004.txt b/src/test/examples/naming101/keep-rules-004.txt
new file mode 100644
index 0000000..a4f3634
--- /dev/null
+++ b/src/test/examples/naming101/keep-rules-004.txt
@@ -0,0 +1,15 @@
+# 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.
+
+-allowaccessmodification
+
+-flattenpackagehierarchy 'naming101'
+
+-keep public class **.a {
+ *;
+}
+
+-keep,allowobfuscation class * {
+ *;
+}
diff --git a/src/test/examples/naming101/keep-rules-005.txt b/src/test/examples/naming101/keep-rules-005.txt
new file mode 100644
index 0000000..5583ccf
--- /dev/null
+++ b/src/test/examples/naming101/keep-rules-005.txt
@@ -0,0 +1,9 @@
+# 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.
+
+-allowaccessmodification
+
+-keep,allowobfuscation class * {
+ *;
+}
diff --git a/src/test/examples/shaking1/print-mapping.ref b/src/test/examples/shaking1/print-mapping.ref
index 8382304..b75dbd3 100644
--- a/src/test/examples/shaking1/print-mapping.ref
+++ b/src/test/examples/shaking1/print-mapping.ref
@@ -1,4 +1,4 @@
shaking1.Shaking -> shaking1.Shaking:
-shaking1.Used -> shaking1.a:
+shaking1.Used -> a.a:
java.lang.String name -> a
java.lang.String method() -> a
diff --git a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
index 57a1ce8..6340728 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
@@ -3,15 +3,18 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.debug;
+import com.android.tools.r8.CompilationException;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.D8Command;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.OffOrAuto;
import com.google.common.collect.ImmutableList;
import java.io.File;
+import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayDeque;
@@ -89,12 +92,15 @@
.get(ToolHelper.BUILD_DIR, "test", "debug_test_resources.jar");
private static final Path DEBUGGEE_JAVA8_JAR = Paths
.get(ToolHelper.BUILD_DIR, "test", "debug_test_resources_java8.jar");
+ private static final Path DEBUGGEE_KOTLIN_JAR = Paths
+ .get(ToolHelper.BUILD_DIR, "test", "debug_test_resources_kotlin.jar");
@ClassRule
public static TemporaryFolder temp = new TemporaryFolder();
private static Path jdwpDexD8 = null;
private static Path debuggeeDexD8 = null;
private static Path debuggeeJava8DexD8 = null;
+ private static Path debuggeeKotlinDexD8 = null;
@Rule
public TestName testName = new TestName();
@@ -103,43 +109,31 @@
public static void setUp() throws Exception {
// Convert jar to dex with d8 with debug info
int minSdk = ToolHelper.getMinApiLevelForDexVm(ToolHelper.getDexVm());
- {
- Path dexOutputDir = temp.newFolder("d8-jdwp-jar").toPath();
- jdwpDexD8 = dexOutputDir.resolve("classes.dex");
- ToolHelper.runD8(
- D8Command.builder()
- .addProgramFiles(JDWP_JAR)
- .setOutputPath(dexOutputDir)
- .setMinApiLevel(minSdk)
- .setMode(CompilationMode.DEBUG)
- .build());
- }
- {
- Path dexOutputDir = temp.newFolder("d8-debuggee-jar").toPath();
- debuggeeDexD8 = dexOutputDir.resolve("classes.dex");
- ToolHelper.runD8(
- D8Command.builder()
- .addProgramFiles(DEBUGGEE_JAR)
- .setOutputPath(dexOutputDir)
- .setMinApiLevel(minSdk)
- .setMode(CompilationMode.DEBUG)
- .build());
- }
- {
- Path dexOutputDir = temp.newFolder("d8-debuggee-java8-jar").toPath();
- debuggeeJava8DexD8 = dexOutputDir.resolve("classes.dex");
- ToolHelper.runD8(
- D8Command.builder()
- .addProgramFiles(DEBUGGEE_JAVA8_JAR)
- .setOutputPath(dexOutputDir)
- .setMinApiLevel(minSdk)
- .setMode(CompilationMode.DEBUG)
- .build(),
- options -> {
- // Enable desugaring for preN runtimes
- options.interfaceMethodDesugaring = OffOrAuto.Auto;
- });
- }
+ jdwpDexD8 = compileJarToDex(JDWP_JAR, minSdk, "d8-jdwp-jar", null);
+ debuggeeDexD8 = compileJarToDex(DEBUGGEE_JAR, minSdk, "d8-debuggee-jar", null);
+ debuggeeJava8DexD8 = compileJarToDex(DEBUGGEE_JAVA8_JAR, minSdk, "d8-debuggee-java8-jar",
+ options -> {
+ // Enable desugaring for preN runtimes
+ options.interfaceMethodDesugaring = OffOrAuto.Auto;
+ });
+ debuggeeKotlinDexD8 = compileJarToDex(DEBUGGEE_KOTLIN_JAR, minSdk, "d8-debuggee-kotlin-jar",
+ null);
+ }
+
+ private static Path compileJarToDex(Path jarToCompile, int minSdk, String tempDirName,
+ Consumer<InternalOptions> optionsConsumer) throws IOException, CompilationException {
+ assert jarToCompile.toFile().exists();
+ Path dexOutputDir = temp.newFolder(tempDirName).toPath();
+ ToolHelper.runD8(
+ D8Command.builder()
+ .addProgramFiles(jarToCompile)
+ .setOutputPath(dexOutputDir)
+ .setMinApiLevel(minSdk)
+ .setMode(CompilationMode.DEBUG)
+ .build(),
+ optionsConsumer);
+ return dexOutputDir.resolve("classes.dex");
+
}
protected final boolean supportsDefaultMethod() {
@@ -158,7 +152,7 @@
protected final void runDebugTest(String debuggeeClass, List<JUnit3Wrapper.Command> commands)
throws Throwable {
- runDebugTest(false, debuggeeClass, commands);
+ runDebugTest(LanguageFeatures.JAVA_7, debuggeeClass, commands);
}
protected final void runDebugTestJava8(String debuggeeClass, JUnit3Wrapper.Command... commands)
@@ -168,12 +162,54 @@
protected final void runDebugTestJava8(String debuggeeClass, List<JUnit3Wrapper.Command> commands)
throws Throwable {
- runDebugTest(true, debuggeeClass, commands);
+ runDebugTest(LanguageFeatures.JAVA_8, debuggeeClass, commands);
}
- private void runDebugTest(boolean useJava8, String debuggeeClass,
- List<JUnit3Wrapper.Command> commands)
+ protected final void runDebugTestKotlin(String debuggeeClass, JUnit3Wrapper.Command... commands)
throws Throwable {
+ runDebugTestKotlin(debuggeeClass, Arrays.asList(commands));
+ }
+
+ protected final void runDebugTestKotlin(String debuggeeClass,
+ List<JUnit3Wrapper.Command> commands) throws Throwable {
+ runDebugTest(LanguageFeatures.KOTLIN, debuggeeClass, commands);
+ }
+
+ protected enum LanguageFeatures {
+ JAVA_7(DEBUGGEE_JAR) {
+ @Override
+ public Path getDexPath() {
+ return debuggeeDexD8;
+ }
+ },
+ JAVA_8(DEBUGGEE_JAVA8_JAR) {
+ @Override
+ public Path getDexPath() {
+ return debuggeeJava8DexD8;
+ }
+ },
+ KOTLIN(DEBUGGEE_KOTLIN_JAR) {
+ @Override
+ public Path getDexPath() {
+ return debuggeeKotlinDexD8;
+ }
+ };
+
+ private final Path jarPath;
+
+ LanguageFeatures(Path jarPath) {
+ this.jarPath = jarPath;
+ }
+
+ public Path getJarPath() {
+ return jarPath;
+ }
+
+ public abstract Path getDexPath();
+ }
+
+ private void runDebugTest(LanguageFeatures languageFeatures, String debuggeeClass,
+ List<JUnit3Wrapper.Command> commands) throws Throwable {
// Skip test due to unsupported runtime.
Assume.assumeTrue("Skipping test " + testName.getMethodName() + " because ART is not supported",
ToolHelper.artSupported());
@@ -183,15 +219,9 @@
String[] paths;
if (RUNTIME_KIND == RuntimeKind.JAVA) {
- paths = new String[] {
- JDWP_JAR.toString(),
- useJava8 ? DEBUGGEE_JAVA8_JAR.toString() : DEBUGGEE_JAR.toString()
- };
+ paths = new String[] { JDWP_JAR.toString(), languageFeatures.getJarPath().toString() };
} else {
- paths = new String[] {
- jdwpDexD8.toString(),
- useJava8 ? debuggeeJava8DexD8.toString() : debuggeeDexD8.toString()
- };
+ paths = new String[] { jdwpDexD8.toString(), languageFeatures.getDexPath().toString() };
}
new JUnit3Wrapper(debuggeeClass, paths, commands).runBare();
}
@@ -580,6 +610,7 @@
}
public String getSourceFile() {
+ // TODO(shertz) support JSR-45
Location location = getLocation();
CommandPacket sourceFileCommand = new CommandPacket(
JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
diff --git a/src/test/java/com/android/tools/r8/debug/KotlinTest.java b/src/test/java/com/android/tools/r8/debug/KotlinTest.java
new file mode 100644
index 0000000..1700964
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debug/KotlinTest.java
@@ -0,0 +1,38 @@
+// 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.debug;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class KotlinTest extends DebugTestBase {
+
+ @Test
+ public void testKotlinApp() throws Throwable {
+ runDebugTestKotlin("KotlinApp",
+ breakpoint("KotlinApp$Companion", "main"),
+ run(),
+ inspect(s -> {
+ Assert.assertEquals("KotlinApp.kt", s.getSourceFile());
+ Assert.assertEquals(8, s.getLineNumber());
+ s.checkLocal("this");
+ s.checkLocal("args");
+ }),
+ stepOver(),
+ inspect(s -> {
+ Assert.assertEquals(9, s.getLineNumber());
+ s.checkLocal("this");
+ s.checkLocal("args");
+ }),
+ stepOver(),
+ inspect(s -> {
+ Assert.assertEquals(10, s.getLineNumber());
+ s.checkLocal("this");
+ s.checkLocal("args");
+ s.checkLocal("instance");
+ }),
+ run());
+ }
+
+}
diff --git a/src/test/java/com/android/tools/r8/naming/PackageNamingTest.java b/src/test/java/com/android/tools/r8/naming/PackageNamingTest.java
index feaf0d9..b8e22d2 100644
--- a/src/test/java/com/android/tools/r8/naming/PackageNamingTest.java
+++ b/src/test/java/com/android/tools/r8/naming/PackageNamingTest.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;
+import static com.android.tools.r8.naming.ClassNameMinifier.getParentPackagePrefix;
import static com.android.tools.r8.utils.DescriptorUtils.getPackageNameFromDescriptor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -15,6 +16,7 @@
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Timing;
import com.google.common.base.CharMatcher;
+import com.google.common.collect.ImmutableList;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collection;
@@ -45,13 +47,19 @@
@Parameters(name = "test: {0} keep: {1}")
public static Collection<Object[]> data() {
- List<String> tests = Arrays.asList("naming044");
+ List<String> tests = Arrays.asList("naming044", "naming101");
Map<String, BiConsumer<DexItemFactory, NamingLens>> inspections = new HashMap<>();
inspections.put("naming044:keep-rules-001.txt", PackageNamingTest::test044_rule001);
inspections.put("naming044:keep-rules-002.txt", PackageNamingTest::test044_rule002);
inspections.put("naming044:keep-rules-003.txt", PackageNamingTest::test044_rule003);
inspections.put("naming044:keep-rules-004.txt", PackageNamingTest::test044_rule004);
+ inspections.put("naming044:keep-rules-005.txt", PackageNamingTest::test044_rule005);
+ inspections.put("naming101:keep-rules-001.txt", PackageNamingTest::test101_rule001);
+ inspections.put("naming101:keep-rules-002.txt", PackageNamingTest::test101_rule002);
+ inspections.put("naming101:keep-rules-003.txt", PackageNamingTest::test101_rule003);
+ inspections.put("naming101:keep-rules-004.txt", PackageNamingTest::test101_rule004);
+ inspections.put("naming101:keep-rules-005.txt", PackageNamingTest::test101_rule005);
return createTests(tests, inspections);
}
@@ -135,4 +143,111 @@
getPackageNameFromDescriptor(naming.lookupDescriptor(sub).toSourceString()),
getPackageNameFromDescriptor(naming.lookupDescriptor(b).toSourceString()));
}
+
+ private static void test044_rule005(DexItemFactory dexItemFactory, NamingLens naming) {
+ // All packages are renamed somehow. Need to check package hierarchy is consistent.
+ DexType a = dexItemFactory.createType("Lnaming044/A;");
+ assertEquals(1, countPackageDepth(naming.lookupDescriptor(a).toSourceString()));
+ DexType b = dexItemFactory.createType("Lnaming044/B;");
+ assertEquals(1, countPackageDepth(naming.lookupDescriptor(b).toSourceString()));
+ assertEquals(
+ getPackageNameFromDescriptor(naming.lookupDescriptor(a).toSourceString()),
+ getPackageNameFromDescriptor(naming.lookupDescriptor(b).toSourceString()));
+
+ DexType sub_a = dexItemFactory.createType("Lnaming044/sub/SubA;");
+ assertEquals(2, countPackageDepth(naming.lookupDescriptor(sub_a).toSourceString()));
+ DexType sub_b = dexItemFactory.createType("Lnaming044/sub/SubB;");
+ assertEquals(2, countPackageDepth(naming.lookupDescriptor(sub_b).toSourceString()));
+ assertEquals(
+ getPackageNameFromDescriptor(naming.lookupDescriptor(sub_a).toSourceString()),
+ getPackageNameFromDescriptor(naming.lookupDescriptor(sub_b).toSourceString()));
+
+ // Lnaming044/B -> La/c --prefix--> La
+ // Lnaming044/sub/SubB -> La/b/b --prefix--> La/b --prefix--> La
+ assertEquals(
+ getParentPackagePrefix(naming.lookupDescriptor(b).toSourceString()),
+ getParentPackagePrefix(
+ getParentPackagePrefix(naming.lookupDescriptor(sub_b).toSourceString())));
+ }
+
+ private static void test101_rule001(DexItemFactory dexItemFactory, NamingLens naming) {
+ // All classes are moved to the top-level package, hence no package separator.
+ DexType c = dexItemFactory.createType("Lnaming101/c;");
+ assertFalse(naming.lookupDescriptor(c).toSourceString().contains("/"));
+
+ DexType abc = dexItemFactory.createType("Lnaming101/a/b/c;");
+ assertFalse(naming.lookupDescriptor(abc).toSourceString().contains("/"));
+ assertNotEquals(
+ naming.lookupDescriptor(abc).toSourceString(),
+ naming.lookupDescriptor(c).toSourceString());
+ }
+
+ private static void test101_rule002(DexItemFactory dexItemFactory, NamingLens naming) {
+ // Check naming101.a.a is kept due to **.a
+ DexType a = dexItemFactory.createType("Lnaming101/a/a;");
+ assertEquals("Lnaming101/a/a;", naming.lookupDescriptor(a).toSourceString());
+ // Repackaged to naming101.a, but naming101.a.a exists to make a name conflict.
+ // Thus, everything else should not be renamed to 'a',
+ // except for naming101.b.a, which is also kept due to **.a
+ List<String> klasses = ImmutableList.of(
+ "Lnaming101/c;",
+ "Lnaming101/d;",
+ "Lnaming101/a/c;",
+ "Lnaming101/a/b/c;",
+ "Lnaming101/b/b;");
+ for (String klass : klasses) {
+ DexType k = dexItemFactory.createType(klass);
+ String renamedName = naming.lookupDescriptor(k).toSourceString();
+ assertEquals("naming101.a", getPackageNameFromDescriptor(renamedName));
+ assertNotEquals("Lnaming101/a/a;", renamedName);
+ }
+ }
+
+ private static void test101_rule003(DexItemFactory dexItemFactory, NamingLens naming) {
+ // All packages are moved to the top-level package, hence only one package separator.
+ DexType aa = dexItemFactory.createType("Lnaming101/a/a;");
+ assertEquals(1, countPackageDepth(naming.lookupDescriptor(aa).toSourceString()));
+
+ DexType ba = dexItemFactory.createType("Lnaming101/b/a;");
+ assertEquals(1, countPackageDepth(naming.lookupDescriptor(ba).toSourceString()));
+
+ assertNotEquals(
+ getPackageNameFromDescriptor(naming.lookupDescriptor(aa).toSourceString()),
+ getPackageNameFromDescriptor(naming.lookupDescriptor(ba).toSourceString()));
+ }
+
+ private static void test101_rule004(DexItemFactory dexItemFactory, NamingLens naming) {
+ // Check naming101.a.a is kept due to **.a
+ DexType a = dexItemFactory.createType("Lnaming101/a/a;");
+ assertEquals("Lnaming101/a/a;", naming.lookupDescriptor(a).toSourceString());
+ // Flattened to naming101, hence all other classes will be in naming101.* package.
+ // Due to naming101.a.a, prefix naming101.a is already used. So, any other classes,
+ // except for naming101.a.c, should not have naming101.a as package.
+ List<String> klasses = ImmutableList.of(
+ "Lnaming101/c;",
+ "Lnaming101/d;",
+ "Lnaming101/a/b/c;",
+ "Lnaming101/b/a;",
+ "Lnaming101/b/b;");
+ for (String klass : klasses) {
+ DexType k = dexItemFactory.createType(klass);
+ String renamedName = naming.lookupDescriptor(k).toSourceString();
+ assertNotEquals("naming101.a", getPackageNameFromDescriptor(renamedName));
+ }
+ }
+
+ private static void test101_rule005(DexItemFactory dexItemFactory, NamingLens naming) {
+ // All packages are renamed somehow. Need to check package hierarchy is consistent.
+ DexType aa = dexItemFactory.createType("Lnaming101/a/a;");
+ assertEquals(2, countPackageDepth(naming.lookupDescriptor(aa).toSourceString()));
+ DexType abc = dexItemFactory.createType("Lnaming101/a/b/c;");
+ assertEquals(3, countPackageDepth(naming.lookupDescriptor(abc).toSourceString()));
+
+ // Lnaming101/a/a; -> La/a/a; --prefix--> La/a
+ // Lnaming101/a/b/c; -> La/a/a/a; --prefix--> La/a/a --prefix--> La/a
+ assertEquals(
+ getParentPackagePrefix(naming.lookupDescriptor(aa).toSourceString()),
+ getParentPackagePrefix(
+ getParentPackagePrefix(naming.lookupDescriptor(abc).toSourceString())));
+ }
}
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 28722af..ea28214 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -445,7 +445,6 @@
ProguardConfigurationParser parser = new ProguardConfigurationParser(new DexItemFactory());
parser.parse(Paths.get(DONT_OPTIMIZE));
ProguardConfiguration config = parser.getConfig();
- assertTrue(config.getOptimizationPasses() == 0);
}
@Test
@@ -453,7 +452,6 @@
ProguardConfigurationParser parser = new ProguardConfigurationParser(new DexItemFactory());
parser.parse(Paths.get(DONT_OPTIMIZE_OVERRIDES_PASSES));
ProguardConfiguration config = parser.getConfig();
- assertTrue(config.getOptimizationPasses() == 0);
}
@Test
@@ -461,9 +459,6 @@
ProguardConfigurationParser parser = new ProguardConfigurationParser(new DexItemFactory());
parser.parse(Paths.get(OPTIMIZATION_PASSES));
ProguardConfiguration config = parser.getConfig();
- // TODO(b/36800551): optimizationPasses should not be set at the moment.
- // assertTrue(config.getOptimizationPasses() == 8);
- assertTrue(config.getOptimizationPasses() == 1);
}
@Test
diff --git a/src/test/java/com/android/tools/r8/utils/DescriptorUtilsTest.java b/src/test/java/com/android/tools/r8/utils/DescriptorUtilsTest.java
index 034a288..58180e3 100644
--- a/src/test/java/com/android/tools/r8/utils/DescriptorUtilsTest.java
+++ b/src/test/java/com/android/tools/r8/utils/DescriptorUtilsTest.java
@@ -44,6 +44,15 @@
}
@Test
+ public void fromDescriptor() throws IOException {
+ String obj = "Ljava/lang/Object;";
+ assertEquals("Object", DescriptorUtils.getSimpleClassNameFromDescriptor(obj));
+ assertEquals("java.lang.Object", DescriptorUtils.getClassNameFromDescriptor(obj));
+ assertEquals("java.lang", DescriptorUtils.getPackageNameFromDescriptor(obj));
+ assertEquals("java/lang/Object", DescriptorUtils.getClassBinaryNameFromDescriptor(obj));
+ }
+
+ @Test
public void toJavaType() throws IOException {
assertEquals("boolean", DescriptorUtils.descriptorToJavaType("Z"));
assertEquals("byte", DescriptorUtils.descriptorToJavaType("B"));
diff --git a/third_party/kotlin.tar.gz.sha1 b/third_party/kotlin.tar.gz.sha1
new file mode 100644
index 0000000..942c691
--- /dev/null
+++ b/third_party/kotlin.tar.gz.sha1
@@ -0,0 +1 @@
+21b6244cb0a5bca1f1d046d00540a610c02cd714
\ No newline at end of file