Do not emit packageName, extraString and extraInt if null or default
Bug: 158400283
Change-Id: I703c078b13ec8cf4fa46cd40b7516d98fb86f5ab
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
index ce0ba80..dfddc1d 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
@@ -83,27 +83,33 @@
KotlinClassHeader header, String packageName) {
List<DexAnnotationElement> elements = new ArrayList<>();
elements.add(
- new DexAnnotationElement(kotlin.metadata.kind, DexValueInt.create(header.getKind())));
- elements.add(
new DexAnnotationElement(
kotlin.metadata.metadataVersion, createIntArray(header.getMetadataVersion())));
elements.add(
new DexAnnotationElement(
kotlin.metadata.bytecodeVersion, createIntArray(header.getBytecodeVersion())));
elements.add(
+ new DexAnnotationElement(kotlin.metadata.kind, DexValueInt.create(header.getKind())));
+ elements.add(
new DexAnnotationElement(kotlin.metadata.data1, createStringArray(header.getData1())));
elements.add(
new DexAnnotationElement(kotlin.metadata.data2, createStringArray(header.getData2())));
- elements.add(
- new DexAnnotationElement(
- kotlin.metadata.extraString,
- new DexValueString(factory.createString(header.getExtraString()))));
- elements.add(
- new DexAnnotationElement(
- kotlin.metadata.packageName, new DexValueString(factory.createString(packageName))));
- elements.add(
- new DexAnnotationElement(
- kotlin.metadata.extraInt, DexValueInt.create(header.getExtraInt())));
+ if (packageName != null && !packageName.isEmpty()) {
+ elements.add(
+ new DexAnnotationElement(
+ kotlin.metadata.packageName, new DexValueString(factory.createString(packageName))));
+ }
+ if (!header.getExtraString().isEmpty()) {
+ elements.add(
+ new DexAnnotationElement(
+ kotlin.metadata.extraString,
+ new DexValueString(factory.createString(header.getExtraString()))));
+ }
+ if (header.getExtraInt() != 0) {
+ elements.add(
+ new DexAnnotationElement(
+ kotlin.metadata.extraInt, DexValueInt.create(header.getExtraInt())));
+ }
DexEncodedAnnotation encodedAnnotation =
new DexEncodedAnnotation(
factory.kotlinMetadataType, elements.toArray(DexAnnotationElement.EMPTY_ARRAY));
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteDoNotEmitValuesIfEmpty.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteDoNotEmitValuesIfEmpty.java
new file mode 100644
index 0000000..788e64b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteDoNotEmitValuesIfEmpty.java
@@ -0,0 +1,81 @@
+// Copyright (c) 2020, 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.kotlin.metadata;
+
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
+import com.android.tools.r8.graph.DexAnnotationElement;
+import com.android.tools.r8.shaking.ProguardKeepAttributes;
+import com.android.tools.r8.utils.codeinspector.AnnotationSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
+import com.google.common.collect.Sets;
+import java.util.Collection;
+import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class MetadataRewriteDoNotEmitValuesIfEmpty extends KotlinMetadataTestBase {
+
+ private final Set<String> nullableFieldKeys = Sets.newHashSet("pn", "xs", "xi");
+
+ @Parameterized.Parameters(name = "{0} target: {1}")
+ public static Collection<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withCfRuntimes().build(), KotlinTargetVersion.values());
+ }
+
+ private final TestParameters parameters;
+
+ public MetadataRewriteDoNotEmitValuesIfEmpty(
+ TestParameters parameters, KotlinTargetVersion targetVersion) {
+ super(targetVersion);
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testKotlinStdLib() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramFiles(ToolHelper.getKotlinStdlibJar())
+ .setMinApi(parameters.getApiLevel())
+ .addKeepAllClassesRule()
+ .addKeepKotlinMetadata()
+ .addKeepAttributes(ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS)
+ .compile()
+ .inspect(this::inspectEmptyValuesAreNotPresent);
+ }
+
+ private void inspectEmptyValuesAreNotPresent(CodeInspector inspector) {
+ boolean seenNullableField = false;
+ boolean seenMetadataWithoutNullableField = false;
+ for (FoundClassSubject clazz : inspector.allClasses()) {
+ AnnotationSubject annotation = clazz.annotation("kotlin.Metadata");
+ if (annotation.isPresent()) {
+ boolean seenNullableFieldForAnnotation = false;
+ for (DexAnnotationElement element : annotation.getAnnotation().elements) {
+ if (nullableFieldKeys.contains(element.name.toString())) {
+ if (element.value.isDexValueInt()) {
+ assertNotEquals(0, element.value.asDexValueInt().value);
+ } else {
+ String value = element.value.asDexValueString().value.toString();
+ assertNotEquals("", value);
+ }
+ seenNullableField = true;
+ seenNullableFieldForAnnotation = true;
+ }
+ }
+ seenMetadataWithoutNullableField |= !seenNullableFieldForAnnotation;
+ }
+ }
+ assertTrue(seenNullableField);
+ assertTrue(seenMetadataWithoutNullableField);
+ }
+}