experimentally add SDIIncluded

This commit is contained in:
InsanusMokrassar 2020-11-12 00:44:19 +06:00
parent d4bca9d09f
commit e0aa2b4456
10 changed files with 75 additions and 2 deletions

View File

@ -46,6 +46,11 @@ kotlin {
implementation kotlin('test-annotations-common') implementation kotlin('test-annotations-common')
} }
} }
jvmMain {
dependencies {
api "org.atteo.classindex:classindex:$classindex_version"
}
}
jvmTest { jvmTest {
dependencies { dependencies {
implementation kotlin('test-junit') implementation kotlin('test-junit')

View File

@ -1,6 +1,7 @@
kotlin.code.style=official kotlin.code.style=official
kotlin_version=1.4.10 kotlin_version=1.4.10
kotlin_serialisation_runtime_version=1.0.1 kotlin_serialisation_runtime_version=1.0.1
classindex_version=3.4
gradle_bintray_plugin_version=1.8.5 gradle_bintray_plugin_version=1.8.5
github_release_plugin_version=2.2.12 github_release_plugin_version=2.2.12

View File

@ -1,12 +1,18 @@
package dev.inmo.sdi package dev.inmo.sdi
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.SerializersModuleBuilder import kotlinx.serialization.modules.SerializersModuleBuilder
import kotlin.reflect.KClass import kotlin.reflect.KClass
@InternalSerializationApi
internal val nonStrictJson = Json { internal val nonStrictJson = Json {
isLenient = true isLenient = true
ignoreUnknownKeys = true ignoreUnknownKeys = true
serializersModule = SerializersModule {
includeClassesForSDI()
}
} }
fun Json.loadModule( fun Json.loadModule(
@ -22,6 +28,7 @@ fun Json.loadModule(
json json
) )
@InternalSerializationApi
fun loadModule( fun loadModule(
json: String, json: String,
vararg additionalClassesToInclude: KClass<*>, vararg additionalClassesToInclude: KClass<*>,

View File

@ -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<String> = [])
internal expect fun getClassesForIncludingInSDI(): List<Pair<KClass<*>, List<String>>>
@Suppress("NOTHING_TO_INLINE")
@InternalSerializationApi
private inline fun <T : Any> KClass<T>.includeInBuilder(
builder: SerializersModuleBuilder
) = builder.contextual(this, serializer())
@InternalSerializationApi
fun SerializersModuleBuilder.includeClassesForSDI() {
getClassesForIncludingInSDI().forEach { (kclass, _) ->
kclass.includeInBuilder(this)
}
}

View File

@ -1,5 +1,6 @@
package dev.inmo.sdi.utils package dev.inmo.sdi.utils
import dev.inmo.sdi.getClassesForIncludingInSDI
import kotlinx.serialization.InternalSerializationApi import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.json.* import kotlinx.serialization.json.*
import kotlinx.serialization.modules.* import kotlinx.serialization.modules.*
@ -7,6 +8,12 @@ import kotlin.reflect.KClass
private typealias PackageOrOtherDependencyNamePair = Pair<String?, String?> private typealias PackageOrOtherDependencyNamePair = Pair<String?, String?>
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<String>): PackageOrOtherDependencyNamePair { private fun JsonElement.resolvePackageName(currentKey: String, otherDependenciesKeys: Set<String>): PackageOrOtherDependencyNamePair {
return when (this) { return when (this) {
is JsonPrimitive -> contentOrNull ?.let { is JsonPrimitive -> contentOrNull ?.let {
@ -16,8 +23,12 @@ private fun JsonElement.resolvePackageName(currentKey: String, otherDependencies
it to null it to null
} }
} ?: throw IllegalArgumentException("Value on dependency name \"$currentKey\" is invalid: provided $this, but expected package name or other dependency name string") } ?: 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 JsonObject -> if (currentKey in otherDependenciesKeys) {
is JsonArray -> return get(0).jsonPrimitive.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)}") 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)}")
} }
} }

View File

@ -19,6 +19,7 @@ class List_Child(override val names: List<String>) : List_ChildAPI
class ListTest { class ListTest {
val servicesNum = 10 val servicesNum = 10
@InternalSerializationApi
@Test @Test
fun test_that_simple_config_correctly_work() { fun test_that_simple_config_correctly_work() {
val names = (0 until servicesNum).map { val names = (0 until servicesNum).map {

View File

@ -48,6 +48,7 @@ class SimpleCustomObject_BusinessService(override val names: List<String>) : Sim
class SimpleCustomObject_BusinessService1(override val names: List<String>) : SimpleCustomObject_ServiceAPI class SimpleCustomObject_BusinessService1(override val names: List<String>) : SimpleCustomObject_ServiceAPI
class SimpleCustomObjectTest { class SimpleCustomObjectTest {
@InternalSerializationApi
@Test @Test
fun test_that_simple_config_correctly_work() { fun test_that_simple_config_correctly_work() {
val names = arrayOf("nameOne", "nameTwo") val names = arrayOf("nameOne", "nameTwo")

View File

@ -21,6 +21,7 @@ class Simple_Controller(@Contextual val service: Simple_ServiceAPI) : Simple_Con
class Simple_BusinessService(override val names: List<String>) : Simple_ServiceAPI class Simple_BusinessService(override val names: List<String>) : Simple_ServiceAPI
class SimpleTest { class SimpleTest {
@InternalSerializationApi
@Test @Test
fun test_that_simple_config_correctly_work() { fun test_that_simple_config_correctly_work() {
val names = arrayOf("nameOne", "nameTwo") val names = arrayOf("nameOne", "nameTwo")

View File

@ -1,5 +1,6 @@
package dev.inmo.sdi package dev.inmo.sdi
import kotlinx.serialization.InternalSerializationApi
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModuleBuilder import kotlinx.serialization.modules.SerializersModuleBuilder
@ -14,6 +15,7 @@ fun Json.loadModule(
) = loadModule(stream.reader().readText(), *additionalClassesToInclude, moduleBuilder = moduleBuilder) ) = loadModule(stream.reader().readText(), *additionalClassesToInclude, moduleBuilder = moduleBuilder)
@InternalSerializationApi
fun loadModule( fun loadModule(
stream: InputStream, stream: InputStream,
vararg additionalClassesToInclude: KClass<*>, vararg additionalClassesToInclude: KClass<*>,
@ -28,6 +30,7 @@ fun Json.loadModule(
) = loadModule(file.inputStream(), *additionalClassesToInclude, moduleBuilder = moduleBuilder) ) = loadModule(file.inputStream(), *additionalClassesToInclude, moduleBuilder = moduleBuilder)
@InternalSerializationApi
fun loadModule( fun loadModule(
file: File, file: File,
vararg additionalClassesToInclude: KClass<*>, vararg additionalClassesToInclude: KClass<*>,

View File

@ -0,0 +1,18 @@
package dev.inmo.sdi
import org.atteo.classindex.ClassIndex
import org.atteo.classindex.IndexAnnotated
import kotlin.reflect.KClass
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS)
@IndexAnnotated
actual annotation class SDIIncluded actual constructor(actual val customNames: Array<String>)
internal actual fun getClassesForIncludingInSDI(): List<Pair<KClass<*>, List<String>>> = ClassIndex.getAnnotated(
SDIIncluded::class.java
).map {
it.kotlin.let {
it to it.annotations.flatMap { (it as? SDIIncluded) ?.customNames ?.toList() ?: emptyList() }
}
}