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

app.softwork.serviceloader.ksp.ServiceLoaderPlugin.kt Maven / Gradle / Ivy

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()
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy