godot.annotation.processor.visitor.RegistrationAnnotationVisitor.kt Maven / Gradle / Ivy
package godot.annotation.processor.visitor
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSFile
import com.google.devtools.ksp.symbol.KSVisitorVoid
import godot.annotation.RegisterClass
import godot.annotation.RegisterConstructor
import godot.annotation.RegisterFunction
import godot.annotation.RegisterProperty
import godot.annotation.RegisterSignal
import godot.annotation.processor.Settings
import godot.annotation.processor.ext.fqNameUnsafe
import godot.annotation.processor.ext.hasCompilationErrors
import godot.annotation.processor.ext.mapToClazz
import godot.entrygenerator.model.RegisteredClass
import godot.entrygenerator.model.SourceFile
/**
* Collects [RegisterClass], [RegisterConstructor], [RegisterFunction], [RegisterProperty], [RegisterSignal] annotations
* for registrar generation and entry generation
*/
internal class RegistrationAnnotationVisitor(
private val settings: Settings,
) : KSVisitorVoid() {
private val registerAnnotations = listOf(
RegisterClass::class.qualifiedName!!,
RegisterConstructor::class.qualifiedName!!,
RegisterFunction::class.qualifiedName!!,
RegisterProperty::class.qualifiedName!!,
RegisterSignal::class.qualifiedName!!
)
private val _registeredClassToKSFileMap: MutableMap = mutableMapOf()
val registeredClassToKSFileMap: Map = _registeredClassToKSFileMap
private val _sourceFilesContainingRegisteredClasses: MutableList = mutableListOf()
val sourceFilesContainingRegisteredClasses: List = _sourceFilesContainingRegisteredClasses
override fun visitFile(file: KSFile, data: Unit) {
val absolutePath = file.filePath
val registeredClasses = file
.declarations
.mapNotNull { declaration ->
when (declaration) {
is KSClassDeclaration -> {
if (declaration.hasCompilationErrors()) {
null
} else {
val clazz = declaration.mapToClazz(settings)
if (clazz is RegisteredClass) {
clazz
} else null
}
}
else -> if (declaration.annotations.any { registerAnnotations.contains(it.fqNameUnsafe) }) {
throw IllegalStateException("${declaration.qualifiedName} was registered top level. Only classes can be registered top level.")
} else {
null
}
}
}
.onEach { registeredClass ->
_registeredClassToKSFileMap[registeredClass] = file
}
.toList()
if (registeredClasses.isNotEmpty()) {
_sourceFilesContainingRegisteredClasses.add(
SourceFile(
absolutePath = absolutePath,
registeredClasses = registeredClasses,
symbolProcessorSource = this
)
)
}
}
}