mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-22 13:46:13 +08:00
fix componentName and smartToString
This commit is contained in:
parent
c35c2c97c8
commit
3806d7ce78
@ -9,14 +9,11 @@
|
||||
|
||||
package net.mamoe.mirai.internal.network.component
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KClassifier
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.KTypeParameter
|
||||
import kotlin.reflect.*
|
||||
import kotlin.reflect.full.allSupertypes
|
||||
|
||||
/**
|
||||
* A key for specific component [T]. Component are not polymorphic.
|
||||
* A key for specific component [T]. Components are not polymorphic.
|
||||
*
|
||||
* @param T is a type hint.
|
||||
*/
|
||||
@ -28,14 +25,36 @@ internal interface ComponentKey<T : Any> {
|
||||
* - If [qualified] is `true`, example: `net.mamoe.mirai.internal.network.components.PacketCodec`.
|
||||
*/
|
||||
fun componentName(qualified: Boolean = false): String {
|
||||
return getComponentTypeArgumentClassifier().renderClassifier(fullName = qualified)
|
||||
val argument = getComponentTypeArgument()
|
||||
argument?.render(qualified)?.let { return it }
|
||||
return argument?.type?.classifier.renderClassifier(qualified)
|
||||
}
|
||||
|
||||
fun smartToString(qualified: Boolean = false): String {
|
||||
return "ComponentKey<${componentName(qualified)}>"
|
||||
}
|
||||
|
||||
private companion object {
|
||||
companion object {
|
||||
// reflection is slow, but it is initialized once only (if memory sufficient).
|
||||
|
||||
private fun KTypeProjection.render(
|
||||
fullName: Boolean
|
||||
): String? {
|
||||
val projection = this
|
||||
|
||||
projection.type?.classifier?.let { classifier ->
|
||||
if (classifier is KClass<*>) {
|
||||
return classifier.run { if (fullName) qualifiedName else simpleName } ?: "?"
|
||||
}
|
||||
}
|
||||
|
||||
projection.type?.arguments?.firstOrNull()?.let { argument ->
|
||||
return argument.render(fullName)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun KClassifier?.renderClassifier(
|
||||
fullName: Boolean
|
||||
): String {
|
||||
@ -53,16 +72,16 @@ internal interface ComponentKey<T : Any> {
|
||||
val upperBounds = upperBounds
|
||||
return when (upperBounds.size) {
|
||||
0 -> toString()
|
||||
1 -> "ComponentKey<${upperBounds[0].renderType(fullName)}>"
|
||||
else -> "ComponentKey<${upperBounds.joinToString(" & ") { it.renderType(fullName) }}>"
|
||||
1 -> upperBounds[0].renderType(fullName)
|
||||
else -> upperBounds.joinToString(" & ") { it.renderType(fullName) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun ComponentKey<*>.getComponentTypeArgumentClassifier(): KClassifier? {
|
||||
private fun ComponentKey<*>.getComponentTypeArgument(): KTypeProjection? {
|
||||
val thisType = this::class.allSupertypes.find { it.classifier == COMPONENT_KEY_K_CLASS }
|
||||
return thisType?.arguments?.firstOrNull()?.type?.classifier
|
||||
return thisType?.arguments?.firstOrNull()
|
||||
}
|
||||
|
||||
val COMPONENT_KEY_K_CLASS = ComponentKey::class
|
||||
private val COMPONENT_KEY_K_CLASS = ComponentKey::class
|
||||
}
|
||||
}
|
@ -13,10 +13,19 @@ import net.mamoe.mirai.internal.test.AbstractTest
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
private class TestComponent {
|
||||
private open class TestComponent {
|
||||
companion object : ComponentKey<TestComponent>
|
||||
}
|
||||
|
||||
|
||||
private interface MyInterface
|
||||
|
||||
private open class TestComponentExt : TestComponent(), MyInterface
|
||||
|
||||
private open class Key<R> : ComponentKey<R> where R : TestComponent, R : MyInterface
|
||||
private class KeyActual : Key<TestComponentExt>()
|
||||
|
||||
|
||||
internal class ComponentKeyTest : AbstractTest() {
|
||||
|
||||
@Test
|
||||
@ -25,9 +34,38 @@ internal class ComponentKeyTest : AbstractTest() {
|
||||
assertEquals(TestComponent::class.qualifiedName!!, TestComponent.componentName(true))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `componentName with erased type argument`() {
|
||||
assertEquals(
|
||||
"TestComponent & MyInterface",
|
||||
Key<TestComponentExt>().componentName(false)
|
||||
)
|
||||
assertEquals(
|
||||
"${TestComponent::class.qualifiedName!!} & ${MyInterface::class.qualifiedName!!}",
|
||||
Key<TestComponentExt>().componentName(true)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `componentName with actual type argument`() {
|
||||
assertEquals(
|
||||
"TestComponentExt",
|
||||
KeyActual().componentName(false)
|
||||
)
|
||||
assertEquals(
|
||||
TestComponentExt::class.qualifiedName!!,
|
||||
KeyActual().componentName(true)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test smartToString`() {
|
||||
assertEquals("ComponentKey<TestComponent>", TestComponent.smartToString(false))
|
||||
assertEquals("ComponentKey<${TestComponent::class.qualifiedName!!}>", TestComponent.smartToString(true))
|
||||
assertEquals(
|
||||
"ComponentKey<${TestComponent::class.qualifiedName!!} & ${MyInterface::class.qualifiedName!!}>",
|
||||
Key<TestComponentExt>().smartToString(true)
|
||||
)
|
||||
assertEquals("ComponentKey<${TestComponentExt::class.qualifiedName!!}>", KeyActual().smartToString(true))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user