From 8215f9d2c6f46203af974f85b1ba80b8100ca9ff Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sun, 26 Feb 2023 14:37:41 +0600 Subject: [PATCH] temporal solution of generating problem --- publish.gradle | 26 +- repos/generator/src/main/kotlin/Processor.kt | 290 ++++++++++-------- .../commonMain/kotlin/GeneratedModelsTest.kt | 7 +- .../test/src/commonMain/kotlin/Test.kt | 3 + 4 files changed, 178 insertions(+), 148 deletions(-) diff --git a/publish.gradle b/publish.gradle index d3300addb04..bd184636fe2 100644 --- a/publish.gradle +++ b/publish.gradle @@ -89,17 +89,17 @@ publishing { } if (project.hasProperty("signing.gnupg.keyName")) { - apply plugin: 'signing' - - signing { - useGpgCmd() - - sign publishing.publications - } - - task signAll { - tasks.withType(Sign).forEach { - dependsOn(it) - } - } +// apply plugin: 'signing' +// +// signing { +// useGpgCmd() +// +// sign publishing.publications +// } +// +// task signAll { +// tasks.withType(Sign).forEach { +// dependsOn(it) +// } +// } } diff --git a/repos/generator/src/main/kotlin/Processor.kt b/repos/generator/src/main/kotlin/Processor.kt index dfa26799239..9e8780b826c 100644 --- a/repos/generator/src/main/kotlin/Processor.kt +++ b/repos/generator/src/main/kotlin/Processor.kt @@ -8,8 +8,13 @@ import com.google.devtools.ksp.processing.Resolver import com.google.devtools.ksp.processing.SymbolProcessor import com.google.devtools.ksp.symbol.KSAnnotated import com.google.devtools.ksp.symbol.KSClassDeclaration +import com.google.devtools.ksp.symbol.KSClassifierReference import com.google.devtools.ksp.symbol.KSPropertyDeclaration +import com.google.devtools.ksp.symbol.KSReferenceElement import com.google.devtools.ksp.symbol.KSType +import com.google.devtools.ksp.symbol.KSTypeAlias +import com.google.devtools.ksp.symbol.KSValueArgument +import com.google.devtools.ksp.symbol.Nullability import com.squareup.kotlinpoet.AnnotationSpec import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock @@ -18,6 +23,7 @@ import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.ParameterSpec import com.squareup.kotlinpoet.PropertySpec +import com.squareup.kotlinpoet.TypeName import com.squareup.kotlinpoet.TypeSpec import com.squareup.kotlinpoet.asTypeName import com.squareup.kotlinpoet.ksp.toAnnotationSpec @@ -31,163 +37,181 @@ import java.io.File import kotlin.reflect.KProperty1 import kotlin.reflect.full.memberProperties +private fun KSClassifierReference.quilifiedName(): String = "${qualifier ?.let { "${it.quilifiedName()}." } ?: ""}${referencedName()}" + class Processor( private val codeGenerator: CodeGenerator ) : SymbolProcessor { + private val KSPropertyDeclaration.typeName: TypeName + get() { + return runCatching { + type.toTypeName() + }.getOrElse { + val element = type.element as KSClassifierReference + (type.element as KSClassifierReference).let { + ClassName( + element.qualifier ?.quilifiedName() ?: "", + element.referencedName() + ) + } + } + } @OptIn(KspExperimental::class) override fun process(resolver: Resolver): List { - resolver.getSymbolsWithAnnotation( + val toRetry = resolver.getSymbolsWithAnnotation( GenerateCRUDModel::class.qualifiedName!! - ).filterIsInstance().forEach { ksClassDeclaration -> - val ksFile = ksClassDeclaration.containingFile ?: return@forEach - FileSpec.builder( - ksClassDeclaration.packageName.asString(), - "GeneratedModels${ksFile.fileName.removeSuffix(".kt")}" - ).apply { - val annotation = ksClassDeclaration.getAnnotationsByType(GenerateCRUDModel::class).first() - addFileComment( - """ + ).filterIsInstance().filterNot { ksClassDeclaration -> + val ksFile = ksClassDeclaration.containingFile ?: return@filterNot false + runCatching { + FileSpec.builder( + ksClassDeclaration.packageName.asString(), + "GeneratedModels${ksFile.fileName.removeSuffix(".kt")}" + ).apply { + val annotation = ksClassDeclaration.getAnnotationsByType(GenerateCRUDModel::class).first() + addFileComment( + """ THIS CODE HAVE BEEN GENERATED AUTOMATICALLY TO REGENERATE IT JUST DELETE FILE ORIGINAL FILE: ${ksFile.fileName} """.trimIndent() - ) - val newName = "New${ksClassDeclaration.simpleName.getShortName()}" - val registeredName = "Registered${ksClassDeclaration.simpleName.getShortName()}" + ) + val newName = "New${ksClassDeclaration.simpleName.getShortName()}" + val registeredName = "Registered${ksClassDeclaration.simpleName.getShortName()}" - val allKSClassProperties = ksClassDeclaration.getAllProperties() - val excludedKSClassProperties = allKSClassProperties.filter { - it.isAnnotationPresent(GenerateCRUDModelExcludeOverride::class) - } - val excludedKSClassPropertiesNames = excludedKSClassProperties.map { it.simpleName.asString() } - val ksClassProperties = allKSClassProperties.filter { - it !in excludedKSClassProperties - } - val ksClassPropertiesNames = ksClassProperties.map { it.simpleName.asString() } - val newNewType = TypeSpec.classBuilder(newName).apply { - val typeBuilder = this - addSuperinterface(ksClassDeclaration.toClassName()) - addModifiers(KModifier.DATA) - if (annotation.serializable) { - addAnnotation(Serializable::class) - if (annotation.generateSerialName) { - addAnnotation(AnnotationSpec.get(SerialName(newName))) - } + val allKSClassProperties = ksClassDeclaration.getAllProperties() + val excludedKSClassProperties = allKSClassProperties.filter { + it.isAnnotationPresent(GenerateCRUDModelExcludeOverride::class) } - primaryConstructor( - FunSpec.constructorBuilder().apply { - ksClassProperties.forEach { - addParameter(it.simpleName.getShortName(), it.type.toTypeName()) - typeBuilder.addProperty( - PropertySpec.builder(it.simpleName.getShortName(), it.type.toTypeName(), KModifier.OVERRIDE).apply { - initializer(it.simpleName.getShortName()) - }.build() + val excludedKSClassPropertiesNames = excludedKSClassProperties.map { it.simpleName.asString() } + val ksClassProperties = allKSClassProperties.filter { + it !in excludedKSClassProperties + } + val ksClassPropertiesNames = ksClassProperties.map { it.simpleName.asString() } + val newNewType = TypeSpec.classBuilder(newName).apply { + val typeBuilder = this + addSuperinterface(ksClassDeclaration.toClassName()) + addModifiers(KModifier.DATA) + if (annotation.serializable) { + addAnnotation(Serializable::class) + if (annotation.generateSerialName) { + addAnnotation(AnnotationSpec.get(SerialName(newName))) + } + } + primaryConstructor( + FunSpec.constructorBuilder().apply { + ksClassProperties.forEach { + addParameter(it.simpleName.getShortName(), it.typeName) + typeBuilder.addProperty( + PropertySpec.builder(it.simpleName.getShortName(), it.typeName, KModifier.OVERRIDE).apply { + initializer(it.simpleName.getShortName()) + }.build() + ) + } + }.build() + ) + }.build() + addType( + newNewType + ) + + val registeredSupertypes = ksClassDeclaration.annotations.filter { + it.shortName.asString() == GenerateCRUDModel::class.simpleName && + it.annotationType.resolve().declaration.qualifiedName ?.asString() == GenerateCRUDModel::class.qualifiedName + }.flatMap { + (it.arguments.first().value as List).map { it.declaration as KSClassDeclaration } + }.toList() + + + val registeredTypesProperties: List = registeredSupertypes.flatMap { registeredType -> + registeredType.getAllProperties() + }.filter { + it.simpleName.asString() !in excludedKSClassPropertiesNames && it.getAnnotationsByType(GenerateCRUDModelExcludeOverride::class).none() + } + val allProperties: List = ksClassProperties.toList() + registeredTypesProperties + val propertiesToOverrideInRegistered = allProperties.distinctBy { it.simpleName.asString() }.sortedBy { property -> + val name = property.simpleName.asString() + + ksClassPropertiesNames.indexOf(name).takeIf { it > -1 } ?.let { + it + allProperties.size + } ?: allProperties.indexOfFirst { it.simpleName.asString() == name } + } + + val newRegisteredType = TypeSpec.classBuilder(registeredName).apply { + val typeBuilder = this + addSuperinterface(ksClassDeclaration.toClassName()) + if (annotation.serializable) { + addAnnotation(Serializable::class) + + if (annotation.generateSerialName) { + addAnnotation( + AnnotationSpec.get(SerialName(registeredName)) ) } + } + addSuperinterfaces(registeredSupertypes.map { it.toClassName() }) + addModifiers(KModifier.DATA) + primaryConstructor( + FunSpec.constructorBuilder().apply { + propertiesToOverrideInRegistered.forEach { + addParameter( + ParameterSpec.builder(it.simpleName.getShortName(), it.typeName).apply { + annotations += it.annotations.map { it.toAnnotationSpec() } + }.build() + ) + typeBuilder.addProperty( + PropertySpec.builder(it.simpleName.getShortName(), it.typeName, KModifier.OVERRIDE).apply { + initializer(it.simpleName.getShortName()) + }.build() + ) + } + }.build() + ) + }.build() + addType( + newRegisteredType + ) + + addFunction( + FunSpec.builder("asNew").apply { + receiver(ksClassDeclaration.toClassName()) + addCode( + CodeBlock.of( + "return ${newNewType.name}(${newNewType.propertySpecs.joinToString { it.name }})" + ) + ) + returns(ClassName(packageName, newNewType.name!!)) }.build() ) - }.build() - addType( - newNewType - ) - val registeredSupertypes = ksClassDeclaration.annotations.filter { - it.shortName.asString() == GenerateCRUDModel::class.simpleName && - it.annotationType.resolve().declaration.qualifiedName ?.asString() == GenerateCRUDModel::class.qualifiedName - }.flatMap { - (it.arguments.first().value as List).map { it.declaration as KSClassDeclaration } - }.toList() - - - val registeredTypesProperties: List = registeredSupertypes.flatMap { registeredType -> - registeredType.getAllProperties() - }.filter { - it.simpleName.asString() !in excludedKSClassPropertiesNames && it.getAnnotationsByType(GenerateCRUDModelExcludeOverride::class).none() - } - val allProperties: List = ksClassProperties.toList() + registeredTypesProperties - val propertiesToOverrideInRegistered = allProperties.distinctBy { it.simpleName.asString() }.sortedBy { property -> - val name = property.simpleName.asString() - - ksClassPropertiesNames.indexOf(name).takeIf { it > -1 } ?.let { - it + allProperties.size - } ?: allProperties.indexOfFirst { it.simpleName.asString() == name } - } - - val newRegisteredType = TypeSpec.classBuilder(registeredName).apply { - val typeBuilder = this - addSuperinterface(ksClassDeclaration.toClassName()) - if (annotation.serializable) { - addAnnotation(Serializable::class) - - if (annotation.generateSerialName) { - addAnnotation( - AnnotationSpec.get(SerialName(registeredName)) - ) - } - } - addSuperinterfaces(registeredSupertypes.map { it.toClassName() }) - addModifiers(KModifier.DATA) - primaryConstructor( - FunSpec.constructorBuilder().apply { - propertiesToOverrideInRegistered.forEach { - addParameter( - ParameterSpec.builder(it.simpleName.getShortName(), it.type.toTypeName()).apply { - annotations += it.annotations.map { it.toAnnotationSpec() } - }.build() - ) - typeBuilder.addProperty( - PropertySpec.builder(it.simpleName.getShortName(), it.type.toTypeName(), KModifier.OVERRIDE).apply { - initializer(it.simpleName.getShortName()) - }.build() - ) + addFunction( + FunSpec.builder("asRegistered").apply { + receiver(ksClassDeclaration.toClassName()) + (registeredTypesProperties.filter { it.simpleName.asString() !in ksClassPropertiesNames }).forEach { + addParameter(it.simpleName.asString(), it.typeName) } + addCode( + CodeBlock.of( + "return ${newRegisteredType.name}(${newRegisteredType.propertySpecs.joinToString { it.name }})" + ) + ) + returns(ClassName(packageName, newRegisteredType.name!!)) }.build() ) - }.build() - addType( - newRegisteredType - ) + }.build().let { + File( + File(ksFile.filePath).parent, + "GeneratedModels${ksFile.fileName}" + ).takeIf { !it.exists() } ?.apply { + parentFile.mkdirs() - addFunction( - FunSpec.builder("asNew").apply { - receiver(ksClassDeclaration.toClassName()) - addCode( - CodeBlock.of( - "return ${newNewType.name}(${newNewType.propertySpecs.joinToString { it.name }})" - ) - ) - returns(ClassName(packageName, newNewType.name!!)) - }.build() - ) - - addFunction( - FunSpec.builder("asRegistered").apply { - receiver(ksClassDeclaration.toClassName()) - (registeredTypesProperties.filter { it.simpleName.asString() !in ksClassPropertiesNames }).forEach { - addParameter(it.simpleName.asString(), it.type.toTypeName()) + writer().use { writer -> + it.writeTo(writer) } - addCode( - CodeBlock.of( - "return ${newRegisteredType.name}(${newRegisteredType.propertySpecs.joinToString { it.name }})" - ) - ) - returns(ClassName(packageName, newRegisteredType.name!!)) - }.build() - ) - }.build().let { - File( - File(ksFile.filePath).parent, - "GeneratedModels${ksFile.fileName}" - ).takeIf { !it.exists() } ?.apply { - parentFile.mkdirs() - - writer().use { writer -> - it.writeTo(writer) } } - } - } + }.isSuccess + }.toList() - return emptyList() + return toRetry } } diff --git a/repos/generator/test/src/commonMain/kotlin/GeneratedModelsTest.kt b/repos/generator/test/src/commonMain/kotlin/GeneratedModelsTest.kt index bbad6b596c2..27111d44cc8 100644 --- a/repos/generator/test/src/commonMain/kotlin/GeneratedModelsTest.kt +++ b/repos/generator/test/src/commonMain/kotlin/GeneratedModelsTest.kt @@ -13,6 +13,7 @@ import kotlinx.serialization.Serializable public data class NewTest( public override val property1: String, public override val property2: Int, + public override val parent: ParentTypeId?, ) : Test @Serializable @@ -21,8 +22,10 @@ public data class RegisteredTest( public override val id: TestId, public override val property1: String, public override val property2: Int, + public override val parent: ParentTypeId?, ) : Test, IRegisteredTest -public fun Test.asNew(): NewTest = NewTest(property1, property2) +public fun Test.asNew(): NewTest = NewTest(property1, property2, parent) -public fun Test.asRegistered(id: TestId): RegisteredTest = RegisteredTest(id, property1, property2) +public fun Test.asRegistered(id: TestId): RegisteredTest = RegisteredTest(id, property1, property2, + parent) diff --git a/repos/generator/test/src/commonMain/kotlin/Test.kt b/repos/generator/test/src/commonMain/kotlin/Test.kt index 4a8ff7754b1..24bc9a92f4b 100644 --- a/repos/generator/test/src/commonMain/kotlin/Test.kt +++ b/repos/generator/test/src/commonMain/kotlin/Test.kt @@ -11,10 +11,13 @@ value class TestId( val long: Long ) +typealias ParentTypeId = TestId + @GenerateCRUDModel(IRegisteredTest::class) sealed interface Test { val property1: String val property2: Int + val parent: ParentTypeId? @GenerateCRUDModelExcludeOverride val excludedProperty: String