Compare commits

..

51 Commits

Author SHA1 Message Date
7ba6eed453 Update CHANGELOG.md 2023-06-30 12:04:42 +06:00
beeb6ecc0a Update CHANGELOG.md 2023-06-30 12:03:17 +06:00
7cdc17a714 Update libs.versions.toml 2023-06-30 12:02:20 +06:00
4765a950a9 start 0.19.7 2023-06-30 12:01:21 +06:00
65e8137e08 Merge pull request #279 from InsanusMokrassar/0.19.6
0.19.6
2023-06-29 20:27:19 +06:00
ae546dd9ad update dependencies 2023-06-29 18:38:58 +06:00
8110c42be0 update compose 2023-06-27 16:53:10 +06:00
bd2b5ae5fc add versions plugin 2023-06-27 16:46:45 +06:00
2ddfffa6a9 start 0.19.6 2023-06-27 16:46:45 +06:00
a4b54e861d Merge pull request #277 from InsanusMokrassar/0.19.5
0.19.5
2023-06-20 20:22:33 +06:00
c6785f1a4f fixes in types generation 2023-06-20 20:20:47 +06:00
83fe621c56 start 0.19.5 2023-06-20 20:16:24 +06:00
b3a93e17eb Merge pull request #275 from InsanusMokrassar/0.19.4
0.19.4
2023-06-19 16:25:43 +06:00
546a391af3 dependencies update 2023-06-19 16:19:14 +06:00
786cf9bd8b fix in koin generator 2023-06-19 13:52:41 +06:00
dfd6fe062d start 0.19.4 2023-06-19 13:45:29 +06:00
b6ef818613 Merge pull request #274 from InsanusMokrassar/0.19.3
0.19.3
2023-06-19 08:45:45 +06:00
b0f9e9c30a generic-oriented koin definitions 2023-06-19 00:32:45 +06:00
7e5c88ddc3 koin generator improvements 2023-06-18 23:38:36 +06:00
9824c3e00f start 0.19.3 2023-06-18 23:11:50 +06:00
9171d5ed11 update dokka version and return js kdocs 2023-06-09 12:01:11 +06:00
a1830ebb82 Merge pull request #269 from InsanusMokrassar/0.19.2
0.19.2
2023-06-02 13:02:38 +06:00
22d2a3d9bf Update CHANGELOG.md 2023-06-02 12:47:45 +06:00
c9b97fc965 Update libs.versions.toml 2023-06-02 12:46:56 +06:00
51f85becd5 Merge pull request #267 from InsanusMokrassar/0.19.2
0.19.2
2023-06-02 12:39:27 +06:00
a8a281cfb4 downgrade kotlin-poet version 2023-06-02 12:19:02 +06:00
ddd1304949 update dependencies 2023-06-02 12:17:21 +06:00
86d70b6c02 start 0.19.2 2023-06-02 12:11:49 +06:00
a22bdb39e7 Merge pull request #261 from InsanusMokrassar/0.19.1
update kotlin poet (0.19.1)
2023-05-29 17:35:29 +06:00
7ae4d5ef95 update kotlin poet 2023-05-29 17:31:40 +06:00
a2038cbefa Merge pull request #259 from InsanusMokrassar/0.19.1
0.19.1
2023-05-29 17:28:19 +06:00
992091eade Update CHANGELOG.md 2023-05-29 17:27:57 +06:00
e3bfead0c5 Update libs.versions.toml 2023-05-29 10:15:19 +06:00
0de96141fd start 0.19.1 2023-05-29 10:14:35 +06:00
fa18d15c3c Merge pull request #257 from InsanusMokrassar/0.19.0
0.19.0
2023-05-26 20:17:30 +06:00
ea9dbf2371 Koin.get and Scope.get with opportunity to get dependency by its type and definition 2023-05-25 21:12:21 +06:00
d34e3ec7a9 update dependencies 2023-05-25 21:08:12 +06:00
c8833a36af start 0.19.0 2023-05-25 20:58:05 +06:00
a067cb0c0f Merge pull request #256 from InsanusMokrassar/0.18.4
0.18.4
2023-05-14 16:51:57 +06:00
999c8327bd lazyInject 2023-05-14 16:36:24 +06:00
c2ec73c70a start 0.18.4 2023-05-14 16:28:03 +06:00
702f782fc1 Merge pull request #254 from InsanusMokrassar/0.18.3
0.18.3
2023-05-12 14:30:37 +06:00
25dbcaaf83 update dependencies 2023-05-12 00:51:38 +06:00
b00d454a24 start 0.18.3 2023-05-12 00:26:16 +06:00
dbc921d56d Merge pull request #250 from InsanusMokrassar/0.18.2
0.18.2
2023-05-10 10:19:47 +06:00
438fefa7a3 fixes 2023-05-09 15:09:50 +06:00
5d74eac814 Update libs.versions.toml 2023-05-09 01:41:25 +06:00
9fb62e1e25 start 0.18.2 and make json of Startup customizable 2023-05-09 01:38:04 +06:00
3e366ea73b Update libs.versions.toml 2023-05-06 01:54:15 +06:00
0ff895bffa Update gradle.properties 2023-05-06 01:53:33 +06:00
c5bb120280 Merge pull request #248 from InsanusMokrassar/0.18.1
0.18.1
2023-05-05 22:26:53 +06:00
23 changed files with 655 additions and 149 deletions

View File

@@ -1,5 +1,75 @@
# Changelog # Changelog
## 0.19.7
* `Versions`:
* `Coroutines`: `1.7.1` -> `1.7.2`
## 0.19.6
* `Versions`:
* `Coroutines`: `1.6.4` -> `1.7.1`
* `Ktor`: `2.3.1` -> `2.3.2`
* `Compose`: `1.4.0` -> `1.4.1`
## 0.19.5
* `Repos`:
* `Generator`:
* Fixes in new type generation
## 0.19.4
* `Versions`:
* `Koin`: `3.4.1` -> `3.4.2`
* `Android Fragments`: `1.5.7` -> `1.6.0`
* `Koin`
* `Generator`
* Fixes in new generic generator part
## 0.19.3
* `Koin`
* `Generator`
* New getter methods now available with opportunity to use parameters
* Old notation `*Single` and `*Factory` is deprecated since this release. With old
will be generated new `single*` and `factory*` notations for new generations
* Add opportunity to use generic-oriented koin definitions
## 0.19.2
* `Versions`:
* `Ktor`: `2.3.0` -> `2.3.1`
* `Koin`: `3.4.0` -> `3.4.1`
* `Uuid`: `0.7.0` -> `0.7.1`
## 0.19.1
* `Versions`:
* `Korlibs`: `4.0.1` -> `4.0.3`
* `Kotlin Poet`: `1.13.2` -> `1.14.0`
## 0.19.0
* `Versions`:
* `Korlibs`: `3.4.0` -> `4.0.1`
## 0.18.4
* `Koin`:
* New extension `lazyInject`
## 0.18.3
* `Versions`:
* `Serialization`: `1.5.0` -> `1.5.1`
* `Android Cor Ktx`: `1.10.0` -> `1.10.1`
## 0.18.2
* `Startup`:
* Now internal `Json` is fully customizable
## 0.18.1 ## 0.18.1
* `Common`: * `Common`:

View File

@@ -17,6 +17,10 @@ buildscript {
} }
} }
plugins {
alias(libs.plugins.versions)
}
allprojects { allprojects {
repositories { repositories {
mavenLocal() mavenLocal()
@@ -38,3 +42,4 @@ allprojects {
apply from: "./extensions.gradle" apply from: "./extensions.gradle"
apply from: "./github_release.gradle" apply from: "./github_release.gradle"
apply from: "./versions_plugin_setup.gradle"

View File

@@ -1,6 +1,6 @@
package dev.inmo.micro_utils.crypto package dev.inmo.micro_utils.crypto
import com.soywiz.krypto.md5 import korlibs.crypto.md5
typealias MD5 = String typealias MD5 = String

View File

@@ -13,10 +13,10 @@ repositories {
kotlin { kotlin {
jvm() jvm()
// js(IR) { js(IR) {
// browser() browser()
// nodejs() nodejs()
// } }
android {} android {}
sourceSets { sourceSets {
@@ -26,44 +26,44 @@ kotlin {
project.parent.subprojects.forEach { project.parent.subprojects.forEach {
if ( if (
it != project it != project
&& it.hasProperty("kotlin") && it.hasProperty("kotlin")
&& it.kotlin.sourceSets.any { it.name.contains("commonMain") } && it.kotlin.sourceSets.any { it.name.contains("commonMain") }
// && it.kotlin.sourceSets.any { it.name.contains("jsMain") } && it.kotlin.sourceSets.any { it.name.contains("jsMain") }
&& it.kotlin.sourceSets.any { it.name.contains("jvmMain") } && it.kotlin.sourceSets.any { it.name.contains("jvmMain") }
&& it.kotlin.sourceSets.any { it.name.contains("androidMain") } && it.kotlin.sourceSets.any { it.name.contains("androidMain") }
) { ) {
api it api it
} }
} }
} }
} }
// jsMain { jsMain {
// dependencies { dependencies {
// implementation kotlin('stdlib') implementation kotlin('stdlib')
// project.parent.subprojects.forEach { project.parent.subprojects.forEach {
// if ( if (
// it != project it != project
// && it.hasProperty("kotlin") && it.hasProperty("kotlin")
// && it.kotlin.sourceSets.any { it.name.contains("commonMain") } && it.kotlin.sourceSets.any { it.name.contains("commonMain") }
// && it.kotlin.sourceSets.any { it.name.contains("jsMain") } && it.kotlin.sourceSets.any { it.name.contains("jsMain") }
// ) { ) {
// api it api it
// } }
// } }
// } }
// } }
jvmMain { jvmMain {
dependencies { dependencies {
implementation kotlin('stdlib') implementation kotlin('stdlib')
project.parent.subprojects.forEach { project.parent.subprojects.forEach {
if ( if (
it != project it != project
&& it.hasProperty("kotlin") && it.hasProperty("kotlin")
&& it.kotlin.sourceSets.any { it.name.contains("commonMain") } && it.kotlin.sourceSets.any { it.name.contains("commonMain") }
&& it.kotlin.sourceSets.any { it.name.contains("jvmMain") } && it.kotlin.sourceSets.any { it.name.contains("jvmMain") }
) { ) {
api it api it
} }
@@ -76,10 +76,10 @@ kotlin {
project.parent.subprojects.forEach { project.parent.subprojects.forEach {
if ( if (
it != project it != project
&& it.hasProperty("kotlin") && it.hasProperty("kotlin")
&& it.kotlin.sourceSets.any { it.name.contains("commonMain") } && it.kotlin.sourceSets.any { it.name.contains("commonMain") }
&& it.kotlin.sourceSets.any { it.name.contains("androidMain") } && it.kotlin.sourceSets.any { it.name.contains("androidMain") }
) { ) {
api it api it
} }
@@ -116,9 +116,9 @@ tasks.dokkaHtml {
sourceRoots.setFrom(findSourcesWithName("commonMain")) sourceRoots.setFrom(findSourcesWithName("commonMain"))
} }
// named("jsMain") { named("jsMain") {
// sourceRoots.setFrom(findSourcesWithName("jsMain", "commonMain")) sourceRoots.setFrom(findSourcesWithName("jsMain"))
// } }
named("jvmMain") { named("jvmMain") {
sourceRoots.setFrom(findSourcesWithName("jvmMain")) sourceRoots.setFrom(findSourcesWithName("jvmMain"))

View File

@@ -14,5 +14,5 @@ crypto_js_version=4.1.1
# Project data # Project data
group=dev.inmo group=dev.inmo
version=0.18.1 version=0.19.7
android_code_version=192 android_code_version=203

View File

@@ -1,36 +1,38 @@
[versions] [versions]
kt = "1.8.20" kt = "1.8.20"
kt-serialization = "1.5.0" kt-serialization = "1.5.1"
kt-coroutines = "1.6.4" kt-coroutines = "1.7.2"
kslog = "1.1.1" kslog = "1.1.1"
jb-compose = "1.4.0" jb-compose = "1.4.1"
jb-exposed = "0.41.1" jb-exposed = "0.41.1"
jb-dokka = "1.8.10" jb-dokka = "1.8.20"
korlibs = "3.4.0" korlibs = "4.0.3"
uuid = "0.7.0" uuid = "0.7.1"
ktor = "2.3.0" ktor = "2.3.2"
gh-release = "2.4.1" gh-release = "2.4.1"
koin = "3.4.0" koin = "3.4.2"
okio = "3.3.0" okio = "3.3.0"
ksp = "1.8.20-1.0.11" ksp = "1.8.20-1.0.11"
kotlin-poet = "1.13.0" kotlin-poet = "1.14.2"
versions = "0.47.0"
android-gradle = "7.4.2" android-gradle = "7.4.2"
dexcount = "4.0.0" dexcount = "4.0.0"
android-coreKtx = "1.10.0" android-coreKtx = "1.10.1"
android-recyclerView = "1.3.0" android-recyclerView = "1.3.0"
android-appCompat = "1.6.1" android-appCompat = "1.6.1"
android-fragment = "1.5.7" android-fragment = "1.6.0"
android-espresso = "3.5.1" android-espresso = "3.5.1"
android-test = "1.1.5" android-test = "1.1.5"
@@ -109,3 +111,5 @@ buildscript-android-dexcount = { module = "com.getkeepsafe.dexcount:dexcount-gra
[plugins] [plugins]
jb-compose = { id = "org.jetbrains.compose", version.ref = "jb-compose" } jb-compose = { id = "org.jetbrains.compose", version.ref = "jb-compose" }
versions = { id = "com.github.ben-manes.versions", version.ref = "versions" }

View File

@@ -13,3 +13,8 @@ dependencies {
api libs.kotlin.poet api libs.kotlin.poet
api libs.ksp api libs.ksp
} }
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

View File

@@ -9,19 +9,28 @@ 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.KSFile import com.google.devtools.ksp.symbol.KSFile
import com.google.devtools.ksp.symbol.Modifier
import com.squareup.kotlinpoet.AnnotationSpec
import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.CodeBlock
import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.FileSpec
import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.ParameterSpec import com.squareup.kotlinpoet.ParameterSpec
import com.squareup.kotlinpoet.ParameterizedTypeName
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
import com.squareup.kotlinpoet.PropertySpec import com.squareup.kotlinpoet.PropertySpec
import com.squareup.kotlinpoet.TypeName
import com.squareup.kotlinpoet.TypeVariableName
import com.squareup.kotlinpoet.asTypeName import com.squareup.kotlinpoet.asTypeName
import com.squareup.kotlinpoet.ksp.toClassName import com.squareup.kotlinpoet.ksp.toClassName
import com.squareup.kotlinpoet.ksp.toTypeName import com.squareup.kotlinpoet.ksp.toTypeName
import com.squareup.kotlinpoet.ksp.writeTo import com.squareup.kotlinpoet.ksp.writeTo
import dev.inmo.micro_utils.koin.annotations.GenerateGenericKoinDefinition
import dev.inmo.micro_utils.koin.annotations.GenerateKoinDefinition import dev.inmo.micro_utils.koin.annotations.GenerateKoinDefinition
import org.koin.core.Koin import org.koin.core.Koin
import org.koin.core.module.Module import org.koin.core.module.Module
import org.koin.core.parameter.ParametersDefinition
import org.koin.core.scope.Scope import org.koin.core.scope.Scope
import java.io.File import java.io.File
import kotlin.reflect.KClass import kotlin.reflect.KClass
@@ -32,11 +41,236 @@ class Processor(
private val definitionClassName = ClassName("org.koin.core.definition", "Definition") private val definitionClassName = ClassName("org.koin.core.definition", "Definition")
private val koinDefinitionClassName = ClassName("org.koin.core.definition", "KoinDefinition") private val koinDefinitionClassName = ClassName("org.koin.core.definition", "KoinDefinition")
private fun FileSpec.Builder.addCodeForType(
targetType: TypeName,
name: String,
nullable: Boolean,
generateSingle: Boolean,
generateFactory: Boolean,
) {
val targetTypeAsGenericType = (targetType as? TypeVariableName) ?.copy(reified = true)
fun addGetterProperty(
receiver: KClass<*>
) {
addProperty(
PropertySpec.builder(
name,
targetType,
).apply {
addKdoc(
"""
@return Definition by key "${name}"
""".trimIndent()
)
getter(
FunSpec.getterBuilder().apply {
targetTypeAsGenericType ?.let {
addModifiers(KModifier.INLINE)
}
addCode(
"return " + (if (nullable) {
"getOrNull"
} else {
"get"
}) + "(named(\"${name}\"))"
)
}.build()
)
targetTypeAsGenericType ?.let {
addTypeVariable(it)
}
receiver(receiver)
}.build()
)
}
if (targetTypeAsGenericType == null) {
addGetterProperty(Scope::class)
addGetterProperty(Koin::class)
}
val parametersDefinitionClassName = ClassName(
"org.koin.core.parameter",
"ParametersDefinition"
)
fun addGetterMethod(
receiver: KClass<*>
) {
addFunction(
FunSpec.builder(
name
).apply {
addKdoc(
"""
@return Definition by key "${name}" with [parameters]
""".trimIndent()
)
receiver(receiver)
addParameter(
ParameterSpec(
"parameters",
parametersDefinitionClassName.let {
if (targetTypeAsGenericType != null) {
it.copy(nullable = true)
} else {
it
}
},
KModifier.NOINLINE
).toBuilder().apply {
if (targetTypeAsGenericType != null) {
defaultValue("null")
}
}.build()
)
addModifiers(KModifier.INLINE)
targetTypeAsGenericType ?.let {
addTypeVariable(it)
returns(it.copy(nullable = nullable))
} ?: returns(targetType)
addCode(
"return " + (if (nullable) {
"getOrNull"
} else {
"get"
}) + "(named(\"${name}\"), parameters)"
)
}.build()
)
}
addGetterMethod(Scope::class)
addGetterMethod(Koin::class)
fun FunSpec.Builder.addDefinitionParameter() {
val definitionModifiers = if (targetTypeAsGenericType == null) {
arrayOf()
} else {
arrayOf(KModifier.NOINLINE)
}
addParameter(
ParameterSpec.builder(
"definition",
definitionClassName.parameterizedBy(targetType.copy(nullable = false)),
*definitionModifiers
).build()
)
}
if (generateSingle) {
fun FunSpec.Builder.configure(
useInstead: String? = null
) {
addKdoc(
"""
Will register [definition] with [org.koin.core.module.Module.single] and key "${name}"
""".trimIndent()
)
receiver(Module::class)
addParameter(
ParameterSpec.builder(
"createdAtStart",
Boolean::class
).apply {
defaultValue("false")
}.build()
)
addDefinitionParameter()
returns(koinDefinitionClassName.parameterizedBy(targetType.copy(nullable = false)))
addCode(
"return single(named(\"${name}\"), createdAtStart = createdAtStart, definition = definition)"
)
targetTypeAsGenericType ?.let {
addTypeVariable(it)
addModifiers(KModifier.INLINE)
}
if (useInstead != null) {
addAnnotation(
AnnotationSpec.builder(
Deprecated::class
).apply {
addMember(
CodeBlock.of(
"""
"This definition is old style and should not be used anymore. Use $useInstead instead"
""".trimIndent()
)
)
addMember(CodeBlock.of("ReplaceWith(\"$useInstead\")"))
}.build()
)
}
}
val actualSingleName = "single${name.replaceFirstChar { it.uppercase() }}"
if (targetTypeAsGenericType == null) { // classic type
addFunction(
FunSpec.builder("${name}Single").apply { configure(actualSingleName) }.build()
)
}
addFunction(
FunSpec.builder(actualSingleName).apply { configure() }.build()
)
}
if (generateFactory) {
fun FunSpec.Builder.configure(
useInstead: String? = null
) {
addKdoc(
"""
Will register [definition] with [org.koin.core.module.Module.factory] and key "${name}"
""".trimIndent()
)
receiver(Module::class)
addDefinitionParameter()
returns(koinDefinitionClassName.parameterizedBy(targetType.copy(nullable = false)))
addCode(
"return factory(named(\"${name}\"), definition = definition)"
)
targetTypeAsGenericType ?.let {
addTypeVariable(it)
addModifiers(KModifier.INLINE)
}
if (useInstead != null) {
addAnnotation(
AnnotationSpec.builder(
Deprecated::class
).apply {
addMember(
CodeBlock.of(
"""
"This definition is old style and should not be used anymore. Use $useInstead instead"
""".trimIndent()
)
)
addMember(CodeBlock.of("ReplaceWith(\"$useInstead\")"))
}.build()
)
}
}
val actualFactoryName = "factory${name.replaceFirstChar { it.uppercase() }}"
if (targetTypeAsGenericType == null) { // classic type
addFunction(
FunSpec.builder("${name}Factory").apply { configure(useInstead = actualFactoryName) }.build()
)
}
addFunction(
FunSpec.builder(actualFactoryName).apply { configure() }.build()
)
}
addImport("org.koin.core.qualifier", "named")
}
@OptIn(KspExperimental::class) @OptIn(KspExperimental::class)
override fun process(resolver: Resolver): List<KSAnnotated> { override fun process(resolver: Resolver): List<KSAnnotated> {
resolver.getSymbolsWithAnnotation( (resolver.getSymbolsWithAnnotation(
GenerateKoinDefinition::class.qualifiedName!! GenerateKoinDefinition::class.qualifiedName!!
).filterIsInstance<KSFile>().forEach { ksFile -> ) + resolver.getSymbolsWithAnnotation(
GenerateGenericKoinDefinition::class.qualifiedName!!
)).filterIsInstance<KSFile>().forEach { ksFile ->
FileSpec.builder( FileSpec.builder(
ksFile.packageName.asString(), ksFile.packageName.asString(),
"GeneratedDefinitions${ksFile.fileName.removeSuffix(".kt")}" "GeneratedDefinitions${ksFile.fileName.removeSuffix(".kt")}"
@@ -72,92 +306,12 @@ class Processor(
}.copy( }.copy(
nullable = it.nullable nullable = it.nullable
) )
fun addGetterProperty(
receiver: KClass<*>
) {
addProperty(
PropertySpec.builder(
it.name,
targetType,
).apply {
addKdoc(
"""
@return Definition by key "${it.name}"
""".trimIndent()
)
getter(
FunSpec.getterBuilder().apply {
addCode(
"return " + (if (it.nullable) {
"getOrNull"
} else {
"get"
}) + "(named(\"${it.name}\"))"
)
}.build()
)
receiver(receiver)
}.build()
)
}
addGetterProperty(Scope::class) addCodeForType(targetType, it.name, it.nullable, it.generateSingle, it.generateFactory)
addGetterProperty(Koin::class) }
ksFile.getAnnotationsByType(GenerateGenericKoinDefinition::class).forEach {
if (it.generateSingle) { val targetType = TypeVariableName("T", Any::class)
addFunction( addCodeForType(targetType, it.name, it.nullable, it.generateSingle, it.generateFactory)
FunSpec.builder("${it.name}Single").apply {
addKdoc(
"""
Will register [definition] with [org.koin.core.module.Module.single] and key "${it.name}"
""".trimIndent()
)
receiver(Module::class)
addParameter(
ParameterSpec.builder(
"createdAtStart",
Boolean::class
).apply {
defaultValue("false")
}.build()
)
addParameter(
ParameterSpec.builder(
"definition",
definitionClassName.parameterizedBy(targetType.copy(nullable = false))
).build()
)
returns(koinDefinitionClassName.parameterizedBy(targetType.copy(nullable = false)))
addCode(
"return single(named(\"${it.name}\"), createdAtStart = createdAtStart, definition = definition)"
)
}.build()
)
}
if (it.generateFactory) {
addFunction(
FunSpec.builder("${it.name}Factory").apply {
addKdoc(
"""
Will register [definition] with [org.koin.core.module.Module.factory] and key "${it.name}"
""".trimIndent()
)
receiver(Module::class)
addParameter(
ParameterSpec.builder(
"definition",
definitionClassName.parameterizedBy(targetType.copy(nullable = false))
).build()
)
returns(koinDefinitionClassName.parameterizedBy(targetType.copy(nullable = false)))
addCode(
"return factory(named(\"${it.name}\"), definition = definition)"
)
}.build()
)
}
addImport("org.koin.core.qualifier", "named")
} }
}.build().let { }.build().let {
File( File(

View File

@@ -3,12 +3,15 @@
// ORIGINAL FILE: Test.kt // ORIGINAL FILE: Test.kt
package dev.inmo.micro_utils.koin.generator.test package dev.inmo.micro_utils.koin.generator.test
import kotlin.Any
import kotlin.Boolean import kotlin.Boolean
import kotlin.Deprecated
import kotlin.String import kotlin.String
import org.koin.core.Koin import org.koin.core.Koin
import org.koin.core.definition.Definition import org.koin.core.definition.Definition
import org.koin.core.definition.KoinDefinition import org.koin.core.definition.KoinDefinition
import org.koin.core.module.Module import org.koin.core.module.Module
import org.koin.core.parameter.ParametersDefinition
import org.koin.core.qualifier.named import org.koin.core.qualifier.named
import org.koin.core.scope.Scope import org.koin.core.scope.Scope
@@ -24,15 +27,98 @@ public val Scope.sampleInfo: Test<String>
public val Koin.sampleInfo: Test<String> public val Koin.sampleInfo: Test<String>
get() = get(named("sampleInfo")) get() = get(named("sampleInfo"))
/**
* @return Definition by key "sampleInfo" with [parameters]
*/
public inline fun Scope.sampleInfo(noinline parameters: ParametersDefinition): Test<String> =
get(named("sampleInfo"), parameters)
/**
* @return Definition by key "sampleInfo" with [parameters]
*/
public inline fun Koin.sampleInfo(noinline parameters: ParametersDefinition): Test<String> =
get(named("sampleInfo"), parameters)
/** /**
* Will register [definition] with [org.koin.core.module.Module.single] and key "sampleInfo" * Will register [definition] with [org.koin.core.module.Module.single] and key "sampleInfo"
*/ */
@Deprecated(
"This definition is old style and should not be used anymore. Use singleSampleInfo instead",
ReplaceWith("singleSampleInfo"),
)
public fun Module.sampleInfoSingle(createdAtStart: Boolean = false, public fun Module.sampleInfoSingle(createdAtStart: Boolean = false,
definition: Definition<Test<String>>): KoinDefinition<Test<String>> = definition: Definition<Test<String>>): KoinDefinition<Test<String>> =
single(named("sampleInfo"), createdAtStart = createdAtStart, definition = definition) single(named("sampleInfo"), createdAtStart = createdAtStart, definition = definition)
/**
* Will register [definition] with [org.koin.core.module.Module.single] and key "sampleInfo"
*/
public fun Module.singleSampleInfo(createdAtStart: Boolean = false,
definition: Definition<Test<String>>): KoinDefinition<Test<String>> =
single(named("sampleInfo"), createdAtStart = createdAtStart, definition = definition)
/** /**
* Will register [definition] with [org.koin.core.module.Module.factory] and key "sampleInfo" * Will register [definition] with [org.koin.core.module.Module.factory] and key "sampleInfo"
*/ */
@Deprecated(
"This definition is old style and should not be used anymore. Use factorySampleInfo instead",
ReplaceWith("factorySampleInfo"),
)
public fun Module.sampleInfoFactory(definition: Definition<Test<String>>): public fun Module.sampleInfoFactory(definition: Definition<Test<String>>):
KoinDefinition<Test<String>> = factory(named("sampleInfo"), definition = definition) KoinDefinition<Test<String>> = factory(named("sampleInfo"), definition = definition)
/**
* Will register [definition] with [org.koin.core.module.Module.factory] and key "sampleInfo"
*/
public fun Module.factorySampleInfo(definition: Definition<Test<String>>):
KoinDefinition<Test<String>> = factory(named("sampleInfo"), definition = definition)
/**
* @return Definition by key "test" with [parameters]
*/
public inline fun <reified T : Any> Scope.test(noinline parameters: ParametersDefinition? = null): T
= get(named("test"), parameters)
/**
* @return Definition by key "test" with [parameters]
*/
public inline fun <reified T : Any> Koin.test(noinline parameters: ParametersDefinition? = null): T
= get(named("test"), parameters)
/**
* Will register [definition] with [org.koin.core.module.Module.single] and key "test"
*/
public inline fun <reified T : Any> Module.singleTest(createdAtStart: Boolean = false, noinline
definition: Definition<T>): KoinDefinition<T> = single(named("test"), createdAtStart =
createdAtStart, definition = definition)
/**
* Will register [definition] with [org.koin.core.module.Module.factory] and key "test"
*/
public inline fun <reified T : Any> Module.factoryTest(noinline definition: Definition<T>):
KoinDefinition<T> = factory(named("test"), definition = definition)
/**
* @return Definition by key "testNullable" with [parameters]
*/
public inline fun <reified T : Any> Scope.testNullable(noinline parameters: ParametersDefinition? =
null): T? = getOrNull(named("testNullable"), parameters)
/**
* @return Definition by key "testNullable" with [parameters]
*/
public inline fun <reified T : Any> Koin.testNullable(noinline parameters: ParametersDefinition? =
null): T? = getOrNull(named("testNullable"), parameters)
/**
* Will register [definition] with [org.koin.core.module.Module.single] and key "testNullable"
*/
public inline fun <reified T : Any> Module.singleTestNullable(createdAtStart: Boolean = false,
noinline definition: Definition<T>): KoinDefinition<T> = single(named("testNullable"),
createdAtStart = createdAtStart, definition = definition)
/**
* Will register [definition] with [org.koin.core.module.Module.factory] and key "testNullable"
*/
public inline fun <reified T : Any> Module.factoryTestNullable(noinline definition: Definition<T>):
KoinDefinition<T> = factory(named("testNullable"), definition = definition)

View File

@@ -1,6 +1,9 @@
@file:GenerateKoinDefinition("sampleInfo", Test::class, String::class, nullable = false) @file:GenerateKoinDefinition("sampleInfo", Test::class, String::class, nullable = false)
@file:GenerateGenericKoinDefinition("test", nullable = false)
@file:GenerateGenericKoinDefinition("testNullable", nullable = true)
package dev.inmo.micro_utils.koin.generator.test package dev.inmo.micro_utils.koin.generator.test
import dev.inmo.micro_utils.koin.annotations.GenerateGenericKoinDefinition
import dev.inmo.micro_utils.koin.annotations.GenerateKoinDefinition import dev.inmo.micro_utils.koin.annotations.GenerateKoinDefinition
import org.koin.core.Koin import org.koin.core.Koin

View File

@@ -0,0 +1,40 @@
package dev.inmo.micro_utils.koin
import org.koin.core.Koin
import org.koin.core.definition.BeanDefinition
import org.koin.core.definition.KoinDefinition
import org.koin.core.instance.InstanceFactory
import org.koin.core.parameter.ParametersDefinition
import org.koin.core.scope.Scope
fun <T> Koin.get(definition: BeanDefinition<T>, parameters: ParametersDefinition? = null): T = get(
definition.primaryType,
definition.qualifier,
parameters
)
fun <T> Koin.get(definition: InstanceFactory<T>, parameters: ParametersDefinition? = null): T = get(
definition.beanDefinition,
parameters
)
fun <T> Koin.get(definition: KoinDefinition<T>, parameters: ParametersDefinition? = null): T = get(
definition.factory,
parameters
)
fun <T> Scope.get(definition: BeanDefinition<T>, parameters: ParametersDefinition? = null): T = get(
definition.primaryType,
definition.qualifier,
parameters
)
fun <T> Scope.get(definition: InstanceFactory<T>, parameters: ParametersDefinition? = null): T = get(
definition.beanDefinition,
parameters
)
fun <T> Scope.get(definition: KoinDefinition<T>, parameters: ParametersDefinition? = null): T = get(
definition.factory,
parameters
)

View File

@@ -0,0 +1,26 @@
package dev.inmo.micro_utils.koin.annotations
import kotlin.reflect.KClass
/**
* Use this annotation to mark files near to which generator should place generated extensions for koin [org.koin.core.scope.Scope]
* and [org.koin.core.Koin]
*
* @param name Name for definitions. This name will be available as extension for [org.koin.core.scope.Scope] and [org.koin.core.Koin]
* @param type Type of extensions. It is base star-typed class
* @param typeArgs Generic types for [type]. For example, if [type] == `Something::class` and [typeArgs] == `G1::class,
* G2::class`, the result type will be `Something<G1, G2>`
* @param nullable In case when true, extension will not throw error when definition has not been registered in koin
* @param generateSingle Generate definition factory with [org.koin.core.module.Module.single]. You will be able to use
* the extension [org.koin.core.module.Module].[name]Single(createdAtStart/* default false */) { /* your definition */ }
* @param generateFactory Generate definition factory with [org.koin.core.module.Module.factory]. You will be able to use
* the extension [org.koin.core.module.Module].[name]Factory { /* your definition */ }
*/
@Target(AnnotationTarget.FILE)
@Repeatable
annotation class GenerateGenericKoinDefinition(
val name: String,
val nullable: Boolean = true,
val generateSingle: Boolean = true,
val generateFactory: Boolean = true
)

View File

@@ -0,0 +1,27 @@
package dev.inmo.micro_utils.koin
import org.koin.core.parameter.ParametersDefinition
import org.koin.core.qualifier.Qualifier
import org.koin.java.KoinJavaComponent
import kotlin.reflect.KClass
fun <T> lazyInject(
kClassFactory: () -> KClass<*>,
qualifier: Qualifier? = null,
parameters: ParametersDefinition? = null
): Lazy<T> {
return lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
KoinJavaComponent.get(kClassFactory().java, qualifier, parameters)
}
}
fun <T> lazyInject(
kClass: KClass<*>,
qualifier: Qualifier? = null,
parameters: ParametersDefinition? = null
): Lazy<T> = lazyInject({ kClass }, qualifier, parameters)
inline fun <reified T> lazyInject(
qualifier: Qualifier? = null,
noinline parameters: ParametersDefinition? = null
): Lazy<T> = lazyInject(T::class, qualifier, parameters)

View File

@@ -1,6 +1,6 @@
package dev.inmo.micro_utils.ktor.common package dev.inmo.micro_utils.ktor.common
import com.soywiz.klock.DateTime import korlibs.time.DateTime
typealias FromToDateTime = Pair<DateTime?, DateTime?> typealias FromToDateTime = Pair<DateTime?, DateTime?>

View File

@@ -1,6 +1,6 @@
package dev.inmo.micro_utils.ktor.server package dev.inmo.micro_utils.ktor.server
import com.soywiz.klock.DateTime import korlibs.time.DateTime
import dev.inmo.micro_utils.ktor.common.FromToDateTime import dev.inmo.micro_utils.ktor.common.FromToDateTime
import io.ktor.http.Parameters import io.ktor.http.Parameters

View File

@@ -14,3 +14,8 @@ dependencies {
api libs.kotlin.poet api libs.kotlin.poet
api libs.ksp api libs.ksp
} }
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

View File

@@ -100,7 +100,11 @@ class Processor(
primaryConstructor( primaryConstructor(
FunSpec.constructorBuilder().apply { FunSpec.constructorBuilder().apply {
ksClassProperties.forEach { ksClassProperties.forEach {
addParameter(it.simpleName.getShortName(), it.typeName) addParameter(
ParameterSpec.builder(it.simpleName.getShortName(), it.typeName).apply {
annotations += it.annotations.map { it.toAnnotationSpec() }
}.build()
)
typeBuilder.addProperty( typeBuilder.addProperty(
PropertySpec.builder(it.simpleName.getShortName(), it.typeName, KModifier.OVERRIDE).apply { PropertySpec.builder(it.simpleName.getShortName(), it.typeName, KModifier.OVERRIDE).apply {
initializer(it.simpleName.getShortName()) initializer(it.simpleName.getShortName())

View File

@@ -11,18 +11,20 @@ import kotlinx.serialization.Serializable
@Serializable @Serializable
@SerialName(value = "NewTest") @SerialName(value = "NewTest")
public data class NewTest( public data class NewTest(
public override val property1: String, override val property1: String,
public override val property2: Int, override val property2: Int,
public override val parent: ParentTypeId?, @Serializable
override val parent: ParentTypeId?,
) : Test ) : Test
@Serializable @Serializable
@SerialName(value = "RegisteredTest") @SerialName(value = "RegisteredTest")
public data class RegisteredTest( public data class RegisteredTest(
public override val id: TestId, override val id: TestId,
public override val property1: String, override val property1: String,
public override val property2: Int, override val property2: Int,
public override val parent: ParentTypeId?, @Serializable
override val parent: ParentTypeId?,
) : Test, IRegisteredTest ) : Test, IRegisteredTest
public fun Test.asNew(): NewTest = NewTest(property1, property2, parent) public fun Test.asNew(): NewTest = NewTest(property1, property2, parent)

View File

@@ -17,6 +17,7 @@ typealias ParentTypeId = TestId
sealed interface Test { sealed interface Test {
val property1: String val property1: String
val property2: Int val property2: Int
@Serializable
val parent: ParentTypeId? val parent: ParentTypeId?
@GenerateCRUDModelExcludeOverride @GenerateCRUDModelExcludeOverride

View File

@@ -2,6 +2,7 @@ plugins {
id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization" id "org.jetbrains.kotlin.plugin.serialization"
id "application" id "application"
id "com.google.devtools.ksp"
} }
apply from: "$mppJvmJsLinuxMingwProjectPresetPath" apply from: "$mppJvmJsLinuxMingwProjectPresetPath"
@@ -11,6 +12,7 @@ kotlin {
commonMain { commonMain {
dependencies { dependencies {
api internalProject("micro_utils.startup.plugin") api internalProject("micro_utils.startup.plugin")
api internalProject("micro_utils.koin")
} }
} }
commonTest { commonTest {
@@ -29,3 +31,10 @@ java {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8
} }
dependencies {
add("kspCommonMainMetadata", project(":micro_utils.koin.generator"))
}
ksp {
}

View File

@@ -0,0 +1,38 @@
// THIS CODE HAVE BEEN GENERATED AUTOMATICALLY
// TO REGENERATE IT JUST DELETE FILE
// ORIGINAL FILE: StartLauncherPlugin.kt
package dev.inmo.micro_utils.startup.launcher
import kotlin.Boolean
import kotlinx.serialization.json.Json
import org.koin.core.Koin
import org.koin.core.definition.Definition
import org.koin.core.definition.KoinDefinition
import org.koin.core.module.Module
import org.koin.core.qualifier.named
import org.koin.core.scope.Scope
/**
* @return Definition by key "baseJsonProvider"
*/
public val Scope.baseJsonProvider: Json?
get() = getOrNull(named("baseJsonProvider"))
/**
* @return Definition by key "baseJsonProvider"
*/
public val Koin.baseJsonProvider: Json?
get() = getOrNull(named("baseJsonProvider"))
/**
* Will register [definition] with [org.koin.core.module.Module.single] and key "baseJsonProvider"
*/
public fun Module.baseJsonProviderSingle(createdAtStart: Boolean = false, definition: Definition<Json>):
KoinDefinition<Json> = single(named("baseJsonProvider"), createdAtStart = createdAtStart, definition
= definition)
/**
* Will register [definition] with [org.koin.core.module.Module.factory] and key "baseJsonProvider"
*/
public fun Module.baseJsonProviderFactory(definition: Definition<Json>): KoinDefinition<Json> =
factory(named("baseJsonProvider"), definition = definition)

View File

@@ -1,9 +1,11 @@
@file:GenerateKoinDefinition("baseJsonProvider", Json::class)
package dev.inmo.micro_utils.startup.launcher package dev.inmo.micro_utils.startup.launcher
import dev.inmo.kslog.common.i import dev.inmo.kslog.common.i
import dev.inmo.kslog.common.taggedLogger import dev.inmo.kslog.common.taggedLogger
import dev.inmo.kslog.common.w import dev.inmo.kslog.common.w
import dev.inmo.micro_utils.coroutines.runCatchingSafely import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.micro_utils.koin.annotations.GenerateKoinDefinition
import dev.inmo.micro_utils.startup.launcher.StartLauncherPlugin.setupDI import dev.inmo.micro_utils.startup.launcher.StartLauncherPlugin.setupDI
import dev.inmo.micro_utils.startup.launcher.StartLauncherPlugin.startPlugin import dev.inmo.micro_utils.startup.launcher.StartLauncherPlugin.startPlugin
import dev.inmo.micro_utils.startup.plugin.StartPlugin import dev.inmo.micro_utils.startup.plugin.StartPlugin
@@ -13,9 +15,10 @@ import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.serialization.SerialFormat import kotlinx.serialization.SerialFormat
import kotlinx.serialization.StringFormat import kotlinx.serialization.StringFormat
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.modules.SerializersModule
import org.koin.core.Koin import org.koin.core.Koin
import org.koin.core.KoinApplication import org.koin.core.KoinApplication
import org.koin.core.context.startKoin import org.koin.core.context.startKoin
@@ -35,7 +38,20 @@ object StartLauncherPlugin : StartPlugin {
single { rawJsonObject } single { rawJsonObject }
single { config } single { config }
single { CoroutineScope(Dispatchers.Default) } single { CoroutineScope(Dispatchers.Default) }
single { defaultJson } binds arrayOf(StringFormat::class, SerialFormat::class) single {
val serializersModules = getAll<SerializersModule>().distinct()
val baseJson = baseJsonProvider ?: defaultJson
if (serializersModules.isEmpty()) {
baseJson
} else {
Json(baseJson) {
serializersModule = SerializersModule {
include(baseJson.serializersModule)
serializersModules.forEach { include(it) }
}
}
}
} binds arrayOf(StringFormat::class, SerialFormat::class)
includes( includes(
config.plugins.mapNotNull { config.plugins.mapNotNull {

View File

@@ -0,0 +1,11 @@
def isNonStable = { String version ->
def stableKeyword = ['RELEASE', 'FINAL', 'GA'].any { it -> version.toUpperCase().contains(it) }
def regex = /^[0-9,.v-]+(-r)?$/
return !stableKeyword && !(version ==~ regex)
}
tasks.named("dependencyUpdates").configure {
rejectVersionIf {
isNonStable(it.candidate.version)
}
}