diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d53ef0..efd50b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # SDI changelogs +## 0.1.2 + +* All reflection support methods are internal +* Added `loadModule` functions for more useful working with modules loading +* `Module` now is not serializable and can be created only via `loadModule` functions (at least, for some time) + ## 0.1.1 * Added opportunity to create objects inside of config: diff --git a/build.gradle b/build.gradle index 0134720..7d8d339 100644 --- a/build.gradle +++ b/build.gradle @@ -36,7 +36,7 @@ kotlin { commonMain { dependencies { implementation kotlin('stdlib') - api "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" + api kotlin('reflect') api "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$kotlin_serialisation_runtime_version" } } diff --git a/src/commonMain/kotlin/com/insanusmokrassar/sdi/HelperTools.kt b/src/commonMain/kotlin/com/insanusmokrassar/sdi/HelperTools.kt new file mode 100644 index 0000000..4686f7a --- /dev/null +++ b/src/commonMain/kotlin/com/insanusmokrassar/sdi/HelperTools.kt @@ -0,0 +1,10 @@ +package com.insanusmokrassar.sdi + +import kotlinx.serialization.ImplicitReflectionSerializer +import kotlinx.serialization.json.Json + +@ImplicitReflectionSerializer +fun Json.loadModule(json: String): Module = parse(ModuleDeserializerStrategy, json) + +@ImplicitReflectionSerializer +fun loadModule(json: String): Module = Json.nonstrict.loadModule(json) diff --git a/src/commonMain/kotlin/com/insanusmokrassar/sdi/Module.kt b/src/commonMain/kotlin/com/insanusmokrassar/sdi/Module.kt new file mode 100644 index 0000000..ea376e6 --- /dev/null +++ b/src/commonMain/kotlin/com/insanusmokrassar/sdi/Module.kt @@ -0,0 +1,5 @@ +package com.insanusmokrassar.sdi + +import kotlinx.serialization.ContextualSerialization + +class Module internal constructor(base: Map) : Map by base \ No newline at end of file diff --git a/src/commonMain/kotlin/com/insanusmokrassar/sdi/ModuleSerializer.kt b/src/commonMain/kotlin/com/insanusmokrassar/sdi/ModuleDeserializerStrategy.kt similarity index 56% rename from src/commonMain/kotlin/com/insanusmokrassar/sdi/ModuleSerializer.kt rename to src/commonMain/kotlin/com/insanusmokrassar/sdi/ModuleDeserializerStrategy.kt index 50516de..3313c4e 100644 --- a/src/commonMain/kotlin/com/insanusmokrassar/sdi/ModuleSerializer.kt +++ b/src/commonMain/kotlin/com/insanusmokrassar/sdi/ModuleDeserializerStrategy.kt @@ -1,19 +1,13 @@ package com.insanusmokrassar.sdi -import com.insanusmokrassar.sdi.utils.* +import com.insanusmokrassar.sdi.utils.createModuleBasedOnConfigRoot import kotlinx.serialization.* -import kotlinx.serialization.internal.* +import kotlinx.serialization.internal.HashMapSerializer +import kotlinx.serialization.internal.StringSerializer import kotlinx.serialization.json.* -import kotlinx.serialization.modules.* -import kotlin.reflect.KClass @ImplicitReflectionSerializer -@Serializable(ModuleSerializer::class) -class Module(base: Map) : Map by base - -@ImplicitReflectionSerializer -@Serializer(Module::class) -internal object ModuleSerializer : KSerializer { +internal object ModuleDeserializerStrategy : DeserializationStrategy { private val internalSerializer = HashMapSerializer(StringSerializer, ContextSerializer(Any::class)) override val descriptor: SerialDescriptor get() = internalSerializer.descriptor @@ -28,7 +22,5 @@ internal object ModuleSerializer : KSerializer { return Module(map) } - override fun serialize(encoder: Encoder, obj: Module) { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. - } + override fun patch(decoder: Decoder, old: Module): Module = throw UpdateNotSupportedException("Module") } diff --git a/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/DependencyResolver.kt b/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/DependencyResolver.kt index 488d650..5ccaf93 100644 --- a/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/DependencyResolver.kt +++ b/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/DependencyResolver.kt @@ -2,7 +2,8 @@ package com.insanusmokrassar.sdi.utils import kotlinx.serialization.* import kotlinx.serialization.json.* -import kotlinx.serialization.modules.* +import kotlinx.serialization.modules.SerializerAlreadyRegisteredException +import kotlinx.serialization.modules.SerializersModuleBuilder import kotlin.reflect.KClass @ImplicitReflectionSerializer @@ -13,7 +14,7 @@ internal class DependencyResolver( private val dependencyGetter: (String) -> Any ) : KSerializer { private val originalSerializer: KSerializer = try { - resolveSerializerByKClass(kClass) + kClass.serializer() } catch (e: Exception) { PolymorphicSerializer(kClass) } diff --git a/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/JsonAdaptations.kt b/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/JsonAdaptations.kt index 7a065b4..2d57c3d 100644 --- a/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/JsonAdaptations.kt +++ b/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/JsonAdaptations.kt @@ -1,8 +1,9 @@ package com.insanusmokrassar.sdi.utils -import kotlinx.serialization.* +import kotlinx.serialization.ImplicitReflectionSerializer import kotlinx.serialization.json.* -import kotlinx.serialization.modules.* +import kotlinx.serialization.modules.SerializerAlreadyRegisteredException +import kotlinx.serialization.modules.SerializersModule private typealias PackageOrOtherDependencyNamePair = Pair @@ -63,25 +64,26 @@ internal fun createModuleBasedOnConfigRoot(jsonObject: JsonObject): Json { key to packageName }.toMap() - return Json( - configuration = JsonConfiguration(useArrayPolymorphism = true), - context = SerializersModule { - keysToPackages.values.forEach { - val kclass = resolveKClassByPackageName(it) + val context = SerializersModule { + keysToPackages.values.forEach { + val kclass = resolveKClassByPackageName(it) - try { - DependencyResolver( - this, - kclass, - { jsonStringFormat } - ) { - caches.getValue(it).invoke() - } - } catch (e: SerializerAlreadyRegisteredException) { - // here we are thinking that already registered + try { + DependencyResolver( + this, + kclass, + { jsonStringFormat } + ) { + caches.getValue(it).invoke() } + } catch (e: SerializerAlreadyRegisteredException) { + // here we are thinking that already registered } } + } + return Json( + configuration = JsonConfiguration(useArrayPolymorphism = true), + context = context ).also { jsonStringFormat = it } diff --git a/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/TypesHelper.kt b/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/TypesHelper.kt index 1dccd38..c869c5d 100644 --- a/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/TypesHelper.kt +++ b/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/TypesHelper.kt @@ -1,24 +1,22 @@ package com.insanusmokrassar.sdi.utils -import kotlinx.serialization.ImplicitReflectionSerializer -import kotlinx.serialization.KSerializer +import kotlinx.serialization.* import kotlin.reflect.KClass -import kotlin.reflect.KType + +internal expect fun resolveKClassByPackageName(packageName: String): KClass<*> @ImplicitReflectionSerializer -expect fun resolveSerializerByPackageName(packageName: String): KSerializer<*> +internal fun resolveSerializerByKClass(kClass: KClass): KSerializer = kClass.serializer() @ImplicitReflectionSerializer -expect fun resolveSerializerByKClass(kClass: KClass): KSerializer +internal fun resolveSerializerByPackageName(packageName: String): KSerializer<*> = resolveSerializerByKClass( + resolveKClassByPackageName(packageName) +) -expect fun resolveKClassByPackageName(packageName: String): KClass<*> - -expect val KClass<*>.currentSupertypes: List - -val KClass<*>.allSubclasses: Set> +internal val KClass<*>.allSubclasses: Set> get() { val subclasses = mutableSetOf>() - val leftToVisit = currentSupertypes.mapNotNull { it.classifier as? KClass<*> }.toMutableList() + val leftToVisit = supertypes.mapNotNull { it.classifier as? KClass<*> }.toMutableList() while (leftToVisit.isNotEmpty()) { val top = leftToVisit.removeAt(0) if (subclasses.add(top)) { diff --git a/src/commonTest/kotlin/com/insanusmokrassar/sdi/ListTest.kt b/src/commonTest/kotlin/com/insanusmokrassar/sdi/ListTest.kt index c93983f..b3351cb 100644 --- a/src/commonTest/kotlin/com/insanusmokrassar/sdi/ListTest.kt +++ b/src/commonTest/kotlin/com/insanusmokrassar/sdi/ListTest.kt @@ -2,7 +2,8 @@ package com.insanusmokrassar.sdi import kotlinx.serialization.* import kotlinx.serialization.json.Json -import kotlin.test.* +import kotlin.test.Test +import kotlin.test.assertEquals interface List_ParentalAPI { val services: List @@ -44,7 +45,7 @@ class ListTest { ] } """.trimIndent() - val module = Json.plain.parse(Module.serializer(), input) + val module = loadModule(input) (module[controllerName] as List_ParentalAPI) val controller = (module[controllerName] as List_Parent) controller.services.forEachIndexed { i, service -> diff --git a/src/commonTest/kotlin/com/insanusmokrassar/sdi/SimpleCustomObjectTest.kt b/src/commonTest/kotlin/com/insanusmokrassar/sdi/SimpleCustomObjectTest.kt index 6d76ace..a6d358b 100644 --- a/src/commonTest/kotlin/com/insanusmokrassar/sdi/SimpleCustomObjectTest.kt +++ b/src/commonTest/kotlin/com/insanusmokrassar/sdi/SimpleCustomObjectTest.kt @@ -2,7 +2,8 @@ package com.insanusmokrassar.sdi import kotlinx.serialization.* import kotlinx.serialization.json.Json -import kotlin.test.* +import kotlin.test.Test +import kotlin.test.assertEquals interface SimpleCustomObject_ControllerAPI { fun showUp() @@ -78,7 +79,7 @@ class SimpleCustomObjectTest { ] } """.trimIndent() - val module = Json.plain.parse(Module.serializer(), input) + val module = loadModule(input) (module[controllerName] as SimpleCustomObject_ControllerAPI) val controller = (module["controller"] as SimpleCustomObject_Controller) diff --git a/src/commonTest/kotlin/com/insanusmokrassar/sdi/SimpleTest.kt b/src/commonTest/kotlin/com/insanusmokrassar/sdi/SimpleTest.kt index 7866ec0..44d1b8d 100644 --- a/src/commonTest/kotlin/com/insanusmokrassar/sdi/SimpleTest.kt +++ b/src/commonTest/kotlin/com/insanusmokrassar/sdi/SimpleTest.kt @@ -2,7 +2,8 @@ package com.insanusmokrassar.sdi import kotlinx.serialization.* import kotlinx.serialization.json.Json -import kotlin.test.* +import kotlin.test.Test +import kotlin.test.assertEquals interface Simple_ControllerAPI { fun showUp() @@ -42,7 +43,7 @@ class SimpleTest { ] } """.trimIndent() - val module = Json.plain.parse(Module.serializer(), input) + val module = loadModule(input) (module[controllerName] as Simple_ControllerAPI) val controller = (module["controller"] as Simple_Controller) assertEquals(names.toList(), controller.service.names) diff --git a/src/jvmMain/kotlin/com/insanusmokrassar/sdi/JVMHelperTools.kt b/src/jvmMain/kotlin/com/insanusmokrassar/sdi/JVMHelperTools.kt new file mode 100644 index 0000000..e32d946 --- /dev/null +++ b/src/jvmMain/kotlin/com/insanusmokrassar/sdi/JVMHelperTools.kt @@ -0,0 +1,18 @@ +package com.insanusmokrassar.sdi + +import kotlinx.io.InputStream +import kotlinx.serialization.ImplicitReflectionSerializer +import kotlinx.serialization.json.Json +import java.io.File + +@ImplicitReflectionSerializer +fun Json.loadModule(stream: InputStream) = loadModule(stream.reader().readText()) + +@ImplicitReflectionSerializer +fun loadModule(stream: InputStream) = Json.nonstrict.loadModule(stream.reader().readText()) + +@ImplicitReflectionSerializer +fun Json.loadModule(file: File) = loadModule(file.inputStream()) + +@ImplicitReflectionSerializer +fun loadModule(file: File) = Json.nonstrict.loadModule(file.inputStream()) diff --git a/src/jvmMain/kotlin/com/insanusmokrassar/sdi/utils/currentSupertypes.kt b/src/jvmMain/kotlin/com/insanusmokrassar/sdi/utils/currentSupertypes.kt deleted file mode 100644 index b31e1a0..0000000 --- a/src/jvmMain/kotlin/com/insanusmokrassar/sdi/utils/currentSupertypes.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.insanusmokrassar.sdi.utils - -import kotlin.reflect.KClass -import kotlin.reflect.KType - -actual val KClass<*>.currentSupertypes: List - get() = this.supertypes diff --git a/src/jvmMain/kotlin/com/insanusmokrassar/sdi/utils/resolveKClassByPackageName.kt b/src/jvmMain/kotlin/com/insanusmokrassar/sdi/utils/resolveKClassByPackageName.kt new file mode 100644 index 0000000..0405c8e --- /dev/null +++ b/src/jvmMain/kotlin/com/insanusmokrassar/sdi/utils/resolveKClassByPackageName.kt @@ -0,0 +1,5 @@ +package com.insanusmokrassar.sdi.utils + +import kotlin.reflect.KClass + +actual fun resolveKClassByPackageName(packageName: String): KClass<*> = Class.forName(packageName).kotlin diff --git a/src/jvmMain/kotlin/com/insanusmokrassar/sdi/utils/resolveSerializerByPackageName.kt b/src/jvmMain/kotlin/com/insanusmokrassar/sdi/utils/resolveSerializerByPackageName.kt deleted file mode 100644 index 238a50e..0000000 --- a/src/jvmMain/kotlin/com/insanusmokrassar/sdi/utils/resolveSerializerByPackageName.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.insanusmokrassar.sdi.utils - -import kotlinx.serialization.* -import kotlin.reflect.KClass - -@ImplicitReflectionSerializer -actual fun resolveSerializerByPackageName(packageName: String): KSerializer<*> = Class.forName(packageName).kotlin.serializer() - -@ImplicitReflectionSerializer -actual fun resolveSerializerByKClass(kClass: KClass): KSerializer = kClass.serializer() - -actual fun resolveKClassByPackageName(packageName: String): KClass<*> = Class.forName(packageName).kotlin