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

jvmMain.com.lt.reflection.provider.VirtualReflectionSymbolProcessor.kt Maven / Gradle / Ivy

package com.lt.reflection.provider

import com.google.devtools.ksp.KspExperimental
import com.google.devtools.ksp.processing.Dependencies
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.processing.SymbolProcessor
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
import com.google.devtools.ksp.symbol.ClassKind
import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSDeclaration
import com.google.devtools.ksp.symbol.KSFile
import com.google.devtools.ksp.validate
import com.lt.reflection.ReflectionObject
import com.lt.reflection.appendText
import com.lt.reflection.options.KSClassConstructorInfo
import com.lt.reflection.options.KspOptions

/**
 * creator: lt  2022/10/20  [email protected]
 * effect : ksp处理程序
 * warning:
 */
internal class VirtualReflectionSymbolProcessor(private val environment: SymbolProcessorEnvironment) :
    SymbolProcessor {
    //只做一轮处理
    private var isHandled = false

    override fun process(resolver: Resolver): List {
        if (isHandled) return listOf()
        isHandled = true
        val kspOptions = KspOptions(environment)
        val packageList = kspOptions.getPackageList()
        val functionName = kspOptions.getFunctionName()
        val ret = mutableListOf()
        val classConstructorList = ArrayList()

        //处理指定包内的构造函数
        resolver.getAllFiles()
            .filter {
                //包名如果是配置的或子包名
                val packageName = it.packageName.asString() + "."
                packageList.any(packageName::contains)
            }.forEach { ksFile ->
                handlerObjectWithKSFile(resolver, ksFile, ret, classConstructorList)
            }
        //处理注解标注的构造函数
        resolver.getSymbolsWithAnnotation(ReflectionObject::class.qualifiedName!!)
            .forEach {
                when (it) {
                    is KSFile -> handlerObjectWithKSFile(resolver, it, ret, classConstructorList)
                    is KSDeclaration -> handlerObjectWithKSClass(it, ret, classConstructorList)
                }
            }

        createFile(classConstructorList, functionName)

        //返回无法处理的符号
        return ret
    }

    //虚拟反射构造函数-处理file
    @OptIn(KspExperimental::class)
    private fun handlerObjectWithKSFile(
        resolver: Resolver,
        ksFile: KSFile,
        ret: MutableList,
        classConstructorList: ArrayList
    ) {
        resolver.getDeclarationsInSourceOrder(ksFile).forEach {
            handlerObjectWithKSClass(it, ret, classConstructorList)
        }
    }

    //虚拟反射构造函数-处理class
    private fun handlerObjectWithKSClass(
        it: KSDeclaration,
        ret: MutableList,
        classConstructorList: ArrayList
    ) {
        if (it is KSClassDeclaration && it.classKind == ClassKind.CLASS) {
            if (!it.validate()) ret.add(it)
            else it.accept(
                VirtualReflectionVisitor(environment, classConstructorList),
                Unit
            )//处理符号
        }
    }

    //生成虚拟反射文件
    private fun createFile(
        classConstructorList: ArrayList,
        functionName: String
    ) {
        val file = environment.codeGenerator.createNewFile(
            Dependencies(
                true,
                *classConstructorList.mapNotNull { it.ksFile }.toSet().toTypedArray()
            ), "", "VirtualReflectionUtil"
        )
        //记录有参数的构造方法,稍后处理
        val haveArgsConstructor = ArrayList()
        file.appendText(
            "fun  kotlin.reflect.KClass.$functionName(): T =\n" +
                    "    VirtualReflectionUtil.$functionName(simpleName!!) as T\n" +
                    "\n" +
                    "fun  kotlin.reflect.KClass.$functionName(vararg args: Any?): T =\n" +
                    "    VirtualReflectionUtil.$functionName(simpleName!!, *args) as T\n" +
                    "\n" +
                    "object VirtualReflectionUtil {\n" +
                    "    fun $functionName(name: String): Any = when (name) {\n"
        )
        //处理空参构造方法
        classConstructorList.forEach {
            if (it.constructorArgsType.isNotEmpty()) {
                haveArgsConstructor.add(it)
                return@forEach
            }
            val name = "${it.packageName}.${it.className}"
            file.appendText("        \"${it.className}\" -> $name()\n")
        }
        file.appendText(
            "        else -> throw RuntimeException(\"\$name: Not find in VirtualReflection config\")\n" +
                    "    }\n" +
                    "\n" +
                    "    fun $functionName(name: String, vararg args: Any?): Any = when {\n"
        )
        //处理有参构造方法
        haveArgsConstructor.forEach {
            val name = "${it.packageName}.${it.className}"
            file.appendText(
                "        name == \"${it.className}\" && args.size == ${it.constructorArgsType.size} -> $name("
            )
            //处理参数强转
            it.constructorArgsType.forEachIndexed { index, s ->
                file.appendText("args[$index] as $s, ")
            }
            file.appendText(")\n")
        }
        file.appendText(
            "        else -> throw RuntimeException(\"\$name: Not find in VirtualReflection config\")\n" +
                    "    }\n" +
                    "}"
        )
        file.close()
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy