mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2025-09-08 09:47:09 +00:00
first version of parameters variations
This commit is contained in:
@@ -8,14 +8,13 @@ import com.google.devtools.ksp.processing.SymbolProcessor
|
|||||||
import com.google.devtools.ksp.symbol.*
|
import com.google.devtools.ksp.symbol.*
|
||||||
import com.squareup.kotlinpoet.*
|
import com.squareup.kotlinpoet.*
|
||||||
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
|
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
|
||||||
import com.squareup.kotlinpoet.ksp.toClassName
|
|
||||||
import com.squareup.kotlinpoet.ksp.toKModifier
|
import com.squareup.kotlinpoet.ksp.toKModifier
|
||||||
import com.squareup.kotlinpoet.ksp.toTypeName
|
import com.squareup.kotlinpoet.ksp.toTypeName
|
||||||
import dev.inmo.micro_ksp.generator.companion
|
|
||||||
import dev.inmo.micro_ksp.generator.findSubClasses
|
import dev.inmo.micro_ksp.generator.findSubClasses
|
||||||
import dev.inmo.micro_ksp.generator.writeFile
|
import dev.inmo.micro_ksp.generator.writeFile
|
||||||
import dev.inmo.micro_utils.ksp.variations.GenerateVariations
|
import dev.inmo.micro_utils.ksp.variations.GenerateVariations
|
||||||
import dev.inmo.micro_utils.ksp.variations.GenerationVariant
|
import dev.inmo.micro_utils.ksp.variations.GenerationVariant
|
||||||
|
import kotlin.math.pow
|
||||||
|
|
||||||
class Processor(
|
class Processor(
|
||||||
private val codeGenerator: CodeGenerator
|
private val codeGenerator: CodeGenerator
|
||||||
@@ -50,73 +49,212 @@ class Processor(
|
|||||||
) {
|
) {
|
||||||
val annotation = ksFunctionDeclaration.getAnnotationsByType(GenerateVariations::class).first()
|
val annotation = ksFunctionDeclaration.getAnnotationsByType(GenerateVariations::class).first()
|
||||||
val variations: List<Pair<List<GenerationVariant>, KSValueParameter>> = ksFunctionDeclaration.parameters.mapNotNull {
|
val variations: List<Pair<List<GenerationVariant>, KSValueParameter>> = ksFunctionDeclaration.parameters.mapNotNull {
|
||||||
val variationAnnotations = it.getAnnotationsByType(GenerationVariant::class).toList().ifEmpty { return@mapNotNull null }
|
val variationAnnotations = it.getAnnotationsByType(GenerationVariant::class).toList()
|
||||||
variationAnnotations to it
|
variationAnnotations to it
|
||||||
}
|
}
|
||||||
val accumulatedGenerations = mutableSetOf<FunSpec>()
|
val accumulatedGenerations = mutableSetOf<Pair<FunSpec, Map<String, String>>>()
|
||||||
|
val baseFunctionParameters = ksFunctionDeclaration.parameters.mapNotNull {
|
||||||
|
ParameterSpec
|
||||||
|
.builder(
|
||||||
|
it.name ?.asString() ?: return@mapNotNull null,
|
||||||
|
it.type.toTypeName(),
|
||||||
|
)
|
||||||
|
.apply {
|
||||||
|
if (it.isCrossInline) {
|
||||||
|
addModifiers(KModifier.CROSSINLINE)
|
||||||
|
}
|
||||||
|
if (it.isVal) {
|
||||||
|
addModifiers(KModifier.VALUE)
|
||||||
|
}
|
||||||
|
if (it.isNoInline) {
|
||||||
|
addModifiers(KModifier.NOINLINE)
|
||||||
|
}
|
||||||
|
if (it.isVararg) {
|
||||||
|
addModifiers(KModifier.VARARG)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.build() to it.hasDefault
|
||||||
|
}
|
||||||
|
val baseFunctionFunSpecs = mutableListOf<Pair<FunSpec, Map<String, String>>>()
|
||||||
|
let {
|
||||||
|
var defaultParametersIndicator = 0u
|
||||||
|
val maxIndicator = baseFunctionParameters.filter { it.second }.foldIndexed(0u) { index, acc, _ ->
|
||||||
|
2.0.pow(index).toUInt() + acc
|
||||||
|
}
|
||||||
|
while (defaultParametersIndicator <= maxIndicator) {
|
||||||
|
var currentDefaultParameterIndex = 0u
|
||||||
|
val baseFunctionDefaults = mutableMapOf<String, String>()
|
||||||
|
val funSpec = FunSpec.builder(ksFunctionDeclaration.simpleName.asString()).apply {
|
||||||
|
modifiers.addAll(ksFunctionDeclaration.modifiers.mapNotNull { it.toKModifier() })
|
||||||
|
ksFunctionDeclaration.extensionReceiver ?.let {
|
||||||
|
receiver(it.toTypeName())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
baseFunctionParameters.forEach { (parameter, hasDefault) ->
|
||||||
|
if (hasDefault) {
|
||||||
|
val shouldBeIncluded = (2.0.pow(currentDefaultParameterIndex.toInt()).toUInt()).and(defaultParametersIndicator) > 0u
|
||||||
|
currentDefaultParameterIndex++
|
||||||
|
|
||||||
|
if (!shouldBeIncluded) {
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
}
|
||||||
|
funSpec.addParameter(parameter)
|
||||||
|
val name = parameter.name
|
||||||
|
val defaultValueString = if (parameter.modifiers.contains(KModifier.VARARG)) {
|
||||||
|
"*$name"
|
||||||
|
} else {
|
||||||
|
"$name"
|
||||||
|
}
|
||||||
|
baseFunctionDefaults[parameter.name] = defaultValueString
|
||||||
|
}
|
||||||
|
baseFunctionFunSpecs.add(
|
||||||
|
funSpec.build() to baseFunctionDefaults.toMap()
|
||||||
|
)
|
||||||
|
defaultParametersIndicator++
|
||||||
|
}
|
||||||
|
}
|
||||||
variations.forEach { (variations, parameter) ->
|
variations.forEach { (variations, parameter) ->
|
||||||
if (accumulatedGenerations.isEmpty()) {
|
(baseFunctionFunSpecs + accumulatedGenerations).forEach { (accumulatedGeneration, baseDefaults) ->
|
||||||
|
if ((parameter.name ?.asString() ?: "this") !in baseDefaults.keys) {
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
variations.forEach { variation ->
|
variations.forEach { variation ->
|
||||||
|
val defaults = mutableMapOf<String, String>()
|
||||||
accumulatedGenerations.add(
|
accumulatedGenerations.add(
|
||||||
FunSpec.builder(ksFunctionDeclaration.simpleName.asString()).apply {
|
FunSpec.builder(accumulatedGeneration.name).apply {
|
||||||
modifiers.addAll(ksFunctionDeclaration.modifiers.mapNotNull { it.toKModifier() })
|
modifiers.addAll(accumulatedGeneration.modifiers)
|
||||||
ksFunctionDeclaration.parameters.forEach {
|
accumulatedGeneration.receiverType ?.let {
|
||||||
|
receiver(it)
|
||||||
|
}
|
||||||
|
accumulatedGeneration.parameters.forEach {
|
||||||
parameters.add(
|
parameters.add(
|
||||||
(if (it == parameter) {
|
(if (it.name == (parameter.name ?.asString() ?: "this")) {
|
||||||
ParameterSpec
|
ParameterSpec
|
||||||
.builder(
|
.builder(
|
||||||
variation.argName,
|
variation.argName,
|
||||||
if (variation.varargTypes.isEmpty()) {
|
if (variation.varargTypes.isEmpty()) {
|
||||||
variation.type.asTypeName()
|
ClassName.bestGuess(variation.type)
|
||||||
} else {
|
} else {
|
||||||
variation.type.parameterizedBy(*variation.varargTypes)
|
ClassName.bestGuess(variation.type).parameterizedBy(
|
||||||
|
*variation.varargTypes.map { it.asTypeName() }.toTypedArray()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.apply {
|
.apply {
|
||||||
val name = it.name ?.asString() ?: "this"
|
val defaultValueString = if (it.modifiers.contains(KModifier.VARARG)) {
|
||||||
if (it.isVararg) {
|
"""
|
||||||
defaultValue(
|
*${variation.argName}.map { it.${variation.conversion} }.toTypedArray()
|
||||||
"""
|
""".trimIndent()
|
||||||
*$name.map { it.${variation.conversion} }.toTypedArray()
|
|
||||||
""".trimIndent()
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
defaultValue("$name.${variation.conversion}")
|
"${variation.argName}.${variation.conversion}"
|
||||||
}
|
}
|
||||||
|
defaults[it.name] = defaultValueString
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ParameterSpec
|
it.toBuilder()
|
||||||
.builder(
|
|
||||||
it.name ?.asString() ?: return@forEach,
|
|
||||||
it.type.toTypeName(),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.apply {
|
|
||||||
if (it.isCrossInline) {
|
|
||||||
addModifiers(KModifier.CROSSINLINE)
|
|
||||||
}
|
|
||||||
if (it.isVal) {
|
|
||||||
addModifiers(KModifier.VALUE)
|
|
||||||
}
|
|
||||||
if (it.isNoInline) {
|
|
||||||
addModifiers(KModifier.NOINLINE)
|
|
||||||
}
|
|
||||||
if (it.isVararg) {
|
|
||||||
addModifiers(KModifier.VARARG)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}.build()
|
val parameters = accumulatedGeneration.parameters.joinToString(", ") {
|
||||||
|
val itName = it.name
|
||||||
|
"""
|
||||||
|
$itName = ${defaults[itName] ?: baseDefaults[itName] ?: itName}
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
addCode(
|
||||||
|
"""
|
||||||
|
return ${ksFunctionDeclaration.simpleName.asString()}(
|
||||||
|
$parameters
|
||||||
|
)
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}.build() to defaults.toMap()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// if (accumulatedGenerations.isEmpty()) {
|
||||||
|
// variations.forEach { variation ->
|
||||||
|
// val defaults = mutableMapOf<String, String>()
|
||||||
|
// accumulatedGenerations.add(
|
||||||
|
// FunSpec.builder(ksFunctionDeclaration.simpleName.asString()).apply {
|
||||||
|
// modifiers.addAll(ksFunctionDeclaration.modifiers.mapNotNull { it.toKModifier() })
|
||||||
|
// ksFunctionDeclaration.extensionReceiver ?.let {
|
||||||
|
// receiver(it.toTypeName())
|
||||||
|
// }
|
||||||
|
// ksFunctionDeclaration.parameters.forEach {
|
||||||
|
// parameters.add(
|
||||||
|
// (if (it == parameter) {
|
||||||
|
// ParameterSpec
|
||||||
|
// .builder(
|
||||||
|
// variation.argName,
|
||||||
|
// if (variation.varargTypes.isEmpty()) {
|
||||||
|
// ClassName.bestGuess(variation.type)
|
||||||
|
// } else {
|
||||||
|
// ClassName.bestGuess(variation.type).parameterizedBy(
|
||||||
|
// *variation.varargTypes.map { it.asTypeName() }.toTypedArray()
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
// } else {
|
||||||
|
// ParameterSpec
|
||||||
|
// .builder(
|
||||||
|
// it.name ?.asString() ?: return@forEach,
|
||||||
|
// it.type.toTypeName(),
|
||||||
|
// )
|
||||||
|
// })
|
||||||
|
// .apply {
|
||||||
|
// if (it.isCrossInline) {
|
||||||
|
// addModifiers(KModifier.CROSSINLINE)
|
||||||
|
// }
|
||||||
|
// if (it.isVal) {
|
||||||
|
// addModifiers(KModifier.VALUE)
|
||||||
|
// }
|
||||||
|
// if (it.isNoInline) {
|
||||||
|
// addModifiers(KModifier.NOINLINE)
|
||||||
|
// }
|
||||||
|
// if (it.isVararg) {
|
||||||
|
// addModifiers(KModifier.VARARG)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// .build()
|
||||||
|
// .apply {
|
||||||
|
// val name = it.name ?.asString() ?: "this"
|
||||||
|
// val defaultValueString = if (it.isVararg) {
|
||||||
|
// """
|
||||||
|
// *$name.map { it.${variation.conversion} }.toTypedArray()
|
||||||
|
// """.trimIndent()
|
||||||
|
// } else {
|
||||||
|
// "$name.${variation.conversion}"
|
||||||
|
// }
|
||||||
|
// defaults[this.name] = defaultValueString
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// val parameters = ksFunctionDeclaration.parameters.joinToString(", ") {
|
||||||
|
// val itName = it.name ?.asString() ?: "this"
|
||||||
|
// """
|
||||||
|
// $itName = ${defaults[itName] ?: itName}
|
||||||
|
// """.trimIndent()
|
||||||
|
// }
|
||||||
|
// addCode(
|
||||||
|
// """
|
||||||
|
// return ${ksFunctionDeclaration.simpleName.asString()}(
|
||||||
|
// $parameters
|
||||||
|
// )
|
||||||
|
// """.trimIndent()
|
||||||
|
// )
|
||||||
|
// }.build() to defaults.toMap()
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// val reusingGenerations = accumulatedGenerations.toList()
|
||||||
|
// reusingGenerations
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
accumulatedGenerations.forEach {
|
accumulatedGenerations.forEach {
|
||||||
addFunction(it)
|
addFunction(it.first)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,8 +9,25 @@ data class Sample(
|
|||||||
fun sample(
|
fun sample(
|
||||||
@GenerationVariant(
|
@GenerationVariant(
|
||||||
"example",
|
"example",
|
||||||
Sample::class,
|
"Sample",
|
||||||
"value"
|
"value"
|
||||||
)
|
)
|
||||||
example: String = "12"
|
example: String = "12"
|
||||||
) = println(example)
|
) = println(example)
|
||||||
|
|
||||||
|
@GenerateVariations
|
||||||
|
suspend fun Sample.sample2(
|
||||||
|
@GenerationVariant(
|
||||||
|
"arg12",
|
||||||
|
"kotlin.Int",
|
||||||
|
"toString()"
|
||||||
|
)
|
||||||
|
arg1: String = "1",
|
||||||
|
@GenerationVariant(
|
||||||
|
"arg22",
|
||||||
|
"kotlin.String",
|
||||||
|
"toInt()"
|
||||||
|
)
|
||||||
|
arg2: Int = 2,
|
||||||
|
arg3: Boolean = false
|
||||||
|
) = println(arg1)
|
||||||
|
@@ -7,7 +7,7 @@ import kotlin.reflect.KClass
|
|||||||
@Target(AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.VALUE_PARAMETER)
|
@Target(AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.VALUE_PARAMETER)
|
||||||
annotation class GenerationVariant(
|
annotation class GenerationVariant(
|
||||||
val argName: String,
|
val argName: String,
|
||||||
val type: KClass<*>,
|
val type: String,
|
||||||
val conversion: String,
|
val conversion: String,
|
||||||
vararg val varargTypes: KClass<*>
|
vararg val varargTypes: KClass<*>
|
||||||
)
|
)
|
||||||
|
Reference in New Issue
Block a user