fixes for generics

This commit is contained in:
2025-02-12 14:32:14 +06:00
parent 99783f281d
commit 5c28255e06
9 changed files with 122 additions and 120 deletions

View File

@@ -0,0 +1,25 @@
package dev.inmo.micro_ksp.generator
import com.google.devtools.ksp.KSTypeNotPresentException
import com.google.devtools.ksp.KSTypesNotPresentException
import com.google.devtools.ksp.KspExperimental
import com.google.devtools.ksp.symbol.KSType
import com.squareup.kotlinpoet.asClassName
import com.squareup.kotlinpoet.ksp.toClassName
import kotlin.reflect.KClass
@OptIn(KspExperimental::class)
inline fun convertToClassName(getter: () -> KClass<*>) = try {
getter().asClassName()
} catch (e: KSTypeNotPresentException) {
e.ksType.toClassName()
}
@OptIn(KspExperimental::class)
inline fun convertToClassNames(getter: () -> List<KClass<*>>) = try {
getter().map { it.asClassName() }
} catch (e: KSTypesNotPresentException) {
e.ksTypes.map {
it.toClassName()
}
}

View File

@@ -9,6 +9,7 @@ repositories {
} }
dependencies { dependencies {
implementation libs.kt.stdlib
api project(":micro_utils.ksp.generator") api project(":micro_utils.ksp.generator")
api project(":micro_utils.ksp.variations") api project(":micro_utils.ksp.variations")
api libs.kotlin.poet api libs.kotlin.poet

View File

@@ -1,5 +1,6 @@
package dev.inmo.micro_utils.ksp.variations.generator package dev.inmo.micro_utils.ksp.variations.generator
import com.google.devtools.ksp.KSTypeNotPresentException
import com.google.devtools.ksp.KspExperimental import com.google.devtools.ksp.KspExperimental
import com.google.devtools.ksp.getAnnotationsByType import com.google.devtools.ksp.getAnnotationsByType
import com.google.devtools.ksp.processing.CodeGenerator import com.google.devtools.ksp.processing.CodeGenerator
@@ -8,8 +9,11 @@ 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.convertToClassName
import dev.inmo.micro_ksp.generator.convertToClassNames
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
@@ -128,27 +132,33 @@ class Processor(
receiver(it) receiver(it)
} }
accumulatedGeneration.parameters.forEach { accumulatedGeneration.parameters.forEach {
val actualName = if (variation.argName.isEmpty()) it.name else variation.argName
parameters.add( parameters.add(
(if (it.name == (parameter.name ?.asString() ?: "this")) { (if (it.name == (parameter.name ?.asString() ?: "this")) {
val type = convertToClassName { variation.type }
val genericTypes = convertToClassNames { variation.genericTypes.toList() }
ParameterSpec ParameterSpec
.builder( .builder(
variation.argName, actualName,
if (variation.varargTypes.isEmpty()) { if (genericTypes.isEmpty()) {
ClassName.bestGuess(variation.type) type
} else { } else {
ClassName.bestGuess(variation.type).parameterizedBy( type.parameterizedBy(
*variation.varargTypes.map { it.asTypeName() }.toTypedArray() *genericTypes.toTypedArray()
) )
} }
) )
.apply { .apply {
val defaultValueString = if (it.modifiers.contains(KModifier.VARARG)) { addModifiers(it.modifiers)
""" val defaultValueString = """
*${variation.argName}.map { it.${variation.conversion} }.toTypedArray() with(${actualName}) {${
""".trimIndent() if (it.modifiers.contains(KModifier.VARARG)) {
} else { "map { it.${variation.conversion} }.toTypedArray()"
"${variation.argName}.${variation.conversion}" } else {
} "${variation.conversion}"
}
}}
""".trimIndent()
defaults[it.name] = defaultValueString defaults[it.name] = defaultValueString
} }
} else { } else {
@@ -174,84 +184,6 @@ class Processor(
) )
} }
} }
// 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.first) addFunction(it.first)

View File

@@ -12,6 +12,7 @@ kotlin {
sourceSets { sourceSets {
commonMain { commonMain {
dependencies { dependencies {
implementation libs.kt.stdlib
api project(":micro_utils.ksp.variations") api project(":micro_utils.ksp.variations")
} }
} }

View File

@@ -1,32 +1,51 @@
package dev.inmo.micro_utils.ksp.variations.generator.test
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
data class Sample( data class SimpleType(
val value: String val value: String
) )
data class GenericType<T>(
val value: T
)
@GenerateVariations @GenerateVariations
fun sample( fun sample(
@GenerationVariant( @GenerationVariant(
"example", SimpleType::class,
"Sample", "value",
"value" )
@GenerationVariant(
GenericType::class,
"value.toString()",
genericTypes = arrayOf(Int::class)
) )
example: String = "12" example: String = "12"
) = println(example) ) = println(example)
@GenerateVariations @GenerateVariations
suspend fun Sample.sample2( fun sampleVararg(
@GenerationVariant( @GenerationVariant(
SimpleType::class,
"value",
)
vararg example: String = arrayOf("12")
) = println(example.joinToString())
@GenerateVariations
suspend fun SimpleType.sample2(
@GenerationVariant(
Int::class,
"toString()",
"arg12", "arg12",
"kotlin.Int",
"toString()"
) )
arg1: String = "1", arg1: String = "1",
@GenerationVariant( @GenerationVariant(
String::class,
"toInt()",
"arg22", "arg22",
"kotlin.String",
"toInt()"
) )
arg2: Int = 2, arg2: Int = 2,
arg3: Boolean = false arg3: Boolean = false

View File

@@ -1,47 +1,49 @@
// THIS CODE HAVE BEEN GENERATED AUTOMATICALLY // THIS CODE HAVE BEEN GENERATED AUTOMATICALLY
// TO REGENERATE IT JUST DELETE FILE // TO REGENERATE IT JUST DELETE FILE
// ORIGINAL FILE: SampleFun.kt // ORIGINAL FILE: SampleFun.kt
package dev.inmo.micro_utils.ksp.variations.generator.test
import kotlin.Boolean import kotlin.Boolean
import kotlin.Int import kotlin.Int
import kotlin.String import kotlin.String
import kotlin.Unit import kotlin.Unit
public suspend fun Sample.sample2(arg12: Int): Unit = sample2( public suspend fun SimpleType.sample2(arg12: Int): Unit = sample2(
arg1 = arg12.toString() arg1 = with(arg12) {toString()}
) )
public suspend fun Sample.sample2(arg12: Int, arg2: Int): Unit = sample2( public suspend fun SimpleType.sample2(arg12: Int, arg2: Int): Unit = sample2(
arg1 = arg12.toString(), arg2 = arg2 arg1 = with(arg12) {toString()}, arg2 = arg2
) )
public suspend fun Sample.sample2(arg12: Int, arg3: Boolean): Unit = sample2( public suspend fun SimpleType.sample2(arg12: Int, arg3: Boolean): Unit = sample2(
arg1 = arg12.toString(), arg3 = arg3 arg1 = with(arg12) {toString()}, arg3 = arg3
) )
public suspend fun Sample.sample2( public suspend fun SimpleType.sample2(
arg12: Int, arg12: Int,
arg2: Int, arg2: Int,
arg3: Boolean, arg3: Boolean,
): Unit = sample2( ): Unit = sample2(
arg1 = arg12.toString(), arg2 = arg2, arg3 = arg3 arg1 = with(arg12) {toString()}, arg2 = arg2, arg3 = arg3
) )
public suspend fun Sample.sample2(arg22: String): Unit = sample2( public suspend fun SimpleType.sample2(arg22: String): Unit = sample2(
arg2 = arg22.toInt() arg2 = with(arg22) {toInt()}
) )
public suspend fun Sample.sample2(arg1: String, arg22: String): Unit = sample2( public suspend fun SimpleType.sample2(arg1: String, arg22: String): Unit = sample2(
arg1 = arg1, arg2 = arg22.toInt() arg1 = arg1, arg2 = with(arg22) {toInt()}
) )
public suspend fun Sample.sample2(arg22: String, arg3: Boolean): Unit = sample2( public suspend fun SimpleType.sample2(arg22: String, arg3: Boolean): Unit = sample2(
arg2 = arg22.toInt(), arg3 = arg3 arg2 = with(arg22) {toInt()}, arg3 = arg3
) )
public suspend fun Sample.sample2( public suspend fun SimpleType.sample2(
arg1: String, arg1: String,
arg22: String, arg22: String,
arg3: Boolean, arg3: Boolean,
): Unit = sample2( ): Unit = sample2(
arg1 = arg1, arg2 = arg22.toInt(), arg3 = arg3 arg1 = arg1, arg2 = with(arg22) {toInt()}, arg3 = arg3
) )

View File

@@ -1,8 +1,15 @@
// THIS CODE HAVE BEEN GENERATED AUTOMATICALLY // THIS CODE HAVE BEEN GENERATED AUTOMATICALLY
// TO REGENERATE IT JUST DELETE FILE // TO REGENERATE IT JUST DELETE FILE
// ORIGINAL FILE: SampleFun.kt // ORIGINAL FILE: SampleFun.kt
package dev.inmo.micro_utils.ksp.variations.generator.test
import kotlin.Int
import kotlin.Unit import kotlin.Unit
public fun sample(example: Sample): Unit = sample( public fun sample(example: SimpleType): Unit = sample(
example = example.value example = with(example) {value}
)
public fun sample(example: GenericType<Int>): Unit = sample(
example = with(example) {value.toString()}
) )

View File

@@ -0,0 +1,10 @@
// THIS CODE HAVE BEEN GENERATED AUTOMATICALLY
// TO REGENERATE IT JUST DELETE FILE
// ORIGINAL FILE: SampleFun.kt
package dev.inmo.micro_utils.ksp.variations.generator.test
import kotlin.Unit
public fun sampleVararg(vararg example: SimpleType): Unit = sampleVararg(
example = with(example) {map { it.value }.toTypedArray()}
)

View File

@@ -2,12 +2,17 @@ package dev.inmo.micro_utils.ksp.variations
import kotlin.reflect.KClass import kotlin.reflect.KClass
/**
* @param argName New argument name. Default - empty - means "use default arg name"
* @param type Qualified class name, like "dev.inmo.micro_utils.ksp.variants.GenerationVariant"
* @param conversion Conversion string with `this`
*/
@Retention(AnnotationRetention.BINARY) @Retention(AnnotationRetention.BINARY)
@Repeatable @Repeatable
@Target(AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.VALUE_PARAMETER) @Target(AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.VALUE_PARAMETER)
annotation class GenerationVariant( annotation class GenerationVariant(
val argName: String, val type: KClass<*>,
val type: String,
val conversion: String, val conversion: String,
vararg val varargTypes: KClass<*> val argName: String = "",
vararg val genericTypes: KClass<*>
) )