com.jtransc.ast.ast_annotation.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jtransc-core Show documentation
Show all versions of jtransc-core Show documentation
JVM AOT compiler currently generating JavaScript, C++, Haxe, with initial focus on Kotlin and games.
package com.jtransc.ast
import com.jtransc.annotation.JTranscMethodBodyList
import com.jtransc.gen.TargetName
import java.lang.reflect.Proxy
import kotlin.reflect.KProperty1
data class AstAnnotation(
val type: AstType.REF,
val elements: Map,
val runtimeVisible: Boolean
) {
private var typedObject: Any? = null
private fun getAllDescendantAnnotations(value: Any?): List {
return when (value) {
is AstAnnotation -> getAllDescendantAnnotations(elements.values.toList())
is List<*> -> value.filterIsInstance() + value.filterIsInstance>().flatMap { getAllDescendantAnnotations(it) }
else -> listOf()
}
}
fun getAllDescendantAnnotations(): List {
var out = arrayListOf()
out.add(this)
out.addAll(getAllDescendantAnnotations(this))
return out
}
inline fun toObject(): T? {
return this.toObject(T::class.java)
}
fun toObject(clazz: Class): T? {
return if (clazz.name == this.type.fqname) toAnyObject() as T else null
}
fun toAnyObject(): Any? {
if (typedObject == null) {
val classLoader = this.javaClass.classLoader
fun minicast(it: Any?, type: Class<*>): Any? {
return when (it) {
is List<*> -> {
val array = java.lang.reflect.Array.newInstance(type.componentType, it.size)
for (n in 0 until it.size) java.lang.reflect.Array.set(array, n, minicast(it[n], type.componentType))
array
}
is AstAnnotation -> {
it.toAnyObject()
}
else -> {
it
}
}
}
typedObject = Proxy.newProxyInstance(classLoader, arrayOf(classLoader.loadClass(this.type.fqname))) { proxy, method, args ->
val valueUncasted = this.elements[method.name] ?: method.defaultValue
val returnType = method.returnType
minicast(valueUncasted, returnType)
}
}
return typedObject!!
}
}
fun AstAnnotation.getRefTypesFqName(): List {
val out = hashSetOf()
out += this.type.getRefTypesFqName()
for (e in this.elements.values) {
when (e) {
is AstAnnotation -> {
out += e.getRefTypesFqName()
}
is List<*> -> {
for (i in e) {
when (i) {
is AstAnnotation -> {
out += i.getRefTypesFqName()
}
}
}
}
}
//println("" + e + " : " + e?.javaClass)
}
return out.toList()
}
class AstAnnotationList(val containerRef: AstRef, val list: List) {
val byClassName by lazy { list.groupBy { it.type.fqname } }
inline fun getTypedList(field: KProperty1>): List {
val single = this.getTyped()
val list = this.getTyped()
return listOf(single).filterNotNull() + (if (list != null) field.get(list).toList() else listOf())
}
inline fun getTyped(): T? = byClassName[T::class.java.name]?.firstOrNull()?.toObject()
inline fun getAllTyped(): List = byClassName[T::class.java.name]?.map { it.toObject() }?.filterNotNull() ?: listOf()
operator fun get(name: FqName): AstAnnotation? = byClassName[name.fqname]?.firstOrNull()
inline fun contains(): Boolean = T::class.java.name in byClassName
}
class NativeBody(val lines: List, val cond: String = "") {
val value = lines.joinToString("\n")
}
fun AstAnnotationList.getBodiesForTarget(targetName: TargetName): List {
val extra = when (targetName.name) {
"js" -> this.list.filter { it.type.name.simpleName == "JsMethodBody" }.map { NativeBody(listOf(it.elements["value"]?.toString() ?: "")) }
else -> listOf()
}
return this.getTypedList(JTranscMethodBodyList::value).filter { targetName.matches(it.target) }.map { NativeBody(it.value.toList(), it.cond) } + extra
}
fun AstAnnotationList.getCallSiteBodiesForTarget(targetName: TargetName): String? {
return this.getTypedList(com.jtransc.annotation.JTranscCallSiteBodyList::value).filter { targetName.matches(it.target) }.map { it.value.joinToString("\n") }.firstOrNull()
}