From cdb542627efe97e3eb2f3b89023cc1fbd71a2957 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Wed, 17 Apr 2024 14:03:54 -0400 Subject: [PATCH] Update kotlinx-metadata APIs for changes (#1766) * Update to kotlinx-metadata 0.8.0 * Propagate lenient param * Update API * Remove redundant asClassHeader() * Update CHANGELOG * PR number chicken and egg problem --- docs/changelog.md | 1 + .../kotlinx-metadata/api/kotlinx-metadata.api | 48 +++++------ .../kotlinpoet/metadata/KotlinPoetMetadata.kt | 61 +++++++------ .../classinspectors/ElementsClassInspector.kt | 14 +-- .../ReflectiveClassInspector.kt | 12 ++- .../metadata/specs/KotlinPoetMetadataSpecs.kt | 86 ++++++++++++------- .../metadata/specs/MultiClassInspectorTest.kt | 8 +- .../specs/ReflectiveClassInspectorTest.kt | 4 +- 8 files changed, 137 insertions(+), 97 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index bb9eb3ced5..b5c9fd2f60 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -11,6 +11,7 @@ Change Log * Fix: Omit implicit modifiers on FileSpec.scriptBuilder (#1813). * Fix: Fix trailing newline in PropertySpec (#1827). * Change: kotlinx-metadata 0.9.0. Note that the `KotlinClassMetadata .read` is deprecated in 0.9.0 and replaced with `readStrict` (#1830). + * Note: we now also `lenient` parameters to map to the underlying `readStrict()` and `readLenient()` calls (#1766). * Fix: `KSAnnotation.toAnnotationSpec` writes varargs in place instead of making them an array to work around a Kotlin issue with `OptIn` annotations (#1831). * Fix: `MemberName`s without a package are now correctly imported (#1841) diff --git a/interop/kotlinx-metadata/api/kotlinx-metadata.api b/interop/kotlinx-metadata/api/kotlinx-metadata.api index 091b3030be..f03284c058 100644 --- a/interop/kotlinx-metadata/api/kotlinx-metadata.api +++ b/interop/kotlinx-metadata/api/kotlinx-metadata.api @@ -1,9 +1,9 @@ public final class com/squareup/kotlinpoet/metadata/KotlinPoetMetadata { - public static final fun readKotlinClassMetadata (Lkotlin/Metadata;)Lkotlinx/metadata/jvm/KotlinClassMetadata; - public static final fun toKmClass (Ljava/lang/Class;)Lkotlinx/metadata/KmClass; - public static final fun toKmClass (Ljavax/lang/model/element/TypeElement;)Lkotlinx/metadata/KmClass; - public static final fun toKmClass (Lkotlin/Metadata;)Lkotlinx/metadata/KmClass; - public static final fun toKmClass (Lkotlin/reflect/KClass;)Lkotlinx/metadata/KmClass; + public static final fun readKotlinClassMetadata (Lkotlin/Metadata;Z)Lkotlinx/metadata/jvm/KotlinClassMetadata; + public static final fun toKmClass (Ljava/lang/Class;Z)Lkotlinx/metadata/KmClass; + public static final fun toKmClass (Ljavax/lang/model/element/TypeElement;Z)Lkotlinx/metadata/KmClass; + public static final fun toKmClass (Lkotlin/Metadata;Z)Lkotlinx/metadata/KmClass; + public static final fun toKmClass (Lkotlin/reflect/KClass;Z)Lkotlinx/metadata/KmClass; } public abstract interface annotation class com/squareup/kotlinpoet/metadata/KotlinPoetMetadataPreview : java/lang/annotation/Annotation { @@ -11,9 +11,9 @@ public abstract interface annotation class com/squareup/kotlinpoet/metadata/Kotl public final class com/squareup/kotlinpoet/metadata/classinspectors/ElementsClassInspector : com/squareup/kotlinpoet/metadata/specs/ClassInspector { public static final field Companion Lcom/squareup/kotlinpoet/metadata/classinspectors/ElementsClassInspector$Companion; - public synthetic fun (Ljavax/lang/model/util/Elements;Ljavax/lang/model/util/Types;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (ZLjavax/lang/model/util/Elements;Ljavax/lang/model/util/Types;Lkotlin/jvm/internal/DefaultConstructorMarker;)V public fun containerData (Lkotlinx/metadata/KmDeclarationContainer;Lcom/squareup/kotlinpoet/ClassName;Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/metadata/specs/ContainerData; - public static final fun create (Ljavax/lang/model/util/Elements;Ljavax/lang/model/util/Types;)Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector; + public static final fun create (ZLjavax/lang/model/util/Elements;Ljavax/lang/model/util/Types;)Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector; public fun declarationContainerFor (Lcom/squareup/kotlinpoet/ClassName;)Lkotlinx/metadata/KmDeclarationContainer; public fun enumEntry (Lcom/squareup/kotlinpoet/ClassName;Ljava/lang/String;)Lcom/squareup/kotlinpoet/metadata/specs/EnumEntryData; public fun getSupportsNonRuntimeRetainedAnnotations ()Z @@ -22,14 +22,14 @@ public final class com/squareup/kotlinpoet/metadata/classinspectors/ElementsClas } public final class com/squareup/kotlinpoet/metadata/classinspectors/ElementsClassInspector$Companion { - public final fun create (Ljavax/lang/model/util/Elements;Ljavax/lang/model/util/Types;)Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector; + public final fun create (ZLjavax/lang/model/util/Elements;Ljavax/lang/model/util/Types;)Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector; } public final class com/squareup/kotlinpoet/metadata/classinspectors/ReflectiveClassInspector : com/squareup/kotlinpoet/metadata/specs/ClassInspector { public static final field Companion Lcom/squareup/kotlinpoet/metadata/classinspectors/ReflectiveClassInspector$Companion; - public synthetic fun (Ljava/lang/ClassLoader;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (ZLjava/lang/ClassLoader;Lkotlin/jvm/internal/DefaultConstructorMarker;)V public fun containerData (Lkotlinx/metadata/KmDeclarationContainer;Lcom/squareup/kotlinpoet/ClassName;Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/metadata/specs/ContainerData; - public static final fun create (Ljava/lang/ClassLoader;)Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector; + public static final fun create (ZLjava/lang/ClassLoader;)Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector; public fun declarationContainerFor (Lcom/squareup/kotlinpoet/ClassName;)Lkotlinx/metadata/KmDeclarationContainer; public fun enumEntry (Lcom/squareup/kotlinpoet/ClassName;Ljava/lang/String;)Lcom/squareup/kotlinpoet/metadata/specs/EnumEntryData; public fun getSupportsNonRuntimeRetainedAnnotations ()Z @@ -38,8 +38,8 @@ public final class com/squareup/kotlinpoet/metadata/classinspectors/ReflectiveCl } public final class com/squareup/kotlinpoet/metadata/classinspectors/ReflectiveClassInspector$Companion { - public final fun create (Ljava/lang/ClassLoader;)Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector; - public static synthetic fun create$default (Lcom/squareup/kotlinpoet/metadata/classinspectors/ReflectiveClassInspector$Companion;Ljava/lang/ClassLoader;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector; + public final fun create (ZLjava/lang/ClassLoader;)Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector; + public static synthetic fun create$default (Lcom/squareup/kotlinpoet/metadata/classinspectors/ReflectiveClassInspector$Companion;ZLjava/lang/ClassLoader;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector; } public final class com/squareup/kotlinpoet/metadata/specs/ClassData : com/squareup/kotlinpoet/metadata/specs/ContainerData { @@ -196,22 +196,22 @@ public final class com/squareup/kotlinpoet/metadata/specs/KmTypesKt { public final class com/squareup/kotlinpoet/metadata/specs/KotlinPoetMetadataSpecs { public static final fun getPackageName (Ljavax/lang/model/element/Element;)Ljava/lang/String; - public static final fun toFileSpec (Ljava/lang/Class;Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector;)Lcom/squareup/kotlinpoet/FileSpec; - public static final fun toFileSpec (Ljavax/lang/model/element/TypeElement;Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector;)Lcom/squareup/kotlinpoet/FileSpec; - public static final fun toFileSpec (Lkotlin/reflect/KClass;Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector;)Lcom/squareup/kotlinpoet/FileSpec; + public static final fun toFileSpec (Ljava/lang/Class;ZLcom/squareup/kotlinpoet/metadata/specs/ClassInspector;)Lcom/squareup/kotlinpoet/FileSpec; + public static final fun toFileSpec (Ljavax/lang/model/element/TypeElement;ZLcom/squareup/kotlinpoet/metadata/specs/ClassInspector;)Lcom/squareup/kotlinpoet/FileSpec; + public static final fun toFileSpec (Lkotlin/reflect/KClass;ZLcom/squareup/kotlinpoet/metadata/specs/ClassInspector;)Lcom/squareup/kotlinpoet/FileSpec; public static final fun toFileSpec (Lkotlinx/metadata/KmClass;Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector;Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/FileSpec; public static final fun toFileSpec (Lkotlinx/metadata/KmPackage;Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector;Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/FileSpec; - public static synthetic fun toFileSpec$default (Ljava/lang/Class;Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec; - public static synthetic fun toFileSpec$default (Ljavax/lang/model/element/TypeElement;Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec; - public static synthetic fun toFileSpec$default (Lkotlin/reflect/KClass;Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec; + public static synthetic fun toFileSpec$default (Ljava/lang/Class;ZLcom/squareup/kotlinpoet/metadata/specs/ClassInspector;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec; + public static synthetic fun toFileSpec$default (Ljavax/lang/model/element/TypeElement;ZLcom/squareup/kotlinpoet/metadata/specs/ClassInspector;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec; + public static synthetic fun toFileSpec$default (Lkotlin/reflect/KClass;ZLcom/squareup/kotlinpoet/metadata/specs/ClassInspector;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec; public static synthetic fun toFileSpec$default (Lkotlinx/metadata/KmClass;Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector;Lcom/squareup/kotlinpoet/ClassName;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec; - public static final fun toTypeSpec (Ljava/lang/Class;Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector;)Lcom/squareup/kotlinpoet/TypeSpec; - public static final fun toTypeSpec (Ljavax/lang/model/element/TypeElement;Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector;)Lcom/squareup/kotlinpoet/TypeSpec; - public static final fun toTypeSpec (Lkotlin/reflect/KClass;Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector;)Lcom/squareup/kotlinpoet/TypeSpec; + public static final fun toTypeSpec (Ljava/lang/Class;ZLcom/squareup/kotlinpoet/metadata/specs/ClassInspector;)Lcom/squareup/kotlinpoet/TypeSpec; + public static final fun toTypeSpec (Ljavax/lang/model/element/TypeElement;ZLcom/squareup/kotlinpoet/metadata/specs/ClassInspector;)Lcom/squareup/kotlinpoet/TypeSpec; + public static final fun toTypeSpec (Lkotlin/reflect/KClass;ZLcom/squareup/kotlinpoet/metadata/specs/ClassInspector;)Lcom/squareup/kotlinpoet/TypeSpec; public static final fun toTypeSpec (Lkotlinx/metadata/KmClass;Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector;Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/TypeSpec; - public static synthetic fun toTypeSpec$default (Ljava/lang/Class;Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/TypeSpec; - public static synthetic fun toTypeSpec$default (Ljavax/lang/model/element/TypeElement;Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/TypeSpec; - public static synthetic fun toTypeSpec$default (Lkotlin/reflect/KClass;Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/TypeSpec; + public static synthetic fun toTypeSpec$default (Ljava/lang/Class;ZLcom/squareup/kotlinpoet/metadata/specs/ClassInspector;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/TypeSpec; + public static synthetic fun toTypeSpec$default (Ljavax/lang/model/element/TypeElement;ZLcom/squareup/kotlinpoet/metadata/specs/ClassInspector;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/TypeSpec; + public static synthetic fun toTypeSpec$default (Lkotlin/reflect/KClass;ZLcom/squareup/kotlinpoet/metadata/specs/ClassInspector;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/TypeSpec; public static synthetic fun toTypeSpec$default (Lkotlinx/metadata/KmClass;Lcom/squareup/kotlinpoet/metadata/specs/ClassInspector;Lcom/squareup/kotlinpoet/ClassName;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/TypeSpec; } diff --git a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/KotlinPoetMetadata.kt b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/KotlinPoetMetadata.kt index 08338983cc..12fef0fce4 100644 --- a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/KotlinPoetMetadata.kt +++ b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/KotlinPoetMetadata.kt @@ -35,28 +35,45 @@ import kotlinx.metadata.jvm.Metadata @Target(CLASS, FUNCTION, PROPERTY) public annotation class KotlinPoetMetadataPreview -/** @return a new [KmClass] representation of the Kotlin metadata for [this] class. */ +/** + * @param lenient see docs on [KotlinClassMetadata.readStrict] and [KotlinClassMetadata.readLenient] for more details. + * @return a new [KmClass] representation of the Kotlin metadata for [this] class. + */ @KotlinPoetMetadataPreview -public fun KClass<*>.toKmClass(): KmClass = java.toKmClass() +public fun KClass<*>.toKmClass(lenient: Boolean): KmClass = java.toKmClass(lenient) -/** @return a new [KmClass] representation of the Kotlin metadata for [this] class. */ +/** + * @param lenient see docs on [KotlinClassMetadata.readStrict] and [KotlinClassMetadata.readLenient] for more details. + * @return a new [KmClass] representation of the Kotlin metadata for [this] class. + */ @KotlinPoetMetadataPreview -public fun Class<*>.toKmClass(): KmClass = readMetadata(::getAnnotation).toKmClass() +public fun Class<*>.toKmClass(lenient: Boolean): KmClass = readMetadata(::getAnnotation).toKmClass(lenient) -/** @return a new [KmClass] representation of the Kotlin metadata for [this] type. */ +/** + * @param lenient see docs on [KotlinClassMetadata.readStrict] and [KotlinClassMetadata.readLenient] for more details. + * @return a new [KmClass] representation of the Kotlin metadata for [this] type. + */ @KotlinPoetMetadataPreview -public fun TypeElement.toKmClass(): KmClass = readMetadata(::getAnnotation).toKmClass() +public fun TypeElement.toKmClass(lenient: Boolean): KmClass = readMetadata(::getAnnotation).toKmClass(lenient) +/** + * @param lenient see docs on [KotlinClassMetadata.readStrict] and [KotlinClassMetadata.readLenient] for more details. + */ @KotlinPoetMetadataPreview -public fun Metadata.toKmClass(): KmClass { - return toKotlinClassMetadata() +public fun Metadata.toKmClass(lenient: Boolean): KmClass { + return toKotlinClassMetadata(lenient) .kmClass } +/** + * @param lenient see docs on [KotlinClassMetadata.readStrict] and [KotlinClassMetadata.readLenient] for more details. + */ @KotlinPoetMetadataPreview -public inline fun Metadata.toKotlinClassMetadata(): T { +public inline fun Metadata.toKotlinClassMetadata( + lenient: Boolean, +): T { val expectedType = T::class - val metadata = readKotlinClassMetadata() + val metadata = readKotlinClassMetadata(lenient) return when (expectedType) { KotlinClassMetadata.Class::class -> { check(metadata is KotlinClassMetadata.Class) @@ -82,14 +99,16 @@ public inline fun Metadata.toKotlinClassMetada * Returns the [KotlinClassMetadata] this represents. In general you should only use this function * when you don't know what the underlying [KotlinClassMetadata] subtype is, otherwise you should * use one of the more direct functions like [toKmClass]. + * + * @param lenient see docs on [KotlinClassMetadata.readStrict] and [KotlinClassMetadata.readLenient] for more details. */ @KotlinPoetMetadataPreview -public fun Metadata.readKotlinClassMetadata(): KotlinClassMetadata { - val metadata = KotlinClassMetadata.readStrict(asClassHeader()) - checkNotNull(metadata) { - "Could not parse metadata! Try bumping kotlinpoet and/or kotlinx-metadata version." +public fun Metadata.readKotlinClassMetadata(lenient: Boolean): KotlinClassMetadata { + return if (lenient) { + KotlinClassMetadata.readLenient(this) + } else { + KotlinClassMetadata.readStrict(this) } - return metadata } private inline fun readMetadata(lookup: ((Class) -> Metadata?)): Metadata { @@ -97,15 +116,3 @@ private inline fun readMetadata(lookup: ((Class) -> Metadata?)): Metad "No Metadata annotation found! Must be Kotlin code built with the standard library on the classpath." } } - -private fun Metadata.asClassHeader(): Metadata { - return Metadata( - kind = kind, - metadataVersion = metadataVersion, - data1 = data1, - data2 = data2, - extraString = extraString, - packageName = packageName, - extraInt = extraInt, - ) -} diff --git a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ElementsClassInspector.kt b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ElementsClassInspector.kt index 0282913c9d..b3abb1965b 100644 --- a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ElementsClassInspector.kt +++ b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ElementsClassInspector.kt @@ -92,6 +92,7 @@ private typealias ElementsModifier = javax.lang.model.element.Modifier */ @KotlinPoetMetadataPreview public class ElementsClassInspector private constructor( + private val lenient: Boolean, private val elements: Elements, private val types: Types, ) : ClassInspector { @@ -115,7 +116,7 @@ public class ElementsClassInspector private constructor( ?: error("No type element found for: $className.") val metadata = typeElement.getAnnotation(Metadata::class.java) - return when (val kotlinClassMetadata = metadata.readKotlinClassMetadata()) { + return when (val kotlinClassMetadata = metadata.readKotlinClassMetadata(lenient)) { is KotlinClassMetadata.Class -> kotlinClassMetadata.kmClass is KotlinClassMetadata.FileFacade -> kotlinClassMetadata.kmPackage else -> TODO("Not implemented yet: ${kotlinClassMetadata.javaClass.simpleName}") @@ -207,7 +208,7 @@ public class ElementsClassInspector private constructor( .filter { types.isSubtype(enumTypeAsType, it.superclass) } .find { it.simpleName.contentEquals(memberName) }.toOptional() }.nullableValue - val declarationContainer = member?.getAnnotation(Metadata::class.java)?.toKmClass() + val declarationContainer = member?.getAnnotation(Metadata::class.java)?.toKmClass(lenient) val entry = ElementFilter.fieldsIn(enumType.enclosedElements) .find { it.simpleName.contentEquals(memberName) } @@ -571,11 +572,14 @@ public class ElementsClassInspector private constructor( } public companion object { - /** @return an [Elements]-based implementation of [ClassInspector]. */ + /** + * @param lenient see docs on [KotlinClassMetadata.readStrict] and [KotlinClassMetadata.readLenient] for more details. + * @return an [Elements]-based implementation of [ClassInspector]. + */ @JvmStatic @KotlinPoetMetadataPreview - public fun create(elements: Elements, types: Types): ClassInspector { - return ElementsClassInspector(elements, types) + public fun create(lenient: Boolean, elements: Elements, types: Types): ClassInspector { + return ElementsClassInspector(lenient, elements, types) } private val JVM_STATIC = JvmStatic::class.asClassName() diff --git a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ReflectiveClassInspector.kt b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ReflectiveClassInspector.kt index d4c74eb3db..df578d46c9 100644 --- a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ReflectiveClassInspector.kt +++ b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ReflectiveClassInspector.kt @@ -75,6 +75,7 @@ import kotlinx.metadata.kind @KotlinPoetMetadataPreview public class ReflectiveClassInspector private constructor( + private val lenient: Boolean, private val classLoader: ClassLoader?, ) : ClassInspector { @@ -105,7 +106,7 @@ public class ReflectiveClassInspector private constructor( ?: error("No type element found for: $className.") val metadata = clazz.getAnnotation(Metadata::class.java) - return when (val kotlinClassMetadata = metadata.readKotlinClassMetadata()) { + return when (val kotlinClassMetadata = metadata.readKotlinClassMetadata(lenient)) { is KotlinClassMetadata.Class -> kotlinClassMetadata.kmClass is KotlinClassMetadata.FileFacade -> kotlinClassMetadata.kmPackage else -> TODO("Not implemented yet: ${kotlinClassMetadata.javaClass.simpleName}") @@ -251,7 +252,7 @@ public class ReflectiveClassInspector private constructor( // class. null } else { - enumEntry.javaClass.getAnnotation(Metadata::class.java)?.toKmClass() + enumEntry.javaClass.getAnnotation(Metadata::class.java)?.toKmClass(lenient) }, annotations = clazz.getField(enumEntry.name).annotationSpecs(), ) @@ -542,10 +543,13 @@ public class ReflectiveClassInspector private constructor( } public companion object { + /** + * @param lenient see docs on [KotlinClassMetadata.readStrict] and [KotlinClassMetadata.readLenient] for more details. + */ @JvmStatic @KotlinPoetMetadataPreview - public fun create(classLoader: ClassLoader? = null): ClassInspector { - return ReflectiveClassInspector(classLoader) + public fun create(lenient: Boolean, classLoader: ClassLoader? = null): ClassInspector { + return ReflectiveClassInspector(lenient, classLoader) } private val Class<*>.descriptor: String diff --git a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/KotlinPoetMetadataSpecs.kt b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/KotlinPoetMetadataSpecs.kt index 7317a74050..322a25ed39 100644 --- a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/KotlinPoetMetadataSpecs.kt +++ b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/KotlinPoetMetadataSpecs.kt @@ -33,13 +33,11 @@ import com.squareup.kotlinpoet.KModifier.CROSSINLINE import com.squareup.kotlinpoet.KModifier.DATA import com.squareup.kotlinpoet.KModifier.EXPECT import com.squareup.kotlinpoet.KModifier.EXTERNAL -import com.squareup.kotlinpoet.KModifier.FINAL import com.squareup.kotlinpoet.KModifier.INFIX import com.squareup.kotlinpoet.KModifier.INLINE import com.squareup.kotlinpoet.KModifier.INNER import com.squareup.kotlinpoet.KModifier.LATEINIT import com.squareup.kotlinpoet.KModifier.NOINLINE -import com.squareup.kotlinpoet.KModifier.OPEN import com.squareup.kotlinpoet.KModifier.OPERATOR import com.squareup.kotlinpoet.KModifier.PRIVATE import com.squareup.kotlinpoet.KModifier.PUBLIC @@ -112,6 +110,7 @@ import kotlinx.metadata.isTailrec import kotlinx.metadata.isValue import kotlinx.metadata.isVar import kotlinx.metadata.jvm.JvmMethodSignature +import kotlinx.metadata.jvm.KotlinClassMetadata import kotlinx.metadata.jvm.getterSignature import kotlinx.metadata.jvm.setterSignature import kotlinx.metadata.jvm.signature @@ -120,45 +119,69 @@ import kotlinx.metadata.kind import kotlinx.metadata.modality import kotlinx.metadata.visibility -/** @return a [TypeSpec] ABI representation of this [KClass]. */ +/** + * @param lenient see docs on [KotlinClassMetadata.readStrict] and [KotlinClassMetadata.readLenient] for more details. + * @return a [TypeSpec] ABI representation of this [KClass]. + */ @KotlinPoetMetadataPreview public fun KClass<*>.toTypeSpec( + lenient: Boolean, classInspector: ClassInspector? = null, -): TypeSpec = java.toTypeSpec(classInspector) +): TypeSpec = java.toTypeSpec(lenient, classInspector) -/** @return a [TypeSpec] ABI representation of this [KClass]. */ +/** + * @param lenient see docs on [KotlinClassMetadata.readStrict] and [KotlinClassMetadata.readLenient] for more details. + * @return a [TypeSpec] ABI representation of this [KClass]. + */ @OptIn(DelicateKotlinPoetApi::class) @KotlinPoetMetadataPreview public fun Class<*>.toTypeSpec( + lenient: Boolean, classInspector: ClassInspector? = null, -): TypeSpec = toKmClass().toTypeSpec(classInspector, asClassName()) +): TypeSpec = toKmClass(lenient).toTypeSpec(classInspector, asClassName()) -/** @return a [TypeSpec] ABI representation of this [TypeElement]. */ +/** + * @param lenient see docs on [KotlinClassMetadata.readStrict] and [KotlinClassMetadata.readLenient] for more details. + * @return a [TypeSpec] ABI representation of this [TypeElement]. + */ @OptIn(DelicateKotlinPoetApi::class) @KotlinPoetMetadataPreview public fun TypeElement.toTypeSpec( + lenient: Boolean, classInspector: ClassInspector? = null, -): TypeSpec = toKmClass().toTypeSpec(classInspector, asClassName()) +): TypeSpec = toKmClass(lenient).toTypeSpec(classInspector, asClassName()) -/** @return a [FileSpec] ABI representation of this [KClass]. */ +/** + * @param lenient see docs on [KotlinClassMetadata.readStrict] and [KotlinClassMetadata.readLenient] for more details. + * @return a [FileSpec] ABI representation of this [KClass]. + */ @KotlinPoetMetadataPreview public fun KClass<*>.toFileSpec( + lenient: Boolean, classInspector: ClassInspector? = null, -): FileSpec = java.toFileSpec(classInspector) +): FileSpec = java.toFileSpec(lenient, classInspector) -/** @return a [FileSpec] ABI representation of this [KClass]. */ +/** + * @param lenient see docs on [KotlinClassMetadata.readStrict] and [KotlinClassMetadata.readLenient] for more details. + * @return a [FileSpec] ABI representation of this [KClass]. + */ @KotlinPoetMetadataPreview public fun Class<*>.toFileSpec( + lenient: Boolean, classInspector: ClassInspector? = null, -): FileSpec = FileSpec.get(`package`.name, toTypeSpec(classInspector)) +): FileSpec = FileSpec.get(`package`.name, toTypeSpec(lenient, classInspector)) -/** @return a [FileSpec] ABI representation of this [TypeElement]. */ +/** + * @param lenient see docs on [KotlinClassMetadata.readStrict] and [KotlinClassMetadata.readLenient] for more details. + * @return a [FileSpec] ABI representation of this [TypeElement]. + */ @KotlinPoetMetadataPreview public fun TypeElement.toFileSpec( + lenient: Boolean, classInspector: ClassInspector? = null, ): FileSpec = FileSpec.get( packageName = packageName, - typeSpec = toTypeSpec(classInspector), + typeSpec = toTypeSpec(lenient, classInspector), ) /** @return a [TypeSpec] ABI representation of this [KmClass]. */ @@ -670,21 +693,23 @@ private fun KmProperty.toPropertySpec( } } } - setterSignature?.let { setterSignature -> - if (containerData is ClassData && - !containerData.declarationContainer.isAnnotation && - !containerData.declarationContainer.isInterface && - classInspector?.supportsNonRuntimeRetainedAnnotations == false && - modality != Modality.OPEN && modality != Modality.ABSTRACT - ) { - // Infer if JvmName was used - // We skip annotation types for this because they can't have vars. - // We skip interface types or open/abstract properties because they can't have @JvmName. - setterSignature.jvmNameAnnotation( - metadataName = "set${name.safeCapitalize(Locale.US)}", - useSiteTarget = UseSiteTarget.SET, - )?.let { jvmNameAnnotation -> - mutableAnnotations += jvmNameAnnotation + if (setter != null) { + setterSignature?.let { setterSignature -> + if (containerData is ClassData && + !containerData.declarationContainer.isAnnotation && + !containerData.declarationContainer.isInterface && + classInspector?.supportsNonRuntimeRetainedAnnotations == false && + modality != Modality.OPEN && modality != Modality.ABSTRACT + ) { + // Infer if JvmName was used + // We skip annotation types for this because they can't have vars. + // We skip interface types or open/abstract properties because they can't have @JvmName. + setterSignature.jvmNameAnnotation( + metadataName = "set${name.safeCapitalize(Locale.US)}", + useSiteTarget = UseSiteTarget.SET, + )?.let { jvmNameAnnotation -> + mutableAnnotations += jvmNameAnnotation + } } } } @@ -780,7 +805,7 @@ private fun KmProperty.toPropertySpec( )?.let(::getter) } if (setter != null && !isDelegated && modality != Modality.ABSTRACT) { - propertyAccessor(modifierSet, this@toPropertySpec.setter!!, FunSpec.setterBuilder(), isOverride)?.let(::setter) + propertyAccessor(modifierSet, setter!!, FunSpec.setterBuilder(), isOverride)?.let(::setter) } } .tag(this) @@ -880,7 +905,6 @@ private inline fun setOf(body: MutableSet.() -> Unit): Set { private val METADATA = Metadata::class.asClassName() -@Suppress("DEPRECATION") private val JVM_DEFAULT = ClassName("kotlin.jvm", "JvmDefault") private val JVM_STATIC = JvmStatic::class.asClassName() diff --git a/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/MultiClassInspectorTest.kt b/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/MultiClassInspectorTest.kt index 6bb9192a51..185da021d5 100644 --- a/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/MultiClassInspectorTest.kt +++ b/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/MultiClassInspectorTest.kt @@ -59,12 +59,12 @@ abstract class MultiClassInspectorTest { }, REFLECTIVE { override fun create(testInstance: MultiClassInspectorTest): ClassInspector { - return ReflectiveClassInspector.create() + return ReflectiveClassInspector.create(lenient = false) } }, ELEMENTS { override fun create(testInstance: MultiClassInspectorTest): ClassInspector { - return ElementsClassInspector.create(testInstance.compilation.elements, testInstance.compilation.types) + return ElementsClassInspector.create(lenient = false, testInstance.compilation.elements, testInstance.compilation.types) } }, ; @@ -107,12 +107,12 @@ abstract class MultiClassInspectorTest { } protected fun KClass<*>.toTypeSpecWithTestHandler(): TypeSpec { - return toTypeSpec(classInspectorType.create(this@MultiClassInspectorTest)) + return toTypeSpec(lenient = false, classInspectorType.create(this@MultiClassInspectorTest)) } protected fun KClass<*>.toFileSpecWithTestHandler(): FileSpec { val classInspector = classInspectorType.create(this@MultiClassInspectorTest) - return java.annotations.filterIsInstance().first().toKotlinClassMetadata() + return java.annotations.filterIsInstance().first().toKotlinClassMetadata(lenient = false) .kmPackage .toFileSpec(classInspector, asClassName()) } diff --git a/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/ReflectiveClassInspectorTest.kt b/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/ReflectiveClassInspectorTest.kt index a4ecc3defa..13b1703359 100644 --- a/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/ReflectiveClassInspectorTest.kt +++ b/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/ReflectiveClassInspectorTest.kt @@ -41,7 +41,7 @@ class ReflectiveClassInspectorTest { */ @Test fun standardClassLoaderTest() { - val classInspector = ReflectiveClassInspector.create() + val classInspector = ReflectiveClassInspector.create(lenient = false) val className = Person::class.asClassName() val declarationContainer = classInspector.declarationContainerFor(className) assertNotNull(declarationContainer) @@ -74,7 +74,7 @@ class ReflectiveClassInspectorTest { assertEquals(KotlinCompilation.ExitCode.OK, result.exitCode) val classLoader = result.classLoader - val classInspector = ReflectiveClassInspector.create(classLoader) + val classInspector = ReflectiveClassInspector.create(lenient = false, classLoader) val declarationContainer = classInspector.declarationContainerFor(testClassName)