From f869895d6b4daaa41dbe37268183913ecf16a8c9 Mon Sep 17 00:00:00 2001
From: RicardoJiang <2868405029@qq.com>
Date: Fri, 17 Nov 2023 15:00:53 +0800
Subject: [PATCH 1/2] ADD: Kudos function switch

---
 .../json/reader/KudosAndroidJsonReader.kt     |  21 +++-
 .../com/kanyun/kudos/annotations/Kudos.kt     |   2 +-
 .../compiler/KudosCompilerPluginRegistrar.kt  |   8 +-
 .../kudos/compiler/KudosIrClassTransformer.kt |   8 +-
 .../compiler/KudosIrGenerationExtension.kt    |   6 +-
 .../kudos/compiler/KudosIrTransformer.kt      |   3 +-
 .../com/kanyun/kudos/compiler/KudosNames.kt   |   2 +
 .../k1/KudosSyntheticResolveExtension.kt      |  37 +++++--
 .../k2/KudosFirDeclarationGenerator.kt        |  13 ++-
 .../compiler/k2/KudosFirExtensionRegistrar.kt |  11 +-
 .../KudosFirSupertypeGenerationExtension.kt   |  62 ++++++++---
 .../kanyun/kudos/compiler/options/Options.kt  |  32 ++++++
 .../com/kanyun/kudos/compiler/KudosTests.kt   |   6 ++
 .../kanyun/kudos/compiler/base/TestBase.kt    |   1 +
 kudos-compiler/testData/gson/annotation.kt    |  44 ++++++++
 .../testData/jsonReader/annotation.kt         | 100 ++++++++++++++++++
 kudos-compiler/testData/jsonReader/simple.kt  |   4 +-
 .../com/kanyun/kudos/gradle/KudosExtension.kt |   1 +
 .../kanyun/kudos/gradle/KudosGradlePlugin.kt  |   8 +-
 .../java/com/kanyun/kudos/gson/KudosGson.kt   |   2 +
 .../kanyun/kudos/jackson/KudosObjectMapper.kt |   2 +
 21 files changed, 326 insertions(+), 47 deletions(-)
 create mode 100644 kudos-compiler/testData/gson/annotation.kt
 create mode 100644 kudos-compiler/testData/jsonReader/annotation.kt

diff --git a/kudos-android-json-reader/src/main/java/com/kanyun/kudos/json/reader/KudosAndroidJsonReader.kt b/kudos-android-json-reader/src/main/java/com/kanyun/kudos/json/reader/KudosAndroidJsonReader.kt
index a860f74..0f8e959 100644
--- a/kudos-android-json-reader/src/main/java/com/kanyun/kudos/json/reader/KudosAndroidJsonReader.kt
+++ b/kudos-android-json-reader/src/main/java/com/kanyun/kudos/json/reader/KudosAndroidJsonReader.kt
@@ -19,17 +19,23 @@ package com.kanyun.kudos.json.reader
 import android.util.JsonReader
 import com.kanyun.kudos.json.reader.adapter.KudosJsonAdapter
 import com.kanyun.kudos.json.reader.adapter.parseKudosObject
+import java.io.BufferedReader
+import java.io.InputStream
 import java.lang.reflect.Type
 
 object KudosAndroidJsonReader {
     inline fun <reified T> fromJson(json: String): T {
-        return fromJson(json, T::class.java)
+        return fromJson(json.reader().buffered(), T::class.java)
     }
 
-    fun <T> fromJson(json: String, clazz: Class<T>): T {
+    inline fun <reified T> fromJson(inputStream: InputStream): T {
+        return fromJson(inputStream.bufferedReader(), T::class.java)
+    }
+
+    fun <T> fromJson(bufferReader: BufferedReader, clazz: Class<T>): T {
         val adapter = clazz.getDeclaredConstructor().newInstance()
         return if (adapter is KudosJsonAdapter<*>) {
-            val jsonReader = JsonReader(json.reader())
+            val jsonReader = JsonReader(bufferReader)
             adapter.fromJson(jsonReader) as T
         } else {
             throw IllegalArgumentException("class ${clazz.name} must implement KudosJsonAdapter")
@@ -37,7 +43,14 @@ object KudosAndroidJsonReader {
     }
 
     fun <T> fromJson(json: String, type: Type): T {
-        val jsonReader = JsonReader(json.reader())
+        val jsonReader = JsonReader(json.reader().buffered())
+        return parseKudosObject(jsonReader, type) as T
+    }
+
+    fun <T> fromJson(inputStream: InputStream, type: Type): T {
+        val jsonReader = JsonReader(inputStream.bufferedReader())
         return parseKudosObject(jsonReader, type) as T
     }
 }
+
+const val KUDOS_ANDROID_JSON_READER: Int = 3
diff --git a/kudos-annotations/src/main/java/com/kanyun/kudos/annotations/Kudos.kt b/kudos-annotations/src/main/java/com/kanyun/kudos/annotations/Kudos.kt
index c6c3874..cdc51bd 100644
--- a/kudos-annotations/src/main/java/com/kanyun/kudos/annotations/Kudos.kt
+++ b/kudos-annotations/src/main/java/com/kanyun/kudos/annotations/Kudos.kt
@@ -21,4 +21,4 @@ package com.kanyun.kudos.annotations
  */
 @Retention(AnnotationRetention.BINARY)
 @Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
-annotation class Kudos
+annotation class Kudos(vararg val value: Int)
diff --git a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosCompilerPluginRegistrar.kt b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosCompilerPluginRegistrar.kt
index f0090db..419dfca 100644
--- a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosCompilerPluginRegistrar.kt
+++ b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosCompilerPluginRegistrar.kt
@@ -46,11 +46,11 @@ class KudosCompilerPluginRegistrar : CompilerPluginRegistrar() {
         configuration.get(NoArgConfigurationKeys.PRESET)?.forEach { preset ->
             NoArgPluginNames.SUPPORTED_PRESETS[preset]?.let { noArgAnnotations += it }
         }
-
-        IrGenerationExtension.registerExtension(KudosIrGenerationExtension())
-        SyntheticResolveExtension.registerExtension(KudosSyntheticResolveExtension())
+        val kudosAnnotationValueMap = hashMapOf<String, List<Int>>()
+        IrGenerationExtension.registerExtension(KudosIrGenerationExtension(kudosAnnotationValueMap))
+        SyntheticResolveExtension.registerExtension(KudosSyntheticResolveExtension(kudosAnnotationValueMap))
         StorageComponentContainerContributor.registerExtension(KudosComponentContainerContributor(noArgAnnotations))
-        FirExtensionRegistrarAdapter.registerExtension(KudosFirExtensionRegistrar(noArgAnnotations))
+        FirExtensionRegistrarAdapter.registerExtension(KudosFirExtensionRegistrar(noArgAnnotations, kudosAnnotationValueMap))
     }
 
     override val supportsK2: Boolean
diff --git a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosIrClassTransformer.kt b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosIrClassTransformer.kt
index 3d49107..f8e0286 100644
--- a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosIrClassTransformer.kt
+++ b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosIrClassTransformer.kt
@@ -63,6 +63,7 @@ import org.jetbrains.kotlin.ir.types.starProjectedType
 import org.jetbrains.kotlin.ir.types.typeOrNull
 import org.jetbrains.kotlin.ir.types.typeWith
 import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET
+import org.jetbrains.kotlin.ir.util.classId
 import org.jetbrains.kotlin.ir.util.constructors
 import org.jetbrains.kotlin.ir.util.copyTo
 import org.jetbrains.kotlin.ir.util.defaultType
@@ -86,17 +87,20 @@ class KudosIrClassTransformer(
     private val context: IrPluginContext,
     private val irClass: IrClass,
     private val noArgConstructors: MutableMap<IrClass, IrConstructor>,
+    private val kudosAnnotationValueMap: HashMap<String, List<Int>>,
 ) {
 
     private val defaults = HashSet<String>()
 
     fun transform() {
-        if (Options.gson()) {
+        if (Options.isGsonEnabled(kudosAnnotationValueMap, irClass.classId?.asString())) {
             generateJsonAdapter()
         }
         generateNoArgConstructor()
         val validatorFunction = generateValidator()
-        generateFromJson(validatorFunction)
+        if (Options.isAndroidJsonReaderEnabled(kudosAnnotationValueMap, irClass.classId?.asString())) {
+            generateFromJson(validatorFunction)
+        }
     }
 
     private fun generateJsonAdapter() {
diff --git a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosIrGenerationExtension.kt b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosIrGenerationExtension.kt
index 0a8459c..a45b8b1 100644
--- a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosIrGenerationExtension.kt
+++ b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosIrGenerationExtension.kt
@@ -21,9 +21,11 @@ import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
 import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
 import org.jetbrains.kotlin.ir.visitors.acceptVoid
 
-class KudosIrGenerationExtension : IrGenerationExtension {
+class KudosIrGenerationExtension(
+    private val kudosAnnotationValueMap: HashMap<String, List<Int>>,
+) : IrGenerationExtension {
 
     override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) {
-        moduleFragment.acceptVoid(KudosIrTransformer(pluginContext))
+        moduleFragment.acceptVoid(KudosIrTransformer(pluginContext, kudosAnnotationValueMap))
     }
 }
diff --git a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosIrTransformer.kt b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosIrTransformer.kt
index 20fbcd0..c9d4573 100644
--- a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosIrTransformer.kt
+++ b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosIrTransformer.kt
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
  */
 class KudosIrTransformer(
     private val context: IrPluginContext,
+    private val kudosAnnotationValueMap: HashMap<String, List<Int>>,
 ) : IrElementVisitorVoid {
     private val noArgConstructors = mutableMapOf<IrClass, IrConstructor>()
 
@@ -41,6 +42,6 @@ class KudosIrTransformer(
         if (declaration.kind != ClassKind.CLASS) return
         if (!declaration.hasKudosAnnotation()) return
 
-        KudosIrClassTransformer(context, declaration, noArgConstructors).transform()
+        KudosIrClassTransformer(context, declaration, noArgConstructors, kudosAnnotationValueMap).transform()
     }
 }
diff --git a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosNames.kt b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosNames.kt
index f3dd1d4..31d9633 100644
--- a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosNames.kt
+++ b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/KudosNames.kt
@@ -39,6 +39,7 @@ object KudosNames {
     val ADAPTER_FACTORY_NAME = FqName("com.kanyun.kudos.gson.adapter.KudosReflectiveTypeAdapterFactory")
 
     // ClassId
+    val KUDOS_ANNOTATION_CLASS_ID = ClassId(FqName("com.kanyun.kudos.annotations"), Name.identifier("Kudos"))
     val KUDOS_VALIDATOR_CLASS_ID = ClassId(FqName("com.kanyun.kudos.validator"), Name.identifier("KudosValidator"))
     val KUDOS_JSON_ADAPTER_CLASS_ID = ClassId(FqName("com.kanyun.kudos.json.reader.adapter"), Name.identifier("KudosJsonAdapter"))
     val JSON_READER_CLASS_ID = ClassId.fromString("android/util/JsonReader")
@@ -50,6 +51,7 @@ object KudosNames {
     val JSON_TOKEN_NULL_CALLABLE_ID = CallableId(FqName("android.util"), FqName("JsonToken"), Name.identifier("NULL"))
 
     // Name.identifier
+    val KUDOS_VALUE_IDENTIFIER = Name.identifier("value")
     val KUDOS_FROM_JSON_IDENTIFIER = Name.identifier("fromJson")
     val JSON_READER_IDENTIFIER = Name.identifier("jsonReader")
     val KUDOS_FIELD_STATUS_MAP_IDENTIFIER = Name.identifier("kudosFieldStatusMap")
diff --git a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k1/KudosSyntheticResolveExtension.kt b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k1/KudosSyntheticResolveExtension.kt
index b412d27..54900dc 100644
--- a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k1/KudosSyntheticResolveExtension.kt
+++ b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k1/KudosSyntheticResolveExtension.kt
@@ -25,6 +25,8 @@ import com.kanyun.kudos.compiler.KudosNames.KUDOS_NAME
 import com.kanyun.kudos.compiler.KudosNames.KUDOS_VALIDATOR
 import com.kanyun.kudos.compiler.KudosNames.KUDOS_VALIDATOR_CLASS_ID
 import com.kanyun.kudos.compiler.k1.symbol.FromJsonFunctionDescriptorImpl
+import com.kanyun.kudos.compiler.options.Options
+import com.kanyun.kudos.compiler.utils.safeAs
 import org.jetbrains.kotlin.descriptors.ClassDescriptor
 import org.jetbrains.kotlin.descriptors.ClassKind
 import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
@@ -35,6 +37,8 @@ import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
 import org.jetbrains.kotlin.js.descriptorUtils.getKotlinTypeFqName
 import org.jetbrains.kotlin.name.Name
 import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.constants.IntValue
+import org.jetbrains.kotlin.resolve.descriptorUtil.classId
 import org.jetbrains.kotlin.resolve.descriptorUtil.module
 import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
 import org.jetbrains.kotlin.types.KotlinType
@@ -44,7 +48,9 @@ import org.jetbrains.kotlin.types.TypeAttributes
 import org.jetbrains.kotlin.types.TypeProjectionImpl
 import org.jetbrains.kotlin.types.typeUtil.supertypes
 
-class KudosSyntheticResolveExtension : SyntheticResolveExtension {
+class KudosSyntheticResolveExtension(
+    private val kudosAnnotationValueMap: HashMap<String, List<Int>>,
+) : SyntheticResolveExtension {
 
     override fun addSyntheticSupertypes(
         thisDescriptor: ClassDescriptor,
@@ -52,6 +58,11 @@ class KudosSyntheticResolveExtension : SyntheticResolveExtension {
     ) {
         if (thisDescriptor.kind != ClassKind.CLASS) return
         if (thisDescriptor.annotations.hasAnnotation(KUDOS_NAME)) {
+            val kudosAnnotation = thisDescriptor.annotations.findAnnotation(KUDOS_NAME)
+            val annotationValues = kudosAnnotation?.allValueArguments?.values?.firstOrNull()?.value?.safeAs<List<IntValue>>()?.map {
+                it.value
+            }
+            kudosAnnotationValueMap[thisDescriptor.classId?.asString() ?: ""] = annotationValues ?: emptyList()
             val superTypeNames = supertypes.asSequence().flatMap {
                 listOf(it) + it.supertypes()
             }.map {
@@ -68,21 +79,25 @@ class KudosSyntheticResolveExtension : SyntheticResolveExtension {
                     ),
                 )
             }
-            if (KUDOS_JSON_ADAPTER !in superTypeNames) {
-                val kudosJsonAdapter = thisDescriptor.module.findClassAcrossModuleDependencies(KUDOS_JSON_ADAPTER_CLASS_ID)!!
-                supertypes.add(
-                    KotlinTypeFactory.simpleNotNullType(
-                        TypeAttributes.Empty,
-                        kudosJsonAdapter,
-                        listOf(TypeProjectionImpl(thisDescriptor.defaultType)),
-                    ),
-                )
+            if (Options.isAndroidJsonReaderEnabled(kudosAnnotationValueMap, thisDescriptor.classId?.asString())) {
+                if (KUDOS_JSON_ADAPTER !in superTypeNames) {
+                    val kudosJsonAdapter = thisDescriptor.module.findClassAcrossModuleDependencies(KUDOS_JSON_ADAPTER_CLASS_ID)!!
+                    supertypes.add(
+                        KotlinTypeFactory.simpleNotNullType(
+                            TypeAttributes.Empty,
+                            kudosJsonAdapter,
+                            listOf(TypeProjectionImpl(thisDescriptor.defaultType)),
+                        ),
+                    )
+                }
             }
         }
     }
 
     override fun getSyntheticFunctionNames(thisDescriptor: ClassDescriptor): List<Name> {
-        if (thisDescriptor.annotations.hasAnnotation(KUDOS_NAME)) {
+        if (Options.isAndroidJsonReaderEnabled(kudosAnnotationValueMap, thisDescriptor.classId?.asString()) &&
+            thisDescriptor.annotations.hasAnnotation(KUDOS_NAME)
+        ) {
             return listOf(KUDOS_FROM_JSON_IDENTIFIER)
         }
         return super.getSyntheticFunctionNames(thisDescriptor)
diff --git a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k2/KudosFirDeclarationGenerator.kt b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k2/KudosFirDeclarationGenerator.kt
index 82a5c9f..0664ca7 100644
--- a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k2/KudosFirDeclarationGenerator.kt
+++ b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k2/KudosFirDeclarationGenerator.kt
@@ -20,6 +20,7 @@ import com.kanyun.kudos.compiler.KudosNames.JSON_READER_CLASS_ID
 import com.kanyun.kudos.compiler.KudosNames.JSON_READER_IDENTIFIER
 import com.kanyun.kudos.compiler.KudosNames.KUDOS_FROM_JSON_IDENTIFIER
 import com.kanyun.kudos.compiler.KudosNames.KUDOS_NAME
+import com.kanyun.kudos.compiler.options.Options
 import org.jetbrains.kotlin.GeneratedDeclarationKey
 import org.jetbrains.kotlin.descriptors.Modality
 import org.jetbrains.kotlin.fir.FirSession
@@ -48,8 +49,10 @@ import org.jetbrains.kotlin.name.CallableId
 import org.jetbrains.kotlin.name.Name
 import org.jetbrains.kotlin.utils.addToStdlib.runIf
 
-class KudosFirDeclarationGenerator(session: FirSession) :
-    FirDeclarationGenerationExtension(session) {
+class KudosFirDeclarationGenerator(
+    session: FirSession,
+    private val kudosAnnotationValueMap: HashMap<String, List<Int>>,
+) : FirDeclarationGenerationExtension(session) {
 
     companion object {
         private val PREDICATE = LookupPredicate.create {
@@ -71,8 +74,10 @@ class KudosFirDeclarationGenerator(session: FirSession) :
     }
 
     override fun getCallableNamesForClass(classSymbol: FirClassSymbol<*>): Set<Name> {
-        if (classSymbol in matchedClasses) {
-            return kudosMethodsNames
+        if (Options.isAndroidJsonReaderEnabled(kudosAnnotationValueMap, classSymbol.classId.toString())) {
+            if (classSymbol in matchedClasses) {
+                return kudosMethodsNames
+            }
         }
         return super.getCallableNamesForClass(classSymbol)
     }
diff --git a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k2/KudosFirExtensionRegistrar.kt b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k2/KudosFirExtensionRegistrar.kt
index 7226f8d..dedfe74 100644
--- a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k2/KudosFirExtensionRegistrar.kt
+++ b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k2/KudosFirExtensionRegistrar.kt
@@ -17,19 +17,26 @@
 package com.kanyun.kudos.compiler.k2
 
 import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension
+import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
 import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
+import org.jetbrains.kotlin.fir.extensions.FirSupertypeGenerationExtension
 
 /**
  * Created by Benny Huo on 2023/8/21
  */
 class KudosFirExtensionRegistrar(
     private val noArgAnnotations: List<String>,
+    private val kudosAnnotationValueMap: HashMap<String, List<Int>>,
 ) : FirExtensionRegistrar() {
     override fun ExtensionRegistrarContext.configurePlugin() {
         +FirAdditionalCheckersExtension.Factory { session ->
             KudosFirCheckers(session, noArgAnnotations)
         }
-        +::KudosFirSupertypeGenerationExtension
-        +::KudosFirDeclarationGenerator
+        +FirSupertypeGenerationExtension.Factory { session ->
+            KudosFirSupertypeGenerationExtension(session, kudosAnnotationValueMap)
+        }
+        +FirDeclarationGenerationExtension.Factory { session ->
+            KudosFirDeclarationGenerator(session, kudosAnnotationValueMap)
+        }
     }
 }
diff --git a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k2/KudosFirSupertypeGenerationExtension.kt b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k2/KudosFirSupertypeGenerationExtension.kt
index 37fa4b8..843ce0a 100644
--- a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k2/KudosFirSupertypeGenerationExtension.kt
+++ b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k2/KudosFirSupertypeGenerationExtension.kt
@@ -16,20 +16,29 @@
 
 package com.kanyun.kudos.compiler.k2
 
+import com.kanyun.kudos.compiler.KudosNames.KUDOS_ANNOTATION_CLASS_ID
 import com.kanyun.kudos.compiler.KudosNames.KUDOS_JSON_ADAPTER_CLASS_ID
 import com.kanyun.kudos.compiler.KudosNames.KUDOS_NAME
 import com.kanyun.kudos.compiler.KudosNames.KUDOS_VALIDATOR_CLASS_ID
+import com.kanyun.kudos.compiler.options.Options
+import com.kanyun.kudos.compiler.utils.safeAs
 import org.jetbrains.kotlin.fir.FirSession
 import org.jetbrains.kotlin.fir.declarations.FirClass
 import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
 import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
 import org.jetbrains.kotlin.fir.declarations.FirRegularClass
 import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
+import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId
 import org.jetbrains.kotlin.fir.declarations.utils.classId
+import org.jetbrains.kotlin.fir.expressions.FirAnnotation
+import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
+import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
+import org.jetbrains.kotlin.fir.expressions.arguments
 import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
 import org.jetbrains.kotlin.fir.extensions.FirSupertypeGenerationExtension
 import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
 import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
+import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
 import org.jetbrains.kotlin.fir.resolve.toSymbol
 import org.jetbrains.kotlin.fir.scopes.impl.toConeType
 import org.jetbrains.kotlin.fir.symbols.SymbolInternals
@@ -49,6 +58,7 @@ import org.jetbrains.kotlin.name.ClassId
  */
 class KudosFirSupertypeGenerationExtension(
     session: FirSession,
+    private val kudosAnnotationValueMap: HashMap<String, List<Int>>,
 ) : FirSupertypeGenerationExtension(session) {
 
     private val hasKudos = DeclarationPredicate.create {
@@ -66,6 +76,9 @@ class KudosFirSupertypeGenerationExtension(
     ): List<FirResolvedTypeRef> {
         var hasValidator = false
         var hasJsonAdapter = false
+        val annotationValues = classLikeDeclaration.symbol.resolvedAnnotationsWithArguments.getAnnotationByClassId(KUDOS_ANNOTATION_CLASS_ID, session)
+            ?.getIntArrayArgument()
+        kudosAnnotationValueMap[classLikeDeclaration.classId.toString()] = annotationValues ?: emptyList()
         for (superTypeRef in resolvedSupertypes) {
             val superType = superTypeRef.type
             val superTypeClassIds = superType.allSuperTypeClassIds()
@@ -86,19 +99,21 @@ class KudosFirSupertypeGenerationExtension(
                 )
             }
         }
-        if (!hasJsonAdapter) {
-            val genericType = ConeClassLikeTypeImpl(
-                ConeClassLikeLookupTagImpl(classLikeDeclaration.classId),
-                classLikeDeclaration.typeParameters.map {
-                    it.toConeType()
-                }.toTypedArray(),
-                false,
-            )
-            firTypeRefList += buildResolvedTypeRef {
-                type = KUDOS_JSON_ADAPTER_CLASS_ID.constructClassLikeType(
-                    arrayOf(genericType),
-                    isNullable = false,
+        if (Options.isAndroidJsonReaderEnabled(kudosAnnotationValueMap, classLikeDeclaration.classId.toString())) {
+            if (!hasJsonAdapter) {
+                val genericType = ConeClassLikeTypeImpl(
+                    ConeClassLikeLookupTagImpl(classLikeDeclaration.classId),
+                    classLikeDeclaration.typeParameters.map {
+                        it.toConeType()
+                    }.toTypedArray(),
+                    false,
                 )
+                firTypeRefList += buildResolvedTypeRef {
+                    type = KUDOS_JSON_ADAPTER_CLASS_ID.constructClassLikeType(
+                        arrayOf(genericType),
+                        isNullable = false,
+                    )
+                }
             }
         }
         return firTypeRefList
@@ -134,4 +149,27 @@ class KudosFirSupertypeGenerationExtension(
             else -> null
         }
     }
+
+    private fun FirAnnotation.getIntArrayArgument(): List<Int>? {
+        if (this !is FirAnnotationCall) return null
+        return arguments.mapNotNull {
+            when (it.safeAs<FirPropertyAccessExpression>()?.calleeReference?.safeAs<FirSimpleNamedReference>()?.name?.asString()) {
+                "KUDOS_ANDROID_JSON_READER" -> {
+                    Options.KUDOS_ANDROID_JSON_READER
+                }
+
+                "KUDOS_GSON" -> {
+                    Options.KUDOS_GSON
+                }
+
+                "KUDOS_JACKSON" -> {
+                    Options.KUDOS_JACKSON
+                }
+
+                else -> {
+                    null
+                }
+            }
+        }
+    }
 }
diff --git a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/options/Options.kt b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/options/Options.kt
index a343b54..93679a8 100644
--- a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/options/Options.kt
+++ b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/options/Options.kt
@@ -18,6 +18,10 @@ package com.kanyun.kudos.compiler.options
 
 object Options {
 
+    const val KUDOS_GSON = 1
+    const val KUDOS_JACKSON = 2
+    const val KUDOS_ANDROID_JSON_READER = 3
+
     @JvmField
     val gson = Option(
         "gson",
@@ -34,9 +38,37 @@ object Options {
         "<true/false>",
     )
 
+    @JvmField
+    val androidJsonReader = Option(
+        "androidJsonReader",
+        false,
+        "Whether to enable the support for AndroidJsonReader.",
+        "<true/false>",
+    )
+
     val all = Options::class.java.declaredFields.filter {
         it.type == Option::class.java
     }.map {
         it.get(null) as Option<*>
     }
+
+    fun isGsonEnabled(kudosAnnotationValueMap: HashMap<String, List<Int>>, className: String?): Boolean {
+        if (className.isNullOrEmpty()) return false
+        val annotationValue = kudosAnnotationValueMap[className]
+        return if (annotationValue.isNullOrEmpty()) {
+            gson()
+        } else {
+            annotationValue.contains(KUDOS_GSON)
+        }
+    }
+
+    fun isAndroidJsonReaderEnabled(kudosAnnotationValueMap: HashMap<String, List<Int>>, className: String?): Boolean {
+        if (className.isNullOrEmpty()) return false
+        val annotationValue = kudosAnnotationValueMap[className]
+        return if (annotationValue.isNullOrEmpty()) {
+            androidJsonReader()
+        } else {
+            annotationValue.contains(KUDOS_ANDROID_JSON_READER)
+        }
+    }
 }
diff --git a/kudos-compiler/src/test/java/com/kanyun/kudos/compiler/KudosTests.kt b/kudos-compiler/src/test/java/com/kanyun/kudos/compiler/KudosTests.kt
index 93bb0c6..e5056c1 100644
--- a/kudos-compiler/src/test/java/com/kanyun/kudos/compiler/KudosTests.kt
+++ b/kudos-compiler/src/test/java/com/kanyun/kudos/compiler/KudosTests.kt
@@ -45,12 +45,18 @@ class KudosTests : TestBase() {
     @Test
     fun `common_validator`() = testBase()
 
+    @Test
+    fun `gson_annotation`() = testBase()
+
     @Test
     fun `gson_jsonAdapterCheck`() = testBase()
 
     @Test
     fun `gson_notNull`() = testBase()
 
+    @Test
+    fun `jsonReader_annotation`() = testBase()
+
     @Test
     fun `jsonReader_deserialize`() = testBase()
 
diff --git a/kudos-compiler/src/test/java/com/kanyun/kudos/compiler/base/TestBase.kt b/kudos-compiler/src/test/java/com/kanyun/kudos/compiler/base/TestBase.kt
index 4ba48aa..ab2d483 100644
--- a/kudos-compiler/src/test/java/com/kanyun/kudos/compiler/base/TestBase.kt
+++ b/kudos-compiler/src/test/java/com/kanyun/kudos/compiler/base/TestBase.kt
@@ -109,6 +109,7 @@ open class TestBase {
     }
 
     private fun jsonReaderDeserialize(): String {
+        Options.androidJsonReader.set(true)
         return """
             // FILE: JsonReader.kt
             import com.kanyun.kudos.json.reader.KudosAndroidJsonReader
diff --git a/kudos-compiler/testData/gson/annotation.kt b/kudos-compiler/testData/gson/annotation.kt
new file mode 100644
index 0000000..d318861
--- /dev/null
+++ b/kudos-compiler/testData/gson/annotation.kt
@@ -0,0 +1,44 @@
+// SOURCE
+// FILE: Main.kt
+package com.kanyun.kudos.test
+
+import com.kanyun.kudos.annotations.Kudos
+import com.kanyun.kudos.gson.KUDOS_GSON
+
+@Kudos(KUDOS_GSON)
+class Desc(val descDetail: String)
+
+@Kudos(KUDOS_GSON)
+class Project(val projectName: String, val projectId: Int, val tags: List<String>,val desc: Desc)
+
+// EXPECT
+// FILE: compiles.log
+OK
+// FILE: Main.kt.ir
+package com.kanyun.kudos.test
+@Kudos(value = 1)
+@JsonAdapter(value = KudosReflectiveTypeAdapterFactory::class)
+class Desc(val descDetail: String) : KudosValidator {
+    constructor{
+        ctor<Any>()
+        init<Desc>()
+    }
+    override fun validate(status: Map<String, Boolean>) {
+        validateField("descDetail", status)
+    }
+}
+@Kudos(value = 1)
+@JsonAdapter(value = KudosReflectiveTypeAdapterFactory::class)
+class Project(val projectName: String, val projectId: Int, val tags: List<String>, val desc: Desc) : KudosValidator {
+    constructor{
+        ctor<Any>()
+        init<Project>()
+    }
+    override fun validate(status: Map<String, Boolean>) {
+        validateField("projectName", status)
+        validateField("projectId", status)
+        validateField("tags", status)
+        validateField("desc", status)
+        validateCollection("tags", <this>.tags, "List")
+    }
+}
\ No newline at end of file
diff --git a/kudos-compiler/testData/jsonReader/annotation.kt b/kudos-compiler/testData/jsonReader/annotation.kt
new file mode 100644
index 0000000..a57a9f0
--- /dev/null
+++ b/kudos-compiler/testData/jsonReader/annotation.kt
@@ -0,0 +1,100 @@
+// SOURCE
+// FILE: Main.kt
+package com.kanyun.kudos.test
+
+import com.kanyun.kudos.annotations.Kudos
+import com.kanyun.kudos.json.reader.KUDOS_ANDROID_JSON_READER
+
+@Kudos(KUDOS_ANDROID_JSON_READER)
+class Desc(val descDetail: String)
+
+@Kudos(KUDOS_ANDROID_JSON_READER)
+class Project(val projectName: String, val projectId: Int, val tags: List<String>,val desc: Desc)
+
+// EXPECT
+// FILE: compiles.log
+OK
+// FILE: Main.kt.ir
+package com.kanyun.kudos.test
+@Kudos(value = 3)
+class Desc(val descDetail: String) : KudosValidator, KudosJsonAdapter<Desc> {
+    override fun fromJson(jsonReader: JsonReader): Desc {
+        jsonReader.beginObject()
+        while (jsonReader.hasNext()) {
+            val tmp0 = jsonReader.nextName()
+            if (jsonReader.peek() == JsonToken.NULL) {
+                jsonReader.skipValue()
+                continue
+            }
+            when {
+                tmp0 == "descDetail" -> {
+                    <this>.descDetail = jsonReader.nextString()
+                    <this>.kudosFieldStatusMap.put("descDetail", <this>.descDetail != null)
+                }
+                else -> {
+                    jsonReader.skipValue()
+                }
+            }
+        }
+        jsonReader.endObject()
+        validate(<this>.kudosFieldStatusMap)
+        return <this>
+    }
+    constructor{
+        ctor<Any>()
+        init<Desc>()
+    }
+    override fun validate(status: Map<String, Boolean>) {
+        validateField("descDetail", status)
+    }
+    private var kudosFieldStatusMap: Map<String, Boolean> = hashMapOf()
+}
+@Kudos(value = 3)
+class Project(val projectName: String, val projectId: Int, val tags: List<String>, val desc: Desc) : KudosValidator, KudosJsonAdapter<Project> {
+    override fun fromJson(jsonReader: JsonReader): Project {
+        jsonReader.beginObject()
+        while (jsonReader.hasNext()) {
+            val tmp0 = jsonReader.nextName()
+            if (jsonReader.peek() == JsonToken.NULL) {
+                jsonReader.skipValue()
+                continue
+            }
+            when {
+                tmp0 == "projectName" -> {
+                    <this>.projectName = jsonReader.nextString()
+                    <this>.kudosFieldStatusMap.put("projectName", <this>.projectName != null)
+                }
+                tmp0 == "projectId" -> {
+                    <this>.projectId = jsonReader.nextInt()
+                    <this>.kudosFieldStatusMap.put("projectId", <this>.projectId != null)
+                }
+                tmp0 == "tags" -> {
+                    <this>.tags = parseKudosObject(jsonReader, ParameterizedTypeImpl(List<String>::class.javaObjectType, arrayOf(String::class.javaObjectType)))
+                    <this>.kudosFieldStatusMap.put("tags", <this>.tags != null)
+                }
+                tmp0 == "desc" -> {
+                    <this>.desc = parseKudosObject(jsonReader, Desc::class.javaObjectType)
+                    <this>.kudosFieldStatusMap.put("desc", <this>.desc != null)
+                }
+                else -> {
+                    jsonReader.skipValue()
+                }
+            }
+        }
+        jsonReader.endObject()
+        validate(<this>.kudosFieldStatusMap)
+        return <this>
+    }
+    constructor{
+        ctor<Any>()
+        init<Project>()
+    }
+    override fun validate(status: Map<String, Boolean>) {
+        validateField("projectName", status)
+        validateField("projectId", status)
+        validateField("tags", status)
+        validateField("desc", status)
+        validateCollection("tags", <this>.tags, "List")
+    }
+    private var kudosFieldStatusMap: Map<String, Boolean> = hashMapOf()
+}
\ No newline at end of file
diff --git a/kudos-compiler/testData/jsonReader/simple.kt b/kudos-compiler/testData/jsonReader/simple.kt
index 01192d3..77a24be 100644
--- a/kudos-compiler/testData/jsonReader/simple.kt
+++ b/kudos-compiler/testData/jsonReader/simple.kt
@@ -15,7 +15,7 @@ class Project(val projectName: String, val projectId: Int, val tags: List<String
 OK
 // FILE: Main.kt.ir
 package com.kanyun.kudos.test
-@Kudos
+@Kudos(value = )
 class Desc(val descDetail: String) : KudosValidator, KudosJsonAdapter<Desc> {
     override fun fromJson(jsonReader: JsonReader): Desc {
         jsonReader.beginObject()
@@ -48,7 +48,7 @@ class Desc(val descDetail: String) : KudosValidator, KudosJsonAdapter<Desc> {
     }
     private var kudosFieldStatusMap: Map<String, Boolean> = hashMapOf()
 }
-@Kudos
+@Kudos(value = )
 class Project(val projectName: String, val projectId: Int, val tags: List<String>, val desc: Desc) : KudosValidator, KudosJsonAdapter<Project> {
     override fun fromJson(jsonReader: JsonReader): Project {
         jsonReader.beginObject()
diff --git a/kudos-gradle-plugin/src/main/java/com/kanyun/kudos/gradle/KudosExtension.kt b/kudos-gradle-plugin/src/main/java/com/kanyun/kudos/gradle/KudosExtension.kt
index 88fa835..9830bc2 100644
--- a/kudos-gradle-plugin/src/main/java/com/kanyun/kudos/gradle/KudosExtension.kt
+++ b/kudos-gradle-plugin/src/main/java/com/kanyun/kudos/gradle/KudosExtension.kt
@@ -22,4 +22,5 @@ package com.kanyun.kudos.gradle
 open class KudosExtension {
     var gson: Boolean = false
     var jackson: Boolean = false
+    var androidJsonReader: Boolean = false
 }
diff --git a/kudos-gradle-plugin/src/main/java/com/kanyun/kudos/gradle/KudosGradlePlugin.kt b/kudos-gradle-plugin/src/main/java/com/kanyun/kudos/gradle/KudosGradlePlugin.kt
index 1021100..bfefec4 100644
--- a/kudos-gradle-plugin/src/main/java/com/kanyun/kudos/gradle/KudosGradlePlugin.kt
+++ b/kudos-gradle-plugin/src/main/java/com/kanyun/kudos/gradle/KudosGradlePlugin.kt
@@ -46,8 +46,9 @@ open class KudosGradlePlugin : KotlinCompilerPluginSupportPlugin {
                 if (kudosExtension.jackson) {
                     config += "${BuildConfig.KOTLIN_PLUGIN_GROUP}:kudos-jackson:${BuildConfig.KOTLIN_PLUGIN_VERSION}"
                 }
-                // TODO: Add json reader config
-                config += "${BuildConfig.KOTLIN_PLUGIN_GROUP}:kudos-android-json-reader:${BuildConfig.KOTLIN_PLUGIN_VERSION}"
+                if (kudosExtension.androidJsonReader) {
+                    config += "${BuildConfig.KOTLIN_PLUGIN_GROUP}:kudos-android-json-reader:${BuildConfig.KOTLIN_PLUGIN_VERSION}"
+                }
                 config += "${BuildConfig.KOTLIN_PLUGIN_GROUP}:kudos-annotations:${BuildConfig.KOTLIN_PLUGIN_VERSION}"
                 config += "${BuildConfig.KOTLIN_PLUGIN_GROUP}:kudos-runtime:${BuildConfig.KOTLIN_PLUGIN_VERSION}"
             }
@@ -76,6 +77,9 @@ open class KudosGradlePlugin : KotlinCompilerPluginSupportPlugin {
         if (kudosExtension.jackson) {
             options += SubpluginOption("jackson", "true")
         }
+        if (kudosExtension.androidJsonReader) {
+            options += SubpluginOption("androidJsonReader", "true")
+        }
         return project.provider { options }
     }
 }
diff --git a/kudos-gson/src/main/java/com/kanyun/kudos/gson/KudosGson.kt b/kudos-gson/src/main/java/com/kanyun/kudos/gson/KudosGson.kt
index c99a31d..dee29fa 100644
--- a/kudos-gson/src/main/java/com/kanyun/kudos/gson/KudosGson.kt
+++ b/kudos-gson/src/main/java/com/kanyun/kudos/gson/KudosGson.kt
@@ -29,3 +29,5 @@ fun kudosGsonBuilder(): GsonBuilder {
 fun kudosGson(): Gson {
     return kudosGsonBuilder().create()
 }
+
+const val KUDOS_GSON: Int = 1
diff --git a/kudos-jackson/src/main/java/com/kanyun/kudos/jackson/KudosObjectMapper.kt b/kudos-jackson/src/main/java/com/kanyun/kudos/jackson/KudosObjectMapper.kt
index 611697a..752b5d4 100644
--- a/kudos-jackson/src/main/java/com/kanyun/kudos/jackson/KudosObjectMapper.kt
+++ b/kudos-jackson/src/main/java/com/kanyun/kudos/jackson/KudosObjectMapper.kt
@@ -42,3 +42,5 @@ fun kudosObjectMapper(
     }
     return ObjectMapper(jf, sp, deserializationContext)
 }
+
+const val KUDOS_JACKSON: Int = 2

From 3982940e66dc3d80796276aee9e350961085eda7 Mon Sep 17 00:00:00 2001
From: RicardoJiang <2868405029@qq.com>
Date: Tue, 21 Nov 2023 11:11:42 +0800
Subject: [PATCH 2/2] MOD: throw exception when unkown annotation

---
 .../com/kanyun/kudos/json/reader/KudosAndroidJsonReader.kt  | 4 ++--
 .../kudos/compiler/k1/KudosSyntheticResolveExtension.kt     | 3 +++
 .../compiler/k2/KudosFirSupertypeGenerationExtension.kt     | 6 +++---
 .../main/java/com/kanyun/kudos/compiler/options/Options.kt  | 1 +
 4 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/kudos-android-json-reader/src/main/java/com/kanyun/kudos/json/reader/KudosAndroidJsonReader.kt b/kudos-android-json-reader/src/main/java/com/kanyun/kudos/json/reader/KudosAndroidJsonReader.kt
index 0f8e959..4bdd8aa 100644
--- a/kudos-android-json-reader/src/main/java/com/kanyun/kudos/json/reader/KudosAndroidJsonReader.kt
+++ b/kudos-android-json-reader/src/main/java/com/kanyun/kudos/json/reader/KudosAndroidJsonReader.kt
@@ -32,10 +32,10 @@ object KudosAndroidJsonReader {
         return fromJson(inputStream.bufferedReader(), T::class.java)
     }
 
-    fun <T> fromJson(bufferReader: BufferedReader, clazz: Class<T>): T {
+    fun <T> fromJson(bufferedReader: BufferedReader, clazz: Class<T>): T {
         val adapter = clazz.getDeclaredConstructor().newInstance()
         return if (adapter is KudosJsonAdapter<*>) {
-            val jsonReader = JsonReader(bufferReader)
+            val jsonReader = JsonReader(bufferedReader)
             adapter.fromJson(jsonReader) as T
         } else {
             throw IllegalArgumentException("class ${clazz.name} must implement KudosJsonAdapter")
diff --git a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k1/KudosSyntheticResolveExtension.kt b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k1/KudosSyntheticResolveExtension.kt
index 54900dc..aba1964 100644
--- a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k1/KudosSyntheticResolveExtension.kt
+++ b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k1/KudosSyntheticResolveExtension.kt
@@ -60,6 +60,9 @@ class KudosSyntheticResolveExtension(
         if (thisDescriptor.annotations.hasAnnotation(KUDOS_NAME)) {
             val kudosAnnotation = thisDescriptor.annotations.findAnnotation(KUDOS_NAME)
             val annotationValues = kudosAnnotation?.allValueArguments?.values?.firstOrNull()?.value?.safeAs<List<IntValue>>()?.map {
+                if (it.value !in Options.validAnnotationList) {
+                    throw IllegalArgumentException("unknown annotation argument ${it.value}")
+                }
                 it.value
             }
             kudosAnnotationValueMap[thisDescriptor.classId?.asString() ?: ""] = annotationValues ?: emptyList()
diff --git a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k2/KudosFirSupertypeGenerationExtension.kt b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k2/KudosFirSupertypeGenerationExtension.kt
index 843ce0a..076aca5 100644
--- a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k2/KudosFirSupertypeGenerationExtension.kt
+++ b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/k2/KudosFirSupertypeGenerationExtension.kt
@@ -152,8 +152,8 @@ class KudosFirSupertypeGenerationExtension(
 
     private fun FirAnnotation.getIntArrayArgument(): List<Int>? {
         if (this !is FirAnnotationCall) return null
-        return arguments.mapNotNull {
-            when (it.safeAs<FirPropertyAccessExpression>()?.calleeReference?.safeAs<FirSimpleNamedReference>()?.name?.asString()) {
+        return arguments.map {
+            when (val annotationValue = it.safeAs<FirPropertyAccessExpression>()?.calleeReference?.safeAs<FirSimpleNamedReference>()?.name?.asString()) {
                 "KUDOS_ANDROID_JSON_READER" -> {
                     Options.KUDOS_ANDROID_JSON_READER
                 }
@@ -167,7 +167,7 @@ class KudosFirSupertypeGenerationExtension(
                 }
 
                 else -> {
-                    null
+                    throw IllegalArgumentException("unknown annotation argument $annotationValue")
                 }
             }
         }
diff --git a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/options/Options.kt b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/options/Options.kt
index 93679a8..28365fb 100644
--- a/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/options/Options.kt
+++ b/kudos-compiler/src/main/java/com/kanyun/kudos/compiler/options/Options.kt
@@ -21,6 +21,7 @@ object Options {
     const val KUDOS_GSON = 1
     const val KUDOS_JACKSON = 2
     const val KUDOS_ANDROID_JSON_READER = 3
+    val validAnnotationList = listOf(KUDOS_GSON, KUDOS_JACKSON, KUDOS_ANDROID_JSON_READER)
 
     @JvmField
     val gson = Option(