Account for synthetic arguments of enum class initializer
when collecting non-null param hints.
Bug: 121221542
Change-Id: I115d4141f37d207fa0cc4129f46146df2f3d12d4
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index 5a4b204..f69251b 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -321,6 +321,10 @@
return accessFlags.isInterface();
}
+ public boolean isEnum() {
+ return accessFlags.isEnum();
+ }
+
public abstract void addDependencies(MixedSectionCollection collector);
@Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClass.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClass.java
index d15ed5a..4f79660 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClass.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClass.java
@@ -6,6 +6,7 @@
import static kotlinx.metadata.Flag.Property.IS_VAR;
+import com.android.tools.r8.graph.DexClass;
import kotlinx.metadata.KmClassVisitor;
import kotlinx.metadata.KmConstructorVisitor;
import kotlinx.metadata.KmFunctionVisitor;
@@ -14,14 +15,15 @@
public class KotlinClass extends KotlinInfo<KotlinClassMetadata.Class> {
- static KotlinClass fromKotlinClassMetadata(KotlinClassMetadata kotlinClassMetadata) {
+ static KotlinClass fromKotlinClassMetadata(
+ KotlinClassMetadata kotlinClassMetadata, DexClass clazz) {
assert kotlinClassMetadata instanceof KotlinClassMetadata.Class;
KotlinClassMetadata.Class kClass = (KotlinClassMetadata.Class) kotlinClassMetadata;
- return new KotlinClass(kClass);
+ return new KotlinClass(kClass, clazz);
}
- private KotlinClass(KotlinClassMetadata.Class metadata) {
- super(metadata);
+ private KotlinClass(KotlinClassMetadata.Class metadata, DexClass clazz) {
+ super(metadata, clazz);
}
@Override
@@ -38,7 +40,7 @@
@Override
public KmConstructorVisitor visitConstructor(int ctorFlags) {
- return new NonNullParameterHintCollector.ConstructorVisitor(nonNullparamHints);
+ return new NonNullParameterHintCollector.ConstructorVisitor(nonNullparamHints, clazz);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
index 6518bb8..6004201 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
@@ -77,7 +77,7 @@
KotlinClassMetadata kMetadata = KotlinClassMetadata.read(header);
if (kMetadata instanceof KotlinClassMetadata.Class) {
- return KotlinClass.fromKotlinClassMetadata(kMetadata);
+ return KotlinClass.fromKotlinClassMetadata(kMetadata, clazz);
} else if (kMetadata instanceof KotlinClassMetadata.FileFacade) {
return KotlinFile.fromKotlinClassMetadata(kMetadata);
} else if (kMetadata instanceof KotlinClassMetadata.MultiFileClassFacade) {
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
index 7cc8aa1..ef90173 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.kotlin;
+import com.android.tools.r8.graph.DexClass;
import com.google.common.collect.HashBasedTable;
import java.util.BitSet;
import kotlinx.metadata.jvm.KotlinClassMetadata;
@@ -11,12 +12,18 @@
// Provides access to kotlin information.
public abstract class KotlinInfo<MetadataKind extends KotlinClassMetadata> {
MetadataKind metadata;
+ DexClass clazz;
final HashBasedTable<String, String, BitSet> nonNullparamHints = HashBasedTable.create();
KotlinInfo() {
}
KotlinInfo(MetadataKind metadata) {
+ this(metadata, null);
+ }
+
+ KotlinInfo(MetadataKind metadata, DexClass clazz) {
+ this.clazz = clazz;
processMetadata(metadata);
this.metadata = metadata;
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/NonNullParameterHintCollector.java b/src/main/java/com/android/tools/r8/kotlin/NonNullParameterHintCollector.java
index 20621f9..079980f 100644
--- a/src/main/java/com/android/tools/r8/kotlin/NonNullParameterHintCollector.java
+++ b/src/main/java/com/android/tools/r8/kotlin/NonNullParameterHintCollector.java
@@ -6,6 +6,7 @@
import static kotlinx.metadata.Flag.Type.IS_NULLABLE;
+import com.android.tools.r8.graph.DexClass;
import com.google.common.collect.HashBasedTable;
import java.util.BitSet;
import kotlinx.metadata.KmConstructorExtensionVisitor;
@@ -94,8 +95,18 @@
private final String name = "<init>";
private String descriptor = "";
- ConstructorVisitor(HashBasedTable<String, String, BitSet> paramHints) {
+ ConstructorVisitor(HashBasedTable<String, String, BitSet> paramHints, DexClass clazz) {
this.paramHints = paramHints;
+ // Enum constructor has two synthetic arguments to java.lang.Enum's sole constructor:
+ // https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html#Enum-java.lang.String-int-
+ // whereas Kotlin @Metadata is still based on constructor signature, not descriptor.
+ if (clazz != null && clazz.isEnum()) {
+ // name - The name of this enum constant, which is the identifier used to declare it.
+ paramIndex++;
+ // ordinal - The ordinal of this enumeration constant (its position in the enum declaration,
+ // where the initial constant is assigned an ordinal of zero).
+ paramIndex++;
+ }
}
@Override
diff --git a/src/test/java/com/android/tools/r8/naming/EnumMinificationKotlinTest.java b/src/test/java/com/android/tools/r8/naming/EnumMinificationKotlinTest.java
new file mode 100644
index 0000000..179f9c6
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/naming/EnumMinificationKotlinTest.java
@@ -0,0 +1,64 @@
+// Copyright (c) 2018, 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.naming;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import com.android.tools.r8.KotlinTestBase;
+import com.android.tools.r8.R8TestBuilder;
+import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
+import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import com.google.common.collect.Streams;
+import java.util.Collection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class EnumMinificationKotlinTest extends KotlinTestBase {
+ private static final String FOLDER = "minify_enum";
+ private static final String MAIN_CLASS_NAME = "minify_enum.MainKt";
+ private static final String ENUM_CLASS_NAME = "minify_enum.MinifyEnum";
+
+ private final Backend backend;
+ private final boolean minify;
+
+ @Parameterized.Parameters(name = "Backend: {0} target: {1} minify: {2}")
+ public static Collection<Object[]> data() {
+ return buildParameters(Backend.values(), KotlinTargetVersion.values(), BooleanUtils.values());
+ }
+
+ public EnumMinificationKotlinTest(
+ Backend backend, KotlinTargetVersion targetVersion, boolean minify) {
+ super(targetVersion);
+ this.backend = backend;
+ this.minify = minify;
+ }
+
+ @Test
+ public void b121221542() throws Exception {
+ R8TestBuilder builder = testForR8(backend)
+ .addProgramFiles(getKotlinJarFile(FOLDER))
+ .addProgramFiles(getJavaJarFile(FOLDER))
+ .addKeepMainRule(MAIN_CLASS_NAME);
+ if (!minify) {
+ builder.noMinification();
+ }
+ CodeInspector inspector = builder.run(MAIN_CLASS_NAME).inspector();
+ ClassSubject enumClass = inspector.clazz(ENUM_CLASS_NAME);
+ assertThat(enumClass, isPresent());
+ assertEquals(minify, enumClass.isRenamed());
+ MethodSubject clinit = enumClass.clinit();
+ assertThat(clinit, isPresent());
+ assertEquals(0,
+ Streams.stream(clinit.iterateInstructions(InstructionSubject::isThrow)).count());
+ }
+
+}
diff --git a/src/test/kotlinR8TestResources/minify_enum/main.kt b/src/test/kotlinR8TestResources/minify_enum/main.kt
new file mode 100644
index 0000000..d35ecf5
--- /dev/null
+++ b/src/test/kotlinR8TestResources/minify_enum/main.kt
@@ -0,0 +1,16 @@
+// Copyright (c) 2018, 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 minify_enum
+
+enum class MinifyEnum(
+ val nullableStr1: String?,
+ val nullableStr2: String?,
+ val number3: String
+) {
+ UNKNOWN(null, null, "")
+}
+
+fun main(args: Array<String>) {
+ val a = MinifyEnum.UNKNOWN
+}