diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f45ae5..540d171 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # SDI changelogs +## 0.4.0-rc + +**ALL PROJECT HAS MIGRATED FROM PACKAGE `com.insanusmokrassar` TO `dev.inmo`** + +* `Kotlin`: `1.3.72` -> `1.4.21` +* `Serialization`: `0.20.0` -> `1.0.1` +* New annotation `@SDIIncluded` has been added +* Now `KlassIndex` is used to get `SDIIncluded` things +* Now `Module` class is `Serializable` and is able to be deserialized from `Json` (unfortunately, currently is not + supported serialization) + + ## 0.3.1 * `Kotlin`: `1.3.71` -> `1.3.72` diff --git a/README.md b/README.md index 44a5241..9469313 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # SDI - [ ![Download](https://api.bintray.com/packages/insanusmokrassar/InsanusMokrassar/sdi/images/download.svg) ](https://bintray.com/insanusmokrassar/InsanusMokrassar/sdi/_latestVersion) +[![Download](https://api.bintray.com/packages/insanusmokrassar/InsanusMokrassar/sdi/images/download.svg)](https://bintray.com/insanusmokrassar/InsanusMokrassar/sdi/_latestVersion) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/sdi/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/sdi) [![Build Status](https://travis-ci.com/InsanusMokrassar/SDI.svg?branch=master)](https://travis-ci.com/InsanusMokrassar/SDI) diff --git a/build.gradle b/build.gradle index c628ecf..96915a8 100644 --- a/build.gradle +++ b/build.gradle @@ -1,14 +1,13 @@ buildscript { repositories { - mavenLocal() jcenter() mavenCentral() + maven { url "https://plugins.gradle.org/m2/" } } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" - classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$gradle_bintray_plugin_version" classpath "com.github.breadmoirai:github-release:$github_release_plugin_version" } } @@ -16,10 +15,11 @@ buildscript { plugins { id "org.jetbrains.kotlin.multiplatform" version "$kotlin_version" id "org.jetbrains.kotlin.plugin.serialization" version "$kotlin_version" + id "org.jetbrains.kotlin.kapt" version "$kotlin_version" } -project.version = "0.3.1" -project.group = "com.insanusmokrassar" +project.version = "$version" +project.group = "$group" apply from: "publish.gradle" @@ -28,6 +28,7 @@ repositories { jcenter() mavenCentral() maven { url "https://kotlin.bintray.com/kotlinx" } + maven { url 'https://jitpack.io' } } kotlin { @@ -38,7 +39,7 @@ kotlin { dependencies { implementation kotlin('stdlib') api kotlin('reflect') - api "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$kotlin_serialisation_runtime_version" + api "org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlin_serialisation_runtime_version" } } commonTest { @@ -49,7 +50,7 @@ kotlin { } jvmMain { dependencies { - api "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$kotlin_serialisation_runtime_version" + api "com.github.matfax.klassindex:library:$klassindex_version" } } jvmTest { @@ -59,3 +60,7 @@ kotlin { } } } + +dependencies { + kapt "com.github.matfax.klassindex:processor:$klassindex_version" +} diff --git a/gradle.properties b/gradle.properties index 2167b03..4b1d038 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,11 @@ kotlin.code.style=official -kotlin_version=1.3.72 -kotlin_serialisation_runtime_version=0.20.0 +kotlin_version=1.4.21 +kotlin_serialisation_runtime_version=1.0.1 +klassindex_version=4.1.0-rc.1 -gradle_bintray_plugin_version=1.8.5 github_release_plugin_version=2.2.12 +group=dev.inmo +version=0.4.0-rc + kotlin.incremental.multiplatform=true diff --git a/maven.publish.gradle b/maven.publish.gradle deleted file mode 100644 index de68bd9..0000000 --- a/maven.publish.gradle +++ /dev/null @@ -1,53 +0,0 @@ -apply plugin: 'maven-publish' - -task javadocsJar(type: Jar) { - classifier = 'javadoc' -} - -afterEvaluate { - project.publishing.publications.all { - // rename artifacts - groupId "${project.group}" - if (it.name.contains('kotlinMultiplatform')) { - artifactId = "${project.name}" - } else { - artifactId = "${project.name}-$name" - } - } -} - -publishing { - publications.all { - artifact javadocsJar - - pom { - description = "Simple library for creating dependencies tree using Kotlin Serialization" - name = "Simple Dependency Injector" - url = "https://git.insanusmokrassar.com/InsanusMokrassar/SDI" - - scm { - developerConnection = "scm:git:[fetch=]https://git.insanusmokrassar.com/InsanusMokrassar/SDI.git[push=]https://git.insanusmokrassar.com/InsanusMokrassar/SDI.git" - url = "https://git.insanusmokrassar.com/InsanusMokrassar/SDI.git" - } - - developers { - - developer { - id = "InsanusMokrassar" - name = "Ovsiannikov Aleksei" - email = "ovsyannikov.alexey95@gmail.com" - } - - } - - licenses { - - license { - name = "Apache Software License 2.0" - url = "https://git.insanusmokrassar.com/PostsSystem/SDI/src/master/LICENSE" - } - - } - } - } -} \ No newline at end of file diff --git a/mpp_publish_config.kpsb b/mpp_publish_config.kpsb index 0c114e4..0828bf6 100644 --- a/mpp_publish_config.kpsb +++ b/mpp_publish_config.kpsb @@ -1 +1 @@ -{"bintrayConfig":{"repo":"InsanusMokrassar","packageName":"${project.name}","packageVcs":"https://git.insanusmokrassar.com/InsanusMokrassar/SDI.git","autoPublish":true,"overridePublish":true},"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://git.insanusmokrassar.com/PostsSystem/SDI/src/master/LICENSE"}],"mavenConfig":{"name":"Simple Dependency Injector","description":"Simple library for creating dependencies tree using Kotlin Serialization","url":"https://git.insanusmokrassar.com/InsanusMokrassar/SDI","vcsUrl":"https://git.insanusmokrassar.com/InsanusMokrassar/SDI.git","developers":[{"id":"InsanusMokrassar","name":"Ovsiannikov Aleksei","eMail":"ovsyannikov.alexey95@gmail.com"}]},"type":"Multiplatform"} \ No newline at end of file +{"bintrayConfig":{"repo":"InsanusMokrassar","packageName":"${project.name}","packageVcs":"https://git.insanusmokrassar.com/InsanusMokrassar/SDI.git","autoPublish":true,"overridePublish":true},"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://git.insanusmokrassar.com/PostsSystem/SDI/src/master/LICENSE"}],"mavenConfig":{"name":"Simple Dependency Injector","description":"Simple library for creating dependencies tree using Kotlin Serialization","url":"https://git.insanusmokrassar.com/InsanusMokrassar/SDI","vcsUrl":"https://git.insanusmokrassar.com/InsanusMokrassar/SDI.git","developers":[{"id":"InsanusMokrassar","name":"Ovsiannikov Aleksei","eMail":"ovsyannikov.alexey95@gmail.com"}]}} \ No newline at end of file diff --git a/publish.gradle b/publish.gradle index 58338e1..67f4cf9 100644 --- a/publish.gradle +++ b/publish.gradle @@ -1,59 +1,69 @@ -apply plugin: 'com.jfrog.bintray' +apply plugin: 'maven-publish' -apply from: "maven.publish.gradle" - -bintray { - user = project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER') - key = project.hasProperty('BINTRAY_KEY') ? project.property('BINTRAY_KEY') : System.getenv('BINTRAY_KEY') - filesSpec { - from "${buildDir}/publications/" - eachFile { - String directorySubname = it.getFile().parentFile.name - if (it.getName() == "module.json") { - if (directorySubname == "kotlinMultiplatform") { - it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.module") - } else { - it.setPath("${project.name}-${directorySubname}/${project.version}/${project.name}-${directorySubname}-${project.version}.module") - } - } else { - if (directorySubname == "kotlinMultiplatform" && it.getName() == "pom-default.xml") { - it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.pom") - } else { - it.exclude() - } - } - } - into "${project.group}".replace(".", "/") - } - - publish = true - override = true - - pkg { - repo = "InsanusMokrassar" - name = "${project.name}" - vcsUrl = "https://git.insanusmokrassar.com/InsanusMokrassar/SDI.git" - licenses = ["Apache-2.0"] - version { - name = "${project.version}" - released = new Date() - vcsTag = "${project.version}" - gpg { - sign = true - passphrase = project.hasProperty('signing.gnupg.passphrase') ? project.property('signing.gnupg.passphrase') : System.getenv('signing.gnupg.passphrase') - } - } - } +task javadocsJar(type: Jar) { + classifier = 'javadoc' +} +task sourceJar (type : Jar) { + classifier = 'sources' } -bintrayUpload.doFirst { - publications = publishing.publications.collect { +afterEvaluate { + project.publishing.publications.all { + // rename artifacts + groupId "${project.group}" if (it.name.contains('kotlinMultiplatform')) { - null + artifactId = "${project.name}" + artifact sourceJar } else { - it.name + artifactId = "${project.name}-$name" } - } - null + } } -bintrayUpload.dependsOn publishToMavenLocal \ No newline at end of file +publishing { + publications.all { + artifact javadocsJar + + pom { + description = "Simple library for creating dependencies tree using Kotlin Serialization" + name = "Simple Dependency Injector" + url = "https://git.insanusmokrassar.com/InsanusMokrassar/SDI" + + scm { + developerConnection = "scm:git:[fetch=]https://git.insanusmokrassar.com/InsanusMokrassar/SDI.git[push=]https://git.insanusmokrassar.com/InsanusMokrassar/SDI.git" + url = "https://git.insanusmokrassar.com/InsanusMokrassar/SDI.git" + } + + developers { + + developer { + id = "InsanusMokrassar" + name = "Ovsiannikov Aleksei" + email = "ovsyannikov.alexey95@gmail.com" + } + + } + + licenses { + + license { + name = "Apache Software License 2.0" + url = "https://git.insanusmokrassar.com/PostsSystem/SDI/src/master/LICENSE" + } + + } + } + + repositories { + maven { + name = "bintray" + url = uri("https://api.bintray.com/maven/${project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')}/InsanusMokrassar/${project.name}/;publish=1;override=1") + credentials { + username = project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER') + password = project.hasProperty('BINTRAY_KEY') ? project.property('BINTRAY_KEY') : System.getenv('BINTRAY_KEY') + } + } + } + + } +} diff --git a/src/commonMain/kotlin/com/insanusmokrassar/sdi/Module.kt b/src/commonMain/kotlin/com/insanusmokrassar/sdi/Module.kt deleted file mode 100644 index ea376e6..0000000 --- a/src/commonMain/kotlin/com/insanusmokrassar/sdi/Module.kt +++ /dev/null @@ -1,5 +0,0 @@ -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/ModuleDeserializerStrategy.kt b/src/commonMain/kotlin/com/insanusmokrassar/sdi/ModuleDeserializerStrategy.kt deleted file mode 100644 index da0db8e..0000000 --- a/src/commonMain/kotlin/com/insanusmokrassar/sdi/ModuleDeserializerStrategy.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.insanusmokrassar.sdi - -import com.insanusmokrassar.sdi.utils.createModuleBasedOnConfigRoot -import kotlinx.serialization.* -import kotlinx.serialization.builtins.MapSerializer -import kotlinx.serialization.builtins.serializer -import kotlinx.serialization.json.* -import kotlinx.serialization.modules.SerializersModuleBuilder -import kotlin.reflect.KClass - -@ImplicitReflectionSerializer -internal class ModuleDeserializerStrategy( - private val moduleBuilder: (SerializersModuleBuilder.() -> Unit)? = null, - private vararg val additionalClassesToInclude: KClass<*> -) : DeserializationStrategy { - private val internalSerializer = MapSerializer(String.serializer(), ContextSerializer(Any::class)) - override val descriptor: SerialDescriptor - get() = internalSerializer.descriptor - - override fun deserialize(decoder: Decoder): Module { - val json = JsonObjectSerializer.deserialize(decoder) - val jsonSerialFormat = createModuleBasedOnConfigRoot( - json, - moduleBuilder, - decoder.context, - *additionalClassesToInclude - ) - val resultJson = JsonObject( - json.keys.associateWith { JsonPrimitive(it) } - ) - val map = jsonSerialFormat.fromJson(internalSerializer, resultJson) - return Module(map) - } - - override fun patch(decoder: Decoder, old: Module): Module = throw UpdateNotSupportedException("Module") -} diff --git a/src/commonMain/kotlin/com/insanusmokrassar/sdi/HelperTools.kt b/src/commonMain/kotlin/dev/inmo/sdi/HelperTools.kt similarity index 69% rename from src/commonMain/kotlin/com/insanusmokrassar/sdi/HelperTools.kt rename to src/commonMain/kotlin/dev/inmo/sdi/HelperTools.kt index 19aae93..8a04b64 100644 --- a/src/commonMain/kotlin/com/insanusmokrassar/sdi/HelperTools.kt +++ b/src/commonMain/kotlin/dev/inmo/sdi/HelperTools.kt @@ -1,22 +1,25 @@ -package com.insanusmokrassar.sdi +package dev.inmo.sdi -import kotlinx.serialization.ImplicitReflectionSerializer +import kotlinx.serialization.InternalSerializationApi import kotlinx.serialization.json.Json +import kotlinx.serialization.modules.SerializersModule import kotlinx.serialization.modules.SerializersModuleBuilder import kotlin.reflect.KClass +@InternalSerializationApi internal val nonStrictJson = Json { isLenient = true ignoreUnknownKeys = true - serializeSpecialFloatingPointValues = true + serializersModule = SerializersModule { + includeClassesForSDI() + } } -@ImplicitReflectionSerializer fun Json.loadModule( json: String, vararg additionalClassesToInclude: KClass<*>, moduleBuilder: (SerializersModuleBuilder.() -> Unit)? = null -): Module = parse( +): Module = decodeFromString( if (moduleBuilder != null) { ModuleDeserializerStrategy(moduleBuilder, *additionalClassesToInclude) } else { @@ -25,9 +28,12 @@ fun Json.loadModule( json ) -@ImplicitReflectionSerializer +@InternalSerializationApi fun loadModule( json: String, vararg additionalClassesToInclude: KClass<*>, moduleBuilder: (SerializersModuleBuilder.() -> Unit)? = null -): Module = nonStrictJson.loadModule(json, *additionalClassesToInclude, moduleBuilder = moduleBuilder) +): Module = nonStrictJson.loadModule(json, *additionalClassesToInclude) { + includeClassesForSDI() + moduleBuilder ?.invoke(this) +} diff --git a/src/commonMain/kotlin/dev/inmo/sdi/Module.kt b/src/commonMain/kotlin/dev/inmo/sdi/Module.kt new file mode 100644 index 0000000..60a8b9a --- /dev/null +++ b/src/commonMain/kotlin/dev/inmo/sdi/Module.kt @@ -0,0 +1,7 @@ +package dev.inmo.sdi + +import kotlinx.serialization.Contextual +import kotlinx.serialization.Serializable + +@Serializable(ModuleFullSerializer::class) +class Module internal constructor(base: Map) : Map by base \ No newline at end of file diff --git a/src/commonMain/kotlin/dev/inmo/sdi/ModuleDeserializerStrategy.kt b/src/commonMain/kotlin/dev/inmo/sdi/ModuleDeserializerStrategy.kt new file mode 100644 index 0000000..a22873e --- /dev/null +++ b/src/commonMain/kotlin/dev/inmo/sdi/ModuleDeserializerStrategy.kt @@ -0,0 +1,50 @@ +package dev.inmo.sdi + +import dev.inmo.sdi.utils.createModuleBasedOnConfigRoot +import kotlinx.serialization.* +import kotlinx.serialization.builtins.MapSerializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.json.* +import kotlinx.serialization.modules.SerializersModuleBuilder +import kotlin.reflect.KClass + +internal class ModuleDeserializerStrategy( + private val moduleBuilder: (SerializersModuleBuilder.() -> Unit)? = null, + private vararg val additionalClassesToInclude: KClass<*> +) : DeserializationStrategy { + constructor() : this(null) + + private val internalSerializer = MapSerializer(String.serializer(), ContextualSerializer(Any::class)) + override val descriptor: SerialDescriptor + get() = internalSerializer.descriptor + + @InternalSerializationApi + override fun deserialize(decoder: Decoder): Module { + val json = JsonObject.serializer().deserialize(decoder) + val jsonSerialFormat = createModuleBasedOnConfigRoot( + json, + moduleBuilder, + decoder.serializersModule, + *additionalClassesToInclude + ) + val resultJson = JsonObject( + json.keys.associateWith { JsonPrimitive(it) } + ) + val map = jsonSerialFormat.decodeFromJsonElement(internalSerializer, resultJson) + return Module(map) + } +} + +@Serializer(Module::class) +internal class ModuleFullSerializer( + private val moduleBuilder: (SerializersModuleBuilder.() -> Unit)? = null, + private vararg val additionalClassesToInclude: KClass<*> +) : KSerializer, + DeserializationStrategy by ModuleDeserializerStrategy(moduleBuilder, *additionalClassesToInclude) { + constructor() : this(null) + + override fun serialize(encoder: Encoder, value: Module) = throw NotImplementedError("Currently there is no support for serialization of modules") +} diff --git a/src/commonMain/kotlin/dev/inmo/sdi/SDIIncluded.kt b/src/commonMain/kotlin/dev/inmo/sdi/SDIIncluded.kt new file mode 100644 index 0000000..ad2e89d --- /dev/null +++ b/src/commonMain/kotlin/dev/inmo/sdi/SDIIncluded.kt @@ -0,0 +1,25 @@ +package dev.inmo.sdi + +import kotlinx.serialization.InternalSerializationApi +import kotlinx.serialization.modules.SerializersModuleBuilder +import kotlinx.serialization.serializer +import kotlin.reflect.KClass + +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.CLASS) +expect annotation class SDIIncluded(val customNames: Array = []) + +internal expect fun getClassesForIncludingInSDI(): List, List>> + +@Suppress("NOTHING_TO_INLINE") +@InternalSerializationApi +private inline fun KClass.includeInBuilder( + builder: SerializersModuleBuilder +) = builder.contextual(this, serializer()) + +@InternalSerializationApi +fun SerializersModuleBuilder.includeClassesForSDI() { + getClassesForIncludingInSDI().forEach { (kclass, _) -> + kclass.includeInBuilder(this) + } +} diff --git a/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/DependencyResolver.kt b/src/commonMain/kotlin/dev/inmo/sdi/utils/DependencyResolver.kt similarity index 76% rename from src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/DependencyResolver.kt rename to src/commonMain/kotlin/dev/inmo/sdi/utils/DependencyResolver.kt index 8c0eaa0..50bda14 100644 --- a/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/DependencyResolver.kt +++ b/src/commonMain/kotlin/dev/inmo/sdi/utils/DependencyResolver.kt @@ -1,25 +1,25 @@ -package com.insanusmokrassar.sdi.utils +package dev.inmo.sdi.utils import kotlinx.serialization.* +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.json.* import kotlinx.serialization.modules.SerializersModuleBuilder import kotlin.reflect.KClass internal object AlreadyRegisteredException : Exception() -@ImplicitReflectionSerializer internal class DependencyResolver( serialModuleBuilder: SerializersModuleBuilder, kClass: KClass, private val formatterGetter: () -> Json, private val dependencyGetter: (String) -> Any ) : KSerializer { - private val originalSerializer: KSerializer = try { - kClass.serializer() - } catch (e: Exception) { - ContextSerializer(kClass) - } + @InternalSerializationApi + private val originalSerializer: KSerializer = kClass.serializerOrNull() ?: ContextualSerializer(kClass) private val objectsCache = mutableMapOf() + @InternalSerializationApi override val descriptor: SerialDescriptor = originalSerializer.descriptor init { @@ -39,8 +39,9 @@ internal class DependencyResolver( } } + @InternalSerializationApi override fun deserialize(decoder: Decoder): T { - val decoded = decoder.decodeSerializableValue(JsonElementSerializer) + val decoded = decoder.decodeSerializableValue(JsonElement.serializer()) return when { decoded is JsonPrimitive && decoded.contentOrNull != null -> decoded.content.let { dependencyName -> @Suppress("UNCHECKED_CAST") @@ -49,14 +50,15 @@ internal class DependencyResolver( } } decoded is JsonArray -> { - val serializer = resolveSerializerByPackageName(decoded.getPrimitive(0).content) + val serializer = resolveSerializerByPackageName(decoded[0].jsonPrimitive.content) @Suppress("UNCHECKED_CAST") - formatterGetter().fromJson(serializer, decoded[1]) as T + formatterGetter().decodeFromJsonElement(serializer, decoded[1]) as T } - else -> formatterGetter().fromJson(originalSerializer, decoded) + else -> formatterGetter().decodeFromJsonElement(originalSerializer, decoded) } } + @InternalSerializationApi override fun serialize(encoder: Encoder, value: T) { objectsCache.keys.firstOrNull { objectsCache[it] === value diff --git a/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/JsonAdaptations.kt b/src/commonMain/kotlin/dev/inmo/sdi/utils/JsonAdaptations.kt similarity index 79% rename from src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/JsonAdaptations.kt rename to src/commonMain/kotlin/dev/inmo/sdi/utils/JsonAdaptations.kt index 2771ce5..de9580b 100644 --- a/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/JsonAdaptations.kt +++ b/src/commonMain/kotlin/dev/inmo/sdi/utils/JsonAdaptations.kt @@ -1,6 +1,6 @@ -package com.insanusmokrassar.sdi.utils +package dev.inmo.sdi.utils -import kotlinx.serialization.ImplicitReflectionSerializer +import dev.inmo.sdi.getClassesForIncludingInSDI import kotlinx.serialization.InternalSerializationApi import kotlinx.serialization.json.* import kotlinx.serialization.modules.* @@ -8,6 +8,12 @@ import kotlin.reflect.KClass private typealias PackageOrOtherDependencyNamePair = Pair +private val namesToTheirClasses = getClassesForIncludingInSDI().flatMap { + (it.second + it.first.qualifiedName!!).map { name -> + name to it.first.qualifiedName!! + } +}.toMap() + private fun JsonElement.resolvePackageName(currentKey: String, otherDependenciesKeys: Set): PackageOrOtherDependencyNamePair { return when (this) { is JsonPrimitive -> contentOrNull ?.let { @@ -17,16 +23,20 @@ private fun JsonElement.resolvePackageName(currentKey: String, otherDependencies it to null } } ?: throw IllegalArgumentException("Value on dependency name \"$currentKey\" is invalid: provided $this, but expected package name or other dependency name string") - is JsonObject -> return currentKey to null - is JsonArray -> return getPrimitive(0).contentOrNull ?.let { it to null } ?: throw IllegalArgumentException("Value on first argument of dependency value must be its package as a string, but was provided ${get(0)}") + is JsonObject -> if (currentKey in otherDependenciesKeys) { + null to currentKey + } else { + (namesToTheirClasses[currentKey] ?: currentKey) to null + } + is JsonArray -> return get(0).jsonPrimitive.contentOrNull ?.let { (namesToTheirClasses[it] ?: it) to null } ?: throw IllegalArgumentException("Value on first argument of dependency value must be its package as a string, but was provided ${get(0)}") } } -@ImplicitReflectionSerializer +@InternalSerializationApi internal fun createModuleBasedOnConfigRoot( jsonObject: JsonObject, moduleBuilder: (SerializersModuleBuilder.() -> Unit)? = null, - baseContext: SerialModule, + baseContext: SerializersModule, vararg additionalClassesToInclude: KClass<*> ): Json { lateinit var caches: Map Any> @@ -53,7 +63,7 @@ internal fun createModuleBasedOnConfigRoot( } is JsonArray -> { if (elemValue.size > 1) { - elemValue.getObject(1) + elemValue[1].jsonObject } else { JsonObject(emptyMap()) } @@ -61,7 +71,7 @@ internal fun createModuleBasedOnConfigRoot( } val serializer = resolveSerializerByPackageName(packageName) - return@callback jsonStringFormat.fromJson(serializer, argumentsObject) as Any + return@callback jsonStringFormat.decodeFromJsonElement(serializer, argumentsObject) as Any } }.toMap() @@ -105,10 +115,10 @@ internal fun createModuleBasedOnConfigRoot( } } ) - return Json( - configuration = JsonConfiguration(useArrayPolymorphism = true), - context = context - ).also { + return Json { + useArrayPolymorphism = true + serializersModule = context + }.also { jsonStringFormat = it } } diff --git a/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/OptionalContextualIncluding.kt b/src/commonMain/kotlin/dev/inmo/sdi/utils/OptionalContextualIncluding.kt similarity index 70% rename from src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/OptionalContextualIncluding.kt rename to src/commonMain/kotlin/dev/inmo/sdi/utils/OptionalContextualIncluding.kt index 085aa46..e6e315e 100644 --- a/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/OptionalContextualIncluding.kt +++ b/src/commonMain/kotlin/dev/inmo/sdi/utils/OptionalContextualIncluding.kt @@ -1,7 +1,6 @@ -package com.insanusmokrassar.sdi.utils +package dev.inmo.sdi.utils -import kotlinx.serialization.InternalSerializationApi -import kotlinx.serialization.KSerializer +import kotlinx.serialization.* import kotlinx.serialization.modules.* import kotlin.reflect.KClass @@ -11,7 +10,7 @@ fun SerializersModuleBuilder.optionalContextual( ) = try { contextual(kClass, kSerializer) true -} catch (e: SerializerAlreadyRegisteredException) { +} catch (e: SerializationException) { false } diff --git a/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/TypesHelper.kt b/src/commonMain/kotlin/dev/inmo/sdi/utils/TypesHelper.kt similarity index 83% rename from src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/TypesHelper.kt rename to src/commonMain/kotlin/dev/inmo/sdi/utils/TypesHelper.kt index c869c5d..06210f0 100644 --- a/src/commonMain/kotlin/com/insanusmokrassar/sdi/utils/TypesHelper.kt +++ b/src/commonMain/kotlin/dev/inmo/sdi/utils/TypesHelper.kt @@ -1,18 +1,21 @@ -package com.insanusmokrassar.sdi.utils +package dev.inmo.sdi.utils import kotlinx.serialization.* import kotlin.reflect.KClass +import kotlin.reflect.KType internal expect fun resolveKClassByPackageName(packageName: String): KClass<*> -@ImplicitReflectionSerializer +@InternalSerializationApi internal fun resolveSerializerByKClass(kClass: KClass): KSerializer = kClass.serializer() -@ImplicitReflectionSerializer +@InternalSerializationApi internal fun resolveSerializerByPackageName(packageName: String): KSerializer<*> = resolveSerializerByKClass( resolveKClassByPackageName(packageName) ) +internal expect val KClass.supertypes: List + internal val KClass<*>.allSubclasses: Set> get() { val subclasses = mutableSetOf>() diff --git a/src/commonTest/kotlin/com/insanusmokrassar/sdi/ListTest.kt b/src/commonTest/kotlin/dev/inmo/sdi/ListTest.kt similarity index 90% rename from src/commonTest/kotlin/com/insanusmokrassar/sdi/ListTest.kt rename to src/commonTest/kotlin/dev/inmo/sdi/ListTest.kt index 669f8dd..e22ca4c 100644 --- a/src/commonTest/kotlin/com/insanusmokrassar/sdi/ListTest.kt +++ b/src/commonTest/kotlin/dev/inmo/sdi/ListTest.kt @@ -1,4 +1,4 @@ -package com.insanusmokrassar.sdi +package dev.inmo.sdi import kotlinx.serialization.* import kotlin.test.Test @@ -12,14 +12,14 @@ interface List_ChildAPI { } @Serializable -class List_Parent(override val services: List<@ContextualSerialization List_ChildAPI>) : List_ParentalAPI +class List_Parent(override val services: List<@Contextual List_ChildAPI>) : List_ParentalAPI @Serializable class List_Child(override val names: List) : List_ChildAPI -@ImplicitReflectionSerializer class ListTest { val servicesNum = 10 + @InternalSerializationApi @Test fun test_that_simple_config_correctly_work() { val names = (0 until servicesNum).map { diff --git a/src/commonTest/kotlin/com/insanusmokrassar/sdi/SimpleCustomObjectTest.kt b/src/commonTest/kotlin/dev/inmo/sdi/SimpleCustomObjectTest.kt similarity index 86% rename from src/commonTest/kotlin/com/insanusmokrassar/sdi/SimpleCustomObjectTest.kt rename to src/commonTest/kotlin/dev/inmo/sdi/SimpleCustomObjectTest.kt index 579ba31..9f5f1c0 100644 --- a/src/commonTest/kotlin/com/insanusmokrassar/sdi/SimpleCustomObjectTest.kt +++ b/src/commonTest/kotlin/dev/inmo/sdi/SimpleCustomObjectTest.kt @@ -1,4 +1,4 @@ -package com.insanusmokrassar.sdi +package dev.inmo.sdi import kotlinx.serialization.* import kotlin.test.Test @@ -12,28 +12,32 @@ interface SimpleCustomObject_ServiceAPI { } @Serializable -class SimpleCustomObject_Controller(@ContextualSerialization val service: SimpleCustomObject_ServiceAPI) : SimpleCustomObject_ControllerAPI { +class SimpleCustomObject_Controller(@Contextual val service: SimpleCustomObject_ServiceAPI) : + SimpleCustomObject_ControllerAPI { override fun showUp() { println("Inited with name \"${service.names}\"") } } @Serializable -class SimpleCustomObject_CustomController1(@ContextualSerialization val service: SimpleCustomObject_ServiceAPI) : SimpleCustomObject_ControllerAPI { +class SimpleCustomObject_CustomController1(@Contextual val service: SimpleCustomObject_ServiceAPI) : + SimpleCustomObject_ControllerAPI { override fun showUp() { println("Inited with name \"${service.names}\"") } } @Serializable -class SimpleCustomObject_CustomController2(@ContextualSerialization val service: SimpleCustomObject_BusinessService) : SimpleCustomObject_ControllerAPI { +class SimpleCustomObject_CustomController2(@Contextual val service: SimpleCustomObject_BusinessService) : + SimpleCustomObject_ControllerAPI { override fun showUp() { println("Inited with name \"${service.names}\"") } } @Serializable -class SimpleCustomObject_CustomController3(@ContextualSerialization val service: SimpleCustomObject_ServiceAPI) : SimpleCustomObject_ControllerAPI { +class SimpleCustomObject_CustomController3(@Contextual val service: SimpleCustomObject_ServiceAPI) : + SimpleCustomObject_ControllerAPI { override fun showUp() { println("Inited with name \"${service.names}\"") } @@ -43,8 +47,8 @@ class SimpleCustomObject_BusinessService(override val names: List) : Sim @Serializable class SimpleCustomObject_BusinessService1(override val names: List) : SimpleCustomObject_ServiceAPI -@ImplicitReflectionSerializer class SimpleCustomObjectTest { + @InternalSerializationApi @Test fun test_that_simple_config_correctly_work() { val names = arrayOf("nameOne", "nameTwo") diff --git a/src/commonTest/kotlin/com/insanusmokrassar/sdi/SimpleTest.kt b/src/commonTest/kotlin/dev/inmo/sdi/SimpleTest.kt similarity index 88% rename from src/commonTest/kotlin/com/insanusmokrassar/sdi/SimpleTest.kt rename to src/commonTest/kotlin/dev/inmo/sdi/SimpleTest.kt index c528c5b..4d66dcd 100644 --- a/src/commonTest/kotlin/com/insanusmokrassar/sdi/SimpleTest.kt +++ b/src/commonTest/kotlin/dev/inmo/sdi/SimpleTest.kt @@ -1,4 +1,4 @@ -package com.insanusmokrassar.sdi +package dev.inmo.sdi import kotlinx.serialization.* import kotlin.test.Test @@ -12,7 +12,7 @@ interface Simple_ServiceAPI { } @Serializable -class Simple_Controller(@ContextualSerialization val service: Simple_ServiceAPI) : Simple_ControllerAPI { +class Simple_Controller(@Contextual val service: Simple_ServiceAPI) : Simple_ControllerAPI { override fun showUp() { println("Inited with name \"${service.names}\"") } @@ -20,8 +20,8 @@ class Simple_Controller(@ContextualSerialization val service: Simple_ServiceAPI) @Serializable class Simple_BusinessService(override val names: List) : Simple_ServiceAPI -@ImplicitReflectionSerializer class SimpleTest { + @InternalSerializationApi @Test fun test_that_simple_config_correctly_work() { val names = arrayOf("nameOne", "nameTwo") diff --git a/src/jvmMain/kotlin/com/insanusmokrassar/sdi/utils/resolveKClassByPackageName.kt b/src/jvmMain/kotlin/com/insanusmokrassar/sdi/utils/resolveKClassByPackageName.kt deleted file mode 100644 index 0405c8e..0000000 --- a/src/jvmMain/kotlin/com/insanusmokrassar/sdi/utils/resolveKClassByPackageName.kt +++ /dev/null @@ -1,5 +0,0 @@ -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/JVMHelperTools.kt b/src/jvmMain/kotlin/dev/inmo/sdi/JVMHelperTools.kt similarity index 84% rename from src/jvmMain/kotlin/com/insanusmokrassar/sdi/JVMHelperTools.kt rename to src/jvmMain/kotlin/dev/inmo/sdi/JVMHelperTools.kt index 538aed2..4adc715 100644 --- a/src/jvmMain/kotlin/com/insanusmokrassar/sdi/JVMHelperTools.kt +++ b/src/jvmMain/kotlin/dev/inmo/sdi/JVMHelperTools.kt @@ -1,34 +1,36 @@ -package com.insanusmokrassar.sdi +package dev.inmo.sdi +import kotlinx.serialization.InternalSerializationApi import kotlin.reflect.KClass -import kotlinx.serialization.ImplicitReflectionSerializer import kotlinx.serialization.json.Json import kotlinx.serialization.modules.SerializersModuleBuilder import java.io.File import java.io.InputStream -@ImplicitReflectionSerializer + fun Json.loadModule( stream: InputStream, vararg additionalClassesToInclude: KClass<*>, moduleBuilder: (SerializersModuleBuilder.() -> Unit)? = null ) = loadModule(stream.reader().readText(), *additionalClassesToInclude, moduleBuilder = moduleBuilder) -@ImplicitReflectionSerializer + +@InternalSerializationApi fun loadModule( stream: InputStream, vararg additionalClassesToInclude: KClass<*>, moduleBuilder: (SerializersModuleBuilder.() -> Unit)? = null ) = nonStrictJson.loadModule(stream, *additionalClassesToInclude, moduleBuilder = moduleBuilder) -@ImplicitReflectionSerializer + fun Json.loadModule( file: File, vararg additionalClassesToInclude: KClass<*>, moduleBuilder: (SerializersModuleBuilder.() -> Unit)? = null ) = loadModule(file.inputStream(), *additionalClassesToInclude, moduleBuilder = moduleBuilder) -@ImplicitReflectionSerializer + +@InternalSerializationApi fun loadModule( file: File, vararg additionalClassesToInclude: KClass<*>, diff --git a/src/jvmMain/kotlin/dev/inmo/sdi/SDIIncludedRealization.kt b/src/jvmMain/kotlin/dev/inmo/sdi/SDIIncludedRealization.kt new file mode 100644 index 0000000..66ed251 --- /dev/null +++ b/src/jvmMain/kotlin/dev/inmo/sdi/SDIIncludedRealization.kt @@ -0,0 +1,18 @@ +package dev.inmo.sdi + +import com.github.matfax.klassindex.IndexAnnotated +import com.github.matfax.klassindex.KlassIndex +import kotlin.reflect.KClass + +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.CLASS) +@IndexAnnotated +actual annotation class SDIIncluded actual constructor(actual val customNames: Array) + +internal actual fun getClassesForIncludingInSDI(): List, List>> = KlassIndex.getAnnotated( + SDIIncluded::class +).map { + it.let { + it to it.annotations.flatMap { (it as? SDIIncluded) ?.customNames ?.toList() ?: emptyList() } + } +} diff --git a/src/jvmMain/kotlin/dev/inmo/sdi/utils/resolveKClassByPackageName.kt b/src/jvmMain/kotlin/dev/inmo/sdi/utils/resolveKClassByPackageName.kt new file mode 100644 index 0000000..a8965c0 --- /dev/null +++ b/src/jvmMain/kotlin/dev/inmo/sdi/utils/resolveKClassByPackageName.kt @@ -0,0 +1,8 @@ +package dev.inmo.sdi.utils + +import kotlin.reflect.KClass +import kotlin.reflect.KType + +actual fun resolveKClassByPackageName(packageName: String): KClass<*> = Class.forName(packageName).kotlin +internal actual val KClass.supertypes: List + get() = supertypes \ No newline at end of file