mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2025-09-17 14:29:24 +00:00
Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
4c8d92b4c3 | |||
8bbd33c896 | |||
ac33a3580f | |||
a64a32fbe6 | |||
9493e97a38 | |||
88bd770260 | |||
a7bd33b7bf | |||
73c724a2e5 | |||
d8cf3c6726 | |||
15dee238b5 | |||
c70626734e | |||
5a765ea1bc | |||
8215f9d2c6 | |||
d2e6d2ec80 | |||
3718181e8f | |||
0d825cf424 |
20
CHANGELOG.md
20
CHANGELOG.md
@@ -1,5 +1,25 @@
|
||||
# Changelog
|
||||
|
||||
## 0.17.1
|
||||
|
||||
* **Hotfix** for absence of jvm dependencies in android modules
|
||||
* `Versions`:
|
||||
* `Ktor`: `2.2.3` -> `2.2.4`
|
||||
|
||||
## 0.17.0
|
||||
|
||||
* `Versions`:
|
||||
* `Kotlin`: `1.7.20` -> `1.8.10`
|
||||
* `Serialization`: `1.4.1` -> `1.5.0`
|
||||
* `KSLog`: `0.5.4` -> `1.0.0`
|
||||
* `AppCompat`: `1.6.0` -> `1.6.1`
|
||||
|
||||
## 0.16.13
|
||||
|
||||
* `Repos`:
|
||||
* `Generator`:
|
||||
* Module has been created
|
||||
|
||||
## 0.16.12
|
||||
|
||||
* `Repos`:
|
||||
|
@@ -18,6 +18,7 @@ kotlin {
|
||||
api project(":micro_utils.coroutines")
|
||||
api libs.android.fragment
|
||||
}
|
||||
dependsOn jvmMain
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,30 +1,5 @@
|
||||
apply plugin: 'com.getkeepsafe.dexcount'
|
||||
|
||||
ext {
|
||||
jvmKotlinFolderFile = {
|
||||
String sep = File.separator
|
||||
return new File("${project.projectDir}${sep}src${sep}jvmMain${sep}kotlin")
|
||||
}
|
||||
|
||||
enableIncludingJvmCodeInAndroidPart = {
|
||||
File jvmKotlinFolder = jvmKotlinFolderFile()
|
||||
if (jvmKotlinFolder.exists()) {
|
||||
android.sourceSets.main.java.srcDirs += jvmKotlinFolder.path
|
||||
}
|
||||
}
|
||||
|
||||
disableIncludingJvmCodeInAndroidPart = {
|
||||
File jvmKotlinFolder = jvmKotlinFolderFile()
|
||||
String[] oldDirs = android.sourceSets.main.java.srcDirs
|
||||
android.sourceSets.main.java.srcDirs = []
|
||||
for (oldDir in oldDirs) {
|
||||
if (oldDir != jvmKotlinFolder.path) {
|
||||
android.sourceSets.main.java.srcDirs += oldDir
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion libs.versions.android.props.compileSdk.get().toInteger()
|
||||
buildToolsVersion libs.versions.android.props.buildTools.get()
|
||||
@@ -58,10 +33,4 @@ android {
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
String sep = File.separator
|
||||
main.java.srcDirs += "src${sep}main${sep}kotlin"
|
||||
enableIncludingJvmCodeInAndroidPart()
|
||||
}
|
||||
}
|
||||
|
@@ -14,5 +14,5 @@ crypto_js_version=4.1.1
|
||||
# Project data
|
||||
|
||||
group=dev.inmo
|
||||
version=0.16.12
|
||||
android_code_version=180
|
||||
version=0.17.1
|
||||
android_code_version=183
|
||||
|
@@ -1,36 +1,36 @@
|
||||
[versions]
|
||||
|
||||
kt = "1.7.20"
|
||||
kt-serialization = "1.4.1"
|
||||
kt = "1.8.10"
|
||||
kt-serialization = "1.5.0"
|
||||
kt-coroutines = "1.6.4"
|
||||
|
||||
kslog = "0.5.4"
|
||||
kslog = "1.0.0"
|
||||
|
||||
jb-compose = "1.2.2"
|
||||
jb-compose = "1.3.1-rc01"
|
||||
jb-exposed = "0.41.1"
|
||||
jb-dokka = "1.7.20"
|
||||
|
||||
klock = "3.4.0"
|
||||
uuid = "0.6.0"
|
||||
uuid = "0.7.0"
|
||||
|
||||
ktor = "2.2.3"
|
||||
ktor = "2.2.4"
|
||||
|
||||
gh-release = "2.4.1"
|
||||
|
||||
koin = "3.3.2"
|
||||
|
||||
ksp = "1.7.20-1.0.8"
|
||||
ksp = "1.8.10-1.0.9"
|
||||
kotlin-poet = "1.12.0"
|
||||
|
||||
android-gradle = "7.3.0"
|
||||
dexcount = "3.1.0"
|
||||
android-gradle = "7.3.1"
|
||||
dexcount = "4.0.0"
|
||||
|
||||
android-coreKtx = "1.9.0"
|
||||
android-recyclerView = "1.2.1"
|
||||
android-appCompat = "1.6.0"
|
||||
android-appCompat = "1.6.1"
|
||||
android-fragment = "1.5.5"
|
||||
android-espresso = "3.4.0"
|
||||
android-test = "1.1.3"
|
||||
android-espresso = "3.5.1"
|
||||
android-test = "1.1.5"
|
||||
|
||||
android-props-minSdk = "21"
|
||||
android-props-compileSdk = "33"
|
||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@@ -15,7 +15,6 @@ kotlin {
|
||||
api libs.ktor.client
|
||||
}
|
||||
}
|
||||
|
||||
androidMain {
|
||||
dependsOn jvmMain
|
||||
}
|
||||
|
@@ -44,7 +44,8 @@ actual suspend fun <T> HttpClient.uniUpload(
|
||||
val withBinary = data.values.any { it is File || it is UniUploadFileInfo }
|
||||
|
||||
val formData = formData {
|
||||
data.forEach { (k, v) ->
|
||||
for (k in data.keys) {
|
||||
val v = data[k] ?: continue
|
||||
when (v) {
|
||||
is File -> append(
|
||||
k,
|
||||
@@ -89,7 +90,7 @@ actual suspend fun <T> HttpClient.uniUpload(
|
||||
submitForm(
|
||||
url,
|
||||
Parameters.build {
|
||||
formData.forEach {
|
||||
for (it in formData) {
|
||||
val formItem = (it as PartData.FormItem)
|
||||
append(it.name!!, it.value)
|
||||
}
|
||||
|
@@ -17,5 +17,8 @@ kotlin {
|
||||
api libs.ktor.io
|
||||
}
|
||||
}
|
||||
androidMain {
|
||||
dependsOn jvmMain
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -50,6 +50,8 @@ kotlin {
|
||||
implementation libs.android.espresso
|
||||
}
|
||||
}
|
||||
|
||||
androidMain.dependsOn jvmMain
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -61,6 +61,8 @@ kotlin {
|
||||
implementation libs.android.espresso
|
||||
}
|
||||
}
|
||||
|
||||
androidMain.dependsOn jvmMain
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -32,5 +32,3 @@ kotlin {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
disableIncludingJvmCodeInAndroidPart()
|
||||
|
@@ -0,0 +1,35 @@
|
||||
package dev.inmo.micro_utils.repos.annotations
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* Use this annotation and ksp generator (module `micro_utils.repos.generator`) to create the next hierarchy of models:
|
||||
*
|
||||
* * New model. For example: data class NewTest
|
||||
* * Registered model. For example: data class RegisteredTest
|
||||
*
|
||||
* @param registeredSupertypes These [KClass]es will be used as supertypes for registered model
|
||||
* @param serializable If true (default) will generate @[kotlinx.serialization.Serializable] for models. Affects [generateSerialName]
|
||||
* @param serializable If true (default) will generate @[kotlinx.serialization.SerialName] for models with their names as values
|
||||
*
|
||||
* @see GenerateCRUDModelExcludeOverride
|
||||
*/
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
annotation class GenerateCRUDModel(
|
||||
vararg val registeredSupertypes: KClass<*>,
|
||||
val serializable: Boolean = true,
|
||||
val generateSerialName: Boolean = true
|
||||
)
|
||||
|
||||
|
||||
/**
|
||||
* Use this annotation on properties which should be excluded from overriding in models.
|
||||
*
|
||||
* @see GenerateCRUDModel
|
||||
*/
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
annotation class GenerateCRUDModelExcludeOverride
|
||||
|
||||
|
154
repos/generator/README.md
Normal file
154
repos/generator/README.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# Koin generator
|
||||
|
||||
It is Kotlin Symbol Processing generator for simple creating of typical models: `New` and `Registered`.
|
||||
|
||||
1. [What may do this generator](#what-may-do-this-generator)
|
||||
2. [How to add generator](#how-to-add-generator)
|
||||
|
||||
## What may do this generator
|
||||
|
||||
So, you have several known things related to models:
|
||||
|
||||
* Interface with all necessary properties
|
||||
* Id class or some registered marker
|
||||
|
||||
Minimal sample will be next:
|
||||
|
||||
```kotlin
|
||||
@GenerateCRUDModel
|
||||
interface Sample {
|
||||
val property1: String
|
||||
val property2: Int
|
||||
}
|
||||
```
|
||||
|
||||
And generator will create:
|
||||
|
||||
```kotlin
|
||||
@Serializable
|
||||
@SerialName("NewSample")
|
||||
data class NewSample(
|
||||
override val property1: String,
|
||||
override val property2: Int,
|
||||
) : Sample
|
||||
|
||||
@Serializable
|
||||
@SerialName("RegisteredSample")
|
||||
data class RegisteredSample(
|
||||
override val property1: String,
|
||||
override val property2: Int,
|
||||
) : Sample
|
||||
|
||||
fun Sample.asNew(): NewSample = NewSample(property1, property2)
|
||||
|
||||
fun Sample.asRegistered(): RegisteredSample = RegisteredSample(property1, property2)
|
||||
```
|
||||
|
||||
But in most cases you will need to create some id class and registered interface:
|
||||
|
||||
```kotlin
|
||||
@Serializable
|
||||
@JvmInline
|
||||
value class SampleId(
|
||||
val long: Long
|
||||
)
|
||||
|
||||
sealed interface IRegisteredSample : Sample {
|
||||
val id: SampleId
|
||||
|
||||
@GenerateCRUDModelExcludeOverride
|
||||
val excludedProperty2: Boolean
|
||||
get() = false
|
||||
}
|
||||
```
|
||||
|
||||
As you may see, we have added `GenerateCRUDModelExcludeOverride` annotation. Properties marked with this annotation
|
||||
WILL NOT be inclued into overriding in registered class (or your base interface if used there). So, if you will wish to
|
||||
create model with id, use next form:
|
||||
|
||||
```kotlin
|
||||
@GenerateCRUDModel(IRegisteredSample::class)
|
||||
interface Sample {
|
||||
val property1: String
|
||||
val property2: Int
|
||||
}
|
||||
```
|
||||
|
||||
And generated registered class will be changed:
|
||||
|
||||
```kotlin
|
||||
@Serializable
|
||||
@SerialName(value = "NewSample")
|
||||
data class NewSample(
|
||||
override val property1: String,
|
||||
override val property2: Int,
|
||||
) : Sample
|
||||
|
||||
@Serializable
|
||||
@SerialName(value = "RegisteredSample")
|
||||
data class RegisteredSample(
|
||||
override val id: SampleId,
|
||||
override val property1: String,
|
||||
override val property2: Int,
|
||||
) : Sample, IRegisteredSample
|
||||
|
||||
fun Sample.asNew(): NewSample = NewSample(property1, property2)
|
||||
|
||||
fun Sample.asRegistered(id: SampleId): RegisteredSample = RegisteredSample(id, property1, property2)
|
||||
```
|
||||
|
||||
So, full sample will look like:
|
||||
|
||||
```kotlin
|
||||
/**
|
||||
* Your id value class. In fact, but it is not necessary
|
||||
*/
|
||||
@Serializable
|
||||
@JvmInline
|
||||
value class SampleId(
|
||||
val long: Long
|
||||
)
|
||||
|
||||
@GenerateCRUDModel(IRegisteredSample::class)
|
||||
sealed interface Sample {
|
||||
val property1: String
|
||||
val property2: Int
|
||||
|
||||
@GenerateCRUDModelExcludeOverride
|
||||
val excludedProperty: String
|
||||
get() = "excluded"
|
||||
}
|
||||
|
||||
sealed interface IRegisteredSample : Sample {
|
||||
val id: SampleId
|
||||
|
||||
@GenerateCRUDModelExcludeOverride
|
||||
val excludedProperty2: Boolean
|
||||
get() = false
|
||||
}
|
||||
```
|
||||
|
||||
You always may:
|
||||
|
||||
* Use any number of registered classes
|
||||
* Disable serialization for models
|
||||
* Disable serial names generation
|
||||
|
||||
## How to add generator
|
||||
|
||||
**Note: $ksp_version in the samples above is equal to supported `ksp` version presented in `/gradle/libs.versions.toml` of project**
|
||||
|
||||
**Note: $microutils_version in the version of MicroUtils library in your project**
|
||||
|
||||
1. Add `classpath` in `build.gradle` (`classpath "com.google.devtools.ksp:symbol-processing-gradle-plugin:$ksp_version"`)
|
||||
2. Add plugin to the plugins list of your module: `id "com.google.devtools.ksp"`
|
||||
3. In `dependencies` block add to the required target/compile the dependency `dev.inmo:micro_utils.repos.generator:$microutils_version`:
|
||||
```groovy
|
||||
dependencies {
|
||||
add("kspCommonMainMetadata", "dev.inmo:micro_utils.repos.generator:$microutils_version") // will work in commonMain of your multiplatform module
|
||||
add("kspJvm", "dev.inmo:micro_utils.repos.generator:$microutils_version") // will work in main of your JVM module
|
||||
}
|
||||
|
||||
ksp { // this generator do not require any arguments and we should left `ksp` empty
|
||||
}
|
||||
```
|
16
repos/generator/build.gradle
Normal file
16
repos/generator/build.gradle
Normal file
@@ -0,0 +1,16 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.jvm"
|
||||
}
|
||||
|
||||
apply from: "$publishJvmOnlyPath"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api libs.kt.reflect
|
||||
api project(":micro_utils.repos.common")
|
||||
api libs.kotlin.poet
|
||||
api libs.ksp
|
||||
}
|
217
repos/generator/src/main/kotlin/Processor.kt
Normal file
217
repos/generator/src/main/kotlin/Processor.kt
Normal file
@@ -0,0 +1,217 @@
|
||||
package dev.inmo.micro_utils.repos.generator
|
||||
|
||||
import com.google.devtools.ksp.KspExperimental
|
||||
import com.google.devtools.ksp.getAnnotationsByType
|
||||
import com.google.devtools.ksp.isAnnotationPresent
|
||||
import com.google.devtools.ksp.processing.CodeGenerator
|
||||
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
|
||||
import com.squareup.kotlinpoet.FileSpec
|
||||
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
|
||||
import com.squareup.kotlinpoet.ksp.toClassName
|
||||
import com.squareup.kotlinpoet.ksp.toTypeName
|
||||
import dev.inmo.micro_utils.repos.annotations.GenerateCRUDModel
|
||||
import dev.inmo.micro_utils.repos.annotations.GenerateCRUDModelExcludeOverride
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
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<KSAnnotated> {
|
||||
val toRetry = resolver.getSymbolsWithAnnotation(
|
||||
GenerateCRUDModel::class.qualifiedName!!
|
||||
).filterIsInstance<KSClassDeclaration>().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 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)))
|
||||
}
|
||||
}
|
||||
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()
|
||||
)
|
||||
|
||||
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().let {
|
||||
File(
|
||||
File(ksFile.filePath).parent,
|
||||
"GeneratedModels${ksFile.fileName}"
|
||||
).takeIf { !it.exists() } ?.apply {
|
||||
parentFile.mkdirs()
|
||||
|
||||
writer().use { writer ->
|
||||
it.writeTo(writer)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.isSuccess
|
||||
}.toList()
|
||||
|
||||
return toRetry
|
||||
}
|
||||
}
|
11
repos/generator/src/main/kotlin/Provider.kt
Normal file
11
repos/generator/src/main/kotlin/Provider.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
package dev.inmo.micro_utils.repos.generator
|
||||
|
||||
import com.google.devtools.ksp.processing.SymbolProcessor
|
||||
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
|
||||
import com.google.devtools.ksp.processing.SymbolProcessorProvider
|
||||
|
||||
class Provider : SymbolProcessorProvider {
|
||||
override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor = Processor(
|
||||
environment.codeGenerator
|
||||
)
|
||||
}
|
@@ -0,0 +1 @@
|
||||
dev.inmo.micro_utils.repos.generator.Provider
|
27
repos/generator/test/build.gradle
Normal file
27
repos/generator/test/build.gradle
Normal file
@@ -0,0 +1,27 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
id "com.google.devtools.ksp"
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
|
||||
|
||||
kotlin {
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
api project(":micro_utils.repos.common")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
add("kspCommonMainMetadata", project(":micro_utils.repos.generator"))
|
||||
}
|
||||
|
||||
ksp {
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
// THIS CODE HAVE BEEN GENERATED AUTOMATICALLY
|
||||
// TO REGENERATE IT JUST DELETE FILE
|
||||
// ORIGINAL FILE: Test.kt
|
||||
package dev.inmo.micro_utils.repos.generator.test
|
||||
|
||||
import kotlin.Int
|
||||
import kotlin.String
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName(value = "NewTest")
|
||||
public data class NewTest(
|
||||
public override val property1: String,
|
||||
public override val property2: Int,
|
||||
public override val parent: ParentTypeId?,
|
||||
) : Test
|
||||
|
||||
@Serializable
|
||||
@SerialName(value = "RegisteredTest")
|
||||
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, parent)
|
||||
|
||||
public fun Test.asRegistered(id: TestId): RegisteredTest = RegisteredTest(id, property1, property2,
|
||||
parent)
|
33
repos/generator/test/src/commonMain/kotlin/Test.kt
Normal file
33
repos/generator/test/src/commonMain/kotlin/Test.kt
Normal file
@@ -0,0 +1,33 @@
|
||||
package dev.inmo.micro_utils.repos.generator.test
|
||||
|
||||
import dev.inmo.micro_utils.repos.annotations.GenerateCRUDModel
|
||||
import dev.inmo.micro_utils.repos.annotations.GenerateCRUDModelExcludeOverride
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlin.jvm.JvmInline
|
||||
|
||||
@Serializable
|
||||
@JvmInline
|
||||
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
|
||||
get() = "excluded"
|
||||
}
|
||||
|
||||
sealed interface IRegisteredTest : Test {
|
||||
val id: TestId
|
||||
|
||||
@GenerateCRUDModelExcludeOverride
|
||||
val excludedProperty2: Boolean
|
||||
get() = false
|
||||
}
|
1
repos/generator/test/src/main/AndroidManifest.xml
Normal file
1
repos/generator/test/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1 @@
|
||||
<manifest package="dev.inmo.micro_utils.repos.generator.test"/>
|
@@ -18,6 +18,8 @@ String[] includes = [
|
||||
":language_codes",
|
||||
":language_codes:generator",
|
||||
":repos:common",
|
||||
":repos:generator",
|
||||
":repos:generator:test",
|
||||
":repos:cache",
|
||||
":repos:exposed",
|
||||
":repos:inmemory",
|
||||
|
Reference in New Issue
Block a user