Skip to content

Commit

Permalink
feat(generator): introduce ArgVariant annotation
Browse files Browse the repository at this point in the history
New annotation provides an ability to generate methods definitions for different types and names.
  • Loading branch information
SpaiR committed Aug 26, 2024
1 parent cae0581 commit 8ddc93b
Show file tree
Hide file tree
Showing 8 changed files with 505 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import spoon.reflect.declaration.CtElement
import spoon.reflect.declaration.CtField
import spoon.reflect.declaration.CtMethod
import spoon.reflect.declaration.CtType
import kotlin.math.max

class BindingSourceProcessor(
private val type: CtType<*>
Expand Down Expand Up @@ -101,7 +102,53 @@ class BindingSourceProcessor(
contentToReplace[ReplacePos(it.position.sourceStart, it.position.sourceEnd + 6)] = ""
}

val content = jvmMethodContent(method) + jniMethodContent(method)
val content = mutableListOf<String>()

// Handle argument variants
if (method.parameters.find { it.hasAnnotation(A_NAME_ARG_VARIANT) } != null) {
data class ArgVar(val idx: Int, val type: String, val name: String)

val variants = mutableListOf<ArgVar>()

method.parameters.forEachIndexed { idx, p ->
if (p.hasAnnotation(A_NAME_ARG_VARIANT)) {
val a = p.getAnnotation(A_NAME_ARG_VARIANT)!!
val types = (a.getValueAsObject(A_VALUE_TYPE) as Array<*>).map { it.toString() }
val names = (a.getValueAsObject(A_VALUE_NAME) as Array<*>).map { it.toString() }

if (types.isNotEmpty() && names.isNotEmpty() && types.size != names.size) {
error("Types size should be the as names! Current: types=${types.size}, names=${names.size}")
}

for (i in 0 until max(types.size, names.size)) {
variants += ArgVar(
idx,
types.getOrNull(i) ?: p.type.simpleName,
names.getOrNull(i) ?: p.simpleName,
)
}
}
}

val variantsMap = variants.groupBy { it.idx }
val variantsCount = variantsMap.values.first().size

for (i in 0 until variantsCount) {
val m = method.clone()
m.setParent<Nothing>(method.parent)
variantsMap.values.forEach { vList ->
val v = vList[i]
val p = m.parameters[v.idx]
p.setAnnotations<Nothing>(p.annotations.filterNot { it.name == A_NAME_ARG_VARIANT })
p.setType<Nothing>(m.factory.createTypeParameterReference(v.type))
p.setSimpleName<Nothing>(v.name)
}
content += jvmMethodContent(m) + jniMethodContent(m)
}
} else {
content += jvmMethodContent(method) + jniMethodContent(method)
}

contentToReplace[method.findReplacePos()] = content.joinWithIndention()
return contentToReplace
}
Expand Down
8 changes: 2 additions & 6 deletions buildSrc/src/main/kotlin/tool/generator/api/jni_content.kt
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ private fun convertParams2jni(f: Factory, params: List<CtParameter<*>>, defaults
result += f.createParameter<Nothing>().apply {
val type = if (p.type.isPtrClass()) {
f.createTypeParam("long")
} else if (p.type.isClass) {
} else {
when (p.type.simpleName) {
"ImBoolean" -> f.createTypeParam("boolean[]")
"ImShort" -> f.createTypeParam("short[]")
Expand All @@ -120,8 +120,6 @@ private fun convertParams2jni(f: Factory, params: List<CtParameter<*>>, defaults
"ImDouble" -> f.createTypeParam("double[]")
else -> p.type
}
} else {
p.type
}

setType<Nothing>(type)
Expand All @@ -138,7 +136,7 @@ private fun joinInBodyParams(params: List<CtParameter<*>>, defaults: IntArray):
"reinterpret_cast<${p.type.simpleName}*>(${p.simpleName})"
} else if (p.isPrimitivePtrType()) {
"&${p.simpleName}[0]"
} else if (p.type.isClass) {
} else {
when (p.type.simpleName) {
"ImBoolean", "ImShort", "ImInt", "ImFloat", "ImLong", "ImDouble" -> {
"(${p.simpleName} != NULL ? &${p.simpleName}[0] : NULL)"
Expand Down Expand Up @@ -166,8 +164,6 @@ private fun joinInBodyParams(params: List<CtParameter<*>>, defaults: IntArray):

else -> p.simpleName
}
} else {
p.simpleName
}
}

Expand Down
6 changes: 2 additions & 4 deletions buildSrc/src/main/kotlin/tool/generator/api/jvm_content.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ private fun joinInBodyParams(params: List<CtParameter<*>>, defaults: IntArray):
fun param2str(p: CtParameter<*>): String {
return if (p.type.isPtrClass()) {
"${p.simpleName}.$PTR_JVM_FIELD"
} else if (p.type.isClass) {
} else {
when (p.type.simpleName) {
"ImBoolean", "ImShort", "ImInt", "ImFloat", "ImLong", "ImDouble" -> {
"${p.simpleName} != null ? ${p.simpleName}.getData() : null"
Expand All @@ -42,8 +42,6 @@ private fun joinInBodyParams(params: List<CtParameter<*>>, defaults: IntArray):

else -> p.simpleName
}
} else {
p.simpleName
}
}

Expand Down Expand Up @@ -147,7 +145,7 @@ private fun createMethod(origM: CtMethod<*>, params: List<CtParameter<*>>, defau
append(createBodyStaticStructReturn(origM, params, defaults))
} else if (DST_RETURN_TYPE_SET.contains(origM.type.simpleName)) {
append(createBodyDstReturn(origM, params, defaults))
} else if (origM.type.isClass && !origM.type.isPrimitive && !origM.isType("void") && !origM.isType("String") && !origM.isPrimitivePtrType()) {
} else if (origM.type.isPtrClass()) {
append(createBodyStructReturn(origM, params, defaults))
} else {
if (!origM.isType("void")) {
Expand Down
2 changes: 2 additions & 0 deletions buildSrc/src/main/kotlin/tool/generator/api/util.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const val A_NAME_OPT_ARG = "OptArg"
const val A_NAME_EXCLUDED_SOURCE = "ExcludedSource"
const val A_NAME_RETURN_VALUE = "ReturnValue"
const val A_NAME_ARG_VALUE = "ArgValue"
const val A_NAME_ARG_VARIANT = "ArgVariant"
const val A_NAME_TYPE_ARRAY = "TypeArray"
const val A_NAME_TYPE_STD_STRING = "TypeStdString"

Expand Down Expand Up @@ -56,6 +57,7 @@ val CLEANUP_ANNOTATIONS_LIST = listOf(
A_NAME_RETURN_VALUE,
A_NAME_OPT_ARG,
A_NAME_ARG_VALUE,
A_NAME_ARG_VARIANT,
A_NAME_TYPE_ARRAY,
A_NAME_TYPE_STD_STRING,
A_NAME_BINDING_AST_ENUM,
Expand Down
Loading

0 comments on commit 8ddc93b

Please sign in to comment.