mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2024-11-19 23:03:49 +00:00
temporal solution of generating problem
This commit is contained in:
parent
d2e6d2ec80
commit
8215f9d2c6
@ -89,17 +89,17 @@ publishing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (project.hasProperty("signing.gnupg.keyName")) {
|
if (project.hasProperty("signing.gnupg.keyName")) {
|
||||||
apply plugin: 'signing'
|
// apply plugin: 'signing'
|
||||||
|
//
|
||||||
signing {
|
// signing {
|
||||||
useGpgCmd()
|
// useGpgCmd()
|
||||||
|
//
|
||||||
sign publishing.publications
|
// sign publishing.publications
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
task signAll {
|
// task signAll {
|
||||||
tasks.withType(Sign).forEach {
|
// tasks.withType(Sign).forEach {
|
||||||
dependsOn(it)
|
// dependsOn(it)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,13 @@ import com.google.devtools.ksp.processing.Resolver
|
|||||||
import com.google.devtools.ksp.processing.SymbolProcessor
|
import com.google.devtools.ksp.processing.SymbolProcessor
|
||||||
import com.google.devtools.ksp.symbol.KSAnnotated
|
import com.google.devtools.ksp.symbol.KSAnnotated
|
||||||
import com.google.devtools.ksp.symbol.KSClassDeclaration
|
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.KSPropertyDeclaration
|
||||||
|
import com.google.devtools.ksp.symbol.KSReferenceElement
|
||||||
import com.google.devtools.ksp.symbol.KSType
|
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.AnnotationSpec
|
||||||
import com.squareup.kotlinpoet.ClassName
|
import com.squareup.kotlinpoet.ClassName
|
||||||
import com.squareup.kotlinpoet.CodeBlock
|
import com.squareup.kotlinpoet.CodeBlock
|
||||||
@ -18,6 +23,7 @@ import com.squareup.kotlinpoet.FunSpec
|
|||||||
import com.squareup.kotlinpoet.KModifier
|
import com.squareup.kotlinpoet.KModifier
|
||||||
import com.squareup.kotlinpoet.ParameterSpec
|
import com.squareup.kotlinpoet.ParameterSpec
|
||||||
import com.squareup.kotlinpoet.PropertySpec
|
import com.squareup.kotlinpoet.PropertySpec
|
||||||
|
import com.squareup.kotlinpoet.TypeName
|
||||||
import com.squareup.kotlinpoet.TypeSpec
|
import com.squareup.kotlinpoet.TypeSpec
|
||||||
import com.squareup.kotlinpoet.asTypeName
|
import com.squareup.kotlinpoet.asTypeName
|
||||||
import com.squareup.kotlinpoet.ksp.toAnnotationSpec
|
import com.squareup.kotlinpoet.ksp.toAnnotationSpec
|
||||||
@ -31,163 +37,181 @@ import java.io.File
|
|||||||
import kotlin.reflect.KProperty1
|
import kotlin.reflect.KProperty1
|
||||||
import kotlin.reflect.full.memberProperties
|
import kotlin.reflect.full.memberProperties
|
||||||
|
|
||||||
|
private fun KSClassifierReference.quilifiedName(): String = "${qualifier ?.let { "${it.quilifiedName()}." } ?: ""}${referencedName()}"
|
||||||
|
|
||||||
class Processor(
|
class Processor(
|
||||||
private val codeGenerator: CodeGenerator
|
private val codeGenerator: CodeGenerator
|
||||||
) : SymbolProcessor {
|
) : 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)
|
@OptIn(KspExperimental::class)
|
||||||
override fun process(resolver: Resolver): List<KSAnnotated> {
|
override fun process(resolver: Resolver): List<KSAnnotated> {
|
||||||
resolver.getSymbolsWithAnnotation(
|
val toRetry = resolver.getSymbolsWithAnnotation(
|
||||||
GenerateCRUDModel::class.qualifiedName!!
|
GenerateCRUDModel::class.qualifiedName!!
|
||||||
).filterIsInstance<KSClassDeclaration>().forEach { ksClassDeclaration ->
|
).filterIsInstance<KSClassDeclaration>().filterNot { ksClassDeclaration ->
|
||||||
val ksFile = ksClassDeclaration.containingFile ?: return@forEach
|
val ksFile = ksClassDeclaration.containingFile ?: return@filterNot false
|
||||||
FileSpec.builder(
|
runCatching {
|
||||||
ksClassDeclaration.packageName.asString(),
|
FileSpec.builder(
|
||||||
"GeneratedModels${ksFile.fileName.removeSuffix(".kt")}"
|
ksClassDeclaration.packageName.asString(),
|
||||||
).apply {
|
"GeneratedModels${ksFile.fileName.removeSuffix(".kt")}"
|
||||||
val annotation = ksClassDeclaration.getAnnotationsByType(GenerateCRUDModel::class).first()
|
).apply {
|
||||||
addFileComment(
|
val annotation = ksClassDeclaration.getAnnotationsByType(GenerateCRUDModel::class).first()
|
||||||
"""
|
addFileComment(
|
||||||
|
"""
|
||||||
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: ${ksFile.fileName}
|
ORIGINAL FILE: ${ksFile.fileName}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
val newName = "New${ksClassDeclaration.simpleName.getShortName()}"
|
val newName = "New${ksClassDeclaration.simpleName.getShortName()}"
|
||||||
val registeredName = "Registered${ksClassDeclaration.simpleName.getShortName()}"
|
val registeredName = "Registered${ksClassDeclaration.simpleName.getShortName()}"
|
||||||
|
|
||||||
val allKSClassProperties = ksClassDeclaration.getAllProperties()
|
val allKSClassProperties = ksClassDeclaration.getAllProperties()
|
||||||
val excludedKSClassProperties = allKSClassProperties.filter {
|
val excludedKSClassProperties = allKSClassProperties.filter {
|
||||||
it.isAnnotationPresent(GenerateCRUDModelExcludeOverride::class)
|
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)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
primaryConstructor(
|
val excludedKSClassPropertiesNames = excludedKSClassProperties.map { it.simpleName.asString() }
|
||||||
FunSpec.constructorBuilder().apply {
|
val ksClassProperties = allKSClassProperties.filter {
|
||||||
ksClassProperties.forEach {
|
it !in excludedKSClassProperties
|
||||||
addParameter(it.simpleName.getShortName(), it.type.toTypeName())
|
}
|
||||||
typeBuilder.addProperty(
|
val ksClassPropertiesNames = ksClassProperties.map { it.simpleName.asString() }
|
||||||
PropertySpec.builder(it.simpleName.getShortName(), it.type.toTypeName(), KModifier.OVERRIDE).apply {
|
val newNewType = TypeSpec.classBuilder(newName).apply {
|
||||||
initializer(it.simpleName.getShortName())
|
val typeBuilder = this
|
||||||
}.build()
|
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<KSType>).map { it.declaration as KSClassDeclaration }
|
||||||
|
}.toList()
|
||||||
|
|
||||||
|
|
||||||
|
val registeredTypesProperties: List<KSPropertyDeclaration> = registeredSupertypes.flatMap { registeredType ->
|
||||||
|
registeredType.getAllProperties()
|
||||||
|
}.filter {
|
||||||
|
it.simpleName.asString() !in excludedKSClassPropertiesNames && it.getAnnotationsByType(GenerateCRUDModelExcludeOverride::class).none()
|
||||||
|
}
|
||||||
|
val allProperties: List<KSPropertyDeclaration> = 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()
|
||||||
)
|
)
|
||||||
}.build()
|
|
||||||
addType(
|
|
||||||
newNewType
|
|
||||||
)
|
|
||||||
|
|
||||||
val registeredSupertypes = ksClassDeclaration.annotations.filter {
|
addFunction(
|
||||||
it.shortName.asString() == GenerateCRUDModel::class.simpleName &&
|
FunSpec.builder("asRegistered").apply {
|
||||||
it.annotationType.resolve().declaration.qualifiedName ?.asString() == GenerateCRUDModel::class.qualifiedName
|
receiver(ksClassDeclaration.toClassName())
|
||||||
}.flatMap {
|
(registeredTypesProperties.filter { it.simpleName.asString() !in ksClassPropertiesNames }).forEach {
|
||||||
(it.arguments.first().value as List<KSType>).map { it.declaration as KSClassDeclaration }
|
addParameter(it.simpleName.asString(), it.typeName)
|
||||||
}.toList()
|
|
||||||
|
|
||||||
|
|
||||||
val registeredTypesProperties: List<KSPropertyDeclaration> = registeredSupertypes.flatMap { registeredType ->
|
|
||||||
registeredType.getAllProperties()
|
|
||||||
}.filter {
|
|
||||||
it.simpleName.asString() !in excludedKSClassPropertiesNames && it.getAnnotationsByType(GenerateCRUDModelExcludeOverride::class).none()
|
|
||||||
}
|
|
||||||
val allProperties: List<KSPropertyDeclaration> = 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()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
addCode(
|
||||||
|
CodeBlock.of(
|
||||||
|
"return ${newRegisteredType.name}(${newRegisteredType.propertySpecs.joinToString { it.name }})"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
returns(ClassName(packageName, newRegisteredType.name!!))
|
||||||
}.build()
|
}.build()
|
||||||
)
|
)
|
||||||
}.build()
|
}.build().let {
|
||||||
addType(
|
File(
|
||||||
newRegisteredType
|
File(ksFile.filePath).parent,
|
||||||
)
|
"GeneratedModels${ksFile.fileName}"
|
||||||
|
).takeIf { !it.exists() } ?.apply {
|
||||||
|
parentFile.mkdirs()
|
||||||
|
|
||||||
addFunction(
|
writer().use { writer ->
|
||||||
FunSpec.builder("asNew").apply {
|
it.writeTo(writer)
|
||||||
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())
|
|
||||||
}
|
}
|
||||||
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import kotlinx.serialization.Serializable
|
|||||||
public data class NewTest(
|
public data class NewTest(
|
||||||
public override val property1: String,
|
public override val property1: String,
|
||||||
public override val property2: Int,
|
public override val property2: Int,
|
||||||
|
public override val parent: ParentTypeId?,
|
||||||
) : Test
|
) : Test
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -21,8 +22,10 @@ public data class RegisteredTest(
|
|||||||
public override val id: TestId,
|
public override val id: TestId,
|
||||||
public override val property1: String,
|
public override val property1: String,
|
||||||
public override val property2: Int,
|
public override val property2: Int,
|
||||||
|
public override val parent: ParentTypeId?,
|
||||||
) : Test, IRegisteredTest
|
) : 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)
|
||||||
|
@ -11,10 +11,13 @@ value class TestId(
|
|||||||
val long: Long
|
val long: Long
|
||||||
)
|
)
|
||||||
|
|
||||||
|
typealias ParentTypeId = TestId
|
||||||
|
|
||||||
@GenerateCRUDModel(IRegisteredTest::class)
|
@GenerateCRUDModel(IRegisteredTest::class)
|
||||||
sealed interface Test {
|
sealed interface Test {
|
||||||
val property1: String
|
val property1: String
|
||||||
val property2: Int
|
val property2: Int
|
||||||
|
val parent: ParentTypeId?
|
||||||
|
|
||||||
@GenerateCRUDModelExcludeOverride
|
@GenerateCRUDModelExcludeOverride
|
||||||
val excludedProperty: String
|
val excludedProperty: String
|
||||||
|
Loading…
Reference in New Issue
Block a user