You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
3.6 KiB
Kotlin
99 lines
3.6 KiB
Kotlin
4 years ago
|
package me.eater.threedom.kapt
|
||
|
|
||
|
import org.yanex.takenoko.*
|
||
|
import java.io.File
|
||
|
import javax.annotation.processing.*
|
||
|
import javax.lang.model.SourceVersion
|
||
|
import javax.lang.model.element.Element
|
||
|
import javax.lang.model.element.TypeElement
|
||
|
import javax.tools.Diagnostic.Kind.ERROR
|
||
|
|
||
|
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
||
|
@SupportedAnnotationTypes("me.eater.threedom.kapt.EventName")
|
||
|
@SupportedOptions(EventNameProcessor.KAPT_KOTLIN_GENERATED_OPTION_NAME, "org.gradle.annotation.processing.aggregating")
|
||
|
class EventNameProcessor : AbstractProcessor() {
|
||
|
companion object {
|
||
|
const val KAPT_KOTLIN_GENERATED_OPTION_NAME = "kapt.kotlin.generated"
|
||
|
}
|
||
|
|
||
|
override fun process(annotations: MutableSet<out TypeElement>?, roundEnv: RoundEnvironment): Boolean {
|
||
|
val annotatedElements = roundEnv.getElementsAnnotatedWith(EventName::class.java)
|
||
|
if (annotatedElements.isEmpty()) return false
|
||
|
|
||
|
val kaptKotlinGeneratedDir = processingEnv.options[KAPT_KOTLIN_GENERATED_OPTION_NAME] ?: run {
|
||
|
processingEnv.messager.printMessage(ERROR, "Can't find the target directory for generated Kotlin files.")
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
val generatedKtFile = kotlinFile("me.eater.threedom.generated") {
|
||
|
objectDeclaration("EventNames") {
|
||
|
val eventNames = mutableMapOf<String, String>()
|
||
|
|
||
|
for (element in annotatedElements) {
|
||
|
val typeElement = element.toTypeElementOrNull() ?: continue
|
||
|
val eventName = typeElement.getAnnotation(EventName::class.java).eventName
|
||
|
|
||
|
if (eventName in eventNames) {
|
||
|
processingEnv.messager.printMessage(
|
||
|
ERROR,
|
||
|
"Class ${eventNames[eventName]} already uses the event name '${eventName}'",
|
||
|
element
|
||
|
)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
eventNames[typeElement.qualifiedName.toString()] = eventName
|
||
|
|
||
|
property(eventName) {
|
||
|
initializer(typeElement.qualifiedName.toString() + "::class")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
property("EVENT_MAPPING") {
|
||
|
initializer(
|
||
|
"mapOf(\n${eventNames.map { (k, v) -> " \"" + k.replace('"', '\"') + "\" to \"" + v.replace('"', '\"') + '"' }
|
||
|
.joinToString(",\n")}\n)"
|
||
|
)
|
||
|
}
|
||
|
|
||
|
function("getEventName") {
|
||
|
param<String>("eventClass")
|
||
|
returnType<String>()
|
||
|
|
||
|
body {
|
||
|
append("return EVENT_MAPPING[eventClass] ?: eventClass")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function(
|
||
|
"getEventName", INLINE
|
||
|
) {
|
||
|
typeParam("reified T")
|
||
|
returnType<String>()
|
||
|
|
||
|
body {
|
||
|
append("return getEventName(T::class.java.name)")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
File("$kaptKotlinGeneratedDir/me/eater/threedom/generated", "EventNames.kt").apply {
|
||
|
parentFile.mkdirs()
|
||
|
writeText(generatedKtFile.accept(PrettyPrinter(PrettyPrinterConfiguration())))
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
|
||
|
fun Element.toTypeElementOrNull(): TypeElement? {
|
||
|
if (this !is TypeElement) {
|
||
|
processingEnv.messager.printMessage(ERROR, "Invalid element type, class expected", this)
|
||
|
return null
|
||
|
}
|
||
|
|
||
|
return this
|
||
|
}
|
||
|
}
|