app.softwork.serviceloader.ksp.ServiceLoaderPlugin.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ksp-plugin Show documentation
Show all versions of ksp-plugin Show documentation
A Gradle plugin to generate and validate service loaders
The newest version!
package app.softwork.serviceloader.ksp
import app.softwork.serviceloader.*
import com.google.devtools.ksp.*
import com.google.devtools.ksp.processing.*
import com.google.devtools.ksp.symbol.*
public class ServiceLoaderPlugin(private val codeGenerator: CodeGenerator) : SymbolProcessor {
override fun process(resolver: Resolver): List {
val providers = mutableMapOf>()
for (annotatedClass in resolver.getSymbolsWithAnnotation(ServiceLoader::class.qualifiedName!!)) {
if (annotatedClass is KSClassDeclaration) {
for (anno in annotatedClass.annotations) {
if (anno.shortName.getShortName() == ServiceLoader::class.simpleName) {
val provider = anno.arguments.single().value as KSType
val providerDec = provider.declaration
require(annotatedClass.getAllSuperTypes().any {
it.declaration == providerDec
}) {
"Class $annotatedClass does not implement or inherit $provider."
}
require(annotatedClass.getConstructors().any {
it.isPublic() && it.parameters.isEmpty()
}) {
"Class $annotatedClass does not have a public zero arg constructor."
}
require(!annotatedClass.isAbstract()) {
"Class $annotatedClass is abstract."
}
requireNotNull(annotatedClass.qualifiedName) {
"Class $annotatedClass is local."
}
val providerName = providerDec.qualifiedName!!.asString()
val found = providers[provider.toString()]
providers[providerName] = if (found == null) {
mutableListOf(annotatedClass)
} else {
found.add(annotatedClass)
found
}
}
}
}
}
for ((provider, classes) in providers) {
codeGenerator.createNewFileByPath(
Dependencies(false, sources = classes.map { it.containingFile!! }.toTypedArray()),
"META-INF/services/$provider",
extensionName = ""
).bufferedWriter().use {
for (impl in classes) {
it.appendLine(impl.qualifiedName!!.asString())
}
}
}
return emptyList()
}
}