Merge commit '1240b3d2d5a9a2349305ac803c954ebcaad549f4' into dev-release
diff --git a/build.gradle b/build.gradle
index a3021ec..870b615 100644
--- a/build.gradle
+++ b/build.gradle
@@ -44,8 +44,8 @@
mockitoVersion = '2.10.0'
// The kotlin version is only here to specify the kotlin language level,
// all kotlin compilations are done in tests.
- kotlinVersion = '1.6.0'
- kotlinExtMetadataJVMVersion = '0.5.0'
+ kotlinVersion = '1.8.0'
+ kotlinExtMetadataJVMVersion = '0.6.0'
smaliVersion = '2.2b4'
errorproneVersion = '2.3.2'
testngVersion = '6.10'
@@ -286,7 +286,7 @@
main17Implementation group: 'org.ow2.asm', name: 'asm-tree', version: asmVersion
main17Implementation group: 'org.ow2.asm', name: 'asm-analysis', version: asmVersion
main17Implementation group: 'org.ow2.asm', name: 'asm-util', version: asmVersion
-
+
examplesTestNGRunnerCompile group: 'org.testng', name: 'testng', version: testngVersion
testCompile sourceSets.examples.output
diff --git a/src/main/java/com/android/tools/r8/kotlin/KmVisitorProviders.java b/src/main/java/com/android/tools/r8/kotlin/KmVisitorProviders.java
deleted file mode 100644
index 65bdeec..0000000
--- a/src/main/java/com/android/tools/r8/kotlin/KmVisitorProviders.java
+++ /dev/null
@@ -1,134 +0,0 @@
-// 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;
-
-import kotlinx.metadata.KmAnnotation;
-import kotlinx.metadata.KmContractVisitor;
-import kotlinx.metadata.KmEffectExpressionVisitor;
-import kotlinx.metadata.KmEffectInvocationKind;
-import kotlinx.metadata.KmEffectType;
-import kotlinx.metadata.KmEffectVisitor;
-import kotlinx.metadata.KmFunctionVisitor;
-import kotlinx.metadata.KmLambdaVisitor;
-import kotlinx.metadata.KmPropertyVisitor;
-import kotlinx.metadata.KmTypeAliasVisitor;
-import kotlinx.metadata.KmTypeParameterVisitor;
-import kotlinx.metadata.KmTypeVisitor;
-import kotlinx.metadata.KmValueParameterVisitor;
-import kotlinx.metadata.KmVariance;
-import kotlinx.metadata.KmVersionRequirementVisitor;
-
-/**
- * The reason for having these visitor providers is to make the separation of concern a bit easier
- * while also working with the kotlinx.metadata visitors as shown by the following example:
- *
- * <p>Say we have the following structure KotlinTypeInfo: { TypeProjects:
- * [KotlinTypeProjectionInfo(StarProjection)] }
- *
- * <p>Now the KmTypeVisitor (we use to generate the KotlinTypeInfo, has a visitProjection(int flags,
- * KmVariance variance) generator that will return a new KmTypeVisitor, however, if the projection
- * is a star projection, the generator visitStarProjection() should be used.
- *
- * <p>The information about the projection being a star projection is contained in the
- * KotlinTypeProjectionInfo. As a result, KotlinTypeInfo should query the object for picking the
- * right generator, the KotlinTypeProjectionInfo should return a KmTypeProjection object, or we
- * simply capture the generators lazily (by these providers), such that the object with all the
- * information can decide when/what object to create.
- *
- * <p>Another benefit of this approach than using the build in visitors is that shared structures,
- * such as KotlinAnnotationInfo that can be on type-aliases, functions and properties will not have
- * to take in three different type of visitors.
- */
-public class KmVisitorProviders {
-
- @FunctionalInterface
- public interface KmAnnotationVisitorProvider {
-
- void get(KmAnnotation annotation);
- }
-
- @FunctionalInterface
- public interface KmFunctionVisitorProvider {
-
- KmFunctionVisitor get(int flags, String name);
- }
-
- public interface KmLambdaVisitorProvider {
-
- KmLambdaVisitor get();
- }
-
- @FunctionalInterface
- public interface KmPropertyVisitorProvider {
-
- KmPropertyVisitor get(int flags, String name, int getterFlags, int setterFlags);
- }
-
- @FunctionalInterface
- public interface KmTypeAliasVisitorProvider {
-
- KmTypeAliasVisitor get(int flags, String name);
- }
-
- @FunctionalInterface
- public interface KmTypeParameterVisitorProvider {
-
- KmTypeParameterVisitor get(int flags, String name, int id, KmVariance variance);
- }
-
- @FunctionalInterface
- public interface KmTypeProjectionVisitorProvider {
-
- KmTypeVisitor get(int flags, KmVariance variance);
- }
-
- @FunctionalInterface
- public interface KmTypeStarProjectionVisitorProvider {
-
- void get();
- }
-
- @FunctionalInterface
- public interface KmTypeVisitorProvider {
-
- KmTypeVisitor get(int flags);
- }
-
- @FunctionalInterface
- public interface KmValueParameterVisitorProvider {
-
- KmValueParameterVisitor get(int flags, String name);
- }
-
- @FunctionalInterface
- public interface KmFlexibleUpperBoundVisitorProvider {
-
- KmTypeVisitor get(int flags, String typeFlexibilityId);
- }
-
- @FunctionalInterface
- public interface KmVersionRequirementVisitorProvider {
-
- KmVersionRequirementVisitor get();
- }
-
- @FunctionalInterface
- public interface KmContractVisitorProvider {
-
- KmContractVisitor get();
- }
-
- @FunctionalInterface
- public interface KmEffectVisitorProvider {
-
- KmEffectVisitor get(KmEffectType type, KmEffectInvocationKind effectInvocationKind);
- }
-
- @FunctionalInterface
- public interface KmEffectExpressionVisitorProvider {
-
- KmEffectExpressionVisitor get();
- }
-}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationInfo.java
index 249f68f..759ef69 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationInfo.java
@@ -14,6 +14,7 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Consumer;
import kotlinx.metadata.KmAnnotation;
import kotlinx.metadata.KmAnnotationArgument;
@@ -49,8 +50,7 @@
return builder.build();
}
- boolean rewrite(
- KmVisitorProviders.KmAnnotationVisitorProvider visitorProvider, AppView<?> appView) {
+ boolean rewrite(Consumer<KmAnnotation> annotationConsumer, AppView<?> appView) {
BooleanBox rewritten = new BooleanBox(false);
rewritten.or(
annotationType.toRenamedDescriptorOrDefault(
@@ -72,7 +72,7 @@
}
},
appView)));
- visitorProvider.get(new KmAnnotation(classifier, rewrittenArguments));
+ annotationConsumer.accept(new KmAnnotation(classifier, rewrittenArguments));
},
appView,
null));
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java
index 810f2de..d59a9ca 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java
@@ -4,9 +4,12 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.getCompatibleKotlinInfo;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteList;
import static com.android.tools.r8.kotlin.KotlinMetadataUtils.toJvmFieldSignature;
import static com.android.tools.r8.kotlin.KotlinMetadataUtils.toJvmMethodSignature;
import static com.android.tools.r8.utils.FunctionUtils.forEachApply;
+import static kotlinx.metadata.jvm.KotlinClassMetadata.Companion;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
@@ -17,6 +20,7 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
@@ -26,13 +30,12 @@
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
+import kotlin.Metadata;
import kotlinx.metadata.KmClass;
import kotlinx.metadata.KmConstructor;
import kotlinx.metadata.KmType;
-import kotlinx.metadata.jvm.JvmClassExtensionVisitor;
import kotlinx.metadata.jvm.JvmExtensionsKt;
import kotlinx.metadata.jvm.JvmMethodSignature;
-import kotlinx.metadata.jvm.KotlinClassHeader;
import kotlinx.metadata.jvm.KotlinClassMetadata;
public class KotlinClassInfo implements KotlinClassLevelInfo {
@@ -57,6 +60,8 @@
private final KotlinTypeInfo inlineClassUnderlyingType;
private final int jvmFlags;
private final String companionObjectName;
+ // Collection of context receiver types
+ private final List<KotlinTypeInfo> contextReceiverTypes;
// List of tracked assignments of kotlin metadata.
private final KotlinMetadataMembersTracker originalMembersWithKotlinInfo;
@@ -82,7 +87,8 @@
KotlinTypeInfo inlineClassUnderlyingType,
KotlinMetadataMembersTracker originalMembersWithKotlinInfo,
int jvmFlags,
- String companionObjectName) {
+ String companionObjectName,
+ List<KotlinTypeInfo> contextReceiverTypes) {
this.flags = flags;
this.name = name;
this.nameCanBeSynthesizedFromClassOrAnonymousObjectOrigin =
@@ -105,6 +111,7 @@
this.originalMembersWithKotlinInfo = originalMembersWithKotlinInfo;
this.jvmFlags = jvmFlags;
this.companionObjectName = companionObjectName;
+ this.contextReceiverTypes = contextReceiverTypes;
}
public static KotlinClassInfo create(
@@ -188,7 +195,10 @@
KotlinTypeInfo.create(kmClass.getInlineClassUnderlyingType(), factory, reporter),
originalMembersWithKotlinInfo,
JvmExtensionsKt.getJvmFlags(kmClass),
- setCompanionObject(kmClass, hostClass, reporter));
+ setCompanionObject(kmClass, hostClass, reporter),
+ ListUtils.map(
+ kmClass.getContextReceiverTypes(),
+ contextRecieverType -> KotlinTypeInfo.create(contextRecieverType, factory, reporter)));
}
private static KotlinTypeReference getAnonymousObjectOrigin(
@@ -279,7 +289,7 @@
}
@Override
- public Pair<KotlinClassHeader, Boolean> rewrite(DexClass clazz, AppView<?> appView) {
+ public Pair<Metadata, Boolean> rewrite(DexClass clazz, AppView<?> appView) {
KmClass kmClass = new KmClass();
// TODO(b/154348683): Set flags.
kmClass.setFlags(flags);
@@ -356,27 +366,29 @@
// Rewrite functions, type-aliases and type-parameters.
rewritten |=
declarationContainerInfo.rewrite(
- kmClass::visitFunction,
- kmClass::visitProperty,
- kmClass::visitTypeAlias,
+ kmClass.getFunctions()::add,
+ kmClass.getProperties()::add,
+ kmClass.getTypeAliases()::add,
clazz,
appView,
rewrittenReferences);
// Rewrite type parameters.
- for (KotlinTypeParameterInfo typeParameter : typeParameters) {
- rewritten |= typeParameter.rewrite(kmClass::visitTypeParameter, appView);
- }
+ rewritten |=
+ rewriteList(
+ appView, typeParameters, kmClass.getTypeParameters(), KotlinTypeParameterInfo::rewrite);
// Rewrite super types.
+ List<KmType> rewrittenSuperTypes = kmClass.getSupertypes();
for (KotlinTypeInfo superType : superTypes) {
// Ensure the rewritten super type is not this type.
if (clazz.getType() != superType.rewriteType(appView.graphLens())) {
- rewritten |= superType.rewrite(kmClass::visitSupertype, appView);
+ rewritten |= superType.rewrite(rewrittenSuperTypes::add, appView);
} else {
rewritten = true;
}
}
// Rewrite nested classes.
- for (KotlinTypeReference nestedClass : nestedClasses) {
+ List<String> rewrittenNestedClasses = kmClass.getNestedClasses();
+ for (KotlinTypeReference nestedClass : this.nestedClasses) {
Box<String> nestedDescriptorBox = new Box<>();
boolean nestedClassRewritten =
nestedClass.toRenamedBinaryNameOrDefault(nestedDescriptorBox::set, appView, null);
@@ -386,20 +398,21 @@
// is the name we should record.
String nestedDescriptor = nestedDescriptorBox.get();
int innerClassIndex = nestedDescriptor.lastIndexOf(DescriptorUtils.INNER_CLASS_SEPARATOR);
- kmClass.visitNestedClass(nestedDescriptor.substring(innerClassIndex + 1));
+ rewrittenNestedClasses.add(nestedDescriptor.substring(innerClassIndex + 1));
} else {
- kmClass.visitNestedClass(nestedClass.getOriginalName());
+ rewrittenNestedClasses.add(nestedClass.getOriginalName());
}
}
rewritten |= nestedClassRewritten;
}
- // Rewrite sealed sub classes.
+ // Rewrite sealed sub-classes.
+ List<String> rewrittenSealedClasses = kmClass.getSealedSubclasses();
for (KotlinTypeReference sealedSubClass : sealedSubClasses) {
rewritten |=
sealedSubClass.toRenamedBinaryNameOrDefault(
sealedName -> {
if (sealedName != null) {
- kmClass.visitSealedSubclass(
+ rewrittenSealedClasses.add(
sealedName.replace(
DescriptorUtils.INNER_CLASS_SEPARATOR,
DescriptorUtils.JAVA_PACKAGE_SEPARATOR));
@@ -408,34 +421,36 @@
appView,
null);
}
- rewritten |= versionRequirements.rewrite(kmClass::visitVersionRequirement);
+ rewritten |= versionRequirements.rewrite(kmClass.getVersionRequirements()::addAll);
if (inlineClassUnderlyingPropertyName != null && inlineClassUnderlyingType != null) {
kmClass.setInlineClassUnderlyingPropertyName(inlineClassUnderlyingPropertyName);
rewritten |=
- inlineClassUnderlyingType.rewrite(kmClass::visitInlineClassUnderlyingType, appView);
+ inlineClassUnderlyingType.rewrite(kmClass::setInlineClassUnderlyingType, appView);
}
- JvmClassExtensionVisitor extensionVisitor =
- (JvmClassExtensionVisitor) kmClass.visitExtensions(JvmClassExtensionVisitor.TYPE);
- extensionVisitor.visitJvmFlags(jvmFlags);
- extensionVisitor.visitModuleName(moduleName);
+ rewritten |=
+ rewriteList(
+ appView,
+ contextReceiverTypes,
+ kmClass.getContextReceiverTypes(),
+ KotlinTypeInfo::rewrite);
+ JvmExtensionsKt.setJvmFlags(kmClass, jvmFlags);
+ JvmExtensionsKt.setModuleName(kmClass, moduleName);
if (anonymousObjectOrigin != null) {
rewritten |=
anonymousObjectOrigin.toRenamedBinaryNameOrDefault(
renamedAnon -> {
if (renamedAnon != null) {
- extensionVisitor.visitAnonymousObjectOriginName(renamedAnon);
+ JvmExtensionsKt.setAnonymousObjectOriginName(kmClass, renamedAnon);
}
},
appView,
null);
}
rewritten |=
- localDelegatedProperties.rewrite(extensionVisitor::visitLocalDelegatedProperty, appView);
- extensionVisitor.visitEnd();
- KotlinClassMetadata.Class.Writer writer = new KotlinClassMetadata.Class.Writer();
- kmClass.accept(writer);
+ localDelegatedProperties.rewrite(
+ JvmExtensionsKt.getLocalDelegatedProperties(kmClass)::add, appView);
return Pair.create(
- writer.write().getHeader(),
+ Companion.writeClass(kmClass, getCompatibleKotlinInfo(), 0).getAnnotationData(),
rewritten || !originalMembersWithKotlinInfo.isEqual(rewrittenReferences, appView));
}
@@ -457,6 +472,7 @@
forEachApply(superTypes, type -> type::trace, definitionSupplier);
forEachApply(sealedSubClasses, sealedClass -> sealedClass::trace, definitionSupplier);
forEachApply(nestedClasses, nested -> nested::trace, definitionSupplier);
+ forEachApply(contextReceiverTypes, nested -> nested::trace, definitionSupplier);
localDelegatedProperties.trace(definitionSupplier);
// TODO(b/154347404): trace enum entries.
if (anonymousObjectOrigin != null) {
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassLevelInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassLevelInfo.java
index e8f7fd0..d634e88 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassLevelInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassLevelInfo.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Pair;
-import kotlinx.metadata.jvm.KotlinClassHeader;
+import kotlin.Metadata;
public interface KotlinClassLevelInfo extends EnqueuerMetadataTraceable {
@@ -56,7 +56,7 @@
return null;
}
- Pair<KotlinClassHeader, Boolean> rewrite(DexClass clazz, AppView<?> appView);
+ Pair<Metadata, Boolean> rewrite(DexClass clazz, AppView<?> appView);
String getPackageName();
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 eb07f4b..7bae38e 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
@@ -21,8 +21,8 @@
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.function.Consumer;
+import kotlin.Metadata;
import kotlinx.metadata.InconsistentKotlinMetadataException;
-import kotlinx.metadata.jvm.KotlinClassHeader;
import kotlinx.metadata.jvm.KotlinClassMetadata;
import kotlinx.metadata.jvm.KotlinClassMetadata.FileFacade;
import kotlinx.metadata.jvm.KotlinClassMetadata.MultiFileClassFacade;
@@ -121,8 +121,8 @@
Integer xi = extraInt == null ? null : (Integer) extraInt.value.getBoxedValue();
try {
- KotlinClassHeader header = new KotlinClassHeader(k, mv, d1, d2, xs, pn, xi);
- return KotlinClassMetadata.read(header);
+ return KotlinClassMetadata.read(
+ new KotlinMetadataAnnotationWrapper(k, mv, d1, d2, xs, pn, xi));
} catch (ClassCastException | InconsistentKotlinMetadataException | MetadataError e) {
throw new KotlinMetadataException(e);
}
@@ -142,8 +142,9 @@
KotlinClassMetadata kMetadata,
AppView<?> appView,
Consumer<DexEncodedMethod> keepByteCode) {
- String packageName = kMetadata.getHeader().getPackageName();
- int[] metadataVersion = kMetadata.getHeader().getMetadataVersion();
+ Metadata annotationData = kMetadata.getAnnotationData();
+ String packageName = annotationData.pn();
+ int[] metadataVersion = annotationData.mv();
if (kMetadata instanceof KotlinClassMetadata.Class) {
return KotlinClassInfo.create(
(KotlinClassMetadata.Class) kMetadata,
@@ -178,7 +179,7 @@
kotlin,
appView);
} else {
- throw new MetadataError("unsupported 'k' value: " + kMetadata.getHeader().getKind());
+ throw new MetadataError("unsupported 'k' value: " + annotationData.k());
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinConstructorInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinConstructorInfo.java
index 4c93733..c8dac29 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinConstructorInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinConstructorInfo.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteList;
import static com.android.tools.r8.utils.FunctionUtils.forEachApply;
import com.android.tools.r8.graph.AppView;
@@ -67,10 +68,13 @@
method,
appView);
}
- for (KotlinValueParameterInfo valueParameterInfo : valueParameters) {
- rewritten |= valueParameterInfo.rewrite(kmConstructor::visitValueParameter, appView);
- }
- rewritten |= versionRequirements.rewrite(kmConstructor::visitVersionRequirement);
+ rewritten |=
+ rewriteList(
+ appView,
+ valueParameters,
+ kmConstructor.getValueParameters(),
+ KotlinValueParameterInfo::rewrite);
+ rewritten |= versionRequirements.rewrite(kmConstructor.getVersionRequirements()::addAll);
kmClass.getConstructors().add(kmConstructor);
return rewritten;
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinContractInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinContractInfo.java
index c437bba..57466ae 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinContractInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinContractInfo.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.consume;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteList;
import static com.android.tools.r8.utils.FunctionUtils.forEachApply;
import com.android.tools.r8.graph.AppView;
@@ -13,8 +15,8 @@
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
import java.util.List;
+import java.util.function.Consumer;
import kotlinx.metadata.KmContract;
-import kotlinx.metadata.KmContractVisitor;
import kotlinx.metadata.KmEffect;
public class KotlinContractInfo implements EnqueuerMetadataTraceable {
@@ -48,17 +50,11 @@
forEachApply(effects, effect -> effect::trace, definitionSupplier);
}
- boolean rewrite(
- KmVisitorProviders.KmContractVisitorProvider visitorProvider, AppView<?> appView) {
+ boolean rewrite(Consumer<KmContract> consumer, AppView<?> appView) {
if (this == NO_EFFECT) {
return false;
}
- boolean rewritten = false;
- KmContractVisitor kmContractVisitor = visitorProvider.get();
- for (KotlinEffectInfo effect : effects) {
- rewritten |= effect.rewrite(kmContractVisitor::visitEffect, appView);
- }
- kmContractVisitor.visitEnd();
- return rewritten;
+ KmContract kmContract = consume(new KmContract(), consumer);
+ return rewriteList(appView, effects, kmContract.getEffects(), KotlinEffectInfo::rewrite);
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
index 9307053..9abed29 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.kotlin;
import static com.android.tools.r8.kotlin.KotlinMetadataUtils.isValidMethodDescriptor;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteList;
import static com.android.tools.r8.kotlin.KotlinMetadataUtils.toDefaultJvmMethodSignature;
import static com.android.tools.r8.utils.FunctionUtils.forEachApply;
@@ -179,17 +180,15 @@
}
boolean rewrite(
- KmVisitorProviders.KmFunctionVisitorProvider functionProvider,
- KmVisitorProviders.KmPropertyVisitorProvider propertyProvider,
- KmVisitorProviders.KmTypeAliasVisitorProvider typeAliasProvider,
+ Consumer<KmFunction> functionConsumer,
+ Consumer<KmProperty> propertyConsumer,
+ Consumer<KmTypeAlias> typeAliasConsumer,
DexClass clazz,
AppView<?> appView,
KotlinMetadataMembersTracker rewrittenMembersWithKotlinInfo) {
// Type aliases only have a representation here, so we can generate them directly.
- boolean rewritten = false;
- for (KotlinTypeAliasInfo typeAlias : typeAliases) {
- rewritten |= typeAlias.rewrite(typeAliasProvider, appView);
- }
+ boolean rewritten =
+ rewriteList(appView, typeAliases, typeAliasConsumer, KotlinTypeAliasInfo::rewrite);
// For properties, we need to combine potentially a field, setter and getter.
Map<KotlinPropertyInfo, KotlinPropertyGroup> properties = new LinkedHashMap<>();
for (DexEncodedField field : clazz.fields()) {
@@ -203,7 +202,7 @@
}
for (DexEncodedMethod method : clazz.methods()) {
if (method.getKotlinInfo().isFunction()) {
- rewritten |= method.getKotlinInfo().asFunction().rewrite(functionProvider, method, appView);
+ rewritten |= method.getKotlinInfo().asFunction().rewrite(functionConsumer, method, appView);
rewrittenMembersWithKotlinInfo.add(method.getReference());
continue;
}
@@ -225,19 +224,25 @@
KotlinPropertyGroup kotlinPropertyGroup = properties.get(kotlinPropertyInfo);
rewritten |=
kotlinPropertyInfo.rewrite(
- propertyProvider,
+ propertyConsumer,
kotlinPropertyGroup.backingField,
kotlinPropertyGroup.getter,
kotlinPropertyGroup.setter,
appView);
}
// Add all not backed functions and properties.
- for (KotlinFunctionInfo notBackedFunction : functionsWithNoBacking) {
- rewritten |= notBackedFunction.rewrite(functionProvider, null, appView);
- }
- for (KotlinPropertyInfo notBackedProperty : propertiesWithNoBacking) {
- rewritten |= notBackedProperty.rewrite(propertyProvider, null, null, null, appView);
- }
+ rewritten |=
+ rewriteList(
+ appView,
+ functionsWithNoBacking,
+ functionConsumer,
+ KotlinFunctionInfo::rewriteNoBacking);
+ rewritten |=
+ rewriteList(
+ appView,
+ propertiesWithNoBacking,
+ propertyConsumer,
+ KotlinPropertyInfo::rewriteNoBacking);
return rewritten;
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinEffectExpressionInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinEffectExpressionInfo.java
index 18afe26..4268f32 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinEffectExpressionInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinEffectExpressionInfo.java
@@ -4,19 +4,21 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.consume;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteIfNotNull;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteList;
import static com.android.tools.r8.utils.FunctionUtils.forEachApply;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.kotlin.KmVisitorProviders.KmEffectExpressionVisitorProvider;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
import java.util.List;
+import java.util.function.Consumer;
import kotlinx.metadata.KmConstantValue;
import kotlinx.metadata.KmEffectExpression;
-import kotlinx.metadata.KmEffectExpressionVisitor;
public class KotlinEffectExpressionInfo implements EnqueuerMetadataTraceable {
@@ -84,26 +86,31 @@
forEachApply(orArguments, arg -> arg::trace, definitionSupplier);
}
- boolean rewrite(KmEffectExpressionVisitorProvider provider, AppView<?> appView) {
+ boolean rewrite(Consumer<KmEffectExpression> consumer, AppView<?> appView) {
if (this == NO_EXPRESSION) {
return false;
}
- KmEffectExpressionVisitor visitor = provider.get();
- visitor.visit(flags, parameterIndex);
+ KmEffectExpression effectExpression = consume(new KmEffectExpression(), consumer);
+ effectExpression.setFlags(flags);
+ effectExpression.setParameterIndex(parameterIndex);
if (constantValue != null) {
- visitor.visitConstantValue(constantValue.getValue());
+ effectExpression.setConstantValue(constantValue);
}
- boolean rewritten = false;
- if (isInstanceType != null) {
- rewritten |= isInstanceType.rewrite(visitor::visitIsInstanceType, appView);
- }
- for (KotlinEffectExpressionInfo andArgument : andArguments) {
- rewritten |= andArgument.rewrite(visitor::visitAndArgument, appView);
- }
- for (KotlinEffectExpressionInfo orArgument : orArguments) {
- rewritten |= orArgument.rewrite(visitor::visitAndArgument, appView);
- }
- visitor.visitEnd();
+ boolean rewritten =
+ rewriteIfNotNull(
+ appView, isInstanceType, effectExpression::setInstanceType, KotlinTypeInfo::rewrite);
+ rewritten |=
+ rewriteList(
+ appView,
+ andArguments,
+ effectExpression.getAndArguments(),
+ KotlinEffectExpressionInfo::rewrite);
+ rewritten |=
+ rewriteList(
+ appView,
+ orArguments,
+ effectExpression.getOrArguments(),
+ KotlinEffectExpressionInfo::rewrite);
return rewritten;
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinEffectInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinEffectInfo.java
index e93b126..4f38113 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinEffectInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinEffectInfo.java
@@ -4,19 +4,20 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.consume;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteList;
import static com.android.tools.r8.utils.FunctionUtils.forEachApply;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.kotlin.KmVisitorProviders.KmEffectVisitorProvider;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
import java.util.List;
+import java.util.function.Consumer;
import kotlinx.metadata.KmEffect;
import kotlinx.metadata.KmEffectInvocationKind;
import kotlinx.metadata.KmEffectType;
-import kotlinx.metadata.KmEffectVisitor;
public class KotlinEffectInfo implements EnqueuerMetadataTraceable {
@@ -50,14 +51,15 @@
conclusion.trace(definitionSupplier);
}
- boolean rewrite(KmEffectVisitorProvider visitorProvider, AppView<?> appView) {
- KmEffectVisitor kmEffectVisitor = visitorProvider.get(type, invocationKind);
- boolean rewritten =
- conclusion.rewrite(kmEffectVisitor::visitConclusionOfConditionalEffect, appView);
- for (KotlinEffectExpressionInfo constructorArgument : constructorArguments) {
- rewritten |= constructorArgument.rewrite(kmEffectVisitor::visitConstructorArgument, appView);
- }
- kmEffectVisitor.visitEnd();
+ boolean rewrite(Consumer<KmEffect> consumer, AppView<?> appView) {
+ KmEffect kmEffect = consume(new KmEffect(type, invocationKind), consumer);
+ boolean rewritten = conclusion.rewrite(kmEffect::setConclusion, appView);
+ rewritten |=
+ rewriteList(
+ appView,
+ constructorArguments,
+ kmEffect.getConstructorArguments(),
+ KotlinEffectExpressionInfo::rewrite);
return rewritten;
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java
index 3daa33d..59e482f 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java
@@ -4,15 +4,17 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.getCompatibleKotlinInfo;
+import static kotlinx.metadata.jvm.KotlinClassMetadata.Companion;
+
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.utils.Pair;
import java.util.function.Consumer;
+import kotlin.Metadata;
import kotlinx.metadata.KmPackage;
-import kotlinx.metadata.jvm.KotlinClassHeader;
-import kotlinx.metadata.jvm.KotlinClassMetadata;
import kotlinx.metadata.jvm.KotlinClassMetadata.FileFacade;
// Holds information about Metadata.FileFacade
@@ -57,12 +59,12 @@
}
@Override
- public Pair<KotlinClassHeader, Boolean> rewrite(DexClass clazz, AppView<?> appView) {
+ public Pair<Metadata, Boolean> rewrite(DexClass clazz, AppView<?> appView) {
KmPackage kmPackage = new KmPackage();
boolean rewritten = packageInfo.rewrite(kmPackage, clazz, appView);
- KotlinClassMetadata.FileFacade.Writer writer = new KotlinClassMetadata.FileFacade.Writer();
- kmPackage.accept(writer);
- return Pair.create(writer.write().getHeader(), rewritten);
+ return Pair.create(
+ Companion.writeFileFacade(kmPackage, getCompatibleKotlinInfo(), 0).getAnnotationData(),
+ rewritten);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinFlexibleTypeUpperBoundInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinFlexibleTypeUpperBoundInfo.java
index 35e52f5..1edbe51 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinFlexibleTypeUpperBoundInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinFlexibleTypeUpperBoundInfo.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
+import java.util.function.Consumer;
import kotlinx.metadata.KmFlexibleTypeUpperBound;
public class KotlinFlexibleTypeUpperBoundInfo implements EnqueuerMetadataTraceable {
@@ -37,8 +38,7 @@
KotlinTypeInfo.create(flexibleTypeUpperBound.getType(), factory, reporter));
}
- boolean rewrite(
- KmVisitorProviders.KmFlexibleUpperBoundVisitorProvider visitorProvider, AppView<?> appView) {
+ boolean rewrite(Consumer<KmFlexibleTypeUpperBound> consumer, AppView<?> appView) {
if (this == NO_FLEXIBLE_UPPER_BOUND) {
// Nothing to do.
return false;
@@ -47,7 +47,9 @@
assert false;
return false;
}
- return kotlinTypeInfo.rewrite(flags -> visitorProvider.get(flags, typeFlexibilityId), appView);
+ return kotlinTypeInfo.rewrite(
+ kmType -> consumer.accept(new KmFlexibleTypeUpperBound(kmType, typeFlexibilityId)),
+ appView);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java
index f5b40c2..351acc9 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java
@@ -4,18 +4,21 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.consume;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteIfNotNull;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteList;
import static com.android.tools.r8.utils.FunctionUtils.forEachApply;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Reporter;
import java.util.List;
+import java.util.function.Consumer;
import kotlinx.metadata.KmFunction;
-import kotlinx.metadata.KmFunctionVisitor;
import kotlinx.metadata.jvm.JvmExtensionsKt;
-import kotlinx.metadata.jvm.JvmFunctionExtensionVisitor;
// Holds information about KmFunction
public final class KotlinFunctionInfo implements KotlinMethodLevelInfo {
@@ -41,6 +44,8 @@
private final KotlinContractInfo contract;
// A value describing if any of the parameters are crossinline.
private final boolean crossInlineParameter;
+ // Collection of context receiver types
+ private final List<KotlinTypeInfo> contextReceiverTypes;
private KotlinFunctionInfo(
int flags,
@@ -53,7 +58,8 @@
KotlinTypeReference lambdaClassOrigin,
KotlinVersionRequirementInfo versionRequirements,
KotlinContractInfo contract,
- boolean crossInlineParameter) {
+ boolean crossInlineParameter,
+ List<KotlinTypeInfo> contextReceiverTypes) {
this.flags = flags;
this.name = name;
this.returnType = returnType;
@@ -65,6 +71,7 @@
this.versionRequirements = versionRequirements;
this.contract = contract;
this.crossInlineParameter = crossInlineParameter;
+ this.contextReceiverTypes = contextReceiverTypes;
}
public boolean hasCrossInlineParameter() {
@@ -98,7 +105,10 @@
getlambdaClassOrigin(kmFunction, factory),
KotlinVersionRequirementInfo.create(kmFunction.getVersionRequirements()),
KotlinContractInfo.create(kmFunction.getContract(), factory, reporter),
- isCrossInline);
+ isCrossInline,
+ ListUtils.map(
+ kmFunction.getContextReceiverTypes(),
+ contextRecieverType -> KotlinTypeInfo.create(contextRecieverType, factory, reporter)));
}
private static KotlinTypeReference getlambdaClassOrigin(
@@ -115,10 +125,11 @@
return name;
}
- boolean rewrite(
- KmVisitorProviders.KmFunctionVisitorProvider visitorProvider,
- DexEncodedMethod method,
- AppView<?> appView) {
+ boolean rewriteNoBacking(Consumer<KmFunction> consumer, AppView<?> appView) {
+ return rewrite(consumer, null, appView);
+ }
+
+ boolean rewrite(Consumer<KmFunction> consumer, DexEncodedMethod method, AppView<?> appView) {
// TODO(b/154348683): Check method for flags to pass in.
boolean rewritten = false;
String finalName = name;
@@ -132,36 +143,51 @@
finalName = rewrittenName;
}
}
- KmFunctionVisitor kmFunction = visitorProvider.get(flags, finalName);
+ KmFunction kmFunction = consume(new KmFunction(flags, finalName), consumer);
// TODO(b/154348149): ReturnType could have been merged to a subtype.
- rewritten |= returnType.rewrite(kmFunction::visitReturnType, appView);
- for (KotlinValueParameterInfo valueParameterInfo : valueParameters) {
- rewritten |= valueParameterInfo.rewrite(kmFunction::visitValueParameter, appView);
+ rewritten |= returnType.rewrite(kmFunction::setReturnType, appView);
+ rewritten |=
+ rewriteList(
+ appView,
+ valueParameters,
+ kmFunction.getValueParameters(),
+ KotlinValueParameterInfo::rewrite);
+ rewritten |=
+ rewriteList(
+ appView,
+ typeParameters,
+ kmFunction.getTypeParameters(),
+ KotlinTypeParameterInfo::rewrite);
+ rewritten |=
+ rewriteList(
+ appView,
+ contextReceiverTypes,
+ kmFunction.getContextReceiverTypes(),
+ KotlinTypeInfo::rewrite);
+ rewritten |=
+ rewriteIfNotNull(
+ appView,
+ receiverParameterType,
+ kmFunction::setReceiverParameterType,
+ KotlinTypeInfo::rewrite);
+ rewritten |= versionRequirements.rewrite(kmFunction.getVersionRequirements()::addAll);
+ if (signature != null) {
+ rewritten |=
+ signature.rewrite(
+ signature -> JvmExtensionsKt.setSignature(kmFunction, signature), method, appView);
}
- for (KotlinTypeParameterInfo typeParameterInfo : typeParameters) {
- rewritten |= typeParameterInfo.rewrite(kmFunction::visitTypeParameter, appView);
- }
- if (receiverParameterType != null) {
- rewritten |= receiverParameterType.rewrite(kmFunction::visitReceiverParameterType, appView);
- }
- rewritten |= versionRequirements.rewrite(kmFunction::visitVersionRequirement);
- JvmFunctionExtensionVisitor extensionVisitor =
- (JvmFunctionExtensionVisitor) kmFunction.visitExtensions(JvmFunctionExtensionVisitor.TYPE);
- if (signature != null && extensionVisitor != null) {
- rewritten |= signature.rewrite(extensionVisitor::visit, method, appView);
- }
- if (lambdaClassOrigin != null && extensionVisitor != null) {
+ if (lambdaClassOrigin != null) {
rewritten |=
lambdaClassOrigin.toRenamedBinaryNameOrDefault(
lambdaClassOriginName -> {
if (lambdaClassOriginName != null) {
- extensionVisitor.visitLambdaClassOriginName(lambdaClassOriginName);
+ JvmExtensionsKt.setLambdaClassOriginName(kmFunction, lambdaClassOriginName);
}
},
appView,
null);
}
- rewritten |= contract.rewrite(kmFunction::visitContract, appView);
+ rewritten |= contract.rewrite(kmFunction::setContract, appView);
return rewritten;
}
@@ -187,6 +213,7 @@
receiverParameterType.trace(definitionSupplier);
}
forEachApply(typeParameters, param -> param::trace, definitionSupplier);
+ forEachApply(contextReceiverTypes, type -> type::trace, definitionSupplier);
if (signature != null) {
signature.trace(definitionSupplier);
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java
index 2760ece..2c5e817 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java
@@ -70,6 +70,10 @@
return new KotlinJvmMethodSignatureInfo(name, returnType, parameters.build());
}
+ boolean rewriteNoBacking(Consumer<JvmMethodSignature> consumer, AppView<?> appView) {
+ return rewrite(consumer, null, appView);
+ }
+
boolean rewrite(
Consumer<JvmMethodSignature> consumer, DexEncodedMethod method, AppView<?> appView) {
if (invalidDescriptor != null) {
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java
index ffe08b4..9900e81 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.consume;
import static com.android.tools.r8.kotlin.KotlinMetadataUtils.toJvmMethodSignature;
import com.android.tools.r8.graph.AppView;
@@ -13,6 +14,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
+import java.util.function.Consumer;
import kotlinx.metadata.KmLambda;
import kotlinx.metadata.jvm.JvmExtensionsKt;
import kotlinx.metadata.jvm.JvmMethodSignature;
@@ -56,12 +58,10 @@
return new KotlinLambdaInfo(kotlinFunctionInfo, false);
}
- boolean rewrite(
- KmVisitorProviders.KmLambdaVisitorProvider visitorProvider,
- DexClass clazz,
- AppView<?> appView) {
+ boolean rewrite(Consumer<KmLambda> consumer, DexClass clazz, AppView<?> appView) {
+ KmLambda kmLambda = consume(new KmLambda(), consumer);
if (!hasBacking) {
- function.rewrite(visitorProvider.get()::visitFunction, null, appView);
+ function.rewrite(kmLambda::setFunction, null, appView);
return true;
}
DexEncodedMethod backing = null;
@@ -71,7 +71,7 @@
break;
}
}
- return function.rewrite(visitorProvider.get()::visitFunction, backing, appView);
+ return function.rewrite(kmLambda::setFunction, backing, appView);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinLocalDelegatedPropertyInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinLocalDelegatedPropertyInfo.java
index 4bdce09..9fb8b43 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinLocalDelegatedPropertyInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinLocalDelegatedPropertyInfo.java
@@ -4,16 +4,17 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteList;
import static com.android.tools.r8.utils.FunctionUtils.forEachApply;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.kotlin.KmVisitorProviders.KmPropertyVisitorProvider;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
import java.util.List;
+import java.util.function.Consumer;
import kotlinx.metadata.KmProperty;
public class KotlinLocalDelegatedPropertyInfo implements EnqueuerMetadataTraceable {
@@ -51,11 +52,7 @@
forEachApply(propertyInfos, prop -> prop::trace, definitionSupplier);
}
- boolean rewrite(KmPropertyVisitorProvider visitorProvider, AppView<?> appView) {
- boolean rewritten = false;
- for (KotlinPropertyInfo propertyInfo : propertyInfos) {
- rewritten |= propertyInfo.rewrite(visitorProvider, null, null, null, appView);
- }
- return rewritten;
+ boolean rewrite(Consumer<KmProperty> consumer, AppView<?> appView) {
+ return rewriteList(appView, propertyInfos, consumer, KotlinPropertyInfo::rewriteNoBacking);
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataAnnotationWrapper.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataAnnotationWrapper.java
new file mode 100644
index 0000000..efbe154
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataAnnotationWrapper.java
@@ -0,0 +1,123 @@
+// Copyright (c) 2023, 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;
+
+import com.android.tools.r8.errors.Unreachable;
+import java.lang.annotation.Annotation;
+import kotlin.Metadata;
+import kotlinx.metadata.jvm.KotlinClassMetadata;
+
+/***
+ * This is a wrapper around kotlin.Metadata needed for tests to access the internal data. The need
+ * for the wrapper comes from R8 relocating kotlin.* to com.android.tools.r8.kotlin.* in R8lib but
+ * not in tests, so kotlin.Metadata cannot cross the boundary.
+ *
+ * Additionally, it is also used for passing in an instance of kotlin.Metadata which cannot be
+ * instantiated from Java.
+ */
+public class KotlinMetadataAnnotationWrapper implements kotlin.Metadata {
+
+ private static final String[] NULL_STRING_ARRAY = new String[0];
+ private static final int[] NULL_INT_ARRAY = new int[0];
+
+ private final int kind;
+ private final int[] metadataVersion;
+ private final String[] data1;
+ private final String[] data2;
+ private final int extraInt;
+ private final String extraString;
+ private final String packageName;
+
+ public KotlinMetadataAnnotationWrapper(
+ Integer kind,
+ int[] metadataVersion,
+ String[] data1,
+ String[] data2,
+ String extraString,
+ String packageName,
+ Integer extraInt) {
+ // The default values here are taking from the constructor of KotlinClassHeader.
+ this.kind = kind == null ? 1 : kind;
+ this.metadataVersion = metadataVersion == null ? NULL_INT_ARRAY : metadataVersion;
+ this.data1 = data1 == null ? NULL_STRING_ARRAY : data1;
+ this.data2 = data2 == null ? NULL_STRING_ARRAY : data2;
+ this.extraString = extraString == null ? "" : extraString;
+ this.packageName = packageName == null ? "" : packageName;
+ this.extraInt = extraInt == null ? 0 : extraInt;
+ }
+
+ public static KotlinMetadataAnnotationWrapper wrap(KotlinClassMetadata classMetadata) {
+ Metadata annotationData = classMetadata.getAnnotationData();
+ return new KotlinMetadataAnnotationWrapper(
+ annotationData.k(),
+ annotationData.mv(),
+ annotationData.d1(),
+ annotationData.d2(),
+ annotationData.xs(),
+ annotationData.pn(),
+ annotationData.xi());
+ }
+
+ public int kind() {
+ return kind;
+ }
+
+ public String[] data1() {
+ return data1;
+ }
+
+ public String[] data2() {
+ return data2;
+ }
+
+ public String packageName() {
+ return pn();
+ }
+
+ @Override
+ public int[] bv() {
+ throw new Unreachable("Field is deprecated and should not be used");
+ }
+
+ @Override
+ public String[] d1() {
+ return data1;
+ }
+
+ @Override
+ public String[] d2() {
+ return data2;
+ }
+
+ @Override
+ public int xi() {
+ return extraInt;
+ }
+
+ @Override
+ public String xs() {
+ return extraString;
+ }
+
+ @Override
+ public int k() {
+ return kind;
+ }
+
+ @Override
+ public int[] mv() {
+ return metadataVersion;
+ }
+
+ @Override
+ public String pn() {
+ return packageName;
+ }
+
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ throw new Unreachable("Should never be called");
+ }
+}
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 c06aea8..e57fc63 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
@@ -27,7 +27,6 @@
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
-import kotlinx.metadata.jvm.KotlinClassHeader;
public class KotlinMetadataRewriter {
@@ -155,17 +154,16 @@
DexAnnotation oldMeta,
WriteMetadataFieldInfo writeMetadataFieldInfo) {
try {
- Pair<KotlinClassHeader, Boolean> kotlinClassHeader = kotlinInfo.rewrite(clazz, appView);
+ Pair<kotlin.Metadata, Boolean> kotlinMetadata = kotlinInfo.rewrite(clazz, appView);
// TODO(b/185756596): Remove when special handling is no longer needed.
- if (!kotlinClassHeader.getSecond()
- && appView.options().testing.keepMetadataInR8IfNotRewritten) {
+ if (!kotlinMetadata.getSecond() && appView.options().testing.keepMetadataInR8IfNotRewritten) {
// No rewrite occurred and the data is the same as before.
assert appView.checkForTesting(
() ->
verifyRewrittenMetadataIsEquivalent(
clazz.annotations().getFirstMatching(factory.kotlinMetadataType),
createKotlinMetadataAnnotation(
- kotlinClassHeader.getFirst(),
+ kotlinMetadata.getFirst(),
kotlinInfo.getPackageName(),
getMaxVersion(METADATA_VERSION_1_4, kotlinInfo.getMetadataVersion()),
writeMetadataFieldInfo)));
@@ -173,7 +171,7 @@
}
DexAnnotation newMeta =
createKotlinMetadataAnnotation(
- kotlinClassHeader.getFirst(),
+ kotlinMetadata.getFirst(),
kotlinInfo.getPackageName(),
getMaxVersion(METADATA_VERSION_1_4, kotlinInfo.getMetadataVersion()),
writeMetadataFieldInfo);
@@ -222,7 +220,7 @@
}
private DexAnnotation createKotlinMetadataAnnotation(
- KotlinClassHeader header,
+ kotlin.Metadata metadata,
String packageName,
int[] metadataVersion,
WriteMetadataFieldInfo writeMetadataFieldInfo) {
@@ -234,31 +232,30 @@
}
if (writeMetadataFieldInfo.writeKind) {
elements.add(
- new DexAnnotationElement(kotlin.metadata.kind, DexValueInt.create(header.getKind())));
+ new DexAnnotationElement(kotlin.metadata.kind, DexValueInt.create(metadata.k())));
}
if (writeMetadataFieldInfo.writeData1) {
elements.add(
- new DexAnnotationElement(kotlin.metadata.data1, createStringArray(header.getData1())));
+ new DexAnnotationElement(kotlin.metadata.data1, createStringArray(metadata.d1())));
}
if (writeMetadataFieldInfo.writeData2) {
elements.add(
- new DexAnnotationElement(kotlin.metadata.data2, createStringArray(header.getData2())));
+ new DexAnnotationElement(kotlin.metadata.data2, createStringArray(metadata.d2())));
}
if (writeMetadataFieldInfo.writePackageName && packageName != null && !packageName.isEmpty()) {
elements.add(
new DexAnnotationElement(
kotlin.metadata.packageName, new DexValueString(factory.createString(packageName))));
}
- if (writeMetadataFieldInfo.writeExtraString && !header.getExtraString().isEmpty()) {
+ if (writeMetadataFieldInfo.writeExtraString && !metadata.xs().isEmpty()) {
elements.add(
new DexAnnotationElement(
kotlin.metadata.extraString,
- new DexValueString(factory.createString(header.getExtraString()))));
+ new DexValueString(factory.createString(metadata.xs()))));
}
- if (writeMetadataFieldInfo.writeExtraInt && header.getExtraInt() != 0) {
+ if (writeMetadataFieldInfo.writeExtraInt && metadata.xi() != 0) {
elements.add(
- new DexAnnotationElement(
- kotlin.metadata.extraInt, DexValueInt.create(header.getExtraInt())));
+ new DexAnnotationElement(kotlin.metadata.extraInt, DexValueInt.create(metadata.xi())));
}
DexEncodedAnnotation encodedAnnotation =
new DexEncodedAnnotation(
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java
index d5884f5..67a900a 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java
@@ -20,7 +20,11 @@
import com.android.tools.r8.shaking.ProguardKeepRuleType;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.Pair;
+import com.android.tools.r8.utils.TriFunction;
import com.google.common.base.Strings;
+import java.util.List;
+import java.util.function.Consumer;
+import kotlin.Metadata;
import kotlinx.metadata.KmExtensionType;
import kotlinx.metadata.KmProperty;
import kotlinx.metadata.KmPropertyExtensionVisitor;
@@ -28,7 +32,7 @@
import kotlinx.metadata.jvm.JvmFieldSignature;
import kotlinx.metadata.jvm.JvmMethodSignature;
import kotlinx.metadata.jvm.JvmPropertyExtensionVisitor;
-import kotlinx.metadata.jvm.KotlinClassHeader;
+import kotlinx.metadata.jvm.KotlinClassMetadata;
public class KotlinMetadataUtils {
@@ -50,7 +54,7 @@
}
@Override
- public Pair<KotlinClassHeader, Boolean> rewrite(DexClass clazz, AppView<?> appView) {
+ public Pair<Metadata, Boolean> rewrite(DexClass clazz, AppView<?> appView) {
throw new Unreachable("Should never be called");
}
@@ -232,4 +236,42 @@
}
return DescriptorUtils.descriptorToKotlinClassifier(descriptor);
}
+
+ static int[] getCompatibleKotlinInfo() {
+ return KotlinClassMetadata.COMPATIBLE_METADATA_VERSION;
+ }
+
+ static <TKm> TKm consume(TKm tKm, Consumer<TKm> consumer) {
+ consumer.accept(tKm);
+ return tKm;
+ }
+
+ static <TInfo, TKm> boolean rewriteIfNotNull(
+ AppView<?> appView,
+ TInfo info,
+ Consumer<TKm> newTConsumer,
+ TriFunction<TInfo, Consumer<TKm>, AppView<?>, Boolean> rewrite) {
+ return info != null ? rewrite.apply(info, newTConsumer, appView) : false;
+ }
+
+ static <TInfo, TKm> boolean rewriteList(
+ AppView<?> appView,
+ List<TInfo> ts,
+ List<TKm> newTs,
+ TriFunction<TInfo, Consumer<TKm>, AppView<?>, Boolean> rewrite) {
+ assert newTs.isEmpty();
+ return rewriteList(appView, ts, newTs::add, rewrite);
+ }
+
+ static <TInfo, TKm> boolean rewriteList(
+ AppView<?> appView,
+ List<TInfo> ts,
+ Consumer<TKm> newTConsumer,
+ TriFunction<TInfo, Consumer<TKm>, AppView<?>, Boolean> rewrite) {
+ boolean rewritten = false;
+ for (TInfo t : ts) {
+ rewritten |= rewrite.apply(t, newTConsumer, appView);
+ }
+ return rewritten;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataWriter.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataWriter.java
index 1e4d633..dfb5d76 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataWriter.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataWriter.java
@@ -379,20 +379,31 @@
indent,
"constructors",
sb,
- newIndent -> {
- appendKmList(
- newIndent,
- "KmConstructor",
- sb,
- kmClass.getConstructors().stream()
- .sorted(
- Comparator.comparing(
- kmConstructor -> JvmExtensionsKt.getSignature(kmConstructor).asString()))
- .collect(Collectors.toList()),
- (nextIndent, constructor) -> {
- appendKmConstructor(nextIndent, sb, constructor);
- });
- });
+ newIndent ->
+ appendKmList(
+ newIndent,
+ "KmConstructor",
+ sb,
+ kmClass.getConstructors().stream()
+ .sorted(
+ Comparator.comparing(
+ kmConstructor ->
+ JvmExtensionsKt.getSignature(kmConstructor).asString()))
+ .collect(Collectors.toList()),
+ (nextIndent, constructor) -> {
+ appendKmConstructor(nextIndent, sb, constructor);
+ }));
+ appendKeyValue(
+ indent,
+ "contextReceiverTypes",
+ sb,
+ newIndent ->
+ appendKmList(
+ newIndent,
+ "KmType",
+ sb,
+ kmClass.getContextReceiverTypes(),
+ (nextIndent, kmType) -> appendKmType(nextIndent, sb, kmType)));
appendKmDeclarationContainer(indent, sb, kmClass);
}
@@ -458,6 +469,17 @@
appendKmContract(nextIndent, sb, contract);
});
}
+ appendKeyValue(
+ newIndent,
+ "contextReceiverTypes",
+ sb,
+ newNewIndent ->
+ appendKmList(
+ newNewIndent,
+ "KmType",
+ sb,
+ function.getContextReceiverTypes(),
+ (nextIndent, kmType) -> appendKmType(nextIndent, sb, kmType)));
JvmMethodSignature signature = JvmExtensionsKt.getSignature(function);
appendKeyValue(
newIndent, "signature", sb, signature != null ? signature.asString() : "null");
@@ -500,6 +522,17 @@
sb,
nextIndent -> appendValueParameter(nextIndent, sb, kmProperty.getSetterParameter()));
appendKmVersionRequirement(newIndent, sb, kmProperty.getVersionRequirements());
+ appendKeyValue(
+ newIndent,
+ "contextReceiverTypes",
+ sb,
+ newNewIndent ->
+ appendKmList(
+ newNewIndent,
+ "KmType",
+ sb,
+ kmProperty.getContextReceiverTypes(),
+ (nextIndent, kmType) -> appendKmType(nextIndent, sb, kmType)));
appendKeyValue(newIndent, "jvmFlags", sb, JvmExtensionsKt.getJvmFlags(kmProperty) + "");
JvmFieldSignature fieldSignature = JvmExtensionsKt.getFieldSignature(kmProperty);
appendKeyValue(
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java
index 2a89998..7f0b67f 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java
@@ -4,7 +4,9 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.getCompatibleKotlinInfo;
import static com.android.tools.r8.utils.FunctionUtils.forEachApply;
+import static kotlinx.metadata.jvm.KotlinClassMetadata.Companion;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
@@ -14,8 +16,7 @@
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
-import kotlinx.metadata.jvm.KotlinClassHeader;
-import kotlinx.metadata.jvm.KotlinClassMetadata;
+import kotlin.Metadata;
import kotlinx.metadata.jvm.KotlinClassMetadata.MultiFileClassFacade;
// Holds information about Metadata.MultiFileClassFace
@@ -55,7 +56,7 @@
}
@Override
- public Pair<KotlinClassHeader, Boolean> rewrite(DexClass clazz, AppView<?> appView) {
+ public Pair<Metadata, Boolean> rewrite(DexClass clazz, AppView<?> appView) {
List<String> partClassNameStrings = new ArrayList<>(partClassNames.size());
boolean rewritten = false;
for (KotlinTypeReference partClassName : partClassNames) {
@@ -69,9 +70,10 @@
appView,
null);
}
- KotlinClassMetadata.MultiFileClassFacade.Writer writer =
- new KotlinClassMetadata.MultiFileClassFacade.Writer();
- return Pair.create(writer.write(partClassNameStrings).getHeader(), rewritten);
+ return Pair.create(
+ Companion.writeMultiFileClassFacade(partClassNameStrings, getCompatibleKotlinInfo(), 0)
+ .getAnnotationData(),
+ rewritten);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java
index 62460ae..a51defc 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java
@@ -4,15 +4,17 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.getCompatibleKotlinInfo;
+import static kotlinx.metadata.jvm.KotlinClassMetadata.Companion;
+
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.utils.Pair;
import java.util.function.Consumer;
+import kotlin.Metadata;
import kotlinx.metadata.KmPackage;
-import kotlinx.metadata.jvm.KotlinClassHeader;
-import kotlinx.metadata.jvm.KotlinClassMetadata;
import kotlinx.metadata.jvm.KotlinClassMetadata.MultiFileClassPart;
// Holds information about Metadata.MultiFileClassPartInfo
@@ -63,13 +65,13 @@
}
@Override
- public Pair<KotlinClassHeader, Boolean> rewrite(DexClass clazz, AppView<?> appView) {
+ public Pair<Metadata, Boolean> rewrite(DexClass clazz, AppView<?> appView) {
KmPackage kmPackage = new KmPackage();
boolean rewritten = packageInfo.rewrite(kmPackage, clazz, appView);
- KotlinClassMetadata.MultiFileClassPart.Writer writer =
- new KotlinClassMetadata.MultiFileClassPart.Writer();
- kmPackage.accept(writer);
- return Pair.create(writer.write(facadeClassName).getHeader(), rewritten);
+ return Pair.create(
+ Companion.writeMultiFileClassPart(kmPackage, facadeClassName, getCompatibleKotlinInfo(), 0)
+ .getAnnotationData(),
+ rewritten);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java
index a0f0e81..721cd75 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java
@@ -18,7 +18,6 @@
import java.util.function.Consumer;
import kotlinx.metadata.KmPackage;
import kotlinx.metadata.jvm.JvmExtensionsKt;
-import kotlinx.metadata.jvm.JvmPackageExtensionVisitor;
// Holds information about a KmPackage object.
public class KotlinPackageInfo implements EnqueuerMetadataTraceable {
@@ -77,18 +76,16 @@
KotlinMetadataMembersTracker rewrittenReferences = new KotlinMetadataMembersTracker(appView);
boolean rewritten =
containerInfo.rewrite(
- kmPackage::visitFunction,
- kmPackage::visitProperty,
- kmPackage::visitTypeAlias,
+ kmPackage.getFunctions()::add,
+ kmPackage.getProperties()::add,
+ kmPackage.getTypeAliases()::add,
clazz,
appView,
rewrittenReferences);
- JvmPackageExtensionVisitor extensionVisitor =
- (JvmPackageExtensionVisitor) kmPackage.visitExtensions(JvmPackageExtensionVisitor.TYPE);
rewritten |=
- localDelegatedProperties.rewrite(extensionVisitor::visitLocalDelegatedProperty, appView);
- extensionVisitor.visitModuleName(moduleName);
- extensionVisitor.visitEnd();
+ localDelegatedProperties.rewrite(
+ JvmExtensionsKt.getLocalDelegatedProperties(kmPackage)::add, appView);
+ JvmExtensionsKt.setModuleName(kmPackage, moduleName);
return rewritten || !originalMembersWithKotlinInfo.isEqual(rewrittenReferences, appView);
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinPropertyInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinPropertyInfo.java
index 6d10139..fc8e889 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinPropertyInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinPropertyInfo.java
@@ -4,6 +4,9 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.consume;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteIfNotNull;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteList;
import static com.android.tools.r8.utils.FunctionUtils.forEachApply;
import com.android.tools.r8.graph.AppView;
@@ -11,15 +14,12 @@
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.utils.Box;
+import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Reporter;
import java.util.List;
+import java.util.function.Consumer;
import kotlinx.metadata.KmProperty;
-import kotlinx.metadata.KmPropertyVisitor;
import kotlinx.metadata.jvm.JvmExtensionsKt;
-import kotlinx.metadata.jvm.JvmFieldSignature;
-import kotlinx.metadata.jvm.JvmMethodSignature;
-import kotlinx.metadata.jvm.JvmPropertyExtensionVisitor;
// Holds information about KmProperty
public class KotlinPropertyInfo implements KotlinFieldLevelInfo, KotlinMethodLevelInfo {
@@ -58,6 +58,8 @@
private final KotlinJvmMethodSignatureInfo syntheticMethodForAnnotations;
private final KotlinJvmMethodSignatureInfo syntheticMethodForDelegate;
+ // Collection of context receiver types
+ private final List<KotlinTypeInfo> contextReceiverTypes;
private KotlinPropertyInfo(
int flags,
@@ -74,7 +76,8 @@
KotlinJvmMethodSignatureInfo getterSignature,
KotlinJvmMethodSignatureInfo setterSignature,
KotlinJvmMethodSignatureInfo syntheticMethodForAnnotations,
- KotlinJvmMethodSignatureInfo syntheticMethodForDelegate) {
+ KotlinJvmMethodSignatureInfo syntheticMethodForDelegate,
+ List<KotlinTypeInfo> contextReceiverTypes) {
this.flags = flags;
this.getterFlags = getterFlags;
this.setterFlags = setterFlags;
@@ -90,6 +93,7 @@
this.setterSignature = setterSignature;
this.syntheticMethodForAnnotations = syntheticMethodForAnnotations;
this.syntheticMethodForDelegate = syntheticMethodForDelegate;
+ this.contextReceiverTypes = contextReceiverTypes;
}
public static KotlinPropertyInfo create(
@@ -113,7 +117,10 @@
KotlinJvmMethodSignatureInfo.create(
JvmExtensionsKt.getSyntheticMethodForAnnotations(kmProperty), factory),
KotlinJvmMethodSignatureInfo.create(
- JvmExtensionsKt.getSyntheticMethodForDelegate(kmProperty), factory));
+ JvmExtensionsKt.getSyntheticMethodForDelegate(kmProperty), factory),
+ ListUtils.map(
+ kmProperty.getContextReceiverTypes(),
+ contextRecieverType -> KotlinTypeInfo.create(contextRecieverType, factory, reporter)));
}
@Override
@@ -138,60 +145,81 @@
return setterSignature;
}
+ boolean rewriteNoBacking(Consumer<KmProperty> consumer, AppView<?> appView) {
+ return rewrite(consumer, null, null, null, appView);
+ }
+
boolean rewrite(
- KmVisitorProviders.KmPropertyVisitorProvider visitorProvider,
+ Consumer<KmProperty> consumer,
DexEncodedField field,
DexEncodedMethod getter,
DexEncodedMethod setter,
AppView<?> appView) {
// TODO(b/154348683): Flags again.
- KmPropertyVisitor kmProperty = visitorProvider.get(flags, name, getterFlags, setterFlags);
+ KmProperty kmProperty =
+ consume(new KmProperty(flags, name, getterFlags, setterFlags), consumer);
// TODO(b/154348149): ReturnType could have been merged to a subtype.
- boolean rewritten = false;
- if (returnType != null) {
- rewritten = returnType.rewrite(kmProperty::visitReturnType, appView);
+ boolean rewritten =
+ rewriteIfNotNull(appView, returnType, kmProperty::setReturnType, KotlinTypeInfo::rewrite);
+ rewritten |=
+ rewriteIfNotNull(
+ appView,
+ receiverParameterType,
+ kmProperty::setReceiverParameterType,
+ KotlinTypeInfo::rewrite);
+ rewritten |=
+ rewriteIfNotNull(
+ appView,
+ setterParameter,
+ kmProperty::setSetterParameter,
+ KotlinValueParameterInfo::rewrite);
+ rewritten |=
+ rewriteList(
+ appView,
+ typeParameters,
+ kmProperty.getTypeParameters(),
+ KotlinTypeParameterInfo::rewrite);
+ rewritten |=
+ rewriteList(
+ appView,
+ contextReceiverTypes,
+ kmProperty.getContextReceiverTypes(),
+ KotlinTypeInfo::rewrite);
+ rewritten |= versionRequirements.rewrite(kmProperty.getVersionRequirements()::addAll);
+ if (fieldSignature != null) {
+ rewritten |=
+ fieldSignature.rewrite(
+ newSignature -> JvmExtensionsKt.setFieldSignature(kmProperty, newSignature),
+ field,
+ appView);
}
- if (receiverParameterType != null) {
- rewritten |= receiverParameterType.rewrite(kmProperty::visitReceiverParameterType, appView);
+ if (getterSignature != null) {
+ rewritten |=
+ getterSignature.rewrite(
+ newSignature -> JvmExtensionsKt.setGetterSignature(kmProperty, newSignature),
+ getter,
+ appView);
}
- if (setterParameter != null) {
- rewritten |= setterParameter.rewrite(kmProperty::visitSetterParameter, appView);
+ if (setterSignature != null) {
+ rewritten |=
+ setterSignature.rewrite(
+ newSignature -> JvmExtensionsKt.setSetterSignature(kmProperty, newSignature),
+ setter,
+ appView);
}
- for (KotlinTypeParameterInfo typeParameter : typeParameters) {
- rewritten |= typeParameter.rewrite(kmProperty::visitTypeParameter, appView);
- }
- rewritten |= versionRequirements.rewrite(kmProperty::visitVersionRequirement);
- JvmPropertyExtensionVisitor extensionVisitor =
- (JvmPropertyExtensionVisitor) kmProperty.visitExtensions(JvmPropertyExtensionVisitor.TYPE);
- if (extensionVisitor != null) {
- Box<JvmFieldSignature> rewrittenFieldSignature = new Box<>();
- if (fieldSignature != null) {
- rewritten |= fieldSignature.rewrite(rewrittenFieldSignature::set, field, appView);
- }
- Box<JvmMethodSignature> rewrittenGetterSignature = new Box<>();
- if (getterSignature != null) {
- rewritten |= getterSignature.rewrite(rewrittenGetterSignature::set, getter, appView);
- }
- Box<JvmMethodSignature> rewrittenSetterSignature = new Box<>();
- if (setterSignature != null) {
- rewritten |= setterSignature.rewrite(rewrittenSetterSignature::set, setter, appView);
- }
- extensionVisitor.visit(
- jvmFlags,
- rewrittenFieldSignature.get(),
- rewrittenGetterSignature.get(),
- rewrittenSetterSignature.get());
- if (syntheticMethodForAnnotations != null) {
- rewritten |=
- syntheticMethodForAnnotations.rewrite(
- extensionVisitor::visitSyntheticMethodForAnnotations, null, appView);
- }
- if (syntheticMethodForDelegate != null) {
- rewritten |=
- syntheticMethodForDelegate.rewrite(
- extensionVisitor::visitSyntheticMethodForDelegate, null, appView);
- }
- }
+ JvmExtensionsKt.setJvmFlags(kmProperty, jvmFlags);
+ rewritten |=
+ rewriteIfNotNull(
+ appView,
+ syntheticMethodForAnnotations,
+ newMethod -> JvmExtensionsKt.setSyntheticMethodForAnnotations(kmProperty, newMethod),
+ KotlinJvmMethodSignatureInfo::rewriteNoBacking);
+ rewritten |=
+ rewriteIfNotNull(
+ appView,
+ syntheticMethodForDelegate,
+ newMethod -> JvmExtensionsKt.setSyntheticMethodForDelegate(kmProperty, newMethod),
+ KotlinJvmMethodSignatureInfo::rewriteNoBacking);
return rewritten;
}
@@ -207,6 +235,7 @@
setterParameter.trace(definitionSupplier);
}
forEachApply(typeParameters, param -> param::trace, definitionSupplier);
+ forEachApply(contextReceiverTypes, type -> type::trace, definitionSupplier);
if (fieldSignature != null) {
fieldSignature.trace(definitionSupplier);
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java
index fb9b55f..2fb5dd1 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java
@@ -4,14 +4,17 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.getCompatibleKotlinInfo;
+import static kotlinx.metadata.jvm.KotlinClassMetadata.Companion;
+
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexDefinitionSupplier;
+import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.Pair;
+import kotlin.Metadata;
import kotlinx.metadata.KmLambda;
-import kotlinx.metadata.jvm.KotlinClassHeader;
import kotlinx.metadata.jvm.KotlinClassMetadata.SyntheticClass;
-import kotlinx.metadata.jvm.KotlinClassMetadata.SyntheticClass.Writer;
// Holds information about a Metadata.SyntheticClass object.
public class KotlinSyntheticClassInfo implements KotlinClassLevelInfo {
@@ -73,15 +76,17 @@
}
@Override
- public Pair<KotlinClassHeader, Boolean> rewrite(DexClass clazz, AppView<?> appView) {
- Writer writer = new Writer();
- boolean rewritten = false;
- if (lambda != null) {
- KmLambda kmLambda = new KmLambda();
- rewritten = lambda.rewrite(() -> kmLambda, clazz, appView);
- kmLambda.accept(writer);
+ public Pair<Metadata, Boolean> rewrite(DexClass clazz, AppView<?> appView) {
+ if (lambda == null) {
+ return Pair.create(
+ Companion.writeSyntheticClass(getCompatibleKotlinInfo(), 0).getAnnotationData(), false);
}
- return Pair.create(writer.write().getHeader(), rewritten);
+ Box<KmLambda> newLambda = new Box<>();
+ boolean rewritten = lambda.rewrite(newLambda::set, clazz, appView);
+ assert newLambda.isSet();
+ return Pair.create(
+ Companion.writeLambda(newLambda.get(), getCompatibleKotlinInfo(), 0).getAnnotationData(),
+ rewritten);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeAliasInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeAliasInfo.java
index 8f89b9e..6bb9e59 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeAliasInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeAliasInfo.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.consume;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteList;
import static com.android.tools.r8.utils.FunctionUtils.forEachApply;
import com.android.tools.r8.graph.AppView;
@@ -12,8 +14,8 @@
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
import java.util.List;
+import java.util.function.Consumer;
import kotlinx.metadata.KmTypeAlias;
-import kotlinx.metadata.KmTypeAliasVisitor;
// Holds information about KmTypeAlias
public class KotlinTypeAliasInfo implements EnqueuerMetadataTraceable {
@@ -57,18 +59,20 @@
KotlinVersionRequirementInfo.create(alias.getVersionRequirements()));
}
- boolean rewrite(
- KmVisitorProviders.KmTypeAliasVisitorProvider visitorProvider, AppView<?> appView) {
- KmTypeAliasVisitor kmTypeAliasVisitor = visitorProvider.get(flags, name);
- boolean rewritten = underlyingType.rewrite(kmTypeAliasVisitor::visitUnderlyingType, appView);
- rewritten |= expandedType.rewrite(kmTypeAliasVisitor::visitExpandedType, appView);
- for (KotlinTypeParameterInfo typeParameter : typeParameters) {
- rewritten |= typeParameter.rewrite(kmTypeAliasVisitor::visitTypeParameter, appView);
- }
- for (KotlinAnnotationInfo annotation : annotations) {
- rewritten |= annotation.rewrite(kmTypeAliasVisitor::visitAnnotation, appView);
- }
- rewritten |= versionRequirements.rewrite(kmTypeAliasVisitor::visitVersionRequirement);
+ boolean rewrite(Consumer<KmTypeAlias> consumer, AppView<?> appView) {
+ KmTypeAlias kmTypeAlias = consume(new KmTypeAlias(flags, name), consumer);
+ boolean rewritten = underlyingType.rewrite(kmTypeAlias::setUnderlyingType, appView);
+ rewritten |= expandedType.rewrite(kmTypeAlias::setExpandedType, appView);
+ rewritten |=
+ rewriteList(
+ appView,
+ typeParameters,
+ kmTypeAlias.getTypeParameters(),
+ KotlinTypeParameterInfo::rewrite);
+ rewritten |=
+ rewriteList(
+ appView, annotations, kmTypeAlias.getAnnotations(), KotlinAnnotationInfo::rewrite);
+ rewritten |= versionRequirements.rewrite(kmTypeAlias.getVersionRequirements()::addAll);
return rewritten;
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeInfo.java
index a20d86c..93735f4 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeInfo.java
@@ -4,6 +4,9 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.consume;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteIfNotNull;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteList;
import static com.android.tools.r8.utils.FunctionUtils.forEachApply;
import com.android.tools.r8.graph.AppView;
@@ -15,11 +18,10 @@
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
import java.util.List;
+import java.util.function.Consumer;
import kotlinx.metadata.KmType;
import kotlinx.metadata.KmTypeProjection;
-import kotlinx.metadata.KmTypeVisitor;
import kotlinx.metadata.jvm.JvmExtensionsKt;
-import kotlinx.metadata.jvm.JvmTypeExtensionVisitor;
// Provides access to Kotlin information about a kotlin type.
public class KotlinTypeInfo implements EnqueuerMetadataTraceable {
@@ -82,34 +84,28 @@
return arguments.build();
}
- boolean rewrite(KmVisitorProviders.KmTypeVisitorProvider visitorProvider, AppView<?> appView) {
+ boolean rewrite(Consumer<KmType> consumer, AppView<?> appView) {
// TODO(b/154348683): Check for correct flags
- KmTypeVisitor kmTypeVisitor = visitorProvider.get(flags);
- boolean rewritten = classifier.rewrite(kmTypeVisitor, appView);
- if (abbreviatedType != null) {
- rewritten |= abbreviatedType.rewrite(kmTypeVisitor::visitAbbreviatedType, appView);
- }
- if (outerType != null) {
- rewritten |= outerType.rewrite(kmTypeVisitor::visitOuterType, appView);
- }
- for (KotlinTypeProjectionInfo argument : arguments) {
- rewritten |=
- argument.rewrite(
- kmTypeVisitor::visitArgument, kmTypeVisitor::visitStarProjection, appView);
- }
+ KmType kmType = consume(new KmType(flags), consumer);
+ boolean rewritten = classifier.rewrite(kmType, appView);
rewritten |=
- flexibleTypeUpperBound.rewrite(kmTypeVisitor::visitFlexibleTypeUpperBound, appView);
+ rewriteIfNotNull(
+ appView, abbreviatedType, kmType::setAbbreviatedType, KotlinTypeInfo::rewrite);
+ rewritten |=
+ rewriteIfNotNull(appView, outerType, kmType::setOuterType, KotlinTypeInfo::rewrite);
+ rewritten |=
+ rewriteList(appView, arguments, kmType.getArguments(), KotlinTypeProjectionInfo::rewrite);
+ rewritten |= flexibleTypeUpperBound.rewrite(kmType::setFlexibleTypeUpperBound, appView);
if (annotations.isEmpty() && !isRaw) {
return rewritten;
}
- JvmTypeExtensionVisitor extensionVisitor =
- (JvmTypeExtensionVisitor) kmTypeVisitor.visitExtensions(JvmTypeExtensionVisitor.TYPE);
- if (extensionVisitor != null) {
- for (KotlinAnnotationInfo annotation : annotations) {
- rewritten |= annotation.rewrite(extensionVisitor::visitAnnotation, appView);
- }
- extensionVisitor.visit(isRaw);
- }
+ rewritten |=
+ rewriteList(
+ appView,
+ annotations,
+ JvmExtensionsKt.getAnnotations(kmType),
+ KotlinAnnotationInfo::rewrite);
+ JvmExtensionsKt.setRaw(kmType, isRaw);
return rewritten;
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeParameterInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeParameterInfo.java
index e6cc10f..03bfcb5 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeParameterInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeParameterInfo.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.consume;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteList;
import static com.android.tools.r8.utils.FunctionUtils.forEachApply;
import com.android.tools.r8.graph.AppView;
@@ -13,12 +15,11 @@
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
import java.util.List;
+import java.util.function.Consumer;
import kotlinx.metadata.KmType;
import kotlinx.metadata.KmTypeParameter;
-import kotlinx.metadata.KmTypeParameterVisitor;
import kotlinx.metadata.KmVariance;
import kotlinx.metadata.jvm.JvmExtensionsKt;
-import kotlinx.metadata.jvm.JvmTypeParameterExtensionVisitor;
// Provides access to Kotlin information about a type-parameter.
public class KotlinTypeParameterInfo implements EnqueuerMetadataTraceable {
@@ -83,24 +84,21 @@
return builder.build();
}
- boolean rewrite(
- KmVisitorProviders.KmTypeParameterVisitorProvider visitorProvider, AppView<?> appView) {
- KmTypeParameterVisitor kmTypeParameterVisitor = visitorProvider.get(flags, name, id, variance);
- boolean rewritten = false;
- for (KotlinTypeInfo originalUpperBound : originalUpperBounds) {
- rewritten |= originalUpperBound.rewrite(kmTypeParameterVisitor::visitUpperBound, appView);
- }
- if (annotations.isEmpty()) {
- return rewritten;
- }
- JvmTypeParameterExtensionVisitor extensionVisitor =
- (JvmTypeParameterExtensionVisitor)
- kmTypeParameterVisitor.visitExtensions(JvmTypeParameterExtensionVisitor.TYPE);
- if (extensionVisitor != null) {
- for (KotlinAnnotationInfo annotation : annotations) {
- rewritten |= annotation.rewrite(extensionVisitor::visitAnnotation, appView);
- }
- }
+ boolean rewrite(Consumer<KmTypeParameter> consumer, AppView<?> appView) {
+ KmTypeParameter kmTypeParameter =
+ consume(new KmTypeParameter(flags, name, id, variance), consumer);
+ boolean rewritten =
+ rewriteList(
+ appView,
+ originalUpperBounds,
+ kmTypeParameter.getUpperBounds(),
+ KotlinTypeInfo::rewrite);
+ rewritten |=
+ rewriteList(
+ appView,
+ annotations,
+ JvmExtensionsKt.getAnnotations(kmTypeParameter),
+ KotlinAnnotationInfo::rewrite);
return rewritten;
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeProjectionInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeProjectionInfo.java
index 85791fe..5ac01e6 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeProjectionInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeProjectionInfo.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
+import java.util.function.Consumer;
import kotlinx.metadata.KmTypeProjection;
import kotlinx.metadata.KmVariance;
@@ -34,15 +35,13 @@
return variance == null && typeInfo == null;
}
- boolean rewrite(
- KmVisitorProviders.KmTypeProjectionVisitorProvider visitorProvider,
- KmVisitorProviders.KmTypeStarProjectionVisitorProvider starProjectionProvider,
- AppView<?> appView) {
+ boolean rewrite(Consumer<KmTypeProjection> consumer, AppView<?> appView) {
if (isStarProjection()) {
- starProjectionProvider.get();
+ consumer.accept(KmTypeProjection.STAR);
return false;
} else {
- return typeInfo.rewrite(flags -> visitorProvider.get(flags, variance), appView);
+ return typeInfo.rewrite(
+ kmType -> consumer.accept(new KmTypeProjection(variance, kmType)), appView);
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java
index 1e12db6..68a79f2 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java
@@ -4,6 +4,9 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.consume;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteIfNotNull;
+
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexItemFactory;
@@ -11,9 +14,9 @@
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
import java.util.List;
+import java.util.function.Consumer;
import kotlinx.metadata.KmType;
import kotlinx.metadata.KmValueParameter;
-import kotlinx.metadata.KmValueParameterVisitor;
import kotlinx.metadata.internal.metadata.deserialization.Flags;
// Provides access to Kotlin information about value parameter.
@@ -65,14 +68,15 @@
return builder.build();
}
- boolean rewrite(
- KmVisitorProviders.KmValueParameterVisitorProvider visitorProvider, AppView<?> appView) {
- KmValueParameterVisitor kmValueParameterVisitor = visitorProvider.get(flags, name);
- boolean rewritten = type.rewrite(kmValueParameterVisitor::visitType, appView);
- if (varargElementType != null) {
- rewritten |=
- varargElementType.rewrite(kmValueParameterVisitor::visitVarargElementType, appView);
- }
+ boolean rewrite(Consumer<KmValueParameter> consumer, AppView<?> appView) {
+ KmValueParameter kmValueParameter = consume(new KmValueParameter(flags, name), consumer);
+ boolean rewritten = type.rewrite(kmValueParameter::setType, appView);
+ rewritten |=
+ rewriteIfNotNull(
+ appView,
+ varargElementType,
+ kmValueParameter::setVarargElementType,
+ KotlinTypeInfo::rewrite);
return rewritten;
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinVersionRequirementInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinVersionRequirementInfo.java
index 3ab63f9..c82b039 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinVersionRequirementInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinVersionRequirementInfo.java
@@ -6,20 +6,17 @@
import com.google.common.collect.ImmutableList;
import java.util.List;
-import kotlinx.metadata.KmVersion;
+import java.util.function.Consumer;
import kotlinx.metadata.KmVersionRequirement;
-import kotlinx.metadata.KmVersionRequirementLevel;
-import kotlinx.metadata.KmVersionRequirementVersionKind;
-import kotlinx.metadata.KmVersionRequirementVisitor;
class KotlinVersionRequirementInfo {
private static final KotlinVersionRequirementInfo NO_VERSION_REQUIREMENTS =
new KotlinVersionRequirementInfo(ImmutableList.of());
- private final List<KotlinVersionRequirementPoint> versionRequirements;
+ private final List<KmVersionRequirement> versionRequirements;
- private KotlinVersionRequirementInfo(List<KotlinVersionRequirementPoint> versionRequirements) {
+ private KotlinVersionRequirementInfo(List<KmVersionRequirement> versionRequirements) {
this.versionRequirements = versionRequirements;
}
@@ -27,57 +24,14 @@
if (kmVersionRequirements.isEmpty()) {
return NO_VERSION_REQUIREMENTS;
}
- ImmutableList.Builder<KotlinVersionRequirementPoint> builder = ImmutableList.builder();
- for (KmVersionRequirement kmVersionRequirement : kmVersionRequirements) {
- builder.add(KotlinVersionRequirementPoint.create(kmVersionRequirement));
- }
- return new KotlinVersionRequirementInfo(builder.build());
+ return new KotlinVersionRequirementInfo(ImmutableList.copyOf(kmVersionRequirements));
}
- boolean rewrite(KmVisitorProviders.KmVersionRequirementVisitorProvider visitorProvider) {
+ boolean rewrite(Consumer<List<KmVersionRequirement>> consumer) {
if (this == NO_VERSION_REQUIREMENTS) {
return false;
}
- for (KotlinVersionRequirementPoint versionRequirement : versionRequirements) {
- versionRequirement.rewrite(visitorProvider.get());
- }
+ consumer.accept(versionRequirements);
return false;
}
-
- private static class KotlinVersionRequirementPoint {
-
- private final Integer errorCode;
- private final KmVersionRequirementVersionKind kind;
- private final KmVersionRequirementLevel level;
- private final String message;
- private final KmVersion version;
-
- private KotlinVersionRequirementPoint(
- KmVersionRequirementVersionKind kind,
- KmVersionRequirementLevel level,
- Integer errorCode,
- String message,
- KmVersion version) {
- this.errorCode = errorCode;
- this.kind = kind;
- this.level = level;
- this.message = message;
- this.version = version;
- }
-
- private static KotlinVersionRequirementPoint create(KmVersionRequirement kmVersionRequirement) {
- return new KotlinVersionRequirementPoint(
- kmVersionRequirement.kind,
- kmVersionRequirement.level,
- kmVersionRequirement.getErrorCode(),
- kmVersionRequirement.getMessage(),
- kmVersionRequirement.version);
- }
-
- private void rewrite(KmVersionRequirementVisitor visitor) {
- visitor.visit(kind, level, errorCode, message);
- visitor.visitVersion(version.getMajor(), version.getMinor(), version.getPatch());
- visitor.visitEnd();
- }
- }
}
diff --git a/src/test/java/com/android/tools/r8/KotlinCompilerTool.java b/src/test/java/com/android/tools/r8/KotlinCompilerTool.java
index 36f3b07..259f1a0 100644
--- a/src/test/java/com/android/tools/r8/KotlinCompilerTool.java
+++ b/src/test/java/com/android/tools/r8/KotlinCompilerTool.java
@@ -5,6 +5,7 @@
import static com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion.MAX_SUPPORTED_VERSION;
import static com.android.tools.r8.ToolHelper.isWindows;
+import static com.google.common.io.Files.getNameWithoutExtension;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
@@ -223,6 +224,10 @@
return this;
}
+ public KotlinCompilerTool enableExperimentalContextReceivers() {
+ return addArguments("-Xcontext-receivers");
+ }
+
public KotlinCompilerTool addSourceFiles(Path... files) {
return addSourceFiles(Arrays.asList(files));
}
@@ -268,7 +273,8 @@
try {
// The Kotlin compiler does not require particular naming of files except for
// the extension, so just create a file called source.kt in a new directory.
- Path fileNamedKt = temp.newFolder().toPath().resolve("source.kt");
+ String newFileName = getNameWithoutExtension(fileNotNamedKt.toString()) + ".kt";
+ Path fileNamedKt = temp.newFolder().toPath().resolve(newFileName);
Files.copy(fileNotNamedKt, fileNamedKt);
return fileNamedKt;
} catch (IOException e) {
diff --git a/src/test/java/com/android/tools/r8/SanityCheck.java b/src/test/java/com/android/tools/r8/SanityCheck.java
index b82995c..38fa873 100644
--- a/src/test/java/com/android/tools/r8/SanityCheck.java
+++ b/src/test/java/com/android/tools/r8/SanityCheck.java
@@ -29,7 +29,7 @@
private static final String SRV_PREFIX = "META-INF/services/";
private static final String METADATA_EXTENSION =
- "com.android.tools.r8.jetbrains.kotlinx.metadata.impl.extensions.MetadataExtensions";
+ "com.android.tools.r8.jetbrains.kotlinx.metadata.internal.extensions.MetadataExtensions";
private static final String EXT_IN_SRV = SRV_PREFIX + METADATA_EXTENSION;
private void checkJarContent(
diff --git a/src/test/java/com/android/tools/r8/kotlin/coroutines/KotlinxCoroutinesTestRunner.java b/src/test/java/com/android/tools/r8/kotlin/coroutines/KotlinxCoroutinesTestRunner.java
index 11ad201..4f334aa 100644
--- a/src/test/java/com/android/tools/r8/kotlin/coroutines/KotlinxCoroutinesTestRunner.java
+++ b/src/test/java/com/android/tools/r8/kotlin/coroutines/KotlinxCoroutinesTestRunner.java
@@ -94,7 +94,7 @@
.compile()
.inspect(
inspector ->
- assertEqualMetadata(
+ assertEqualMetadataWithStringPoolValidation(
new CodeInspector(BASE_LIBRARY),
inspector,
(addedStrings, addedNonInitStrings) -> {}))
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/KotlinMetadataTestBase.java b/src/test/java/com/android/tools/r8/kotlin/metadata/KotlinMetadataTestBase.java
index 55a048e..07539ed 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/KotlinMetadataTestBase.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/KotlinMetadataTestBase.java
@@ -15,6 +15,7 @@
import com.android.tools.r8.KotlinTestBase;
import com.android.tools.r8.KotlinTestParameters;
import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.kotlin.KotlinMetadataAnnotationWrapper;
import com.android.tools.r8.kotlin.KotlinMetadataWriter;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.IntBox;
@@ -31,8 +32,8 @@
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import junit.framework.TestCase;
-import kotlinx.metadata.jvm.KotlinClassHeader;
import kotlinx.metadata.jvm.KotlinClassMetadata;
+import org.junit.Assert;
public abstract class KotlinMetadataTestBase extends KotlinTestBase {
@@ -54,7 +55,7 @@
static final String KT_FUNCTION1 = "Lkotlin/Function1;";
static final String KT_COMPARABLE = "Lkotlin/Comparable;";
- public void assertEqualMetadata(
+ public void assertEqualMetadataWithStringPoolValidation(
CodeInspector originalInspector,
CodeInspector rewrittenInspector,
BiConsumer<Integer, Integer> addedStringsInspector) {
@@ -73,9 +74,11 @@
continue;
}
assertNotNull(rewrittenMetadata);
- KotlinClassHeader originalHeader = originalMetadata.getHeader();
- KotlinClassHeader rewrittenHeader = rewrittenMetadata.getHeader();
- TestCase.assertEquals(originalHeader.getKind(), rewrittenHeader.getKind());
+ KotlinMetadataAnnotationWrapper originalHeader =
+ KotlinMetadataAnnotationWrapper.wrap(originalMetadata);
+ KotlinMetadataAnnotationWrapper rewrittenHeader =
+ KotlinMetadataAnnotationWrapper.wrap(rewrittenMetadata);
+ TestCase.assertEquals(originalHeader.kind(), rewrittenHeader.kind());
// We cannot assert equality of the data since it may be ordered differently. However, we
// will check for the changes to the string pool and then validate the same parsing
@@ -87,8 +90,8 @@
.computeIfAbsent(
method.getFinalSignature().toDescriptor(), ignoreArgument(ArrayList::new))
.add(method.getFinalName()));
- HashSet<String> originalStrings = new HashSet<>(Arrays.asList(originalHeader.getData2()));
- HashSet<String> rewrittenStrings = new HashSet<>(Arrays.asList(rewrittenHeader.getData2()));
+ HashSet<String> originalStrings = new HashSet<>(Arrays.asList(originalHeader.data2()));
+ HashSet<String> rewrittenStrings = new HashSet<>(Arrays.asList(rewrittenHeader.data2()));
rewrittenStrings.forEach(
rewrittenString -> {
if (originalStrings.contains(rewrittenString)) {
@@ -108,7 +111,7 @@
}
addedNonInitStrings.increment();
});
- assertEquals(originalHeader.getPackageName(), rewrittenHeader.getPackageName());
+ assertEquals(originalHeader.packageName(), rewrittenHeader.packageName());
String expected = KotlinMetadataWriter.kotlinMetadataToString("", originalMetadata);
String actual = KotlinMetadataWriter.kotlinMetadataToString("", rewrittenMetadata);
@@ -117,6 +120,57 @@
addedStringsInspector.accept(addedStrings.get(), addedNonInitStrings.get());
}
+ public void assertEqualDeserializedMetadata(
+ CodeInspector inspector, CodeInspector otherInspector) {
+ for (FoundClassSubject clazzSubject : otherInspector.allClasses()) {
+ ClassSubject r8Clazz = inspector.clazz(clazzSubject.getOriginalName());
+ assertThat(r8Clazz, isPresent());
+ KotlinClassMetadata originalMetadata = clazzSubject.getKotlinClassMetadata();
+ KotlinClassMetadata rewrittenMetadata = r8Clazz.getKotlinClassMetadata();
+ if (originalMetadata == null) {
+ assertNull(rewrittenMetadata);
+ continue;
+ }
+ assertNotNull(rewrittenMetadata);
+ KotlinMetadataAnnotationWrapper originalHeader =
+ KotlinMetadataAnnotationWrapper.wrap(originalMetadata);
+ KotlinMetadataAnnotationWrapper rewrittenHeader =
+ KotlinMetadataAnnotationWrapper.wrap(rewrittenMetadata);
+ TestCase.assertEquals(originalHeader.kind(), rewrittenHeader.kind());
+ TestCase.assertEquals(originalHeader.packageName(), rewrittenHeader.packageName());
+ // We cannot assert equality of the data since it may be ordered differently. We use the
+ // KotlinMetadataWriter to deserialize the metadata and assert those are equal.
+ String expected = KotlinMetadataWriter.kotlinMetadataToString("", originalMetadata);
+ String actual = KotlinMetadataWriter.kotlinMetadataToString("", rewrittenMetadata);
+ TestCase.assertEquals(expected, actual);
+ }
+ }
+
+ public void assertEqualMetadata(CodeInspector inspector, CodeInspector otherInspector) {
+ for (FoundClassSubject clazzSubject : otherInspector.allClasses()) {
+ ClassSubject r8Clazz = inspector.clazz(clazzSubject.getOriginalName());
+ assertThat(r8Clazz, isPresent());
+ KotlinClassMetadata originalMetadata = clazzSubject.getKotlinClassMetadata();
+ KotlinClassMetadata rewrittenMetadata = r8Clazz.getKotlinClassMetadata();
+ if (originalMetadata == null) {
+ assertNull(rewrittenMetadata);
+ continue;
+ }
+ TestCase.assertNotNull(rewrittenMetadata);
+ KotlinMetadataAnnotationWrapper originalHeader =
+ KotlinMetadataAnnotationWrapper.wrap(originalMetadata);
+ KotlinMetadataAnnotationWrapper rewrittenHeader =
+ KotlinMetadataAnnotationWrapper.wrap(rewrittenMetadata);
+ TestCase.assertEquals(originalHeader.kind(), rewrittenHeader.kind());
+ TestCase.assertEquals(originalHeader.packageName(), rewrittenHeader.packageName());
+ Assert.assertArrayEquals(originalHeader.data1(), rewrittenHeader.data1());
+ Assert.assertArrayEquals(originalHeader.data2(), rewrittenHeader.data2());
+ String expected = KotlinMetadataWriter.kotlinMetadataToString("", originalMetadata);
+ String actual = KotlinMetadataWriter.kotlinMetadataToString("", rewrittenMetadata);
+ TestCase.assertEquals(expected, actual);
+ }
+ }
+
public static void verifyExpectedWarningsFromKotlinReflectAndStdLib(
TestCompileResult<?, ?> compileResult) {
compileResult.assertAllWarningMessagesMatch(
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteBoxedTypesTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteBoxedTypesTest.java
index 5e5fc28..bcbc386 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteBoxedTypesTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteBoxedTypesTest.java
@@ -4,26 +4,13 @@
package com.android.tools.r8.kotlin.metadata;
-import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertNotNull;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertNull;
-
import com.android.tools.r8.KotlinTestParameters;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.kotlin.KotlinMetadataWriter;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.utils.StringUtils;
-import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
-import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
-import java.util.concurrent.ExecutionException;
-import kotlinx.metadata.jvm.KotlinClassHeader;
-import kotlinx.metadata.jvm.KotlinClassMetadata;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -97,7 +84,13 @@
ProguardKeepAttributes.INNER_CLASSES,
ProguardKeepAttributes.ENCLOSING_METHOD)
.compile()
- .inspect(this::inspect)
+ // Since this has a keep-all classes rule, we should just assert that the meta-data is
+ // equal to the original one.
+ .inspect(
+ inspector ->
+ assertEqualDeserializedMetadata(
+ inspector,
+ new CodeInspector(libJars.getForConfiguration(kotlinc, targetVersion))))
.writeToZip();
Path main =
kotlinc(parameters.getRuntime().asCf(), kotlinc, targetVersion)
@@ -112,33 +105,6 @@
.assertSuccessWithOutput(EXPECTED);
}
- private void inspect(CodeInspector inspector) throws IOException, ExecutionException {
- // Since this has a keep-all classes rule, we should just assert that the meta-data is equal to
- // the original one.
- CodeInspector stdLibInspector =
- new CodeInspector(libJars.getForConfiguration(kotlinc, targetVersion));
- for (FoundClassSubject clazzSubject : stdLibInspector.allClasses()) {
- ClassSubject r8Clazz = inspector.clazz(clazzSubject.getOriginalName());
- assertThat(r8Clazz, isPresent());
- KotlinClassMetadata originalMetadata = clazzSubject.getKotlinClassMetadata();
- KotlinClassMetadata rewrittenMetadata = r8Clazz.getKotlinClassMetadata();
- if (originalMetadata == null) {
- assertNull(rewrittenMetadata);
- continue;
- }
- assertNotNull(rewrittenMetadata);
- KotlinClassHeader originalHeader = originalMetadata.getHeader();
- KotlinClassHeader rewrittenHeader = rewrittenMetadata.getHeader();
- assertEquals(originalHeader.getKind(), rewrittenHeader.getKind());
- assertEquals(originalHeader.getPackageName(), rewrittenHeader.getPackageName());
- // We cannot assert equality of the data since it may be ordered differently. Instead we use
- // the KotlinMetadataWriter.
- String expected = KotlinMetadataWriter.kotlinMetadataToString("", originalMetadata);
- String actual = KotlinMetadataWriter.kotlinMetadataToString("", rewrittenMetadata);
- assertEquals(expected, actual);
- }
- }
-
@Test
public void testMetadataForReflect() throws Exception {
Path libJar =
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteContextReceiverTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteContextReceiverTest.java
new file mode 100644
index 0000000..102a056
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteContextReceiverTest.java
@@ -0,0 +1,193 @@
+// Copyright (c) 2023, 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 com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion.KOTLINC_1_8_0;
+import static com.android.tools.r8.KotlinCompilerTool.KotlinTargetVersion.JAVA_8;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.KotlinTestParameters;
+import com.android.tools.r8.R8TestCompileResult;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.shaking.ProguardKeepAttributes;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class MetadataRewriteContextReceiverTest extends KotlinMetadataTestBase {
+
+ private static final String PKG_LIB = PKG + ".context_receiver_lib";
+ private static final String PKG_APP = PKG + ".context_receiver_app";
+ private static final Path LIB_FILE =
+ getFileInTest(PKG_PREFIX + "/context_receiver_lib", "lib.txt");
+ private static final Path MAIN_FILE =
+ getFileInTest(PKG_PREFIX + "/context_receiver_app", "main.txt");
+ private static final String MAIN = PKG_APP + ".MainKt";
+ private final TestParameters parameters;
+
+ private static final String EXPECTED =
+ StringUtils.lines(
+ "FooImpl::m1",
+ "BarImpl::m2",
+ "BazImpl::m3",
+ "BazImpl::m3",
+ "FooImpl::m1",
+ "BarImpl::m2",
+ "Hello World!");
+
+ @Parameterized.Parameters(name = "{0}, {1}")
+ public static Collection<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withCfRuntimes().build(),
+ getKotlinTestParameters()
+ .withCompilersStartingFromIncluding(KOTLINC_1_8_0)
+ .withOldCompilersStartingFrom(KOTLINC_1_8_0)
+ .withTargetVersion(JAVA_8)
+ .build());
+ }
+
+ public MetadataRewriteContextReceiverTest(
+ TestParameters parameters, KotlinTestParameters kotlinParameters) {
+ super(kotlinParameters);
+ this.parameters = parameters;
+ }
+
+ private static final KotlinCompileMemoizer libJars =
+ getCompileMemoizer()
+ .configure(
+ kotlinc ->
+ kotlinc
+ .addSourceFilesWithNonKtExtension(getStaticTemp(), LIB_FILE)
+ .enableExperimentalContextReceivers());
+
+ @Test
+ public void smokeTest() throws Exception {
+ Path output =
+ kotlinc(parameters.getRuntime().asCf(), kotlinc, targetVersion)
+ .addClasspathFiles(libJars.getForConfiguration(kotlinc, targetVersion))
+ .addSourceFilesWithNonKtExtension(temp, MAIN_FILE)
+ .setOutputPath(temp.newFolder().toPath())
+ .enableExperimentalContextReceivers()
+ .compile();
+ testForJvm()
+ .addRunClasspathFiles(
+ kotlinc.getKotlinStdlibJar(),
+ kotlinc.getKotlinReflectJar(),
+ libJars.getForConfiguration(kotlinc, targetVersion))
+ .addClasspath(output)
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void testMetadataForCompilationWithKeepAll() throws Exception {
+ Path libJar =
+ testForR8(parameters.getBackend())
+ .addClasspathFiles(kotlinc.getKotlinAnnotationJar())
+ .addProgramFiles(
+ libJars.getForConfiguration(kotlinc, targetVersion), kotlinc.getKotlinStdlibJar())
+ .addKeepClassAndMembersRules(PKG_LIB + ".*")
+ .addKeepAttributes(
+ ProguardKeepAttributes.SIGNATURE,
+ ProguardKeepAttributes.INNER_CLASSES,
+ ProguardKeepAttributes.ENCLOSING_METHOD)
+ .addKeepKotlinMetadata()
+ .allowDiagnosticWarningMessages()
+ .addOptionsModification(
+ options -> options.testing.keepMetadataInR8IfNotRewritten = false)
+ .compile()
+ // Since this has a keep-all classes rule assert that the meta-data is equal to the
+ // original one.
+ .inspect(
+ inspector ->
+ assertEqualDeserializedMetadata(
+ inspector,
+ new CodeInspector(libJars.getForConfiguration(kotlinc, targetVersion))))
+ .writeToZip();
+ Path main =
+ kotlinc(parameters.getRuntime().asCf(), kotlinc, targetVersion)
+ .addClasspathFiles(libJar)
+ .addSourceFilesWithNonKtExtension(temp, MAIN_FILE)
+ .setOutputPath(temp.newFolder().toPath())
+ .enableExperimentalContextReceivers()
+ .compile();
+ testForJvm()
+ .addRunClasspathFiles(kotlinc.getKotlinStdlibJar(), kotlinc.getKotlinReflectJar(), libJar)
+ .addClasspath(main)
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void testMetadataInExtensionFunction_renamedKotlinSources() throws Exception {
+ R8TestCompileResult r8LibraryResult =
+ testForR8(parameters.getBackend())
+ .addClasspathFiles(kotlinc.getKotlinStdlibJar(), kotlinc.getKotlinAnnotationJar())
+ .addProgramFiles(libJars.getForConfiguration(kotlinc, targetVersion))
+ // Ensure that we do not rename members
+ .addKeepRules("-keepclassmembers class * { *; }")
+ // Keep the Foo class but rename it.
+ .addKeepRules("-keep,allowobfuscation class " + PKG_LIB + ".Foo")
+ // Keep the Bar class but rename it.
+ .addKeepRules("-keep,allowobfuscation class " + PKG_LIB + ".Bar")
+ // Keep the Baz class but rename it.
+ .addKeepRules("-keep,allowobfuscation class " + PKG_LIB + ".Baz")
+ // Keep all Printer fields.
+ .addKeepRules("-keep class " + PKG_LIB + ".Printer { *; }")
+ // Keep Super, but allow minification.
+ .addKeepRules("-keep class " + PKG_LIB + ".LibKt { <methods>; }")
+ .addKeepKotlinMetadata()
+ .compile();
+
+ // Rewrite the kotlin source to rewrite the classes from the mapping file
+ String kotlinSource = FileUtils.readTextFile(MAIN_FILE, StandardCharsets.UTF_8);
+
+ CodeInspector inspector = r8LibraryResult.inspector();
+ // Rewrite the source kotlin file that reference the renamed classes uses in the context
+ // receivers.
+ for (String className : new String[] {"Foo", "Bar", "Baz"}) {
+ String originalClassName = PKG_LIB + "." + className;
+ ClassSubject clazz = inspector.clazz(originalClassName);
+ assertThat(clazz, isPresentAndRenamed());
+ kotlinSource =
+ kotlinSource.replace("import " + originalClassName, "import " + clazz.getFinalName());
+ kotlinSource =
+ kotlinSource.replace(
+ ": " + className + " {",
+ ": "
+ + DescriptorUtils.getSimpleClassNameFromDescriptor(clazz.getFinalDescriptor())
+ + " {");
+ }
+
+ Path newSource = temp.newFolder().toPath().resolve("main.kt");
+ Files.write(newSource, kotlinSource.getBytes(StandardCharsets.UTF_8));
+
+ Path libJar = r8LibraryResult.writeToZip();
+ Path output =
+ kotlinc(parameters.getRuntime().asCf(), kotlinc, targetVersion)
+ .addClasspathFiles(libJar)
+ .addSourceFiles(newSource)
+ .setOutputPath(temp.newFolder().toPath())
+ .enableExperimentalContextReceivers()
+ .compile();
+
+ testForJvm()
+ .addRunClasspathFiles(kotlinc.getKotlinStdlibJar(), libJar)
+ .addClasspath(output)
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInlineClassTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInlineClassTest.java
index af22ae1..0704ecd 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInlineClassTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInlineClassTest.java
@@ -5,24 +5,15 @@
package com.android.tools.r8.kotlin.metadata;
import static com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion.KOTLINC_1_6_0;
-import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion;
import com.android.tools.r8.KotlinTestParameters;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.kotlin.KotlinMetadataWriter;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.utils.StringUtils;
-import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
-import junit.framework.TestCase;
-import kotlinx.metadata.jvm.KotlinClassHeader;
-import kotlinx.metadata.jvm.KotlinClassMetadata;
-import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -84,7 +75,11 @@
"-keep class " + PKG + ".inline_class_lib.LibKt { *** login-*(java.lang.String); }")
.addKeepAttributes(ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS)
.compile()
- .inspect(this::inspect)
+ .inspect(
+ inspector ->
+ assertEqualMetadata(
+ inspector,
+ new CodeInspector(libJars.getForConfiguration(kotlinc, targetVersion))))
.writeToZip();
Path main =
kotlinc(parameters.getRuntime().asCf(), kotlinc, targetVersion)
@@ -98,24 +93,4 @@
.run(parameters.getRuntime(), PKG + ".inline_class_app.MainKt")
.assertSuccessWithOutput(EXPECTED);
}
-
- private void inspect(CodeInspector inspector) throws IOException {
- CodeInspector stdLibInspector =
- new CodeInspector(libJars.getForConfiguration(kotlinc, targetVersion));
- ClassSubject clazzSubject = stdLibInspector.clazz(passwordTypeName);
- ClassSubject r8Clazz = inspector.clazz(clazzSubject.getOriginalName());
- assertThat(r8Clazz, isPresent());
- KotlinClassMetadata originalMetadata = clazzSubject.getKotlinClassMetadata();
- KotlinClassMetadata rewrittenMetadata = r8Clazz.getKotlinClassMetadata();
- TestCase.assertNotNull(rewrittenMetadata);
- KotlinClassHeader originalHeader = originalMetadata.getHeader();
- KotlinClassHeader rewrittenHeader = rewrittenMetadata.getHeader();
- TestCase.assertEquals(originalHeader.getKind(), rewrittenHeader.getKind());
- TestCase.assertEquals(originalHeader.getPackageName(), rewrittenHeader.getPackageName());
- Assert.assertArrayEquals(originalHeader.getData1(), rewrittenHeader.getData1());
- Assert.assertArrayEquals(originalHeader.getData2(), rewrittenHeader.getData2());
- String expected = KotlinMetadataWriter.kotlinMetadataToString("", originalMetadata);
- String actual = KotlinMetadataWriter.kotlinMetadataToString("", rewrittenMetadata);
- TestCase.assertEquals(expected, actual);
- }
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInlinePropertyTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInlinePropertyTest.java
index c693a41..6f78827 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInlinePropertyTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInlinePropertyTest.java
@@ -4,24 +4,13 @@
package com.android.tools.r8.kotlin.metadata;
-import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertNull;
-
import com.android.tools.r8.KotlinTestParameters;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.kotlin.KotlinMetadataWriter;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.utils.StringUtils;
-import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
-import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
-import junit.framework.TestCase;
-import kotlinx.metadata.jvm.KotlinClassHeader;
-import kotlinx.metadata.jvm.KotlinClassMetadata;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -78,7 +67,11 @@
ProguardKeepAttributes.INNER_CLASSES,
ProguardKeepAttributes.ENCLOSING_METHOD)
.compile()
- .inspect(this::inspect)
+ .inspect(
+ inspector ->
+ assertEqualDeserializedMetadata(
+ inspector,
+ new CodeInspector(libJars.getForConfiguration(kotlinc, targetVersion))))
.writeToZip();
Path main =
kotlinc(parameters.getRuntime().asCf(), kotlinc, targetVersion)
@@ -92,29 +85,4 @@
.run(parameters.getRuntime(), PKG + ".inline_property_app.MainKt")
.assertSuccessWithOutput(EXPECTED);
}
-
- private void inspect(CodeInspector inspector) throws IOException {
- CodeInspector stdLibInspector =
- new CodeInspector(libJars.getForConfiguration(kotlinc, targetVersion));
- for (FoundClassSubject clazzSubject : stdLibInspector.allClasses()) {
- ClassSubject r8Clazz = inspector.clazz(clazzSubject.getOriginalName());
- assertThat(r8Clazz, isPresent());
- KotlinClassMetadata originalMetadata = clazzSubject.getKotlinClassMetadata();
- KotlinClassMetadata rewrittenMetadata = r8Clazz.getKotlinClassMetadata();
- if (originalMetadata == null) {
- assertNull(rewrittenMetadata);
- continue;
- }
- TestCase.assertNotNull(rewrittenMetadata);
- KotlinClassHeader originalHeader = originalMetadata.getHeader();
- KotlinClassHeader rewrittenHeader = rewrittenMetadata.getHeader();
- TestCase.assertEquals(originalHeader.getKind(), rewrittenHeader.getKind());
- TestCase.assertEquals(originalHeader.getPackageName(), rewrittenHeader.getPackageName());
- // We cannot assert equality of the data since it may be ordered differently. Instead we use
- // the KotlinMetadataWriter.
- String expected = KotlinMetadataWriter.kotlinMetadataToString("", originalMetadata);
- String actual = KotlinMetadataWriter.kotlinMetadataToString("", rewrittenMetadata);
- TestCase.assertEquals(expected, actual);
- }
- }
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteKeepTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteKeepTest.java
index 24b3e58..ce9fba4 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteKeepTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteKeepTest.java
@@ -10,10 +10,12 @@
import com.android.tools.r8.KotlinTestParameters;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.kotlin.KotlinMetadataAnnotationWrapper;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
import java.util.Collection;
+import kotlinx.metadata.jvm.KotlinClassMetadata;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -68,8 +70,9 @@
if (clazz.getFinalName().startsWith("kotlin.io")
|| clazz.getFinalName().equals("kotlin.Metadata")
|| clazz.getFinalName().equals("kotlin.jvm.JvmName")) {
- assertNotNull(clazz.getKotlinClassMetadata());
- assertNotNull(clazz.getKotlinClassMetadata().getHeader().getData2());
+ KotlinClassMetadata kotlinClassMetadata = clazz.getKotlinClassMetadata();
+ assertNotNull(kotlinClassMetadata);
+ assertNotNull(KotlinMetadataAnnotationWrapper.wrap(kotlinClassMetadata).data2());
} else {
assertNull(clazz.getKotlinClassMetadata());
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteLocalDelegatedPropertyTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteLocalDelegatedPropertyTest.java
index 2a7ee54..9fddbf0 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteLocalDelegatedPropertyTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteLocalDelegatedPropertyTest.java
@@ -70,7 +70,7 @@
.compile()
.inspect(
inspector ->
- assertEqualMetadata(
+ assertEqualMetadataWithStringPoolValidation(
new CodeInspector(jars.getForConfiguration(kotlinc, targetVersion)),
inspector,
(addedStrings, addedNonInitStrings) -> {}))
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewritePassThroughTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewritePassThroughTest.java
index d08e0a0..e06e1ba 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewritePassThroughTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewritePassThroughTest.java
@@ -56,7 +56,7 @@
.assertAllWarningMessagesMatch(equalTo("Resource 'META-INF/MANIFEST.MF' already exists."))
.inspect(
inspector ->
- assertEqualMetadata(
+ assertEqualMetadataWithStringPoolValidation(
new CodeInspector(kotlinc.getKotlinStdlibJar()),
inspector,
(addedStrings, addedNonInitStrings) -> {
@@ -74,7 +74,7 @@
.compile()
.inspect(
inspector ->
- assertEqualMetadata(
+ assertEqualMetadataWithStringPoolValidation(
new CodeInspector(kotlinc.getKotlinStdlibJar()),
inspector,
(addedStrings, addedNonInitStrings) -> {
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteRawTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteRawTest.java
index 7686ac3..6012fb0 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteRawTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteRawTest.java
@@ -96,7 +96,7 @@
.compile()
.inspect(
inspector ->
- assertEqualMetadata(
+ assertEqualMetadataWithStringPoolValidation(
new CodeInspector(libJars.getForConfiguration(kotlinc, targetVersion)),
inspector,
(addedStrings, addedNonInitStrings) -> {}))
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteUnitPrimitiveTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteUnitPrimitiveTest.java
index 5d13395..4683d0b 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteUnitPrimitiveTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteUnitPrimitiveTest.java
@@ -6,27 +6,16 @@
import static com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion.MIN_SUPPORTED_VERSION;
import static com.android.tools.r8.KotlinCompilerTool.KotlinTargetVersion.JAVA_8;
-import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertNull;
import com.android.tools.r8.KotlinTestParameters;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.kotlin.KotlinMetadataWriter;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringUtils;
-import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
-import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
-import junit.framework.TestCase;
-import kotlinx.metadata.jvm.KotlinClassHeader;
-import kotlinx.metadata.jvm.KotlinClassMetadata;
-import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -109,7 +98,12 @@
.compile()
.assertAllWarningMessagesMatch(
equalTo("Resource 'META-INF/MANIFEST.MF' already exists."))
- .inspect(this::inspect)
+ .inspect(
+ inspector ->
+ assertEqualMetadata(
+ inspector,
+ new CodeInspector(
+ kotlincLibJar.getForConfiguration(kotlinc, targetVersion))))
.writeToZip();
Path main =
kotlinc(parameters.getRuntime().asCf(), kotlinc, targetVersion)
@@ -124,29 +118,4 @@
.run(parameters.getRuntime(), PKG_APP + ".MainKt")
.assertSuccessWithOutput(EXPECTED);
}
-
- private void inspect(CodeInspector inspector) throws IOException {
- CodeInspector stdLibInspector =
- new CodeInspector(kotlincLibJar.getForConfiguration(kotlinc, targetVersion));
- for (FoundClassSubject clazzSubject : stdLibInspector.allClasses()) {
- ClassSubject r8Clazz = inspector.clazz(clazzSubject.getOriginalName());
- assertThat(r8Clazz, isPresent());
- KotlinClassMetadata originalMetadata = clazzSubject.getKotlinClassMetadata();
- KotlinClassMetadata rewrittenMetadata = r8Clazz.getKotlinClassMetadata();
- if (originalMetadata == null) {
- assertNull(rewrittenMetadata);
- continue;
- }
- TestCase.assertNotNull(rewrittenMetadata);
- KotlinClassHeader originalHeader = originalMetadata.getHeader();
- KotlinClassHeader rewrittenHeader = rewrittenMetadata.getHeader();
- TestCase.assertEquals(originalHeader.getKind(), rewrittenHeader.getKind());
- TestCase.assertEquals(originalHeader.getPackageName(), rewrittenHeader.getPackageName());
- Assert.assertArrayEquals(originalHeader.getData1(), rewrittenHeader.getData1());
- Assert.assertArrayEquals(originalHeader.getData2(), rewrittenHeader.getData2());
- String expected = KotlinMetadataWriter.kotlinMetadataToString("", originalMetadata);
- String actual = KotlinMetadataWriter.kotlinMetadataToString("", rewrittenMetadata);
- TestCase.assertEquals(expected, actual);
- }
- }
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteValueClassTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteValueClassTest.java
index 6aecc85..b65643f 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteValueClassTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteValueClassTest.java
@@ -9,7 +9,6 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.StringContains.containsString;
-import static org.junit.Assert.assertNull;
import com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion;
import com.android.tools.r8.KotlinTestParameters;
@@ -20,13 +19,9 @@
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
-import junit.framework.TestCase;
-import kotlinx.metadata.jvm.KotlinClassHeader;
-import kotlinx.metadata.jvm.KotlinClassMetadata;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -112,31 +107,13 @@
}
private void inspect(CodeInspector inspector) throws IOException {
- CodeInspector stdLibInspector =
- new CodeInspector(kotlincLibJar.getForConfiguration(kotlinc, targetVersion));
- for (FoundClassSubject clazzSubject : stdLibInspector.allClasses()) {
- ClassSubject r8Clazz = inspector.clazz(clazzSubject.getOriginalName());
- assertThat(r8Clazz, isPresent());
- KotlinClassMetadata originalMetadata = clazzSubject.getKotlinClassMetadata();
- KotlinClassMetadata rewrittenMetadata = r8Clazz.getKotlinClassMetadata();
- if (originalMetadata == null) {
- assertNull(rewrittenMetadata);
- continue;
- }
- TestCase.assertNotNull(rewrittenMetadata);
- KotlinClassHeader originalHeader = originalMetadata.getHeader();
- KotlinClassHeader rewrittenHeader = rewrittenMetadata.getHeader();
- TestCase.assertEquals(originalHeader.getKind(), rewrittenHeader.getKind());
- TestCase.assertEquals(originalHeader.getPackageName(), rewrittenHeader.getPackageName());
- // We cannot assert equality of the data since it may be ordered differently. Instead we use
- // the KotlinMetadataWriter.
- String expected = KotlinMetadataWriter.kotlinMetadataToString("", originalMetadata);
- String actual = KotlinMetadataWriter.kotlinMetadataToString("", rewrittenMetadata);
- TestCase.assertEquals(expected, actual);
- if (r8Clazz.getFinalName().equals(PKG_LIB + ".Name")) {
- assertThat(actual, containsString("inlineClassUnderlyingPropertyName"));
- assertThat(actual, containsString("inlineClassUnderlyingType"));
- }
- }
+ assertEqualDeserializedMetadata(
+ inspector, new CodeInspector(kotlincLibJar.getForConfiguration(kotlinc, targetVersion)));
+ ClassSubject r8Clazz = inspector.clazz(PKG_LIB + ".Name");
+ assertThat(r8Clazz, isPresent());
+ String actual =
+ KotlinMetadataWriter.kotlinMetadataToString("", r8Clazz.getKotlinClassMetadata());
+ assertThat(actual, containsString("inlineClassUnderlyingPropertyName"));
+ assertThat(actual, containsString("inlineClassUnderlyingType"));
}
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/context_receiver_app/main.txt b/src/test/java/com/android/tools/r8/kotlin/metadata/context_receiver_app/main.txt
new file mode 100644
index 0000000..9380c6f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/context_receiver_app/main.txt
@@ -0,0 +1,46 @@
+// Copyright (c) 2023, 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.context_receiver_app
+
+import com.android.tools.r8.kotlin.metadata.context_receiver_lib.Bar
+import com.android.tools.r8.kotlin.metadata.context_receiver_lib.Foo
+import com.android.tools.r8.kotlin.metadata.context_receiver_lib.Baz
+import com.android.tools.r8.kotlin.metadata.context_receiver_lib.Printer
+import com.android.tools.r8.kotlin.metadata.context_receiver_lib.callFooBar
+
+class FooImpl : Foo {
+
+ override fun m1(): String {
+ println("FooImpl::m1")
+ return "Hello "
+ }
+}
+
+class BarImpl : Bar {
+ override fun m2(): String {
+ println("BarImpl::m2")
+ return "World!"
+ }
+}
+
+class BazImpl : Baz {
+ override fun m3(): String {
+ println("BazImpl::m3")
+ return "BazImpl::m3"
+ }
+}
+
+fun main() {
+ with (FooImpl()) {
+ with (BarImpl()) {
+ val printer = Printer()
+ printer.fooBar()
+ with (BazImpl()) {
+ println(printer.getValue)
+ println(callFooBar())
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/context_receiver_lib/lib.txt b/src/test/java/com/android/tools/r8/kotlin/metadata/context_receiver_lib/lib.txt
new file mode 100644
index 0000000..0235848
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/context_receiver_lib/lib.txt
@@ -0,0 +1,35 @@
+// Copyright (c) 2023, 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.context_receiver_lib
+
+interface Foo {
+ fun m1(): String
+}
+
+interface Bar {
+ fun m2(): String
+}
+
+interface Baz {
+ fun m3(): String
+}
+
+context(Foo, Bar)
+class Printer {
+
+ fun fooBar() {
+ m1();
+ m2();
+ }
+
+ context(Baz)
+ val getValue: String
+ get() = if (System.currentTimeMillis() == 0L) "foo" else m3()
+}
+
+context(Foo, Bar)
+fun callFooBar() : String {
+ return m1() + m2();
+}
\ No newline at end of file