From 1db8bf3cdd157981d1e153ebfe7d719d3cf1fd06 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 21 Jan 2024 21:51:17 +0900 Subject: [PATCH 1/9] Update kogera version --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 4d4eecb3..bab72278 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,7 +16,7 @@ val jacksonVersion = libs.versions.jackson.get() val generatedSrcPath = "${layout.buildDirectory.get()}/generated/kotlin" group = groupStr -version = "${jacksonVersion}-beta10" +version = "${jacksonVersion}-beta11" repositories { mavenCentral() From d11be42fb9180674c63ebaea682d62a4a2d7ef11 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 4 Feb 2024 09:57:37 +0900 Subject: [PATCH 2/9] Update workflow --- .github/workflows/lint-and-test-dev.yml | 24 +++++++++++++----------- .github/workflows/test-main.yml | 10 +++++----- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/.github/workflows/lint-and-test-dev.yml b/.github/workflows/lint-and-test-dev.yml index f3df20de..479d8a24 100644 --- a/.github/workflows/lint-and-test-dev.yml +++ b/.github/workflows/lint-and-test-dev.yml @@ -28,6 +28,10 @@ on: - "**.kt" - "**.java" - .github/workflows/lint-and-test-dev.yml + +permissions: + contents: write # for Dependency submission + jobs: lint-and-test-dev: name: lint-and-test-dev @@ -39,20 +43,18 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Validate Gradle wrapper - uses: gradle/wrapper-validation-action@v1 + uses: gradle/wrapper-validation-action@v2 - name: Set up java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '8' distribution: 'corretto' - - name: Lint - uses: gradle/gradle-build-action@v2 + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v3 with: - arguments: lintKotlin + dependency-graph: generate-and-submit + dependency-graph-continue-on-failure: false + - name: Lint + run: ./gradlew lintKotlin - name: Test - uses: gradle/gradle-build-action@v2 - with: - arguments: test - # TODO: Prepare a separate WF to be executed only when there is a change in build.gradle. - - name: Run snapshot action - uses: mikepenz/gradle-dependency-submission@v0.9.1 + run: ./gradlew lintKotlin test diff --git a/.github/workflows/test-main.yml b/.github/workflows/test-main.yml index 26cfd988..fea208cd 100644 --- a/.github/workflows/test-main.yml +++ b/.github/workflows/test-main.yml @@ -63,13 +63,13 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Validate Gradle wrapper - uses: gradle/wrapper-validation-action@v1 + uses: gradle/wrapper-validation-action@v2 - name: 'Set up java ${{ matrix.java-version }}' - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '${{ matrix.java-version }}' distribution: 'corretto' + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v3 - name: Test - uses: gradle/gradle-build-action@v2 - with: - arguments: test + run: ./gradlew lintKotlin test From 2071b0328438b158b19da48d020104af62c1a362 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 4 Feb 2024 10:08:53 +0900 Subject: [PATCH 3/9] Fix build gradle --- build.gradle.kts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index bab72278..7000ab8f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -98,6 +98,11 @@ public val kogeraVersion: Version = VersionUtil.parseVersion("$version", "$group into(file("$generatedSrcPath/${packageStr.replace(".", "/")}")) } + // Added to avoid failure in generating dependency graphs in CI. + lintKotlinMain { + dependsOn.add(generateKogeraVersion) + } + compileKotlin { dependsOn.add(generateKogeraVersion) kotlinOptions.jvmTarget = "1.8" From 76778427ddb931300f940549b52a6c9122ed6b2a Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sat, 10 Feb 2024 02:32:26 +0900 Subject: [PATCH 4/9] Modified to not use deprecated API see: https://github.com/JetBrains/kotlin/blob/e1df52bc0255d24651141f5a2094d3ab7e61d4d2/libraries/kotlinx-metadata/src/kotlinx/metadata/Attributes.kt#L120 https://github.com/JetBrains/kotlin/blob/e1df52bc0255d24651141f5a2094d3ab7e61d4d2/libraries/kotlinx-metadata/src/kotlinx/metadata/internal/FlagDelegatesImpl.kt#L26 --- .../github/projectmapk/jackson/module/kogera/JmClass.kt | 9 +++++---- .../singletonSupport/KotlinBeanDeserializerModifier.kt | 6 ++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/JmClass.kt b/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/JmClass.kt index dad46bb3..02a8a6de 100644 --- a/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/JmClass.kt +++ b/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/JmClass.kt @@ -1,5 +1,6 @@ package io.github.projectmapk.jackson.module.kogera +import kotlinx.metadata.ClassKind import kotlinx.metadata.ClassName import kotlinx.metadata.ExperimentalContextReceivers import kotlinx.metadata.Flags @@ -18,7 +19,6 @@ import kotlinx.metadata.KmTypeParameterVisitor import kotlinx.metadata.KmTypeVisitor import kotlinx.metadata.KmVariance import kotlinx.metadata.KmVersionRequirementVisitor -import kotlinx.metadata.flagsOf import kotlinx.metadata.internal.accept import kotlinx.metadata.internal.metadata.jvm.deserialization.JvmProtoBufUtil import kotlinx.metadata.jvm.getterSignature @@ -26,6 +26,7 @@ import kotlinx.metadata.jvm.signature import java.lang.reflect.Constructor import java.lang.reflect.Field import java.lang.reflect.Method +import kotlinx.metadata.internal.metadata.deserialization.Flags as ProtoFlags // KmClassVisitor with all processing disabled as much as possible to reduce load internal sealed class ReducedKmClassVisitor : KmClassVisitor() { @@ -95,7 +96,7 @@ internal sealed interface JmClass { } } - val flags: Flags + val kind: ClassKind val constructors: List val sealedSubclasses: List val inlineClassUnderlyingType: KmType? @@ -120,7 +121,7 @@ private class JmClassImpl( override val properties: List private var companionPropName: String? = null - override var flags: Flags = flagsOf() + override lateinit var kind: ClassKind override val constructors: MutableList = mutableListOf() override val sealedSubclasses: MutableList = mutableListOf() override var inlineClassUnderlyingType: KmType? = null @@ -181,7 +182,7 @@ private class JmClassImpl( // KmClassVisitor override fun visit(flags: Flags, name: ClassName) { - this.flags = flags + kind = ClassKind.values()[ProtoFlags.CLASS_KIND.get(flags).number] } override fun visitProperty(flags: Flags, name: String, getterFlags: Flags, setterFlags: Flags): KmPropertyVisitor = diff --git a/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/deser/singletonSupport/KotlinBeanDeserializerModifier.kt b/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/deser/singletonSupport/KotlinBeanDeserializerModifier.kt index db2d9d66..8eb7ef6a 100644 --- a/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/deser/singletonSupport/KotlinBeanDeserializerModifier.kt +++ b/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/deser/singletonSupport/KotlinBeanDeserializerModifier.kt @@ -5,7 +5,7 @@ import com.fasterxml.jackson.databind.DeserializationConfig import com.fasterxml.jackson.databind.JsonDeserializer import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier import io.github.projectmapk.jackson.module.kogera.ReflectionCache -import kotlinx.metadata.Flag +import kotlinx.metadata.ClassKind import java.io.Serializable // [module-kotlin#225]: keep Kotlin singletons as singletons @@ -19,10 +19,8 @@ internal class KotlinBeanDeserializerModifier( } private fun objectSingletonInstance(beanClass: Class<*>): Any? = cache.getJmClass(beanClass)?.let { - val flags = it.flags - // It is not assumed that the companion object is the target - if (Flag.Class.IS_OBJECT(flags) && !Flag.Class.IS_COMPANION_OBJECT(flags)) { + if (it.kind == ClassKind.OBJECT) { beanClass.getDeclaredField("INSTANCE").get(null) } else { null From e7f0d2185719d093399398ccc9fb43a86b19dcaf Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sat, 10 Feb 2024 23:28:24 +0900 Subject: [PATCH 5/9] Update kotlinx-metadata-jvm --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1578720a..e730c845 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ junit = "5.10.1" [libraries] kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib" } -kotlinx-metadata-jvm = "org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.7.0" +kotlinx-metadata-jvm = "org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.9.0" jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" } jackson-annotations = { module = "com.fasterxml.jackson.core:jackson-annotations", version.ref = "jackson" } From f1c4186bbb38ebba6e781887236c3b31f7a5e25c Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 11 Feb 2024 00:21:04 +0900 Subject: [PATCH 6/9] Modified based on KmClass --- .../jackson/module/kogera/InternalCommons.kt | 6 + .../jackson/module/kogera/JmClass.kt | 134 ++++-------------- .../jackson/module/kogera/ReflectionCache.kt | 4 +- 3 files changed, 32 insertions(+), 112 deletions(-) diff --git a/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/InternalCommons.kt b/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/InternalCommons.kt index dd28bf91..63f29a15 100644 --- a/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/InternalCommons.kt +++ b/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/InternalCommons.kt @@ -1,10 +1,12 @@ package io.github.projectmapk.jackson.module.kogera import com.fasterxml.jackson.annotation.JsonCreator +import kotlinx.metadata.KmClass import kotlinx.metadata.KmClassifier import kotlinx.metadata.KmType import kotlinx.metadata.isNullable import kotlinx.metadata.jvm.JvmMethodSignature +import kotlinx.metadata.jvm.KotlinClassMetadata import java.lang.reflect.AnnotatedElement import java.lang.reflect.Constructor import java.lang.reflect.Method @@ -12,6 +14,10 @@ import java.lang.reflect.Method internal typealias JavaDuration = java.time.Duration internal typealias KotlinDuration = kotlin.time.Duration +internal fun Class<*>.toKmClass(): KmClass? = getAnnotation(Metadata::class.java)?.let { + (KotlinClassMetadata.readStrict(it) as KotlinClassMetadata.Class).kmClass +} + internal fun Class<*>.isUnboxableValueClass() = this.isAnnotationPresent(JvmInline::class.java) // JmClass must be value class. diff --git a/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/JmClass.kt b/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/JmClass.kt index 02a8a6de..0bceedcb 100644 --- a/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/JmClass.kt +++ b/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/JmClass.kt @@ -1,26 +1,15 @@ +// Visitor API has already been deprecated, but the error is being suppressed for now. +@file:Suppress("DEPRECATION_ERROR") + package io.github.projectmapk.jackson.module.kogera import kotlinx.metadata.ClassKind import kotlinx.metadata.ClassName -import kotlinx.metadata.ExperimentalContextReceivers -import kotlinx.metadata.Flags -import kotlinx.metadata.KmClassExtensionVisitor -import kotlinx.metadata.KmClassVisitor +import kotlinx.metadata.KmClass import kotlinx.metadata.KmConstructor -import kotlinx.metadata.KmConstructorVisitor -import kotlinx.metadata.KmExtensionType import kotlinx.metadata.KmFunction -import kotlinx.metadata.KmFunctionVisitor import kotlinx.metadata.KmProperty -import kotlinx.metadata.KmPropertyVisitor import kotlinx.metadata.KmType -import kotlinx.metadata.KmTypeAliasVisitor -import kotlinx.metadata.KmTypeParameterVisitor -import kotlinx.metadata.KmTypeVisitor -import kotlinx.metadata.KmVariance -import kotlinx.metadata.KmVersionRequirementVisitor -import kotlinx.metadata.internal.accept -import kotlinx.metadata.internal.metadata.jvm.deserialization.JvmProtoBufUtil import kotlinx.metadata.jvm.getterSignature import kotlinx.metadata.jvm.signature import java.lang.reflect.Constructor @@ -28,62 +17,13 @@ import java.lang.reflect.Field import java.lang.reflect.Method import kotlinx.metadata.internal.metadata.deserialization.Flags as ProtoFlags -// KmClassVisitor with all processing disabled as much as possible to reduce load -internal sealed class ReducedKmClassVisitor : KmClassVisitor() { - final override val delegate: KmClassVisitor? get() = null - - // from KmDeclarationContainerVisitor - override fun visitFunction(flags: Flags, name: String): KmFunctionVisitor? = null - override fun visitProperty( - flags: Flags, - name: String, - getterFlags: Flags, - setterFlags: Flags - ): KmPropertyVisitor? = null - override fun visitTypeAlias(flags: Flags, name: String): KmTypeAliasVisitor? = null - override fun visitExtensions(type: KmExtensionType): KmClassExtensionVisitor? = null - - // from KmClassVisitor - override fun visit(flags: Flags, name: ClassName) {} - override fun visitTypeParameter( - flags: Flags, - name: String, - id: Int, - variance: KmVariance - ): KmTypeParameterVisitor? = null - override fun visitSupertype(flags: Flags): KmTypeVisitor? = null - override fun visitConstructor(flags: Flags): KmConstructorVisitor? = null - override fun visitCompanionObject(name: String) {} - override fun visitNestedClass(name: String) {} - override fun visitEnumEntry(name: String) {} - override fun visitSealedSubclass(name: ClassName) {} - override fun visitInlineClassUnderlyingPropertyName(name: String) {} - override fun visitInlineClassUnderlyingType(flags: Flags): KmTypeVisitor? = null - - @OptIn(ExperimentalContextReceivers::class) - override fun visitContextReceiverType(flags: Flags): KmTypeVisitor? = null - override fun visitVersionRequirement(): KmVersionRequirementVisitor? = null - override fun visitEnd() {} -} - // Jackson Metadata Class internal sealed interface JmClass { class CompanionObject(declaringClass: Class<*>, companionObject: String) { - private class ReducedCompanionVisitor(companionClass: Class<*>) : ReducedKmClassVisitor() { - val functions: MutableList = arrayListOf() - - init { - companionClass.getAnnotation(Metadata::class.java)!!.accept(this) - } - - override fun visitFunction(flags: Flags, name: String): KmFunctionVisitor = KmFunction(flags, name) - .apply { functions.add(this) } - } - private val companionField: Field = declaringClass.getDeclaredField(companionObject) val type: Class<*> = companionField.type val isAccessible: Boolean = companionField.isAccessible - private val functions by lazy { ReducedCompanionVisitor(type).functions } + private val functions by lazy { type.toKmClass()!!.functions } val instance: Any by lazy { // To prevent the call from failing, save the initial value and then rewrite the flag. if (!companionField.isAccessible) companionField.isAccessible = true @@ -111,34 +51,35 @@ internal sealed interface JmClass { private class JmClassImpl( clazz: Class<*>, - metadata: Metadata, + kmClass: KmClass, superJmClass: JmClass?, interfaceJmClasses: List -) : ReducedKmClassVisitor(), JmClass { - private val allPropsMap: MutableMap = mutableMapOf() +) : JmClass { + private val allPropsMap: Map // Defined as non-lazy because it is always read in both serialization and deserialization override val properties: List - private var companionPropName: String? = null - override lateinit var kind: ClassKind - override val constructors: MutableList = mutableListOf() - override val sealedSubclasses: MutableList = mutableListOf() - override var inlineClassUnderlyingType: KmType? = null + private val companionPropName: String? = kmClass.companionObject + override val kind: ClassKind = ClassKind.values()[ProtoFlags.CLASS_KIND.get(kmClass.flags).number] + override val constructors: List = kmClass.constructors + override val sealedSubclasses: List = kmClass.sealedSubclasses + override val inlineClassUnderlyingType: KmType? = kmClass.inlineClassUnderlyingType init { - metadata.accept(this) - // Add properties of inherited classes and interfaces // If an `interface` is implicitly implemented by an abstract class, // it is necessary to obtain a more specific type, so always add it from the abstract class first. - (superJmClass as JmClassImpl?)?.allPropsMap?.forEach { - this.allPropsMap.putIfAbsent(it.key, it.value) + val tempPropsMap = ((superJmClass as JmClassImpl?)?.allPropsMap?.toMutableMap() ?: mutableMapOf()).apply { + kmClass.properties.forEach { + this[it.name] = it + } } - @Suppress("UNCHECKED_CAST") - (interfaceJmClasses as List).forEach { i -> - i.allPropsMap.forEach { - this.allPropsMap.putIfAbsent(it.key, it.value) + + allPropsMap = interfaceJmClasses.fold(tempPropsMap) { acc, cur -> + val curProps = (cur as JmClassImpl).allPropsMap + acc.apply { + curProps.forEach { acc.putIfAbsent(it.key, it.value) } } } @@ -179,38 +120,11 @@ private class JmClassImpl( val getterName = getter.name return properties.find { it.getterSignature?.name == getterName } } - - // KmClassVisitor - override fun visit(flags: Flags, name: ClassName) { - kind = ClassKind.values()[ProtoFlags.CLASS_KIND.get(flags).number] - } - - override fun visitProperty(flags: Flags, name: String, getterFlags: Flags, setterFlags: Flags): KmPropertyVisitor = - KmProperty(flags, name, getterFlags, setterFlags).apply { allPropsMap[name] = this } - - override fun visitConstructor(flags: Flags): KmConstructorVisitor = - KmConstructor(flags).apply { constructors.add(this) } - - override fun visitCompanionObject(name: String) { - this.companionPropName = name - } - - override fun visitSealedSubclass(name: ClassName) { - sealedSubclasses.add(name) - } - - override fun visitInlineClassUnderlyingType(flags: Flags): KmTypeVisitor = - KmType(flags).also { inlineClassUnderlyingType = it } -} - -private fun Metadata.accept(visitor: ReducedKmClassVisitor) { - val (strings, proto) = JvmProtoBufUtil.readClassDataFrom(data1.takeIf(Array<*>::isNotEmpty)!!, data2) - proto.accept(visitor, strings) } internal fun JmClass( clazz: Class<*>, - metadata: Metadata, + kmClass: KmClass, superJmClass: JmClass?, interfaceJmClasses: List -): JmClass = JmClassImpl(clazz, metadata, superJmClass, interfaceJmClasses) +): JmClass = JmClassImpl(clazz, kmClass, superJmClass, interfaceJmClasses) diff --git a/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/ReflectionCache.kt b/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/ReflectionCache.kt index 36cc234a..4ef0d005 100644 --- a/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/ReflectionCache.kt +++ b/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/ReflectionCache.kt @@ -48,7 +48,7 @@ internal class ReflectionCache(initialCacheSize: Int, maxCacheSize: Int) : Seria fun getJmClass(clazz: Class<*>): JmClass? { return find(clazz) ?: run { - val metadata = clazz.getAnnotation(Metadata::class.java) ?: return null + val kmClass = clazz.toKmClass() ?: return null // Do not parse super class for interfaces. val superJmClass = if (!clazz.isInterface) { @@ -61,7 +61,7 @@ internal class ReflectionCache(initialCacheSize: Int, maxCacheSize: Int) : Seria } val interfaceJmClasses = clazz.interfaces.mapNotNull { getJmClass(it) } - val value = JmClass(clazz, metadata, superJmClass, interfaceJmClasses) + val value = JmClass(clazz, kmClass, superJmClass, interfaceJmClasses) putIfAbsent(clazz, value) } } From 7daf65073f5cd3772eaf97f6871f9b92ea58e768 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 11 Feb 2024 01:10:38 +0900 Subject: [PATCH 7/9] Add WF name --- .github/workflows/release.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 8d064666..3118b715 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,3 +1,4 @@ +name: release on: workflow_dispatch: jobs: From 95c6931a402b5d86844fad891ac5ff280e55019e Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 11 Feb 2024 01:12:35 +0900 Subject: [PATCH 8/9] Remove lint step Fix for d11be42 --- .github/workflows/test-main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-main.yml b/.github/workflows/test-main.yml index fea208cd..0e1acdcb 100644 --- a/.github/workflows/test-main.yml +++ b/.github/workflows/test-main.yml @@ -72,4 +72,4 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 - name: Test - run: ./gradlew lintKotlin test + run: ./gradlew test From aace9c9463c882d877c593c03efe5ad4ba0168a3 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 11 Feb 2024 01:13:34 +0900 Subject: [PATCH 9/9] Beta1 -> Beta3 --- .github/workflows/test-main.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test-main.yml b/.github/workflows/test-main.yml index 0e1acdcb..850f48e8 100644 --- a/.github/workflows/test-main.yml +++ b/.github/workflows/test-main.yml @@ -47,11 +47,11 @@ jobs: - name: '1.9.21 K2' version: '1.9.21' k2: true - - name: '2.0.0-Beta1' - version: '2.0.0-Beta1' + - name: '2.0.0-Beta3' + version: '2.0.0-Beta3' k2: false - - name: '2.0.0-Beta1 K2' - version: '2.0.0-Beta1' + - name: '2.0.0-Beta3 K2' + version: '2.0.0-Beta3' k2: true env: KOTLIN_VERSION: ${{ matrix.kotlin.version }}