mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2025-09-17 14:29:24 +00:00
Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
f40d33db2a | |||
a5eb0fbd24 | |||
307c8030af | |||
a9016465fa | |||
358b70eb5f | |||
6fcbb80a71 | |||
|
643f6c420b | ||
ac68b0b941 | |||
d62f67bd88 | |||
8718c5e310 | |||
e8273ab80c | |||
2718605987 | |||
d99538d80b | |||
ce7a1e4e21 | |||
921734763d | |||
18c608f569 | |||
b915f6ece2 | |||
24347b422c |
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
@@ -21,4 +21,5 @@ jobs:
|
|||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: ./gradlew publishAllPublicationsToInmoNexusRepository
|
run: ./gradlew publishAllPublicationsToInmoNexusRepository
|
||||||
env:
|
env:
|
||||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
INMONEXUS_USER: ${{ secrets.INMONEXUS_USER }}
|
||||||
|
INMONEXUS_PASSWORD: ${{ secrets.INMONEXUS_PASSWORD }}
|
||||||
|
37
CHANGELOG.md
37
CHANGELOG.md
@@ -1,5 +1,42 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.24.2
|
||||||
|
|
||||||
|
* `Versions`:
|
||||||
|
* `Exposed`: `0.57.0` -> `0.58.0`
|
||||||
|
* `Ksp`:
|
||||||
|
* `Sealed`:
|
||||||
|
* Add annotation `GenerateSealedTypesWorkaround` which allow to generate `subtypes` lists
|
||||||
|
|
||||||
|
## 0.24.1
|
||||||
|
|
||||||
|
* `Versions`:
|
||||||
|
* `Serialization`: `1.7.3` -> `1.8.0`
|
||||||
|
* `SQLite`: `3.47.1.0` -> `3.47.2.0`
|
||||||
|
* `Koin`: `4.0.0` -> `3.10.2`
|
||||||
|
* `OKio`: `3.9.1` -> `3.10.2`
|
||||||
|
|
||||||
|
## 0.24.0
|
||||||
|
|
||||||
|
* `Versions`:
|
||||||
|
* `Coroutines`: `1.9.0` -> `1.10.1`
|
||||||
|
* `KSLog`: `1.3.6` -> `1.4.0`
|
||||||
|
* `Compose`: `1.7.1` -> `1.7.3`
|
||||||
|
* `Ktor`: `3.0.2` -> `3.0.3`
|
||||||
|
* `Common`:
|
||||||
|
* Rename `Progress` to more common `Percentage`. `Progress` now is typealias
|
||||||
|
* Fix of `Progress.compareTo` extension
|
||||||
|
|
||||||
|
## 0.23.2
|
||||||
|
|
||||||
|
* `Versions`:
|
||||||
|
* `Kotlin`: `2.0.21` -> `2.1.0`
|
||||||
|
* `Exposed`: `0.56.0` -> `0.57.0`
|
||||||
|
* `Xerial SQLite`: `3.47.0.0` -> `3.47.1.0`
|
||||||
|
* `Ktor`: `3.0.1` -> `3.0.2`
|
||||||
|
* `Coroutines`:
|
||||||
|
* Small refactor in `AccumulatorFlow` to use `runCatching` instead of `runCatchingSafely`
|
||||||
|
|
||||||
## 0.23.1
|
## 0.23.1
|
||||||
|
|
||||||
* `Versions`:
|
* `Versions`:
|
||||||
|
@@ -0,0 +1,76 @@
|
|||||||
|
package dev.inmo.micro_utils.common
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlin.jvm.JvmInline
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains [of1] as main value, where 100% of percentage is when of1 == 1
|
||||||
|
*
|
||||||
|
* @see invoke
|
||||||
|
* @see partOfTotal
|
||||||
|
* @see of100
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
@JvmInline
|
||||||
|
value class Percentage private constructor(
|
||||||
|
/**
|
||||||
|
* Value of percentage. When it equals to 1, means 100%
|
||||||
|
*/
|
||||||
|
val of1: Double
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* Same as [of1], but float (using [Double.toFloat])
|
||||||
|
*/
|
||||||
|
val of1Float
|
||||||
|
get() = of1.toFloat()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent this percentage as common percentage where 100% is 100%
|
||||||
|
*/
|
||||||
|
val of100
|
||||||
|
get() = of1 * 100
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as [of100], but float (using [Double.toFloat])
|
||||||
|
*/
|
||||||
|
val of100Float
|
||||||
|
get() = of100.toFloat()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as [of100], but int (using [Double.toInt])
|
||||||
|
*/
|
||||||
|
val of100Int
|
||||||
|
get() = of100.toInt()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val rangeOfValues = 0.0 .. 1.0
|
||||||
|
|
||||||
|
val START = Percentage(rangeOfValues.start)
|
||||||
|
val COMPLETED = Percentage(rangeOfValues.endInclusive)
|
||||||
|
|
||||||
|
operator fun invoke(of1: Double) = Percentage(of1.coerceIn(rangeOfValues))
|
||||||
|
operator fun invoke(part: Number, total: Number) = Percentage(
|
||||||
|
part.toDouble() / total.toDouble()
|
||||||
|
)
|
||||||
|
fun of1(of1: Double) = Percentage(of1 = of1)
|
||||||
|
fun of100(of100: Double) = Percentage(of1 = of100 / 100)
|
||||||
|
fun partOfTotal(part: Number, total: Number) = Percentage(part = part, total = total)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typealias Progress = Percentage
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will return [this] [Progress] if [Percentage.of1] in `0 .. 1` range
|
||||||
|
*/
|
||||||
|
fun Progress.ensureStrictOrNull(): Progress? = if (of1 in Percentage.rangeOfValues) this else null
|
||||||
|
/**
|
||||||
|
* Will return [this] [Progress] if [Percentage.of1] in `0 .. 1` range. Otherwise, will throw error
|
||||||
|
* [IllegalArgumentException] due to [require] failure
|
||||||
|
*/
|
||||||
|
fun Progress.ensureStrictOrThrow(): Progress {
|
||||||
|
require(of1 in Percentage.rangeOfValues) {
|
||||||
|
"For strict checks value of percentage must be in ${Percentage.rangeOfValues}, but actual value is $of1"
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
@@ -0,0 +1,80 @@
|
|||||||
|
@file:Suppress(
|
||||||
|
"RemoveRedundantCallsOfConversionMethods",
|
||||||
|
"RedundantVisibilityModifier",
|
||||||
|
)
|
||||||
|
|
||||||
|
package dev.inmo.micro_utils.common
|
||||||
|
|
||||||
|
import kotlin.Byte
|
||||||
|
import kotlin.Double
|
||||||
|
import kotlin.Float
|
||||||
|
import kotlin.Int
|
||||||
|
import kotlin.Long
|
||||||
|
import kotlin.Short
|
||||||
|
import kotlin.Suppress
|
||||||
|
|
||||||
|
public operator fun Percentage.plus(other: Percentage): Percentage = Percentage(of1 + other.of1)
|
||||||
|
|
||||||
|
public operator fun Percentage.minus(other: Percentage): Percentage = Percentage(of1 - other.of1)
|
||||||
|
|
||||||
|
public operator fun Percentage.plus(i: Byte): Percentage = Percentage((of1 + i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.minus(i: Byte): Percentage = Percentage((of1 - i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.times(i: Byte): Percentage = Percentage((of1 * i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.div(i: Byte): Percentage = Percentage((of1 / i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.rem(i: Byte): Percentage = Percentage((of1 % i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.plus(i: Short): Percentage = Percentage((of1 + i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.minus(i: Short): Percentage = Percentage((of1 - i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.times(i: Short): Percentage = Percentage((of1 * i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.div(i: Short): Percentage = Percentage((of1 / i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.rem(i: Short): Percentage = Percentage((of1 % i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.plus(i: Int): Percentage = Percentage((of1 + i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.minus(i: Int): Percentage = Percentage((of1 - i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.times(i: Int): Percentage = Percentage((of1 * i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.div(i: Int): Percentage = Percentage((of1 / i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.rem(i: Int): Percentage = Percentage((of1 % i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.plus(i: Long): Percentage = Percentage((of1 + i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.minus(i: Long): Percentage = Percentage((of1 - i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.times(i: Long): Percentage = Percentage((of1 * i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.div(i: Long): Percentage = Percentage((of1 / i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.rem(i: Long): Percentage = Percentage((of1 % i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.plus(i: Float): Percentage = Percentage((of1 + i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.minus(i: Float): Percentage = Percentage((of1 - i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.times(i: Float): Percentage = Percentage((of1 * i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.div(i: Float): Percentage = Percentage((of1 / i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.rem(i: Float): Percentage = Percentage((of1 % i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.plus(i: Double): Percentage = Percentage((of1 + i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.minus(i: Double): Percentage = Percentage((of1 - i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.times(i: Double): Percentage = Percentage((of1 * i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.div(i: Double): Percentage = Percentage((of1 / i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.rem(i: Double): Percentage = Percentage((of1 % i).toDouble())
|
||||||
|
|
||||||
|
public operator fun Percentage.compareTo(other: Percentage): Int = (of1.compareTo(other.of1))
|
@@ -1,37 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.common
|
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
import kotlin.jvm.JvmInline
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
@JvmInline
|
|
||||||
value class Progress private constructor(
|
|
||||||
val of1: Double
|
|
||||||
) {
|
|
||||||
val of1Float
|
|
||||||
get() = of1.toFloat()
|
|
||||||
val of100
|
|
||||||
get() = of1 * 100
|
|
||||||
val of100Float
|
|
||||||
get() = of100.toFloat()
|
|
||||||
val of100Int
|
|
||||||
get() = of100.toInt()
|
|
||||||
|
|
||||||
init {
|
|
||||||
require(of1 in rangeOfValues) {
|
|
||||||
"Progress main value should be in $rangeOfValues, but incoming value is $of1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val rangeOfValues = 0.0 .. 1.0
|
|
||||||
|
|
||||||
val START = Progress(rangeOfValues.start)
|
|
||||||
val COMPLETED = Progress(rangeOfValues.endInclusive)
|
|
||||||
|
|
||||||
operator fun invoke(of1: Double) = Progress(of1.coerceIn(rangeOfValues))
|
|
||||||
operator fun invoke(part: Number, total: Number) = Progress(
|
|
||||||
part.toDouble() / total.toDouble()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,80 +0,0 @@
|
|||||||
@file:Suppress(
|
|
||||||
"RemoveRedundantCallsOfConversionMethods",
|
|
||||||
"RedundantVisibilityModifier",
|
|
||||||
)
|
|
||||||
|
|
||||||
package dev.inmo.micro_utils.common
|
|
||||||
|
|
||||||
import kotlin.Byte
|
|
||||||
import kotlin.Double
|
|
||||||
import kotlin.Float
|
|
||||||
import kotlin.Int
|
|
||||||
import kotlin.Long
|
|
||||||
import kotlin.Short
|
|
||||||
import kotlin.Suppress
|
|
||||||
|
|
||||||
public operator fun Progress.plus(other: Progress): Progress = Progress(of1 + other.of1)
|
|
||||||
|
|
||||||
public operator fun Progress.minus(other: Progress): Progress = Progress(of1 - other.of1)
|
|
||||||
|
|
||||||
public operator fun Progress.plus(i: Byte): Progress = Progress((of1 + i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.minus(i: Byte): Progress = Progress((of1 - i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.times(i: Byte): Progress = Progress((of1 * i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.div(i: Byte): Progress = Progress((of1 / i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.rem(i: Byte): Progress = Progress((of1 % i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.plus(i: Short): Progress = Progress((of1 + i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.minus(i: Short): Progress = Progress((of1 - i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.times(i: Short): Progress = Progress((of1 * i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.div(i: Short): Progress = Progress((of1 / i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.rem(i: Short): Progress = Progress((of1 % i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.plus(i: Int): Progress = Progress((of1 + i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.minus(i: Int): Progress = Progress((of1 - i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.times(i: Int): Progress = Progress((of1 * i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.div(i: Int): Progress = Progress((of1 / i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.rem(i: Int): Progress = Progress((of1 % i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.plus(i: Long): Progress = Progress((of1 + i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.minus(i: Long): Progress = Progress((of1 - i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.times(i: Long): Progress = Progress((of1 * i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.div(i: Long): Progress = Progress((of1 / i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.rem(i: Long): Progress = Progress((of1 % i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.plus(i: Float): Progress = Progress((of1 + i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.minus(i: Float): Progress = Progress((of1 - i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.times(i: Float): Progress = Progress((of1 * i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.div(i: Float): Progress = Progress((of1 / i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.rem(i: Float): Progress = Progress((of1 % i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.plus(i: Double): Progress = Progress((of1 + i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.minus(i: Double): Progress = Progress((of1 - i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.times(i: Double): Progress = Progress((of1 * i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.div(i: Double): Progress = Progress((of1 / i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.rem(i: Double): Progress = Progress((of1 % i).toDouble())
|
|
||||||
|
|
||||||
public operator fun Progress.compareTo(other: Progress): Int = (of1 - other.of1).toInt()
|
|
@@ -0,0 +1,29 @@
|
|||||||
|
package dev.inmo.micro_utils.common
|
||||||
|
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class PercentageTests {
|
||||||
|
@Test
|
||||||
|
fun testCompareTo() {
|
||||||
|
val step = 0.01
|
||||||
|
|
||||||
|
var i = Percentage.START.of1
|
||||||
|
while (i <= Percentage.COMPLETED.of1) {
|
||||||
|
val percentageI = Percentage(i)
|
||||||
|
|
||||||
|
var j = Percentage.START.of1
|
||||||
|
while (j <= Percentage.COMPLETED.of1) {
|
||||||
|
val percentageJ = Percentage(j)
|
||||||
|
|
||||||
|
assertEquals(percentageI.of1.compareTo(percentageJ.of1), percentageI.compareTo(percentageJ))
|
||||||
|
assertEquals(percentageI.of1 > percentageJ.of1, percentageI > percentageJ)
|
||||||
|
assertEquals(percentageI.of1 < percentageJ.of1, percentageI < percentageJ)
|
||||||
|
|
||||||
|
j += step
|
||||||
|
}
|
||||||
|
|
||||||
|
i += step
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -68,9 +68,9 @@ class AccumulatorFlow<T>(
|
|||||||
override suspend fun collectSafely(collector: FlowCollector<T>) {
|
override suspend fun collectSafely(collector: FlowCollector<T>) {
|
||||||
val channel = Channel<T>(Channel.UNLIMITED, BufferOverflow.SUSPEND)
|
val channel = Channel<T>(Channel.UNLIMITED, BufferOverflow.SUSPEND)
|
||||||
steps.send(SubscribeAccumulatorFlowStep(channel))
|
steps.send(SubscribeAccumulatorFlowStep(channel))
|
||||||
val result = runCatchingSafely {
|
val result = runCatching {
|
||||||
for (data in channel) {
|
for (data in channel) {
|
||||||
val emitResult = runCatchingSafely {
|
val emitResult = runCatching {
|
||||||
collector.emit(data)
|
collector.emit(data)
|
||||||
}
|
}
|
||||||
if (emitResult.isSuccess || emitResult.exceptionOrNull() is CancellationException) {
|
if (emitResult.isSuccess || emitResult.exceptionOrNull() is CancellationException) {
|
||||||
|
@@ -15,5 +15,5 @@ crypto_js_version=4.1.1
|
|||||||
# Project data
|
# Project data
|
||||||
|
|
||||||
group=dev.inmo
|
group=dev.inmo
|
||||||
version=0.23.1
|
version=0.24.2
|
||||||
android_code_version=277
|
android_code_version=281
|
||||||
|
@@ -1,29 +1,29 @@
|
|||||||
[versions]
|
[versions]
|
||||||
|
|
||||||
kt = "2.0.21"
|
kt = "2.1.0"
|
||||||
kt-serialization = "1.7.3"
|
kt-serialization = "1.8.0"
|
||||||
kt-coroutines = "1.9.0"
|
kt-coroutines = "1.10.1"
|
||||||
|
|
||||||
kslog = "1.3.6"
|
kslog = "1.4.0"
|
||||||
|
|
||||||
jb-compose = "1.7.1"
|
jb-compose = "1.7.3"
|
||||||
jb-exposed = "0.56.0"
|
jb-exposed = "0.58.0"
|
||||||
jb-dokka = "1.9.20"
|
jb-dokka = "2.0.0"
|
||||||
|
|
||||||
sqlite = "3.47.0.0"
|
sqlite = "3.47.2.0"
|
||||||
|
|
||||||
korlibs = "5.4.0"
|
korlibs = "5.4.0"
|
||||||
uuid = "0.8.4"
|
uuid = "0.8.4"
|
||||||
|
|
||||||
ktor = "3.0.1"
|
ktor = "3.0.3"
|
||||||
|
|
||||||
gh-release = "2.5.2"
|
gh-release = "2.5.2"
|
||||||
|
|
||||||
koin = "4.0.0"
|
koin = "4.0.1"
|
||||||
|
|
||||||
okio = "3.9.1"
|
okio = "3.10.2"
|
||||||
|
|
||||||
ksp = "2.0.21-1.0.28"
|
ksp = "2.1.0-1.0.29"
|
||||||
kotlin-poet = "1.18.1"
|
kotlin-poet = "1.18.1"
|
||||||
|
|
||||||
versions = "0.51.0"
|
versions = "0.51.0"
|
||||||
|
@@ -3,9 +3,15 @@ package dev.inmo.micro_utils.ksp.sealed.generator
|
|||||||
import com.google.devtools.ksp.KspExperimental
|
import com.google.devtools.ksp.KspExperimental
|
||||||
import com.google.devtools.ksp.getAnnotationsByType
|
import com.google.devtools.ksp.getAnnotationsByType
|
||||||
import com.google.devtools.ksp.symbol.KSClassDeclaration
|
import com.google.devtools.ksp.symbol.KSClassDeclaration
|
||||||
|
import dev.inmo.micro_utils.ksp.sealed.GenerateSealedTypesWorkaround
|
||||||
import dev.inmo.micro_utils.ksp.sealed.GenerateSealedWorkaround
|
import dev.inmo.micro_utils.ksp.sealed.GenerateSealedWorkaround
|
||||||
import dev.inmo.microutils.kps.sealed.GenerateSealedWorkaround as OldGenerateSealedWorkaround
|
import dev.inmo.microutils.kps.sealed.GenerateSealedWorkaround as OldGenerateSealedWorkaround
|
||||||
|
|
||||||
@OptIn(KspExperimental::class)
|
@OptIn(KspExperimental::class)
|
||||||
val KSClassDeclaration.getGenerateSealedWorkaroundAnnotation
|
val KSClassDeclaration.getGenerateSealedWorkaroundAnnotation
|
||||||
get() = (getAnnotationsByType(GenerateSealedWorkaround::class).firstOrNull() ?: getAnnotationsByType(OldGenerateSealedWorkaround::class).firstOrNull())
|
get() = (getAnnotationsByType(GenerateSealedWorkaround::class).firstOrNull() ?: getAnnotationsByType(OldGenerateSealedWorkaround::class).firstOrNull())
|
||||||
|
|
||||||
|
|
||||||
|
@OptIn(KspExperimental::class)
|
||||||
|
val KSClassDeclaration.getGenerateSealedTypesWorkaroundAnnotation
|
||||||
|
get() = getAnnotationsByType(GenerateSealedTypesWorkaround::class).firstOrNull()
|
||||||
|
@@ -6,21 +6,17 @@ import com.google.devtools.ksp.processing.CodeGenerator
|
|||||||
import com.google.devtools.ksp.processing.Resolver
|
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.*
|
import com.google.devtools.ksp.symbol.*
|
||||||
import com.squareup.kotlinpoet.ClassName
|
import com.squareup.kotlinpoet.*
|
||||||
import com.squareup.kotlinpoet.CodeBlock
|
|
||||||
import com.squareup.kotlinpoet.FileSpec
|
|
||||||
import com.squareup.kotlinpoet.FunSpec
|
|
||||||
import com.squareup.kotlinpoet.KModifier
|
|
||||||
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
|
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
|
||||||
import com.squareup.kotlinpoet.PropertySpec
|
|
||||||
import com.squareup.kotlinpoet.asTypeName
|
|
||||||
import com.squareup.kotlinpoet.ksp.toClassName
|
import com.squareup.kotlinpoet.ksp.toClassName
|
||||||
import dev.inmo.micro_ksp.generator.buildSubFileName
|
import dev.inmo.micro_ksp.generator.buildSubFileName
|
||||||
import dev.inmo.micro_ksp.generator.companion
|
import dev.inmo.micro_ksp.generator.companion
|
||||||
import dev.inmo.micro_ksp.generator.findSubClasses
|
import dev.inmo.micro_ksp.generator.findSubClasses
|
||||||
import dev.inmo.micro_ksp.generator.writeFile
|
import dev.inmo.micro_ksp.generator.writeFile
|
||||||
|
import dev.inmo.micro_utils.ksp.sealed.GenerateSealedTypesWorkaround
|
||||||
import dev.inmo.micro_utils.ksp.sealed.GenerateSealedWorkaround
|
import dev.inmo.micro_utils.ksp.sealed.GenerateSealedWorkaround
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
class Processor(
|
class Processor(
|
||||||
private val codeGenerator: CodeGenerator
|
private val codeGenerator: CodeGenerator
|
||||||
@@ -109,6 +105,62 @@ class Processor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(KspExperimental::class)
|
||||||
|
private fun FileSpec.Builder.generateSealedTypesWorkaround(
|
||||||
|
ksClassDeclaration: KSClassDeclaration,
|
||||||
|
resolver: Resolver
|
||||||
|
) {
|
||||||
|
val annotation = ksClassDeclaration.getGenerateSealedTypesWorkaroundAnnotation
|
||||||
|
val subClasses = ksClassDeclaration.resolveSubclasses(
|
||||||
|
searchIn = resolver.getAllFiles(),
|
||||||
|
allowNonSealed = annotation ?.includeNonSealedSubTypes ?: false
|
||||||
|
).distinct()
|
||||||
|
val subClassesNames = subClasses.filter {
|
||||||
|
it.getAnnotationsByType(GenerateSealedWorkaround.Exclude::class).count() == 0
|
||||||
|
}.sortedBy {
|
||||||
|
(it.getAnnotationsByType(GenerateSealedWorkaround.Order::class).firstOrNull()) ?.order ?: 0
|
||||||
|
}.map {
|
||||||
|
it.toClassName()
|
||||||
|
}.toList()
|
||||||
|
val className = ksClassDeclaration.toClassName()
|
||||||
|
val setType = Set::class.asTypeName().parameterizedBy(
|
||||||
|
KClass::class.asTypeName().parameterizedBy(
|
||||||
|
TypeVariableName(
|
||||||
|
"out ${ksClassDeclaration.asStarProjectedType().toClassName().simpleNames.joinToString(".")}",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
addProperty(
|
||||||
|
PropertySpec.builder(
|
||||||
|
"subtypes",
|
||||||
|
setType
|
||||||
|
).apply {
|
||||||
|
modifiers.add(
|
||||||
|
KModifier.PRIVATE
|
||||||
|
)
|
||||||
|
initializer(
|
||||||
|
CodeBlock.of(
|
||||||
|
"""setOf(${subClassesNames.joinToString(",\n") { it.simpleNames.joinToString(".") + "::class" }})"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}.build()
|
||||||
|
)
|
||||||
|
addFunction(
|
||||||
|
FunSpec.builder("subtypes").apply {
|
||||||
|
val companion = ksClassDeclaration.takeIf { it.isCompanionObject } ?.toClassName()
|
||||||
|
?: ksClassDeclaration.companion ?.toClassName()
|
||||||
|
?: ClassName(className.packageName, *className.simpleNames.toTypedArray(), "Companion")
|
||||||
|
receiver(companion)
|
||||||
|
returns(setType)
|
||||||
|
addCode(
|
||||||
|
CodeBlock.of(
|
||||||
|
"""return subtypes"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}.build()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(KspExperimental::class)
|
@OptIn(KspExperimental::class)
|
||||||
override fun process(resolver: Resolver): List<KSAnnotated> {
|
override fun process(resolver: Resolver): List<KSAnnotated> {
|
||||||
(resolver.getSymbolsWithAnnotation(GenerateSealedWorkaround::class.qualifiedName!!)).filterIsInstance<KSClassDeclaration>().forEach {
|
(resolver.getSymbolsWithAnnotation(GenerateSealedWorkaround::class.qualifiedName!!)).filterIsInstance<KSClassDeclaration>().forEach {
|
||||||
@@ -131,6 +183,26 @@ class Processor(
|
|||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(resolver.getSymbolsWithAnnotation(GenerateSealedTypesWorkaround::class.qualifiedName!!)).filterIsInstance<KSClassDeclaration>().forEach {
|
||||||
|
val prefix = (it.getGenerateSealedTypesWorkaroundAnnotation) ?.prefix ?.takeIf {
|
||||||
|
it.isNotEmpty()
|
||||||
|
} ?: it.buildSubFileName.replaceFirst(it.simpleName.asString(), "")
|
||||||
|
it.writeFile(prefix = prefix, suffix = "SealedTypesWorkaround") {
|
||||||
|
FileSpec.builder(
|
||||||
|
it.packageName.asString(),
|
||||||
|
"${it.simpleName.getShortName()}SealedTypesWorkaround"
|
||||||
|
).apply {
|
||||||
|
addFileComment(
|
||||||
|
"""
|
||||||
|
THIS CODE HAVE BEEN GENERATED AUTOMATICALLY
|
||||||
|
TO REGENERATE IT JUST DELETE FILE
|
||||||
|
ORIGINAL FILE: ${it.containingFile ?.fileName}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
generateSealedTypesWorkaround(it, resolver)
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
@@ -1,14 +1,19 @@
|
|||||||
package dev.inmo.micro_utils.ksp.sealed.generator.test
|
package dev.inmo.micro_utils.ksp.sealed.generator.test
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.ksp.sealed.GenerateSealedTypesWorkaround
|
||||||
import dev.inmo.micro_utils.ksp.sealed.GenerateSealedWorkaround
|
import dev.inmo.micro_utils.ksp.sealed.GenerateSealedWorkaround
|
||||||
|
|
||||||
@GenerateSealedWorkaround
|
@GenerateSealedWorkaround
|
||||||
|
@GenerateSealedTypesWorkaround
|
||||||
sealed interface Test {
|
sealed interface Test {
|
||||||
@GenerateSealedWorkaround.Order(2)
|
@GenerateSealedWorkaround.Order(2)
|
||||||
|
@GenerateSealedTypesWorkaround.Order(2)
|
||||||
object A : Test
|
object A : Test
|
||||||
@GenerateSealedWorkaround.Exclude
|
@GenerateSealedWorkaround.Exclude
|
||||||
|
@GenerateSealedTypesWorkaround.Exclude
|
||||||
object B : Test
|
object B : Test
|
||||||
@GenerateSealedWorkaround.Order(0)
|
@GenerateSealedWorkaround.Order(0)
|
||||||
|
@GenerateSealedTypesWorkaround.Order(0)
|
||||||
object C : Test
|
object C : Test
|
||||||
|
|
||||||
// Required for successful sealed workaround generation
|
// Required for successful sealed workaround generation
|
||||||
|
@@ -0,0 +1,12 @@
|
|||||||
|
// THIS CODE HAVE BEEN GENERATED AUTOMATICALLY
|
||||||
|
// TO REGENERATE IT JUST DELETE FILE
|
||||||
|
// ORIGINAL FILE: Test.kt
|
||||||
|
package dev.inmo.micro_utils.ksp.`sealed`.generator.test
|
||||||
|
|
||||||
|
import kotlin.collections.Set
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
private val subtypes: Set<KClass<out Test>> = setOf(Test.C::class,
|
||||||
|
Test.A::class)
|
||||||
|
|
||||||
|
public fun Test.Companion.subtypes(): Set<KClass<out Test>> = subtypes
|
@@ -0,0 +1,15 @@
|
|||||||
|
package dev.inmo.micro_utils.ksp.sealed
|
||||||
|
|
||||||
|
@Retention(AnnotationRetention.BINARY)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
annotation class GenerateSealedTypesWorkaround(
|
||||||
|
val prefix: String = "",
|
||||||
|
val includeNonSealedSubTypes: Boolean = false,
|
||||||
|
) {
|
||||||
|
@Retention(AnnotationRetention.BINARY)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
annotation class Order(val order: Int)
|
||||||
|
@Retention(AnnotationRetention.BINARY)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
annotation class Exclude
|
||||||
|
}
|
@@ -4,7 +4,7 @@ package dev.inmo.micro_utils.ksp.sealed
|
|||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
annotation class GenerateSealedWorkaround(
|
annotation class GenerateSealedWorkaround(
|
||||||
val prefix: String = "",
|
val prefix: String = "",
|
||||||
val includeNonSealedSubTypes: Boolean = false
|
val includeNonSealedSubTypes: Boolean = false,
|
||||||
) {
|
) {
|
||||||
@Retention(AnnotationRetention.BINARY)
|
@Retention(AnnotationRetention.BINARY)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
"extends": [
|
"extends": [
|
||||||
"config:base"
|
"config:recommended"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user