All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.catchpig.ksp.compiler.generator.PrefsGenerator.kt Maven / Gradle / Ivy

There is a newer version: 1.1.4
Show newest version
package com.catchpig.ksp.compiler.generator

import com.catchpig.annotation.Prefs
import com.catchpig.annotation.PrefsField
import com.catchpig.ksp.compiler.ext.getKSClassDeclarations
import com.google.devtools.ksp.KspExperimental
import com.google.devtools.ksp.getAnnotationsByType
import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.KSBuiltIns
import com.google.devtools.ksp.processing.KSPLogger
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSPropertyDeclaration
import com.google.devtools.ksp.validate
import com.squareup.kotlinpoet.*
import com.squareup.kotlinpoet.ksp.toClassName
import com.squareup.kotlinpoet.ksp.writeTo

class PrefsGenerator(
    codeGenerator: CodeGenerator,
    logger: KSPLogger
) : BaseGenerator(codeGenerator, logger) {

    companion object {
        private const val TAG = "PrefsGenerator"
        private val CLASS_NAME_SHARED_PREFERENCES_EDITOR =
            ClassName("android.content.SharedPreferences", "Editor")
        private val CLASS_NAME_SHARED_PREFERENCES =
            ClassName("android.content", "SharedPreferences")

        private val CLASS_NAME_CONTEXT_MANAGER =
            ClassName("com.catchpig.utils.manager", "ContextManager")

    }

    lateinit var ksBuiltIns: KSBuiltIns

    override fun process(resolver: Resolver) {
        ksBuiltIns = resolver.builtIns
        val list = resolver.getKSClassDeclarations()
        if (list.isNotEmpty()) {
            generate(list)
        }
    }

    @OptIn(KspExperimental::class)
    private fun generate(list: List) {
        list.forEach {
            val prefs = it.getAnnotationsByType(Prefs::class).first()
            val className = it.toClassName().simpleName
            warning(TAG, "${className}被SharedPrefs注解")
            val fullPackageName = it.toClassName().packageName
            val typeSpec = TypeSpec
                .objectBuilder("${className}SharedPrefs")
                .addModifiers(KModifier.FINAL, KModifier.PUBLIC)
                .addProperty(addSharedPrefsProperty())
                .addProperty(addSharedPrefsEditorProperty())
                .addInitializerBlock(addCodeBlock(prefs, className))
                .addFunctions(addFuns(it))
                .build()

            FileSpec
                .builder(fullPackageName, typeSpec.name!!)
                .addType(typeSpec)
                .build()
                .writeTo(codeGenerator, false)
        }
    }

    @OptIn(KspExperimental::class)
    private fun addFuns(ksClassDeclaration: KSClassDeclaration): MutableList {
        val className = ksClassDeclaration.toClassName().simpleName
        var funSpecs = ArrayList()
        val fieldElements = ksClassDeclaration.getAllProperties()
        fieldElements.forEach {
            val annotations = it.getAnnotationsByType(PrefsField::class).toList()
            if (annotations.isNotEmpty()) {
                annotations.first().let { prefsField ->
                    val fieldName = it.simpleName.getShortName()
                    warning(TAG, "${className}->${fieldName}被PrefsField注解")
                    val prefsKey = prefsField.value.ifEmpty {
                        fieldName
                    }
                    val funName = fieldName.substring(0, 1).uppercase() + fieldName.substring(1)
                    if (isCreateMethod(it)) {
                        //set方法
                        funSpecs.add(createSetFunction(it, funName, fieldName, prefsKey))
                        //get方法
                        funSpecs.add(createGetFunction(it, funName, prefsKey))
                    } else {
                        error("${fieldName}的类型不支持,只支持Double,Float,Int,Long,String,Boolean")
                    }

                }
            }

        }
        val clearFunSpec = FunSpec
            .builder("clear")
            .addStatement("sharedEditor.clear()")
            .addStatement("sharedEditor.commit()")
            .build()
        funSpecs.add(clearFunSpec)
        return funSpecs
    }

    /**
     * 创建get方法
     */
    private fun createGetFunction(
        ksPropertyDeclaration: KSPropertyDeclaration,
        funName: String,
        prefsKey: String
    ): FunSpec {
        var getFunSpecBuilder = FunSpec
            .builder("get${funName}")

        when (ksPropertyDeclaration.type.resolve()) {
            ksBuiltIns.booleanType -> {
                getFunSpecBuilder = getFunSpecBuilder
                    .addStatement("return sharedPrefs.getBoolean(%S,false)", prefsKey)
                    .returns(BOOLEAN)
            }
            ksBuiltIns.floatType -> {
                getFunSpecBuilder = getFunSpecBuilder
                    .addStatement("return sharedPrefs.getFloat(%S,0f)", prefsKey)
                    .returns(FLOAT)
            }
            ksBuiltIns.intType -> {
                getFunSpecBuilder = getFunSpecBuilder
                    .returns(INT)
                    .addStatement("return sharedPrefs.getInt(%S,0)", prefsKey)
            }
            ksBuiltIns.longType -> {
                getFunSpecBuilder = getFunSpecBuilder
                    .returns(LONG)
                    .addStatement("return sharedPrefs.getLong(%S,0)", prefsKey)
            }
            ksBuiltIns.doubleType -> {
                getFunSpecBuilder = getFunSpecBuilder
                    .returns(DOUBLE)
                    .addStatement(
                        "return sharedPrefs.getString(%S,%S)!!.toDouble()",
                        prefsKey,
                        "0.0"
                    )
            }
            ksBuiltIns.stringType -> {
                getFunSpecBuilder = getFunSpecBuilder
                    .returns(STRING)
                    .addStatement("return sharedPrefs.getString(%S,%S)!!", prefsKey, "")
            }
            else -> {
            }
        }
        return getFunSpecBuilder.build()
    }

    /**
     * 创建set方法
     */
    private fun createSetFunction(
        ksPropertyDeclaration: KSPropertyDeclaration,
        funName: String,
        fieldName: String,
        prefsKey: String
    ): FunSpec {
        var setFunSpecBuilder = FunSpec
            .builder("set${funName}")
        when (ksPropertyDeclaration.type.resolve()) {
            ksBuiltIns.booleanType -> {
                setFunSpecBuilder = setFunSpecBuilder
                    .addParameter(fieldName, BOOLEAN)
                    .addStatement("sharedEditor.putBoolean(%S,$fieldName).apply()", prefsKey)
            }
            ksBuiltIns.floatType -> {
                setFunSpecBuilder = setFunSpecBuilder
                    .addParameter(fieldName, FLOAT)
                    .addStatement("sharedEditor.putFloat(%S,$fieldName).apply()", prefsKey)
            }
            ksBuiltIns.intType -> {
                setFunSpecBuilder = setFunSpecBuilder
                    .addParameter(fieldName, INT)
                    .addStatement("sharedEditor.putInt(%S,$fieldName).apply()", prefsKey)
            }
            ksBuiltIns.longType -> {
                setFunSpecBuilder = setFunSpecBuilder
                    .addParameter(fieldName, LONG)
                    .addStatement("sharedEditor.putLong(%S,$fieldName).apply()", prefsKey)
            }
            ksBuiltIns.doubleType -> {
                setFunSpecBuilder = setFunSpecBuilder
                    .addParameter(fieldName, DOUBLE)
                    .addStatement(
                        "sharedEditor.putString(%S,${fieldName}.toString()).apply()",
                        prefsKey
                    )
            }
            ksBuiltIns.stringType -> {
                setFunSpecBuilder = setFunSpecBuilder
                    .addParameter(fieldName, STRING)
                    .addStatement("sharedEditor.putString(%S,${fieldName}).apply()", prefsKey)
            }
            else -> {
            }
        }
        return setFunSpecBuilder.build()
    }

    /**
     * 初始化参数
     * 包括sharedPrefs和sharedEditor
     */
    private fun addCodeBlock(prefs: Prefs, className: String): CodeBlock {
        var sharedPrefsName = if (prefs.value.isEmpty()) {
            className
        } else {
            prefs.value
        }
        return CodeBlock
            .builder()
            .addStatement(
                "sharedPrefs = %T.getInstance().getContext().getSharedPreferences(\"SharedPrefs_$sharedPrefsName\",%L)",
                CLASS_NAME_CONTEXT_MANAGER,
                prefs.mode.value
            )
            .addStatement("sharedEditor = sharedPrefs.edit()")
            .build()
    }

    /**
     * 添加sharedEditor变量
     */
    private fun addSharedPrefsEditorProperty(): PropertySpec {
        return PropertySpec
            .builder("sharedEditor", CLASS_NAME_SHARED_PREFERENCES_EDITOR)
            .addModifiers(KModifier.PRIVATE)
            .build()
    }

    /**
     * 添加sharedPrefs变量
     */
    private fun addSharedPrefsProperty(): PropertySpec {
        return PropertySpec
            .builder("sharedPrefs", CLASS_NAME_SHARED_PREFERENCES)
            .addModifiers(KModifier.PRIVATE)
            .build()
    }

    /**
     * 是否声场set和get方法
     *
     * 只有类型为Double,Float,Int,Long,String,Boolean才能生成方法
     */
    private fun isCreateMethod(ksPropertyDeclaration: KSPropertyDeclaration): Boolean {
        return when (ksPropertyDeclaration.type.resolve()) {
            ksBuiltIns.booleanType, ksBuiltIns.floatType, ksBuiltIns.intType, ksBuiltIns.longType, ksBuiltIns.doubleType, ksBuiltIns.stringType -> {
                true
            }
            else -> {
                false
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy