From db34b25ef220cf60e84e2372f01a3b03f9685bbb Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 10 Feb 2025 13:35:52 +0600 Subject: [PATCH 01/14] start 0.24.6 --- CHANGELOG.md | 2 ++ gradle.properties | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9174de96bf5..831a7edcf00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +## 0.24.6 + ## 0.24.5 * `Versions`: diff --git a/gradle.properties b/gradle.properties index 3f6658a13df..ce1fb86fb78 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,5 +15,5 @@ crypto_js_version=4.1.1 # Project data group=dev.inmo -version=0.24.5 -android_code_version=285 +version=0.24.6 +android_code_version=286 From f807f2beeb38b83fcff3cabfd29de3b1058b37ea Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Tue, 11 Feb 2025 13:50:58 +0600 Subject: [PATCH 02/14] start add variations generator --- .../src/main/kotlin/FilesWorkaround.kt | 12 +- ksp/variations/build.gradle | 7 + ksp/variations/generator/build.gradle | 21 +++ .../generator/src/main/kotlin/Processor.kt | 148 ++++++++++++++++++ .../generator/src/main/kotlin/Provider.kt | 11 ++ ...ols.ksp.processing.SymbolProcessorProvider | 1 + ksp/variations/generator/test/build.gradle | 27 ++++ .../test/src/commonMain/kotlin/SampleFun.kt | 16 ++ .../commonMain/kotlin/GenerateVariations.kt | 7 + .../commonMain/kotlin/GenerationVariant.kt | 13 ++ settings.gradle | 4 + 11 files changed, 263 insertions(+), 4 deletions(-) create mode 100644 ksp/variations/build.gradle create mode 100644 ksp/variations/generator/build.gradle create mode 100644 ksp/variations/generator/src/main/kotlin/Processor.kt create mode 100644 ksp/variations/generator/src/main/kotlin/Provider.kt create mode 100644 ksp/variations/generator/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider create mode 100644 ksp/variations/generator/test/build.gradle create mode 100644 ksp/variations/generator/test/src/commonMain/kotlin/SampleFun.kt create mode 100644 ksp/variations/src/commonMain/kotlin/GenerateVariations.kt create mode 100644 ksp/variations/src/commonMain/kotlin/GenerationVariant.kt diff --git a/ksp/generator/src/main/kotlin/FilesWorkaround.kt b/ksp/generator/src/main/kotlin/FilesWorkaround.kt index 17bbabc22b4..2dedf08884e 100644 --- a/ksp/generator/src/main/kotlin/FilesWorkaround.kt +++ b/ksp/generator/src/main/kotlin/FilesWorkaround.kt @@ -1,11 +1,13 @@ package dev.inmo.micro_ksp.generator import com.google.devtools.ksp.symbol.KSClassDeclaration +import com.google.devtools.ksp.symbol.KSDeclaration import com.google.devtools.ksp.symbol.KSFile +import com.google.devtools.ksp.symbol.KSFunctionDeclaration import com.squareup.kotlinpoet.FileSpec import java.io.File -fun KSClassDeclaration.writeFile( +fun KSDeclaration.writeFile( prefix: String = "", suffix: String = "", relatedPath: String = "", @@ -21,8 +23,9 @@ fun KSClassDeclaration.writeFile( "$prefix${simpleName.asString()}$suffix.kt" ).takeIf { force || !it.exists() } ?.apply { parentFile.mkdirs() + val fileSpec = fileSpecBuilder() writer().use { writer -> - fileSpecBuilder().writeTo(writer) + fileSpec.writeTo(writer) } } } @@ -42,8 +45,9 @@ fun KSFile.writeFile( "$prefix${fileName.dropLastWhile { it != '.' }.removeSuffix(".")}$suffix.kt" ).takeIf { force || !it.exists() } ?.apply { parentFile.mkdirs() + val fileSpec = fileSpecBuilder() writer().use { writer -> - fileSpecBuilder().writeTo(writer) + fileSpec.writeTo(writer) } } -} \ No newline at end of file +} diff --git a/ksp/variations/build.gradle b/ksp/variations/build.gradle new file mode 100644 index 00000000000..9e169e84113 --- /dev/null +++ b/ksp/variations/build.gradle @@ -0,0 +1,7 @@ +plugins { + id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.kotlin.plugin.serialization" + id "com.android.library" +} + +apply from: "$mppJvmJsAndroidLinuxMingwLinuxArm64Project" diff --git a/ksp/variations/generator/build.gradle b/ksp/variations/generator/build.gradle new file mode 100644 index 00000000000..c951b3a648a --- /dev/null +++ b/ksp/variations/generator/build.gradle @@ -0,0 +1,21 @@ +plugins { + id "org.jetbrains.kotlin.jvm" +} + +apply from: "$publish_jvm" + +repositories { + mavenCentral() +} + +dependencies { + api project(":micro_utils.ksp.generator") + api project(":micro_utils.ksp.variations") + api libs.kotlin.poet + api libs.ksp +} + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} diff --git a/ksp/variations/generator/src/main/kotlin/Processor.kt b/ksp/variations/generator/src/main/kotlin/Processor.kt new file mode 100644 index 00000000000..f62b0fd1410 --- /dev/null +++ b/ksp/variations/generator/src/main/kotlin/Processor.kt @@ -0,0 +1,148 @@ +package dev.inmo.micro_utils.ksp.variations.generator + +import com.google.devtools.ksp.KspExperimental +import com.google.devtools.ksp.getAnnotationsByType +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.* +import com.squareup.kotlinpoet.* +import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy +import com.squareup.kotlinpoet.ksp.toClassName +import com.squareup.kotlinpoet.ksp.toKModifier +import com.squareup.kotlinpoet.ksp.toTypeName +import dev.inmo.micro_ksp.generator.companion +import dev.inmo.micro_ksp.generator.findSubClasses +import dev.inmo.micro_ksp.generator.writeFile +import dev.inmo.micro_utils.ksp.variations.GenerateVariations +import dev.inmo.micro_utils.ksp.variations.GenerationVariant + +class Processor( + private val codeGenerator: CodeGenerator +) : SymbolProcessor { + private fun KSClassDeclaration.findSealedConnection(potentialSealedParent: KSClassDeclaration): Boolean { + val targetClassname = potentialSealedParent.qualifiedName ?.asString() + return superTypes.any { + val itAsDeclaration = it.resolve().declaration as? KSClassDeclaration ?: return@any false + targetClassname == (itAsDeclaration.qualifiedName ?.asString()) || (itAsDeclaration.getSealedSubclasses().any() && itAsDeclaration.findSealedConnection(potentialSealedParent)) + } + } + + private fun KSClassDeclaration.resolveSubclasses( + searchIn: Sequence, + allowNonSealed: Boolean + ): Sequence { + return findSubClasses(searchIn).let { + if (allowNonSealed) { + it + } else { + it.filter { + it.findSealedConnection(this) + } + } + } + } + + @OptIn(KspExperimental::class) + private fun FileSpec.Builder.generateVariations( + ksFunctionDeclaration: KSFunctionDeclaration, + resolver: Resolver + ) { + val annotation = ksFunctionDeclaration.getAnnotationsByType(GenerateVariations::class).first() + val variations: List, KSValueParameter>> = ksFunctionDeclaration.parameters.mapNotNull { + val variationAnnotations = it.getAnnotationsByType(GenerationVariant::class).toList().ifEmpty { return@mapNotNull null } + variationAnnotations to it + } + val accumulatedGenerations = mutableSetOf() + variations.forEach { (variations, parameter) -> + if (accumulatedGenerations.isEmpty()) { + variations.forEach { variation -> + accumulatedGenerations.add( + FunSpec.builder(ksFunctionDeclaration.simpleName.asString()).apply { + modifiers.addAll(ksFunctionDeclaration.modifiers.mapNotNull { it.toKModifier() }) + ksFunctionDeclaration.parameters.forEach { + parameters.add( + (if (it == parameter) { + ParameterSpec + .builder( + variation.argName, + if (variation.varargTypes.isEmpty()) { + variation.type.asTypeName() + } else { + variation.type.parameterizedBy(*variation.varargTypes) + } + ) + .apply { + val name = it.name ?.asString() ?: "this" + if (it.isVararg) { + defaultValue( + """ + *$name.map { it.${variation.conversion} }.toTypedArray() + """.trimIndent() + ) + } else { + defaultValue("$name.${variation.conversion}") + } + } + } else { + ParameterSpec + .builder( + it.name ?.asString() ?: return@forEach, + it.type.toTypeName(), + ) + }) + .apply { + if (it.isCrossInline) { + addModifiers(KModifier.CROSSINLINE) + } + if (it.isVal) { + addModifiers(KModifier.VALUE) + } + if (it.isNoInline) { + addModifiers(KModifier.NOINLINE) + } + if (it.isVararg) { + addModifiers(KModifier.VARARG) + } + } + .build() + ) + } + }.build() + ) + } + } else { + + } + } + accumulatedGenerations.forEach { + addFunction(it) + } + } + + @OptIn(KspExperimental::class) + override fun process(resolver: Resolver): List { + (resolver.getSymbolsWithAnnotation(GenerateVariations::class.qualifiedName!!)).filterIsInstance().forEach { + val prefix = (it.getAnnotationsByType(GenerateVariations::class)).firstOrNull() ?.prefix ?.takeIf { + it.isNotEmpty() + } ?: it.simpleName.asString().replaceFirst(it.simpleName.asString(), "") + it.writeFile(prefix = prefix, suffix = "GeneratedVariation") { + FileSpec.builder( + it.packageName.asString(), + "${it.simpleName.getShortName()}GeneratedVariation" + ).apply { + addFileComment( + """ + THIS CODE HAVE BEEN GENERATED AUTOMATICALLY + TO REGENERATE IT JUST DELETE FILE + ORIGINAL FILE: ${it.containingFile ?.fileName} + """.trimIndent() + ) + generateVariations(it, resolver) + }.build() + } + } + + return emptyList() + } +} diff --git a/ksp/variations/generator/src/main/kotlin/Provider.kt b/ksp/variations/generator/src/main/kotlin/Provider.kt new file mode 100644 index 00000000000..e3721a6b7d0 --- /dev/null +++ b/ksp/variations/generator/src/main/kotlin/Provider.kt @@ -0,0 +1,11 @@ +package dev.inmo.micro_utils.ksp.variations.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 + ) +} diff --git a/ksp/variations/generator/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider b/ksp/variations/generator/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider new file mode 100644 index 00000000000..443f688865d --- /dev/null +++ b/ksp/variations/generator/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider @@ -0,0 +1 @@ +dev.inmo.micro_utils.ksp.variations.generator.Provider diff --git a/ksp/variations/generator/test/build.gradle b/ksp/variations/generator/test/build.gradle new file mode 100644 index 00000000000..f95f5c7bf64 --- /dev/null +++ b/ksp/variations/generator/test/build.gradle @@ -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: "$mppJvmJsAndroidLinuxMingwLinuxArm64Project" + + +kotlin { + sourceSets { + commonMain { + dependencies { + api project(":micro_utils.ksp.variations") + } + } + } +} + + +dependencies { + add("kspCommonMainMetadata", project(":micro_utils.ksp.variations.generator")) +} + +ksp { +} diff --git a/ksp/variations/generator/test/src/commonMain/kotlin/SampleFun.kt b/ksp/variations/generator/test/src/commonMain/kotlin/SampleFun.kt new file mode 100644 index 00000000000..60d0b9e3da0 --- /dev/null +++ b/ksp/variations/generator/test/src/commonMain/kotlin/SampleFun.kt @@ -0,0 +1,16 @@ +import dev.inmo.micro_utils.ksp.variations.GenerateVariations +import dev.inmo.micro_utils.ksp.variations.GenerationVariant + +data class Sample( + val value: String +) + +@GenerateVariations +fun sample( + @GenerationVariant( + "example", + Sample::class, + "value" + ) + example: String = "12" +) = println(example) diff --git a/ksp/variations/src/commonMain/kotlin/GenerateVariations.kt b/ksp/variations/src/commonMain/kotlin/GenerateVariations.kt new file mode 100644 index 00000000000..91122da4bee --- /dev/null +++ b/ksp/variations/src/commonMain/kotlin/GenerateVariations.kt @@ -0,0 +1,7 @@ +package dev.inmo.micro_utils.ksp.variations + +@Retention(AnnotationRetention.BINARY) +@Target(AnnotationTarget.FUNCTION) +annotation class GenerateVariations( + val prefix: String = "" +) diff --git a/ksp/variations/src/commonMain/kotlin/GenerationVariant.kt b/ksp/variations/src/commonMain/kotlin/GenerationVariant.kt new file mode 100644 index 00000000000..93628ece414 --- /dev/null +++ b/ksp/variations/src/commonMain/kotlin/GenerationVariant.kt @@ -0,0 +1,13 @@ +package dev.inmo.micro_utils.ksp.variations + +import kotlin.reflect.KClass + +@Retention(AnnotationRetention.BINARY) +@Repeatable +@Target(AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.VALUE_PARAMETER) +annotation class GenerationVariant( + val argName: String, + val type: KClass<*>, + val conversion: String, + vararg val varargTypes: KClass<*> +) diff --git a/settings.gradle b/settings.gradle index 3c8ea281c61..6379141d8cb 100644 --- a/settings.gradle +++ b/settings.gradle @@ -62,6 +62,10 @@ String[] includes = [ ":ksp:classcasts:generator", ":ksp:classcasts:generator:test", + ":ksp:variations", + ":ksp:variations:generator", + ":ksp:variations:generator:test", + ":dokka" ] From a5008c3d1543125cfe44ead9639ee09b396fe9bd Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 12 Feb 2025 12:20:22 +0600 Subject: [PATCH 03/14] first version of parameters variations --- .../generator/src/main/kotlin/Processor.kt | 222 ++++++++++++++---- .../test/src/commonMain/kotlin/SampleFun.kt | 19 +- .../commonMain/kotlin/GenerationVariant.kt | 2 +- 3 files changed, 199 insertions(+), 44 deletions(-) diff --git a/ksp/variations/generator/src/main/kotlin/Processor.kt b/ksp/variations/generator/src/main/kotlin/Processor.kt index f62b0fd1410..aa8c68569bc 100644 --- a/ksp/variations/generator/src/main/kotlin/Processor.kt +++ b/ksp/variations/generator/src/main/kotlin/Processor.kt @@ -8,14 +8,13 @@ import com.google.devtools.ksp.processing.SymbolProcessor import com.google.devtools.ksp.symbol.* import com.squareup.kotlinpoet.* import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy -import com.squareup.kotlinpoet.ksp.toClassName import com.squareup.kotlinpoet.ksp.toKModifier import com.squareup.kotlinpoet.ksp.toTypeName -import dev.inmo.micro_ksp.generator.companion import dev.inmo.micro_ksp.generator.findSubClasses import dev.inmo.micro_ksp.generator.writeFile import dev.inmo.micro_utils.ksp.variations.GenerateVariations import dev.inmo.micro_utils.ksp.variations.GenerationVariant +import kotlin.math.pow class Processor( private val codeGenerator: CodeGenerator @@ -50,73 +49,212 @@ class Processor( ) { val annotation = ksFunctionDeclaration.getAnnotationsByType(GenerateVariations::class).first() val variations: List, KSValueParameter>> = ksFunctionDeclaration.parameters.mapNotNull { - val variationAnnotations = it.getAnnotationsByType(GenerationVariant::class).toList().ifEmpty { return@mapNotNull null } + val variationAnnotations = it.getAnnotationsByType(GenerationVariant::class).toList() variationAnnotations to it } - val accumulatedGenerations = mutableSetOf() + val accumulatedGenerations = mutableSetOf>>() + val baseFunctionParameters = ksFunctionDeclaration.parameters.mapNotNull { + ParameterSpec + .builder( + it.name ?.asString() ?: return@mapNotNull null, + it.type.toTypeName(), + ) + .apply { + if (it.isCrossInline) { + addModifiers(KModifier.CROSSINLINE) + } + if (it.isVal) { + addModifiers(KModifier.VALUE) + } + if (it.isNoInline) { + addModifiers(KModifier.NOINLINE) + } + if (it.isVararg) { + addModifiers(KModifier.VARARG) + } + } + .build() to it.hasDefault + } + val baseFunctionFunSpecs = mutableListOf>>() + let { + var defaultParametersIndicator = 0u + val maxIndicator = baseFunctionParameters.filter { it.second }.foldIndexed(0u) { index, acc, _ -> + 2.0.pow(index).toUInt() + acc + } + while (defaultParametersIndicator <= maxIndicator) { + var currentDefaultParameterIndex = 0u + val baseFunctionDefaults = mutableMapOf() + val funSpec = FunSpec.builder(ksFunctionDeclaration.simpleName.asString()).apply { + modifiers.addAll(ksFunctionDeclaration.modifiers.mapNotNull { it.toKModifier() }) + ksFunctionDeclaration.extensionReceiver ?.let { + receiver(it.toTypeName()) + } + } + baseFunctionParameters.forEach { (parameter, hasDefault) -> + if (hasDefault) { + val shouldBeIncluded = (2.0.pow(currentDefaultParameterIndex.toInt()).toUInt()).and(defaultParametersIndicator) > 0u + currentDefaultParameterIndex++ + + if (!shouldBeIncluded) { + return@forEach + } + } + funSpec.addParameter(parameter) + val name = parameter.name + val defaultValueString = if (parameter.modifiers.contains(KModifier.VARARG)) { + "*$name" + } else { + "$name" + } + baseFunctionDefaults[parameter.name] = defaultValueString + } + baseFunctionFunSpecs.add( + funSpec.build() to baseFunctionDefaults.toMap() + ) + defaultParametersIndicator++ + } + } variations.forEach { (variations, parameter) -> - if (accumulatedGenerations.isEmpty()) { + (baseFunctionFunSpecs + accumulatedGenerations).forEach { (accumulatedGeneration, baseDefaults) -> + if ((parameter.name ?.asString() ?: "this") !in baseDefaults.keys) { + return@forEach + } variations.forEach { variation -> + val defaults = mutableMapOf() accumulatedGenerations.add( - FunSpec.builder(ksFunctionDeclaration.simpleName.asString()).apply { - modifiers.addAll(ksFunctionDeclaration.modifiers.mapNotNull { it.toKModifier() }) - ksFunctionDeclaration.parameters.forEach { + FunSpec.builder(accumulatedGeneration.name).apply { + modifiers.addAll(accumulatedGeneration.modifiers) + accumulatedGeneration.receiverType ?.let { + receiver(it) + } + accumulatedGeneration.parameters.forEach { parameters.add( - (if (it == parameter) { + (if (it.name == (parameter.name ?.asString() ?: "this")) { ParameterSpec .builder( variation.argName, if (variation.varargTypes.isEmpty()) { - variation.type.asTypeName() + ClassName.bestGuess(variation.type) } else { - variation.type.parameterizedBy(*variation.varargTypes) + ClassName.bestGuess(variation.type).parameterizedBy( + *variation.varargTypes.map { it.asTypeName() }.toTypedArray() + ) } ) .apply { - val name = it.name ?.asString() ?: "this" - if (it.isVararg) { - defaultValue( - """ - *$name.map { it.${variation.conversion} }.toTypedArray() - """.trimIndent() - ) + val defaultValueString = if (it.modifiers.contains(KModifier.VARARG)) { + """ + *${variation.argName}.map { it.${variation.conversion} }.toTypedArray() + """.trimIndent() } else { - defaultValue("$name.${variation.conversion}") + "${variation.argName}.${variation.conversion}" } + defaults[it.name] = defaultValueString } } else { - ParameterSpec - .builder( - it.name ?.asString() ?: return@forEach, - it.type.toTypeName(), - ) + it.toBuilder() }) - .apply { - if (it.isCrossInline) { - addModifiers(KModifier.CROSSINLINE) - } - if (it.isVal) { - addModifiers(KModifier.VALUE) - } - if (it.isNoInline) { - addModifiers(KModifier.NOINLINE) - } - if (it.isVararg) { - addModifiers(KModifier.VARARG) - } - } .build() ) } - }.build() + val parameters = accumulatedGeneration.parameters.joinToString(", ") { + val itName = it.name + """ + $itName = ${defaults[itName] ?: baseDefaults[itName] ?: itName} + """.trimIndent() + } + addCode( + """ + return ${ksFunctionDeclaration.simpleName.asString()}( + $parameters + ) + """.trimIndent() + ) + }.build() to defaults.toMap() ) } - } else { - } +// if (accumulatedGenerations.isEmpty()) { +// variations.forEach { variation -> +// val defaults = mutableMapOf() +// accumulatedGenerations.add( +// FunSpec.builder(ksFunctionDeclaration.simpleName.asString()).apply { +// modifiers.addAll(ksFunctionDeclaration.modifiers.mapNotNull { it.toKModifier() }) +// ksFunctionDeclaration.extensionReceiver ?.let { +// receiver(it.toTypeName()) +// } +// ksFunctionDeclaration.parameters.forEach { +// parameters.add( +// (if (it == parameter) { +// ParameterSpec +// .builder( +// variation.argName, +// if (variation.varargTypes.isEmpty()) { +// ClassName.bestGuess(variation.type) +// } else { +// ClassName.bestGuess(variation.type).parameterizedBy( +// *variation.varargTypes.map { it.asTypeName() }.toTypedArray() +// ) +// } +// ) +// } else { +// ParameterSpec +// .builder( +// it.name ?.asString() ?: return@forEach, +// it.type.toTypeName(), +// ) +// }) +// .apply { +// if (it.isCrossInline) { +// addModifiers(KModifier.CROSSINLINE) +// } +// if (it.isVal) { +// addModifiers(KModifier.VALUE) +// } +// if (it.isNoInline) { +// addModifiers(KModifier.NOINLINE) +// } +// if (it.isVararg) { +// addModifiers(KModifier.VARARG) +// } +// } +// .build() +// .apply { +// val name = it.name ?.asString() ?: "this" +// val defaultValueString = if (it.isVararg) { +// """ +// *$name.map { it.${variation.conversion} }.toTypedArray() +// """.trimIndent() +// } else { +// "$name.${variation.conversion}" +// } +// defaults[this.name] = defaultValueString +// } +// ) +// } +// val parameters = ksFunctionDeclaration.parameters.joinToString(", ") { +// val itName = it.name ?.asString() ?: "this" +// """ +// $itName = ${defaults[itName] ?: itName} +// """.trimIndent() +// } +// addCode( +// """ +// return ${ksFunctionDeclaration.simpleName.asString()}( +// $parameters +// ) +// """.trimIndent() +// ) +// }.build() to defaults.toMap() +// ) +// } +// } else { +// val reusingGenerations = accumulatedGenerations.toList() +// reusingGenerations +// } } accumulatedGenerations.forEach { - addFunction(it) + addFunction(it.first) } } diff --git a/ksp/variations/generator/test/src/commonMain/kotlin/SampleFun.kt b/ksp/variations/generator/test/src/commonMain/kotlin/SampleFun.kt index 60d0b9e3da0..73d367f45df 100644 --- a/ksp/variations/generator/test/src/commonMain/kotlin/SampleFun.kt +++ b/ksp/variations/generator/test/src/commonMain/kotlin/SampleFun.kt @@ -9,8 +9,25 @@ data class Sample( fun sample( @GenerationVariant( "example", - Sample::class, + "Sample", "value" ) example: String = "12" ) = println(example) + +@GenerateVariations +suspend fun Sample.sample2( + @GenerationVariant( + "arg12", + "kotlin.Int", + "toString()" + ) + arg1: String = "1", + @GenerationVariant( + "arg22", + "kotlin.String", + "toInt()" + ) + arg2: Int = 2, + arg3: Boolean = false +) = println(arg1) diff --git a/ksp/variations/src/commonMain/kotlin/GenerationVariant.kt b/ksp/variations/src/commonMain/kotlin/GenerationVariant.kt index 93628ece414..e0fc5b3eb60 100644 --- a/ksp/variations/src/commonMain/kotlin/GenerationVariant.kt +++ b/ksp/variations/src/commonMain/kotlin/GenerationVariant.kt @@ -7,7 +7,7 @@ import kotlin.reflect.KClass @Target(AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.VALUE_PARAMETER) annotation class GenerationVariant( val argName: String, - val type: KClass<*>, + val type: String, val conversion: String, vararg val varargTypes: KClass<*> ) From 99783f281dada1bacadbed7e68550973b169e26e Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 12 Feb 2025 12:37:08 +0600 Subject: [PATCH 04/14] generate sample functions --- .../kotlin/sample2GeneratedVariation.kt | 47 +++++++++++++++++++ .../kotlin/sampleGeneratedVariation.kt | 8 ++++ 2 files changed, 55 insertions(+) create mode 100644 ksp/variations/generator/test/src/commonMain/kotlin/sample2GeneratedVariation.kt create mode 100644 ksp/variations/generator/test/src/commonMain/kotlin/sampleGeneratedVariation.kt diff --git a/ksp/variations/generator/test/src/commonMain/kotlin/sample2GeneratedVariation.kt b/ksp/variations/generator/test/src/commonMain/kotlin/sample2GeneratedVariation.kt new file mode 100644 index 00000000000..7bd0934753c --- /dev/null +++ b/ksp/variations/generator/test/src/commonMain/kotlin/sample2GeneratedVariation.kt @@ -0,0 +1,47 @@ +// THIS CODE HAVE BEEN GENERATED AUTOMATICALLY +// TO REGENERATE IT JUST DELETE FILE +// ORIGINAL FILE: SampleFun.kt +import kotlin.Boolean +import kotlin.Int +import kotlin.String +import kotlin.Unit + +public suspend fun Sample.sample2(arg12: Int): Unit = sample2( + arg1 = arg12.toString() +) + +public suspend fun Sample.sample2(arg12: Int, arg2: Int): Unit = sample2( + arg1 = arg12.toString(), arg2 = arg2 +) + +public suspend fun Sample.sample2(arg12: Int, arg3: Boolean): Unit = sample2( + arg1 = arg12.toString(), arg3 = arg3 +) + +public suspend fun Sample.sample2( + arg12: Int, + arg2: Int, + arg3: Boolean, +): Unit = sample2( + arg1 = arg12.toString(), arg2 = arg2, arg3 = arg3 +) + +public suspend fun Sample.sample2(arg22: String): Unit = sample2( + arg2 = arg22.toInt() +) + +public suspend fun Sample.sample2(arg1: String, arg22: String): Unit = sample2( + arg1 = arg1, arg2 = arg22.toInt() +) + +public suspend fun Sample.sample2(arg22: String, arg3: Boolean): Unit = sample2( + arg2 = arg22.toInt(), arg3 = arg3 +) + +public suspend fun Sample.sample2( + arg1: String, + arg22: String, + arg3: Boolean, +): Unit = sample2( + arg1 = arg1, arg2 = arg22.toInt(), arg3 = arg3 +) diff --git a/ksp/variations/generator/test/src/commonMain/kotlin/sampleGeneratedVariation.kt b/ksp/variations/generator/test/src/commonMain/kotlin/sampleGeneratedVariation.kt new file mode 100644 index 00000000000..c0e3f2100f1 --- /dev/null +++ b/ksp/variations/generator/test/src/commonMain/kotlin/sampleGeneratedVariation.kt @@ -0,0 +1,8 @@ +// THIS CODE HAVE BEEN GENERATED AUTOMATICALLY +// TO REGENERATE IT JUST DELETE FILE +// ORIGINAL FILE: SampleFun.kt +import kotlin.Unit + +public fun sample(example: Sample): Unit = sample( + example = example.value +) From 5c28255e06dae3637b15d90c8384d1a13fdc3e66 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 12 Feb 2025 14:32:14 +0600 Subject: [PATCH 05/14] fixes for generics --- .../src/main/kotlin/KClassWorkarounds.kt | 25 ++++ ksp/variations/generator/build.gradle | 1 + .../generator/src/main/kotlin/Processor.kt | 112 ++++-------------- ksp/variations/generator/test/build.gradle | 1 + .../test/src/commonMain/kotlin/SampleFun.kt | 37 ++++-- .../kotlin/sample2GeneratedVariation.kt | 34 +++--- .../kotlin/sampleGeneratedVariation.kt | 11 +- .../kotlin/sampleVarargGeneratedVariation.kt | 10 ++ .../commonMain/kotlin/GenerationVariant.kt | 11 +- 9 files changed, 122 insertions(+), 120 deletions(-) create mode 100644 ksp/generator/src/main/kotlin/KClassWorkarounds.kt create mode 100644 ksp/variations/generator/test/src/commonMain/kotlin/sampleVarargGeneratedVariation.kt diff --git a/ksp/generator/src/main/kotlin/KClassWorkarounds.kt b/ksp/generator/src/main/kotlin/KClassWorkarounds.kt new file mode 100644 index 00000000000..c3dd6304e47 --- /dev/null +++ b/ksp/generator/src/main/kotlin/KClassWorkarounds.kt @@ -0,0 +1,25 @@ +package dev.inmo.micro_ksp.generator + +import com.google.devtools.ksp.KSTypeNotPresentException +import com.google.devtools.ksp.KSTypesNotPresentException +import com.google.devtools.ksp.KspExperimental +import com.google.devtools.ksp.symbol.KSType +import com.squareup.kotlinpoet.asClassName +import com.squareup.kotlinpoet.ksp.toClassName +import kotlin.reflect.KClass + +@OptIn(KspExperimental::class) +inline fun convertToClassName(getter: () -> KClass<*>) = try { + getter().asClassName() +} catch (e: KSTypeNotPresentException) { + e.ksType.toClassName() +} + +@OptIn(KspExperimental::class) +inline fun convertToClassNames(getter: () -> List>) = try { + getter().map { it.asClassName() } +} catch (e: KSTypesNotPresentException) { + e.ksTypes.map { + it.toClassName() + } +} diff --git a/ksp/variations/generator/build.gradle b/ksp/variations/generator/build.gradle index c951b3a648a..4e4e2e1436d 100644 --- a/ksp/variations/generator/build.gradle +++ b/ksp/variations/generator/build.gradle @@ -9,6 +9,7 @@ repositories { } dependencies { + implementation libs.kt.stdlib api project(":micro_utils.ksp.generator") api project(":micro_utils.ksp.variations") api libs.kotlin.poet diff --git a/ksp/variations/generator/src/main/kotlin/Processor.kt b/ksp/variations/generator/src/main/kotlin/Processor.kt index aa8c68569bc..43305fa14ef 100644 --- a/ksp/variations/generator/src/main/kotlin/Processor.kt +++ b/ksp/variations/generator/src/main/kotlin/Processor.kt @@ -1,5 +1,6 @@ package dev.inmo.micro_utils.ksp.variations.generator +import com.google.devtools.ksp.KSTypeNotPresentException import com.google.devtools.ksp.KspExperimental import com.google.devtools.ksp.getAnnotationsByType import com.google.devtools.ksp.processing.CodeGenerator @@ -8,8 +9,11 @@ import com.google.devtools.ksp.processing.SymbolProcessor import com.google.devtools.ksp.symbol.* import com.squareup.kotlinpoet.* import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy +import com.squareup.kotlinpoet.ksp.toClassName import com.squareup.kotlinpoet.ksp.toKModifier import com.squareup.kotlinpoet.ksp.toTypeName +import dev.inmo.micro_ksp.generator.convertToClassName +import dev.inmo.micro_ksp.generator.convertToClassNames import dev.inmo.micro_ksp.generator.findSubClasses import dev.inmo.micro_ksp.generator.writeFile import dev.inmo.micro_utils.ksp.variations.GenerateVariations @@ -128,27 +132,33 @@ class Processor( receiver(it) } accumulatedGeneration.parameters.forEach { + val actualName = if (variation.argName.isEmpty()) it.name else variation.argName parameters.add( (if (it.name == (parameter.name ?.asString() ?: "this")) { + val type = convertToClassName { variation.type } + val genericTypes = convertToClassNames { variation.genericTypes.toList() } ParameterSpec .builder( - variation.argName, - if (variation.varargTypes.isEmpty()) { - ClassName.bestGuess(variation.type) + actualName, + if (genericTypes.isEmpty()) { + type } else { - ClassName.bestGuess(variation.type).parameterizedBy( - *variation.varargTypes.map { it.asTypeName() }.toTypedArray() + type.parameterizedBy( + *genericTypes.toTypedArray() ) } ) .apply { - val defaultValueString = if (it.modifiers.contains(KModifier.VARARG)) { - """ - *${variation.argName}.map { it.${variation.conversion} }.toTypedArray() - """.trimIndent() - } else { - "${variation.argName}.${variation.conversion}" - } + addModifiers(it.modifiers) + val defaultValueString = """ + with(${actualName}) {${ + if (it.modifiers.contains(KModifier.VARARG)) { + "map { it.${variation.conversion} }.toTypedArray()" + } else { + "${variation.conversion}" + } + }} + """.trimIndent() defaults[it.name] = defaultValueString } } else { @@ -174,84 +184,6 @@ class Processor( ) } } -// if (accumulatedGenerations.isEmpty()) { -// variations.forEach { variation -> -// val defaults = mutableMapOf() -// accumulatedGenerations.add( -// FunSpec.builder(ksFunctionDeclaration.simpleName.asString()).apply { -// modifiers.addAll(ksFunctionDeclaration.modifiers.mapNotNull { it.toKModifier() }) -// ksFunctionDeclaration.extensionReceiver ?.let { -// receiver(it.toTypeName()) -// } -// ksFunctionDeclaration.parameters.forEach { -// parameters.add( -// (if (it == parameter) { -// ParameterSpec -// .builder( -// variation.argName, -// if (variation.varargTypes.isEmpty()) { -// ClassName.bestGuess(variation.type) -// } else { -// ClassName.bestGuess(variation.type).parameterizedBy( -// *variation.varargTypes.map { it.asTypeName() }.toTypedArray() -// ) -// } -// ) -// } else { -// ParameterSpec -// .builder( -// it.name ?.asString() ?: return@forEach, -// it.type.toTypeName(), -// ) -// }) -// .apply { -// if (it.isCrossInline) { -// addModifiers(KModifier.CROSSINLINE) -// } -// if (it.isVal) { -// addModifiers(KModifier.VALUE) -// } -// if (it.isNoInline) { -// addModifiers(KModifier.NOINLINE) -// } -// if (it.isVararg) { -// addModifiers(KModifier.VARARG) -// } -// } -// .build() -// .apply { -// val name = it.name ?.asString() ?: "this" -// val defaultValueString = if (it.isVararg) { -// """ -// *$name.map { it.${variation.conversion} }.toTypedArray() -// """.trimIndent() -// } else { -// "$name.${variation.conversion}" -// } -// defaults[this.name] = defaultValueString -// } -// ) -// } -// val parameters = ksFunctionDeclaration.parameters.joinToString(", ") { -// val itName = it.name ?.asString() ?: "this" -// """ -// $itName = ${defaults[itName] ?: itName} -// """.trimIndent() -// } -// addCode( -// """ -// return ${ksFunctionDeclaration.simpleName.asString()}( -// $parameters -// ) -// """.trimIndent() -// ) -// }.build() to defaults.toMap() -// ) -// } -// } else { -// val reusingGenerations = accumulatedGenerations.toList() -// reusingGenerations -// } } accumulatedGenerations.forEach { addFunction(it.first) diff --git a/ksp/variations/generator/test/build.gradle b/ksp/variations/generator/test/build.gradle index f95f5c7bf64..01cd2b96d53 100644 --- a/ksp/variations/generator/test/build.gradle +++ b/ksp/variations/generator/test/build.gradle @@ -12,6 +12,7 @@ kotlin { sourceSets { commonMain { dependencies { + implementation libs.kt.stdlib api project(":micro_utils.ksp.variations") } } diff --git a/ksp/variations/generator/test/src/commonMain/kotlin/SampleFun.kt b/ksp/variations/generator/test/src/commonMain/kotlin/SampleFun.kt index 73d367f45df..d3a6f87a2dc 100644 --- a/ksp/variations/generator/test/src/commonMain/kotlin/SampleFun.kt +++ b/ksp/variations/generator/test/src/commonMain/kotlin/SampleFun.kt @@ -1,32 +1,51 @@ +package dev.inmo.micro_utils.ksp.variations.generator.test + import dev.inmo.micro_utils.ksp.variations.GenerateVariations import dev.inmo.micro_utils.ksp.variations.GenerationVariant -data class Sample( +data class SimpleType( val value: String ) +data class GenericType( + val value: T +) + @GenerateVariations fun sample( @GenerationVariant( - "example", - "Sample", - "value" + SimpleType::class, + "value", + ) + @GenerationVariant( + GenericType::class, + "value.toString()", + genericTypes = arrayOf(Int::class) ) example: String = "12" ) = println(example) @GenerateVariations -suspend fun Sample.sample2( +fun sampleVararg( @GenerationVariant( + SimpleType::class, + "value", + ) + vararg example: String = arrayOf("12") +) = println(example.joinToString()) + +@GenerateVariations +suspend fun SimpleType.sample2( + @GenerationVariant( + Int::class, + "toString()", "arg12", - "kotlin.Int", - "toString()" ) arg1: String = "1", @GenerationVariant( + String::class, + "toInt()", "arg22", - "kotlin.String", - "toInt()" ) arg2: Int = 2, arg3: Boolean = false diff --git a/ksp/variations/generator/test/src/commonMain/kotlin/sample2GeneratedVariation.kt b/ksp/variations/generator/test/src/commonMain/kotlin/sample2GeneratedVariation.kt index 7bd0934753c..95623116d1f 100644 --- a/ksp/variations/generator/test/src/commonMain/kotlin/sample2GeneratedVariation.kt +++ b/ksp/variations/generator/test/src/commonMain/kotlin/sample2GeneratedVariation.kt @@ -1,47 +1,49 @@ // THIS CODE HAVE BEEN GENERATED AUTOMATICALLY // TO REGENERATE IT JUST DELETE FILE // ORIGINAL FILE: SampleFun.kt +package dev.inmo.micro_utils.ksp.variations.generator.test + import kotlin.Boolean import kotlin.Int import kotlin.String import kotlin.Unit -public suspend fun Sample.sample2(arg12: Int): Unit = sample2( - arg1 = arg12.toString() +public suspend fun SimpleType.sample2(arg12: Int): Unit = sample2( + arg1 = with(arg12) {toString()} ) -public suspend fun Sample.sample2(arg12: Int, arg2: Int): Unit = sample2( - arg1 = arg12.toString(), arg2 = arg2 +public suspend fun SimpleType.sample2(arg12: Int, arg2: Int): Unit = sample2( + arg1 = with(arg12) {toString()}, arg2 = arg2 ) -public suspend fun Sample.sample2(arg12: Int, arg3: Boolean): Unit = sample2( - arg1 = arg12.toString(), arg3 = arg3 +public suspend fun SimpleType.sample2(arg12: Int, arg3: Boolean): Unit = sample2( + arg1 = with(arg12) {toString()}, arg3 = arg3 ) -public suspend fun Sample.sample2( +public suspend fun SimpleType.sample2( arg12: Int, arg2: Int, arg3: Boolean, ): Unit = sample2( - arg1 = arg12.toString(), arg2 = arg2, arg3 = arg3 + arg1 = with(arg12) {toString()}, arg2 = arg2, arg3 = arg3 ) -public suspend fun Sample.sample2(arg22: String): Unit = sample2( - arg2 = arg22.toInt() +public suspend fun SimpleType.sample2(arg22: String): Unit = sample2( + arg2 = with(arg22) {toInt()} ) -public suspend fun Sample.sample2(arg1: String, arg22: String): Unit = sample2( - arg1 = arg1, arg2 = arg22.toInt() +public suspend fun SimpleType.sample2(arg1: String, arg22: String): Unit = sample2( + arg1 = arg1, arg2 = with(arg22) {toInt()} ) -public suspend fun Sample.sample2(arg22: String, arg3: Boolean): Unit = sample2( - arg2 = arg22.toInt(), arg3 = arg3 +public suspend fun SimpleType.sample2(arg22: String, arg3: Boolean): Unit = sample2( + arg2 = with(arg22) {toInt()}, arg3 = arg3 ) -public suspend fun Sample.sample2( +public suspend fun SimpleType.sample2( arg1: String, arg22: String, arg3: Boolean, ): Unit = sample2( - arg1 = arg1, arg2 = arg22.toInt(), arg3 = arg3 + arg1 = arg1, arg2 = with(arg22) {toInt()}, arg3 = arg3 ) diff --git a/ksp/variations/generator/test/src/commonMain/kotlin/sampleGeneratedVariation.kt b/ksp/variations/generator/test/src/commonMain/kotlin/sampleGeneratedVariation.kt index c0e3f2100f1..01a2fb497f1 100644 --- a/ksp/variations/generator/test/src/commonMain/kotlin/sampleGeneratedVariation.kt +++ b/ksp/variations/generator/test/src/commonMain/kotlin/sampleGeneratedVariation.kt @@ -1,8 +1,15 @@ // THIS CODE HAVE BEEN GENERATED AUTOMATICALLY // TO REGENERATE IT JUST DELETE FILE // ORIGINAL FILE: SampleFun.kt +package dev.inmo.micro_utils.ksp.variations.generator.test + +import kotlin.Int import kotlin.Unit -public fun sample(example: Sample): Unit = sample( - example = example.value +public fun sample(example: SimpleType): Unit = sample( + example = with(example) {value} +) + +public fun sample(example: GenericType): Unit = sample( + example = with(example) {value.toString()} ) diff --git a/ksp/variations/generator/test/src/commonMain/kotlin/sampleVarargGeneratedVariation.kt b/ksp/variations/generator/test/src/commonMain/kotlin/sampleVarargGeneratedVariation.kt new file mode 100644 index 00000000000..c79ce7b866a --- /dev/null +++ b/ksp/variations/generator/test/src/commonMain/kotlin/sampleVarargGeneratedVariation.kt @@ -0,0 +1,10 @@ +// THIS CODE HAVE BEEN GENERATED AUTOMATICALLY +// TO REGENERATE IT JUST DELETE FILE +// ORIGINAL FILE: SampleFun.kt +package dev.inmo.micro_utils.ksp.variations.generator.test + +import kotlin.Unit + +public fun sampleVararg(vararg example: SimpleType): Unit = sampleVararg( + example = with(example) {map { it.value }.toTypedArray()} +) diff --git a/ksp/variations/src/commonMain/kotlin/GenerationVariant.kt b/ksp/variations/src/commonMain/kotlin/GenerationVariant.kt index e0fc5b3eb60..da9130f089f 100644 --- a/ksp/variations/src/commonMain/kotlin/GenerationVariant.kt +++ b/ksp/variations/src/commonMain/kotlin/GenerationVariant.kt @@ -2,12 +2,17 @@ package dev.inmo.micro_utils.ksp.variations import kotlin.reflect.KClass +/** + * @param argName New argument name. Default - empty - means "use default arg name" + * @param type Qualified class name, like "dev.inmo.micro_utils.ksp.variants.GenerationVariant" + * @param conversion Conversion string with `this` + */ @Retention(AnnotationRetention.BINARY) @Repeatable @Target(AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.VALUE_PARAMETER) annotation class GenerationVariant( - val argName: String, - val type: String, + val type: KClass<*>, val conversion: String, - vararg val varargTypes: KClass<*> + val argName: String = "", + vararg val genericTypes: KClass<*> ) From 07ad79f0b38ffe2b2137a8d689cdcf88fd1c4f58 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 12 Feb 2025 21:19:40 +0600 Subject: [PATCH 06/14] add including of annotations from source function on variation generation --- ksp/variations/generator/src/main/kotlin/Processor.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ksp/variations/generator/src/main/kotlin/Processor.kt b/ksp/variations/generator/src/main/kotlin/Processor.kt index 43305fa14ef..60869f4088f 100644 --- a/ksp/variations/generator/src/main/kotlin/Processor.kt +++ b/ksp/variations/generator/src/main/kotlin/Processor.kt @@ -9,6 +9,7 @@ import com.google.devtools.ksp.processing.SymbolProcessor import com.google.devtools.ksp.symbol.* import com.squareup.kotlinpoet.* import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy +import com.squareup.kotlinpoet.ksp.toAnnotationSpec import com.squareup.kotlinpoet.ksp.toClassName import com.squareup.kotlinpoet.ksp.toKModifier import com.squareup.kotlinpoet.ksp.toTypeName @@ -90,6 +91,9 @@ class Processor( val baseFunctionDefaults = mutableMapOf() val funSpec = FunSpec.builder(ksFunctionDeclaration.simpleName.asString()).apply { modifiers.addAll(ksFunctionDeclaration.modifiers.mapNotNull { it.toKModifier() }) + ksFunctionDeclaration.annotations.forEach { + addAnnotation(it.toAnnotationSpec(omitDefaultValues = false)) + } ksFunctionDeclaration.extensionReceiver ?.let { receiver(it.toTypeName()) } From 74563bbac9d95f7b727d9c7cf5e41ebdb0131db0 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 12 Feb 2025 21:20:14 +0600 Subject: [PATCH 07/14] small hotfix --- ksp/variations/generator/src/main/kotlin/Processor.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ksp/variations/generator/src/main/kotlin/Processor.kt b/ksp/variations/generator/src/main/kotlin/Processor.kt index 60869f4088f..3c0a0bc1bc1 100644 --- a/ksp/variations/generator/src/main/kotlin/Processor.kt +++ b/ksp/variations/generator/src/main/kotlin/Processor.kt @@ -132,6 +132,9 @@ class Processor( accumulatedGenerations.add( FunSpec.builder(accumulatedGeneration.name).apply { modifiers.addAll(accumulatedGeneration.modifiers) + accumulatedGeneration.annotations.forEach { + addAnnotation(it) + } accumulatedGeneration.receiverType ?.let { receiver(it) } From b81af7e1c84c4dbff2e0b5c7c0cf057bc7d89cd9 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 13 Feb 2025 09:09:01 +0600 Subject: [PATCH 08/14] fill changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 831a7edcf00..a39e69b0fe4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## 0.24.6 +* `KSP`: + * `Variations`: + * Module has been created + ## 0.24.5 * `Versions`: From 9a20e8155e60b4908e35003076b38ab0e1f9e141 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 13 Feb 2025 10:33:40 +0600 Subject: [PATCH 09/14] update dependnecies --- CHANGELOG.md | 5 ++++ gradle/libs.versions.toml | 13 +++++----- .../micro_utils/pagination/QueryExtensions.kt | 24 +++++++++---------- .../exposed/AbstractExposedWriteCRUDRepo.kt | 2 +- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a39e69b0fe4..96dac96f7d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## 0.24.6 +* `Versions`: + * `KSLog`: `1.4.0` -> `1.4.1` + * `Exposed`: `0.58.0` -> `0.59.0` + * `SQLite`: `3.48.0.0` -> `3.49.0.0` + * `AndroidFragment`: `1.8.5` -> `1.8.6` * `KSP`: * `Variations`: * Module has been created diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 02579471e68..acaede35437 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,18 +4,18 @@ kt = "2.1.10" kt-serialization = "1.8.0" kt-coroutines = "1.10.1" -kslog = "1.4.0" +kslog = "1.4.1" jb-compose = "1.7.3" -jb-exposed = "0.58.0" +jb-exposed = "0.59.0" jb-dokka = "2.0.0" -sqlite = "3.48.0.0" +sqlite = "3.49.0.0" korlibs = "5.4.0" uuid = "0.8.4" -ktor = "3.0.3" +ktor = "3.1.0" gh-release = "2.5.2" @@ -28,16 +28,15 @@ kotlin-poet = "1.18.1" versions = "0.51.0" -android-gradle = "8.2.2" +android-gradle = "8.7.+" dexcount = "4.0.0" android-coreKtx = "1.15.0" android-recyclerView = "1.4.0" android-appCompat = "1.7.0" -android-fragment = "1.8.5" +android-fragment = "1.8.6" android-espresso = "3.6.1" android-test = "1.2.1" -android-compose-material3 = "1.3.0" android-props-minSdk = "21" android-props-compileSdk = "35" diff --git a/pagination/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/pagination/QueryExtensions.kt b/pagination/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/pagination/QueryExtensions.kt index 616c28e0b7b..f16fb6dcbcb 100644 --- a/pagination/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/pagination/QueryExtensions.kt +++ b/pagination/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/pagination/QueryExtensions.kt @@ -2,19 +2,19 @@ package dev.inmo.micro_utils.pagination import org.jetbrains.exposed.sql.* -fun Query.paginate(with: Pagination, orderBy: Pair, SortOrder>? = null) = limit( - with.size, - with.firstIndex.toLong() -).let { - if (orderBy != null) { - it.orderBy( - orderBy.first, - orderBy.second - ) - } else { - it +fun Query.paginate(with: Pagination, orderBy: Pair, SortOrder>? = null) = + limit(with.size) + .offset(with.firstIndex.toLong()) + .let { + if (orderBy != null) { + it.orderBy( + orderBy.first, + orderBy.second + ) + } else { + it + } } -} fun Query.paginate(with: Pagination, orderBy: Expression<*>?, reversed: Boolean = false) = paginate( with, diff --git a/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/AbstractExposedWriteCRUDRepo.kt b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/AbstractExposedWriteCRUDRepo.kt index 6126720eb93..c1450e972f3 100644 --- a/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/AbstractExposedWriteCRUDRepo.kt +++ b/repos/exposed/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/exposed/AbstractExposedWriteCRUDRepo.kt @@ -137,7 +137,7 @@ abstract class AbstractExposedWriteCRUDRepo( override suspend fun deleteById(ids: List) { onBeforeDelete(ids) transaction(db = database) { - val deleted = deleteWhere(null, null) { selectByIds(it, ids) } + val deleted = deleteWhere { selectByIds(it, ids) } if (deleted == ids.size) { ids } else { From af286d3d53083aa7ddc2256631a739a62014e659 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 13 Feb 2025 11:04:25 +0600 Subject: [PATCH 10/14] add disabling of publishing for ksp test modules --- gradle/templates/publish.gradle | 34 ++++++++++++---------- ksp/classcasts/generator/test/build.gradle | 2 ++ ksp/sealed/generator/test/build.gradle | 2 ++ ksp/variations/generator/test/build.gradle | 2 ++ 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/gradle/templates/publish.gradle b/gradle/templates/publish.gradle index 740b6a4542f..e71a7ba4309 100644 --- a/gradle/templates/publish.gradle +++ b/gradle/templates/publish.gradle @@ -1,3 +1,7 @@ +if (ext.getProperties()["do_publish"] == false) { + return +} + apply plugin: 'maven-publish' task javadocsJar(type: Jar) { @@ -19,29 +23,29 @@ publishing { } developers { - + developer { id = "InsanusMokrassar" name = "Aleksei Ovsiannikov" email = "ovsyannikov.alexey95@gmail.com" } - + developer { id = "000Sanya" name = "Syrov Aleksandr" email = "000sanya.000sanya@gmail.com" } - + } licenses { - + license { name = "Apache Software License 2.0" url = "https://github.com/InsanusMokrassar/MicroUtils/blob/master/LICENSE" } - + } } repositories { @@ -49,51 +53,51 @@ publishing { maven { name = "GithubPackages" url = uri("https://maven.pkg.github.com/InsanusMokrassar/MicroUtils") - + credentials { username = project.hasProperty('GITHUBPACKAGES_USER') ? project.property('GITHUBPACKAGES_USER') : System.getenv('GITHUBPACKAGES_USER') password = project.hasProperty('GITHUBPACKAGES_PASSWORD') ? project.property('GITHUBPACKAGES_PASSWORD') : System.getenv('GITHUBPACKAGES_PASSWORD') } - + } } if ((project.hasProperty('INMONEXUS_USER') || System.getenv('INMONEXUS_USER') != null) && (project.hasProperty('INMONEXUS_PASSWORD') || System.getenv('INMONEXUS_PASSWORD') != null)) { maven { name = "InmoNexus" url = uri("https://nexus.inmo.dev/repository/maven-releases/") - + credentials { username = project.hasProperty('INMONEXUS_USER') ? project.property('INMONEXUS_USER') : System.getenv('INMONEXUS_USER') password = project.hasProperty('INMONEXUS_PASSWORD') ? project.property('INMONEXUS_PASSWORD') : System.getenv('INMONEXUS_PASSWORD') } - + } } if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) { maven { name = "sonatype" url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/") - + credentials { username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER') password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD') } - + } } } } } - + if (project.hasProperty("signing.gnupg.keyName")) { apply plugin: 'signing' - + signing { useGpgCmd() - + sign publishing.publications } - + task signAll { tasks.withType(Sign).forEach { dependsOn(it) diff --git a/ksp/classcasts/generator/test/build.gradle b/ksp/classcasts/generator/test/build.gradle index fb0690103e3..4f6203b4006 100644 --- a/ksp/classcasts/generator/test/build.gradle +++ b/ksp/classcasts/generator/test/build.gradle @@ -5,6 +5,8 @@ plugins { id "com.google.devtools.ksp" } +ext.do_publish = false + apply from: "$mppJvmJsAndroidLinuxMingwLinuxArm64Project" diff --git a/ksp/sealed/generator/test/build.gradle b/ksp/sealed/generator/test/build.gradle index 9bb06ae1fd8..24de402973e 100644 --- a/ksp/sealed/generator/test/build.gradle +++ b/ksp/sealed/generator/test/build.gradle @@ -5,6 +5,8 @@ plugins { id "com.google.devtools.ksp" } +ext.do_publish = false + apply from: "$mppJvmJsAndroidLinuxMingwLinuxArm64Project" diff --git a/ksp/variations/generator/test/build.gradle b/ksp/variations/generator/test/build.gradle index 01cd2b96d53..b610e624073 100644 --- a/ksp/variations/generator/test/build.gradle +++ b/ksp/variations/generator/test/build.gradle @@ -5,6 +5,8 @@ plugins { id "com.google.devtools.ksp" } +ext.do_publish = false + apply from: "$mppJvmJsAndroidLinuxMingwLinuxArm64Project" From f7a9f2e13d71f25ca252f435577c55c8a2a28708 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 13 Feb 2025 12:13:15 +0600 Subject: [PATCH 11/14] fixes and forcing uppercase for new files --- .../src/main/kotlin/FilesWorkaround.kt | 9 +++++++- .../generator/src/main/kotlin/Processor.kt | 22 +++++++++++++++++-- ...iation.kt => Sample2GeneratedVariation.kt} | 12 ++++++++++ ...riation.kt => SampleGeneratedVariation.kt} | 0 ...n.kt => SampleVarargGeneratedVariation.kt} | 0 5 files changed, 40 insertions(+), 3 deletions(-) rename ksp/variations/generator/test/src/commonMain/kotlin/{sample2GeneratedVariation.kt => Sample2GeneratedVariation.kt} (81%) rename ksp/variations/generator/test/src/commonMain/kotlin/{sampleGeneratedVariation.kt => SampleGeneratedVariation.kt} (100%) rename ksp/variations/generator/test/src/commonMain/kotlin/{sampleVarargGeneratedVariation.kt => SampleVarargGeneratedVariation.kt} (100%) diff --git a/ksp/generator/src/main/kotlin/FilesWorkaround.kt b/ksp/generator/src/main/kotlin/FilesWorkaround.kt index 2dedf08884e..31d8d180e76 100644 --- a/ksp/generator/src/main/kotlin/FilesWorkaround.kt +++ b/ksp/generator/src/main/kotlin/FilesWorkaround.kt @@ -12,15 +12,22 @@ fun KSDeclaration.writeFile( suffix: String = "", relatedPath: String = "", force: Boolean = false, + forceUppercase: Boolean = true, fileSpecBuilder: () -> FileSpec ) { val containingFile = containingFile!! + val simpleName = if (forceUppercase) { + val rawSimpleName = simpleName.asString() + rawSimpleName.replaceFirst(rawSimpleName.first().toString(), rawSimpleName.first().uppercase()) + } else { + simpleName.asString() + } File( File( File(containingFile.filePath).parent, relatedPath ), - "$prefix${simpleName.asString()}$suffix.kt" + "$prefix${simpleName}$suffix.kt" ).takeIf { force || !it.exists() } ?.apply { parentFile.mkdirs() val fileSpec = fileSpecBuilder() diff --git a/ksp/variations/generator/src/main/kotlin/Processor.kt b/ksp/variations/generator/src/main/kotlin/Processor.kt index 3c0a0bc1bc1..59d8ad6bc5e 100644 --- a/ksp/variations/generator/src/main/kotlin/Processor.kt +++ b/ksp/variations/generator/src/main/kotlin/Processor.kt @@ -77,6 +77,11 @@ class Processor( if (it.isVararg) { addModifiers(KModifier.VARARG) } + it.annotations.forEach { + if (it.shortName.asString() == GenerationVariant::class.simpleName) return@forEach + + addAnnotation(it.toAnnotationSpec(omitDefaultValues = false)) + } } .build() to it.hasDefault } @@ -92,11 +97,16 @@ class Processor( val funSpec = FunSpec.builder(ksFunctionDeclaration.simpleName.asString()).apply { modifiers.addAll(ksFunctionDeclaration.modifiers.mapNotNull { it.toKModifier() }) ksFunctionDeclaration.annotations.forEach { + if (it.shortName.asString() == GenerateVariations::class.simpleName) return@forEach + addAnnotation(it.toAnnotationSpec(omitDefaultValues = false)) } ksFunctionDeclaration.extensionReceiver ?.let { receiver(it.toTypeName()) } + ksFunctionDeclaration.returnType ?.let { + returns(it.toTypeName()) + } } baseFunctionParameters.forEach { (parameter, hasDefault) -> if (hasDefault) { @@ -138,6 +148,7 @@ class Processor( accumulatedGeneration.receiverType ?.let { receiver(it) } + returns(accumulatedGeneration.returnType) accumulatedGeneration.parameters.forEach { val actualName = if (variation.argName.isEmpty()) it.name else variation.argName parameters.add( @@ -169,8 +180,15 @@ class Processor( defaults[it.name] = defaultValueString } } else { - it.toBuilder() + it.toBuilder().apply { + defaults[it.name] = it.name + } }) + .apply { + it.annotations.forEach { + addAnnotation(it) + } + } .build() ) } @@ -206,7 +224,7 @@ class Processor( it.writeFile(prefix = prefix, suffix = "GeneratedVariation") { FileSpec.builder( it.packageName.asString(), - "${it.simpleName.getShortName()}GeneratedVariation" + "${it.simpleName.getShortName().let { it.replaceFirst(it.first().toString(), it.first().uppercase()) }}GeneratedVariation" ).apply { addFileComment( """ diff --git a/ksp/variations/generator/test/src/commonMain/kotlin/sample2GeneratedVariation.kt b/ksp/variations/generator/test/src/commonMain/kotlin/Sample2GeneratedVariation.kt similarity index 81% rename from ksp/variations/generator/test/src/commonMain/kotlin/sample2GeneratedVariation.kt rename to ksp/variations/generator/test/src/commonMain/kotlin/Sample2GeneratedVariation.kt index 95623116d1f..6407b494f11 100644 --- a/ksp/variations/generator/test/src/commonMain/kotlin/sample2GeneratedVariation.kt +++ b/ksp/variations/generator/test/src/commonMain/kotlin/Sample2GeneratedVariation.kt @@ -47,3 +47,15 @@ public suspend fun SimpleType.sample2( ): Unit = sample2( arg1 = arg1, arg2 = with(arg22) {toInt()}, arg3 = arg3 ) + +public suspend fun SimpleType.sample2(arg12: Int, arg22: String): Unit = sample2( + arg12 = arg12, arg2 = with(arg22) {toInt()} +) + +public suspend fun SimpleType.sample2( + arg12: Int, + arg22: String, + arg3: Boolean, +): Unit = sample2( + arg12 = arg12, arg2 = with(arg22) {toInt()}, arg3 = arg3 +) diff --git a/ksp/variations/generator/test/src/commonMain/kotlin/sampleGeneratedVariation.kt b/ksp/variations/generator/test/src/commonMain/kotlin/SampleGeneratedVariation.kt similarity index 100% rename from ksp/variations/generator/test/src/commonMain/kotlin/sampleGeneratedVariation.kt rename to ksp/variations/generator/test/src/commonMain/kotlin/SampleGeneratedVariation.kt diff --git a/ksp/variations/generator/test/src/commonMain/kotlin/sampleVarargGeneratedVariation.kt b/ksp/variations/generator/test/src/commonMain/kotlin/SampleVarargGeneratedVariation.kt similarity index 100% rename from ksp/variations/generator/test/src/commonMain/kotlin/sampleVarargGeneratedVariation.kt rename to ksp/variations/generator/test/src/commonMain/kotlin/SampleVarargGeneratedVariation.kt From d8ca29eab1f2ae0d999d87197f3b3126b785d982 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 14 Feb 2025 12:37:40 +0600 Subject: [PATCH 12/14] start deprecation of safely functions --- coroutines/build.gradle | 1 + .../ContextSafelyExceptionHandler.kt | 2 +- .../micro_utils/coroutines/HandleSafely.kt | 39 +++++++++++++ .../micro_utils/coroutines/LaunchLogging.kt | 55 +++++++++++++++++++ .../micro_utils/coroutines/ReplaceResult.kt | 3 + 5 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/LaunchLogging.kt create mode 100644 coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/ReplaceResult.kt diff --git a/coroutines/build.gradle b/coroutines/build.gradle index 42c09d974c4..5b5d02e9f95 100644 --- a/coroutines/build.gradle +++ b/coroutines/build.gradle @@ -11,6 +11,7 @@ kotlin { commonMain { dependencies { api libs.kt.coroutines + api libs.kslog } } jsMain { diff --git a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/ContextSafelyExceptionHandler.kt b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/ContextSafelyExceptionHandler.kt index 140e59ae9e1..8e62a124087 100644 --- a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/ContextSafelyExceptionHandler.kt +++ b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/ContextSafelyExceptionHandler.kt @@ -41,4 +41,4 @@ class ContextSafelyExceptionHandler( ) : CoroutineContext.Element { override val key: CoroutineContext.Key<*> get() = ContextSafelyExceptionHandlerKey -} \ No newline at end of file +} diff --git a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/HandleSafely.kt b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/HandleSafely.kt index ce84e2c71fe..bd29880e3c7 100644 --- a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/HandleSafely.kt +++ b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/HandleSafely.kt @@ -15,6 +15,10 @@ import kotlin.coroutines.coroutineContext * * @return [Result] with result of [block] if no exceptions or [Result] from [onException] execution */ +@Deprecated( + "This function become redundant since coroutines correctly handling throwing exceptions", + replaceWith = ReplaceWith("runCatching(block).replaceIfFailure { onException(it) }") +) suspend inline fun runCatchingSafely( onException: ExceptionHandler, block: suspend () -> T @@ -29,6 +33,10 @@ suspend inline fun runCatchingSafely( } } +@Deprecated( + "This function become redundant since coroutines correctly handling throwing exceptions", + replaceWith = ReplaceWith("runCatching(block).replaceIfFailure { onException(it) }") +) suspend inline fun R.runCatchingSafely( onException: ExceptionHandler, block: suspend R.() -> T @@ -39,10 +47,18 @@ suspend inline fun R.runCatchingSafely( /** * Launching [runCatchingSafely] with [defaultSafelyExceptionHandler] as `onException` parameter */ +@Deprecated( + "This function become redundant since coroutines correctly handling throwing exceptions", + replaceWith = ReplaceWith("runCatching(block).replaceIfFailure { defaultSafelyExceptionHandler(it) }") +) suspend inline fun runCatchingSafely( block: suspend () -> T ): Result = runCatchingSafely(defaultSafelyExceptionHandler, block) +@Deprecated( + "This function become redundant since coroutines correctly handling throwing exceptions", + replaceWith = ReplaceWith("runCatching(block).replaceIfFailure { defaultSafelyExceptionHandler(it) }") +) suspend inline fun R.runCatchingSafely( block: suspend R.() -> T ): Result = runCatchingSafely { @@ -73,6 +89,9 @@ suspend fun contextSafelyExceptionHandler() = coroutineContext[ContextSafelyExce * After all, will be called [withContext] method with created [ContextSafelyExceptionHandler] and block which will call * [safely] method with [safelyExceptionHandler] as onException parameter and [block] as execution block */ +@Deprecated( + "This function become redundant since coroutines correctly handling throwing exceptions", +) suspend fun safelyWithContextExceptionHandler( contextExceptionHandler: ExceptionHandler, safelyExceptionHandler: ExceptionHandler = defaultSafelyExceptionHandler, @@ -94,6 +113,10 @@ suspend fun safelyWithContextExceptionHandler( * * @see runCatchingSafely */ +@Deprecated( + "This function become redundant since coroutines correctly handling throwing exceptions", + replaceWith = ReplaceWith("runCatching(block).replaceIfFailure { onException(it) }.getOrThrow()") +) suspend inline fun safely( onException: ExceptionHandler, block: suspend () -> T @@ -104,9 +127,17 @@ suspend inline fun safely( * * @see runCatchingSafely */ +@Deprecated( + "This function become redundant since coroutines correctly handling throwing exceptions", + replaceWith = ReplaceWith("runCatching(block).replaceIfFailure { defaultSafelyExceptionHandler(it) }.getOrThrow()") +) suspend inline fun safely( block: suspend () -> T ): T = safely(defaultSafelyExceptionHandler, block) +@Deprecated( + "This function become redundant since coroutines correctly handling throwing exceptions", + replaceWith = ReplaceWith("runCatching(block).replaceIfFailure { defaultSafelyExceptionHandler(it) }.getOrThrow()") +) suspend inline fun R.safely( block: suspend R.() -> T ): T = safely { block() } @@ -137,11 +168,19 @@ val defaultSafelyWithoutExceptionHandlerWithNull: ExceptionHandler = { * Shortcut for [safely] with exception handler, that as expected must return null in case of impossible creating of * result from exception (instead of throwing it, by default always returns null) */ +@Deprecated( + "This function become redundant since coroutines correctly handling throwing exceptions", + replaceWith = ReplaceWith("runCatching(block).replaceIfFailure { onException(it) }.getOrNull()") +) suspend fun safelyWithoutExceptions( onException: ExceptionHandler = defaultSafelyExceptionHandler, block: suspend () -> T ): T? = runCatchingSafely(onException, block).getOrNull() +@Deprecated( + "This function become redundant since coroutines correctly handling throwing exceptions", + replaceWith = ReplaceWith("runCatching(block).replaceIfFailure { onException(it) }.getOrNull()") +) suspend fun runCatchingSafelyWithoutExceptions( onException: ExceptionHandler = defaultSafelyExceptionHandler, block: suspend () -> T diff --git a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/LaunchLogging.kt b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/LaunchLogging.kt new file mode 100644 index 00000000000..86ec4a000e1 --- /dev/null +++ b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/LaunchLogging.kt @@ -0,0 +1,55 @@ +package dev.inmo.micro_utils.coroutines + +import dev.inmo.kslog.common.KSLog +import dev.inmo.kslog.common.e +import kotlinx.coroutines.* +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext + +fun CoroutineScope.launchLogging( + errorMessageBuilder: () -> Any = { "Something web wrong" }, + logger: KSLog = KSLog, + context: CoroutineContext = EmptyCoroutineContext, + start: CoroutineStart = CoroutineStart.DEFAULT, + block: suspend CoroutineScope.() -> Unit +) = launch(context, start) { + runCatching { block() }.onFailure { + logger.e(it, errorMessageBuilder) + }.getOrThrow() +} + +fun CoroutineScope.launchLoggingDropExceptions( + errorMessageBuilder: () -> Any = { "Something web wrong" }, + logger: KSLog = KSLog, + context: CoroutineContext = EmptyCoroutineContext, + start: CoroutineStart = CoroutineStart.DEFAULT, + block: suspend CoroutineScope.() -> Unit +) = launch(context, start) { + runCatching { block() }.onFailure { + logger.e(it, errorMessageBuilder) + } // just dropping exception +} + +fun CoroutineScope.asyncLogging( + errorMessageBuilder: () -> Any = { "Something web wrong" }, + logger: KSLog = KSLog, + context: CoroutineContext = EmptyCoroutineContext, + start: CoroutineStart = CoroutineStart.DEFAULT, + block: suspend CoroutineScope.() -> T +) = async(context, start) { + runCatching { block() }.onFailure { + logger.e(it, errorMessageBuilder) + }.getOrThrow() +} + +fun CoroutineScope.asyncLoggingDropExceptions( + errorMessageBuilder: () -> Any = { "Something web wrong" }, + logger: KSLog = KSLog, + context: CoroutineContext = EmptyCoroutineContext, + start: CoroutineStart = CoroutineStart.DEFAULT, + block: suspend CoroutineScope.() -> T +) = async(context, start) { + runCatching { block() }.onFailure { + logger.e(it, errorMessageBuilder) + } +} diff --git a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/ReplaceResult.kt b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/ReplaceResult.kt new file mode 100644 index 00000000000..a9629015e91 --- /dev/null +++ b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/ReplaceResult.kt @@ -0,0 +1,3 @@ +package dev.inmo.micro_utils.coroutines + +inline fun Result.replaceIfFailure(onException: (Throwable) -> T) = if (isSuccess) { this } else { runCatching { onException(exceptionOrNull()!!) } } From 4bfa4c32aa06110b5cf94746a113fbee8268d643 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 14 Feb 2025 13:16:14 +0600 Subject: [PATCH 13/14] fix of #541 --- .../coroutines/FlowSubscription.kt | 48 +++++++++++++++++++ .../coroutines/FlowSubscriptionAsync.kt | 2 +- .../micro_utils/coroutines/LaunchLogging.kt | 16 +++---- .../micro_utils/coroutines/LaunchSafely.kt | 16 +++++++ .../coroutines/RunCatchingLogging.kt | 12 +++++ .../micro_utils/fsm/common/StatesMachine.kt | 8 ++-- .../ktor/client/ActualTemporalUpload.kt | 4 +- .../ktor/client/ActualUniUpload.kt | 4 +- .../TemporalFilesRoutingConfigurator.kt | 4 +- .../repos/cache/full/FullCRUDCacheRepo.kt | 4 +- .../repos/cache/full/FullKeyValueCacheRepo.kt | 4 +- .../cache/full/FullKeyValuesCacheRepo.kt | 4 +- .../full/direct/DirectFullCRUDCacheRepo.kt | 4 +- .../direct/DirectFullKeyValueCacheRepo.kt | 4 +- .../direct/DirectFullKeyValuesCacheRepo.kt | 4 +- 15 files changed, 108 insertions(+), 30 deletions(-) create mode 100644 coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/RunCatchingLogging.kt diff --git a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/FlowSubscription.kt b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/FlowSubscription.kt index fddcc64ac4d..47bd4e1ceaa 100644 --- a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/FlowSubscription.kt +++ b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/FlowSubscription.kt @@ -2,6 +2,7 @@ package dev.inmo.micro_utils.coroutines +import dev.inmo.kslog.common.KSLog import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.* import kotlinx.coroutines.sync.Mutex @@ -16,6 +17,45 @@ inline fun Flow.subscribe(scope: CoroutineScope, noinline block: suspend * Use [subscribe], but all [block]s will be called inside of [safely] function. * Use [onException] to set up your reaction for [Throwable]s */ +inline fun Flow.subscribeLogging( + scope: CoroutineScope, + noinline errorMessageBuilder: T.(Throwable) -> Any = { "Something web wrong" }, + logger: KSLog = KSLog, + noinline block: suspend (T) -> Unit +) = subscribe(scope) { + it.runCatchingLogging( + errorMessageBuilder, + logger + ) { + block(it) + }.getOrThrow() +} + +/** + * Use [subscribeSafelyWithoutExceptions], but all exceptions will be passed to [defaultSafelyExceptionHandler] + */ +inline fun Flow.subscribeLoggingDropExceptions( + scope: CoroutineScope, + noinline errorMessageBuilder: T.(Throwable) -> Any = { "Something web wrong" }, + logger: KSLog = KSLog, + noinline block: suspend (T) -> Unit +) = subscribe(scope) { + it.runCatchingLogging( + errorMessageBuilder, + logger + ) { + block(it) + } +} + +/** + * Use [subscribe], but all [block]s will be called inside of [safely] function. + * Use [onException] to set up your reaction for [Throwable]s + */ +@Deprecated( + "Will be removed soon due to replacement by subscribeLogging", + ReplaceWith("this.subscribeLogging(scope = scope, block = block)") +) inline fun Flow.subscribeSafely( scope: CoroutineScope, noinline onException: ExceptionHandler = defaultSafelyExceptionHandler, @@ -29,6 +69,10 @@ inline fun Flow.subscribeSafely( /** * Use [subscribeSafelyWithoutExceptions], but all exceptions will be passed to [defaultSafelyExceptionHandler] */ +@Deprecated( + "Will be removed soon due to replacement by subscribeLoggingDropExceptions", + ReplaceWith("this.subscribeLoggingDropExceptions(scope = scope, block = block)") +) inline fun Flow.subscribeSafelyWithoutExceptions( scope: CoroutineScope, noinline onException: ExceptionHandler = defaultSafelyWithoutExceptionHandlerWithNull, @@ -42,6 +86,10 @@ inline fun Flow.subscribeSafelyWithoutExceptions( /** * Use [subscribeSafelyWithoutExceptions], but all exceptions inside of [safely] will be skipped */ +@Deprecated( + "Will be removed soon due to replacement by subscribeLoggingDropExceptions", + ReplaceWith("this.subscribeLoggingDropExceptions(scope = scope, block = block)") +) inline fun Flow.subscribeSafelySkippingExceptions( scope: CoroutineScope, noinline block: suspend (T) -> Unit diff --git a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/FlowSubscriptionAsync.kt b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/FlowSubscriptionAsync.kt index 5a8bea14a88..667bba39c3f 100644 --- a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/FlowSubscriptionAsync.kt +++ b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/FlowSubscriptionAsync.kt @@ -15,7 +15,7 @@ private class SubscribeAsyncReceiver( get() = dataChannel init { - scope.launchSafelyWithoutExceptions { + scope.launchLoggingDropExceptions { for (data in dataChannel) { output(data) } diff --git a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/LaunchLogging.kt b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/LaunchLogging.kt index 86ec4a000e1..4409e84f620 100644 --- a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/LaunchLogging.kt +++ b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/LaunchLogging.kt @@ -7,49 +7,49 @@ import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext fun CoroutineScope.launchLogging( - errorMessageBuilder: () -> Any = { "Something web wrong" }, + errorMessageBuilder: CoroutineScope.(Throwable) -> Any = { "Something web wrong" }, logger: KSLog = KSLog, context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> Unit ) = launch(context, start) { runCatching { block() }.onFailure { - logger.e(it, errorMessageBuilder) + logger.e(it) { errorMessageBuilder(it) } }.getOrThrow() } fun CoroutineScope.launchLoggingDropExceptions( - errorMessageBuilder: () -> Any = { "Something web wrong" }, + errorMessageBuilder: CoroutineScope.(Throwable) -> Any = { "Something web wrong" }, logger: KSLog = KSLog, context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> Unit ) = launch(context, start) { runCatching { block() }.onFailure { - logger.e(it, errorMessageBuilder) + logger.e(it) { errorMessageBuilder(it) } } // just dropping exception } fun CoroutineScope.asyncLogging( - errorMessageBuilder: () -> Any = { "Something web wrong" }, + errorMessageBuilder: CoroutineScope.(Throwable) -> Any = { "Something web wrong" }, logger: KSLog = KSLog, context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> T ) = async(context, start) { runCatching { block() }.onFailure { - logger.e(it, errorMessageBuilder) + logger.e(it) { errorMessageBuilder(it) } }.getOrThrow() } fun CoroutineScope.asyncLoggingDropExceptions( - errorMessageBuilder: () -> Any = { "Something web wrong" }, + errorMessageBuilder: CoroutineScope.(Throwable) -> Any = { "Something web wrong" }, logger: KSLog = KSLog, context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> T ) = async(context, start) { runCatching { block() }.onFailure { - logger.e(it, errorMessageBuilder) + logger.e(it) { errorMessageBuilder(it) } } } diff --git a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/LaunchSafely.kt b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/LaunchSafely.kt index 13583d2c622..155e2df47ac 100644 --- a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/LaunchSafely.kt +++ b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/LaunchSafely.kt @@ -4,6 +4,10 @@ import kotlinx.coroutines.* import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext +@Deprecated( + "This method will be removed soon. Use launchLogging instead", + ReplaceWith("this.launchLogging(context = context, start = start, block = block)") +) fun CoroutineScope.launchSafely( context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, @@ -15,6 +19,10 @@ fun CoroutineScope.launchSafely( } } +@Deprecated( + "This method will be removed soon. Use launchLoggingDropExceptions instead", + ReplaceWith("this.launchLoggingDropExceptions(context = context, start = start, block = block)") +) fun CoroutineScope.launchSafelyWithoutExceptions( context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, @@ -26,6 +34,10 @@ fun CoroutineScope.launchSafelyWithoutExceptions( } } +@Deprecated( + "This method will be removed soon. Use asyncLogging instead", + ReplaceWith("this.asyncLogging(context = context, start = start, block = block)") +) fun CoroutineScope.asyncSafely( context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, @@ -37,6 +49,10 @@ fun CoroutineScope.asyncSafely( } } +@Deprecated( + "This method will be removed soon. Use asyncLoggingDropExceptions instead", + ReplaceWith("this.asyncLoggingDropExceptions(context = context, start = start, block = block)") +) fun CoroutineScope.asyncSafelyWithoutExceptions( context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, diff --git a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/RunCatchingLogging.kt b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/RunCatchingLogging.kt new file mode 100644 index 00000000000..7dc9239cd03 --- /dev/null +++ b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/RunCatchingLogging.kt @@ -0,0 +1,12 @@ +package dev.inmo.micro_utils.coroutines + +import dev.inmo.kslog.common.KSLog +import dev.inmo.kslog.common.e + +inline fun R.runCatchingLogging( + noinline errorMessageBuilder: R.(Throwable) -> Any = { "Something web wrong" }, + logger: KSLog = KSLog, + block: R.() -> T +) = runCatching(block).onFailure { + logger.e(it) { errorMessageBuilder(it) } +} diff --git a/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/StatesMachine.kt b/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/StatesMachine.kt index a395137f40e..a6b7eaf8518 100644 --- a/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/StatesMachine.kt +++ b/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/StatesMachine.kt @@ -128,8 +128,10 @@ open class DefaultStatesMachine ( */ override fun start(scope: CoroutineScope): Job { val supervisorScope = scope.LinkedSupervisorScope() - supervisorScope.launchSafelyWithoutExceptions { - (statesManager.getActiveStates().asFlow() + statesManager.onStartChain).subscribeSafelyWithoutExceptions(supervisorScope) { + supervisorScope.launchLoggingDropExceptions { + (statesManager.getActiveStates().asFlow() + statesManager.onStartChain).subscribeSafelyWithoutExceptions( + supervisorScope + ) { supervisorScope.launch { performStateUpdate(Optional.absent(), it, supervisorScope) } } statesManager.onChainStateUpdated.subscribeSafelyWithoutExceptions(supervisorScope) { @@ -140,7 +142,7 @@ open class DefaultStatesMachine ( statesJobsMutex.withLock { val stateInMap = statesJobs.keys.firstOrNull { stateInMap -> stateInMap == removedState } if (stateInMap === removedState) { - statesJobs[stateInMap] ?.cancel() + statesJobs[stateInMap]?.cancel() } } } diff --git a/ktor/client/src/jsMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualTemporalUpload.kt b/ktor/client/src/jsMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualTemporalUpload.kt index 74c34e3414a..0f6a6989ec0 100644 --- a/ktor/client/src/jsMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualTemporalUpload.kt +++ b/ktor/client/src/jsMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualTemporalUpload.kt @@ -2,7 +2,7 @@ package dev.inmo.micro_utils.ktor.client import dev.inmo.micro_utils.common.MPPFile import dev.inmo.micro_utils.coroutines.LinkedSupervisorJob -import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions +import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions import dev.inmo.micro_utils.ktor.common.TemporalFileId import io.ktor.client.HttpClient import io.ktor.client.content.* @@ -27,7 +27,7 @@ suspend fun tempUpload( val request = XMLHttpRequest() request.responseType = XMLHttpRequestResponseType.TEXT request.upload.onprogress = { - subscope.launchSafelyWithoutExceptions { onUpload.onProgress(it.loaded.toLong(), it.total.toLong()) } + subscope.launchLoggingDropExceptions { onUpload.onProgress(it.loaded.toLong(), it.total.toLong()) } } request.onload = { if (request.status == 200.toShort()) { diff --git a/ktor/client/src/jsMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualUniUpload.kt b/ktor/client/src/jsMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualUniUpload.kt index bf1889a949f..4142f3f69a0 100644 --- a/ktor/client/src/jsMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualUniUpload.kt +++ b/ktor/client/src/jsMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualUniUpload.kt @@ -2,7 +2,7 @@ package dev.inmo.micro_utils.ktor.client import dev.inmo.micro_utils.common.MPPFile import dev.inmo.micro_utils.coroutines.LinkedSupervisorJob -import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions +import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions import io.ktor.client.HttpClient import io.ktor.client.content.* import io.ktor.http.Headers @@ -66,7 +66,7 @@ actual suspend fun HttpClient.uniUpload( } request.responseType = XMLHttpRequestResponseType.TEXT request.upload.onprogress = { - subscope.launchSafelyWithoutExceptions { onUpload.onProgress(it.loaded.toLong(), it.total.toLong()) } + subscope.launchLoggingDropExceptions { onUpload.onProgress(it.loaded.toLong(), it.total.toLong()) } } request.onload = { if (request.status == 200.toShort()) { diff --git a/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/TemporalFilesRoutingConfigurator.kt b/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/TemporalFilesRoutingConfigurator.kt index 08a85af4a04..ad35f0c5d00 100644 --- a/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/TemporalFilesRoutingConfigurator.kt +++ b/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/TemporalFilesRoutingConfigurator.kt @@ -3,7 +3,7 @@ package dev.inmo.micro_utils.ktor.server import com.benasher44.uuid.uuid4 import dev.inmo.micro_utils.common.FileName import dev.inmo.micro_utils.common.MPPFile -import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions +import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions import dev.inmo.micro_utils.ktor.common.DefaultTemporalFilesSubPath import dev.inmo.micro_utils.ktor.common.TemporalFileId import dev.inmo.micro_utils.ktor.server.configurators.ApplicationRoutingConfigurator @@ -44,7 +44,7 @@ class TemporalFilesRoutingConfigurator( filesMap: MutableMap, filesMutex: Mutex, onNewFileFlow: Flow - ): Job = scope.launchSafelyWithoutExceptions { + ): Job = scope.launchLoggingDropExceptions { while (currentCoroutineContext().isActive) { val filesWithCreationInfo = filesMap.mapNotNull { (fileId, file) -> fileId to ((Files.getAttribute(file.toPath(), "creationTime") as? FileTime) ?.toMillis() ?: return@mapNotNull null) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullCRUDCacheRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullCRUDCacheRepo.kt index d163b968f9d..e5b6bbd7188 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullCRUDCacheRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullCRUDCacheRepo.kt @@ -2,7 +2,7 @@ package dev.inmo.micro_utils.repos.cache.full import dev.inmo.micro_utils.common.* import dev.inmo.micro_utils.coroutines.SmartRWLocker -import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions +import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions import dev.inmo.micro_utils.coroutines.withReadAcquire import dev.inmo.micro_utils.coroutines.withWriteLock import dev.inmo.micro_utils.pagination.Pagination @@ -116,7 +116,7 @@ open class FullCRUDCacheRepo( CRUDRepo { init { if (!skipStartInvalidate) { - scope.launchSafelyWithoutExceptions { + scope.launchLoggingDropExceptions { if (locker.writeMutex.isLocked) { initialInvalidate() } else { diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValueCacheRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValueCacheRepo.kt index 7defa718495..84697a5a79c 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValueCacheRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValueCacheRepo.kt @@ -2,7 +2,7 @@ package dev.inmo.micro_utils.repos.cache.full import dev.inmo.micro_utils.common.* import dev.inmo.micro_utils.coroutines.SmartRWLocker -import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions +import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions import dev.inmo.micro_utils.coroutines.withReadAcquire import dev.inmo.micro_utils.coroutines.withWriteLock import dev.inmo.micro_utils.pagination.Pagination @@ -141,7 +141,7 @@ open class FullKeyValueCacheRepo( ) { init { if (!skipStartInvalidate) { - scope.launchSafelyWithoutExceptions { + scope.launchLoggingDropExceptions { if (locker.writeMutex.isLocked) { initialInvalidate() } else { diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValuesCacheRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValuesCacheRepo.kt index c68e238d27d..ec146a26eff 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValuesCacheRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValuesCacheRepo.kt @@ -2,7 +2,7 @@ package dev.inmo.micro_utils.repos.cache.full import dev.inmo.micro_utils.common.* import dev.inmo.micro_utils.coroutines.SmartRWLocker -import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions +import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions import dev.inmo.micro_utils.coroutines.withReadAcquire import dev.inmo.micro_utils.coroutines.withWriteLock import dev.inmo.micro_utils.pagination.* @@ -210,7 +210,7 @@ open class FullKeyValuesCacheRepo( WriteKeyValuesRepo by parentRepo { init { if (!skipStartInvalidate) { - scope.launchSafelyWithoutExceptions { + scope.launchLoggingDropExceptions { if (locker.writeMutex.isLocked) { initialInvalidate() } else { diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/direct/DirectFullCRUDCacheRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/direct/DirectFullCRUDCacheRepo.kt index 1a39813ce40..273728e8f9e 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/direct/DirectFullCRUDCacheRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/direct/DirectFullCRUDCacheRepo.kt @@ -2,7 +2,7 @@ package dev.inmo.micro_utils.repos.cache.full.direct import dev.inmo.micro_utils.common.* import dev.inmo.micro_utils.coroutines.SmartRWLocker -import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions +import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions import dev.inmo.micro_utils.coroutines.withReadAcquire import dev.inmo.micro_utils.coroutines.withWriteLock import dev.inmo.micro_utils.pagination.Pagination @@ -82,7 +82,7 @@ open class DirectFullCRUDCacheRepo( CRUDRepo { init { if (!skipStartInvalidate) { - scope.launchSafelyWithoutExceptions { + scope.launchLoggingDropExceptions { if (locker.writeMutex.isLocked) { initialInvalidate() } else { diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/direct/DirectFullKeyValueCacheRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/direct/DirectFullKeyValueCacheRepo.kt index 41b0f66630b..07830395400 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/direct/DirectFullKeyValueCacheRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/direct/DirectFullKeyValueCacheRepo.kt @@ -1,7 +1,7 @@ package dev.inmo.micro_utils.repos.cache.full.direct import dev.inmo.micro_utils.coroutines.SmartRWLocker -import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions +import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions import dev.inmo.micro_utils.coroutines.withReadAcquire import dev.inmo.micro_utils.coroutines.withWriteLock import dev.inmo.micro_utils.pagination.Pagination @@ -117,7 +117,7 @@ open class DirectFullKeyValueCacheRepo( DirectFullReadKeyValueCacheRepo(parentRepo, kvCache, locker) { init { if (!skipStartInvalidate) { - scope.launchSafelyWithoutExceptions { + scope.launchLoggingDropExceptions { if (locker.writeMutex.isLocked) { initialInvalidate() } else { diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/direct/DirectFullKeyValuesCacheRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/direct/DirectFullKeyValuesCacheRepo.kt index a16d3700c9d..e9fd4dbafef 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/direct/DirectFullKeyValuesCacheRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/direct/DirectFullKeyValuesCacheRepo.kt @@ -2,7 +2,7 @@ package dev.inmo.micro_utils.repos.cache.full.direct import dev.inmo.micro_utils.common.* import dev.inmo.micro_utils.coroutines.SmartRWLocker -import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions +import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions import dev.inmo.micro_utils.coroutines.withReadAcquire import dev.inmo.micro_utils.coroutines.withWriteLock import dev.inmo.micro_utils.pagination.* @@ -145,7 +145,7 @@ open class DirectFullKeyValuesCacheRepo( WriteKeyValuesRepo by parentRepo { init { if (!skipStartInvalidate) { - scope.launchSafelyWithoutExceptions { + scope.launchLoggingDropExceptions { if (locker.writeMutex.isLocked) { initialInvalidate() } else { From aa79496a36c21c121e10f5826cba5843cdb6bb34 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 15 Feb 2025 10:04:12 +0600 Subject: [PATCH 14/14] upfill changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96dac96f7d9..ee6c5f60e26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ * `Exposed`: `0.58.0` -> `0.59.0` * `SQLite`: `3.48.0.0` -> `3.49.0.0` * `AndroidFragment`: `1.8.5` -> `1.8.6` +* `Coroutines`: + * Safely functions has been replaced with `Logging` variations (resolve of [#541](https://github.com/InsanusMokrassar/MicroUtils/issues/541)) * `KSP`: * `Variations`: * Module has been created