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