From a2f73de90fb9c9d0ea7a5e7e9e6b9e445a8094ee Mon Sep 17 00:00:00 2001 From: Linnea Gräf Date: Sun, 15 Dec 2024 19:31:46 +0100 Subject: refactor: Move DI to its own package --- collect.py | 11 ++++ src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt | 2 +- src/main/kotlin/moe/nea/ledger/Ledger.kt | 2 +- src/main/kotlin/moe/nea/ledger/LedgerLogger.kt | 2 +- src/main/kotlin/moe/nea/ledger/LogChatCommand.kt | 2 +- src/main/kotlin/moe/nea/ledger/QueryCommand.kt | 2 +- .../kotlin/moe/nea/ledger/TelemetryProvider.kt | 4 +- .../nea/ledger/modules/AuctionHouseDetection.kt | 2 +- .../kotlin/moe/nea/ledger/modules/BankDetection.kt | 2 +- .../moe/nea/ledger/modules/BazaarDetection.kt | 2 +- .../moe/nea/ledger/modules/BazaarOrderDetection.kt | 2 +- .../kotlin/moe/nea/ledger/modules/BitsDetection.kt | 2 +- .../moe/nea/ledger/modules/BitsShopDetection.kt | 2 +- .../moe/nea/ledger/modules/ChestDetection.kt | 2 +- .../nea/ledger/modules/DungeonChestDetection.kt | 2 +- .../kotlin/moe/nea/ledger/modules/KatDetection.kt | 2 +- .../moe/nea/ledger/modules/KuudraChestDetection.kt | 2 +- .../moe/nea/ledger/modules/MinionDetection.kt | 2 +- .../kotlin/moe/nea/ledger/modules/NpcDetection.kt | 2 +- .../moe/nea/ledger/modules/VisitorDetection.kt | 2 +- src/main/kotlin/moe/nea/ledger/utils/DI.kt | 68 ---------------------- src/main/kotlin/moe/nea/ledger/utils/DIProvider.kt | 51 ---------------- src/main/kotlin/moe/nea/ledger/utils/ErrorUtil.kt | 1 + src/main/kotlin/moe/nea/ledger/utils/Inject.kt | 6 -- src/main/kotlin/moe/nea/ledger/utils/di/DI.kt | 68 ++++++++++++++++++++++ .../kotlin/moe/nea/ledger/utils/di/DIProvider.kt | 51 ++++++++++++++++ src/main/kotlin/moe/nea/ledger/utils/di/Inject.kt | 6 ++ 27 files changed, 157 insertions(+), 145 deletions(-) create mode 100644 collect.py delete mode 100644 src/main/kotlin/moe/nea/ledger/utils/DI.kt delete mode 100644 src/main/kotlin/moe/nea/ledger/utils/DIProvider.kt delete mode 100644 src/main/kotlin/moe/nea/ledger/utils/Inject.kt create mode 100644 src/main/kotlin/moe/nea/ledger/utils/di/DI.kt create mode 100644 src/main/kotlin/moe/nea/ledger/utils/di/DIProvider.kt create mode 100644 src/main/kotlin/moe/nea/ledger/utils/di/Inject.kt diff --git a/collect.py b/collect.py new file mode 100644 index 0000000..2a33435 --- /dev/null +++ b/collect.py @@ -0,0 +1,11 @@ +import json +from pathlib import Path + +repo = Path("/home/nea/src/NotEnoughUpdates-REPO") +l = {} +for f in (repo / "items").glob("*.json"): + with f.open('r') as fp: + j = json.load(fp) + l[j["internalname"]] = j["displayname"] +with Path("./compiled.json").open("w") as fp: + json.dump(l, fp) diff --git a/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt b/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt index f2906b8..121586e 100644 --- a/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt +++ b/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt @@ -28,7 +28,7 @@ class ItemIdProvider { private val knownNames = mutableMapOf() @SubscribeEvent - fun onTick(event: RegistrationFinishedEvent) { + fun onRegistrationFinished(event: RegistrationFinishedEvent) { MinecraftForge.EVENT_BUS.post(ExtraSupplyIdEvent(knownNames::put)) } diff --git a/src/main/kotlin/moe/nea/ledger/Ledger.kt b/src/main/kotlin/moe/nea/ledger/Ledger.kt index f8c8d99..b8a4073 100644 --- a/src/main/kotlin/moe/nea/ledger/Ledger.kt +++ b/src/main/kotlin/moe/nea/ledger/Ledger.kt @@ -20,7 +20,7 @@ import moe.nea.ledger.modules.KuudraChestDetection import moe.nea.ledger.modules.MinionDetection import moe.nea.ledger.modules.NpcDetection import moe.nea.ledger.modules.VisitorDetection -import moe.nea.ledger.utils.DI +import moe.nea.ledger.utils.di.DI import moe.nea.ledger.utils.ErrorUtil import net.minecraft.client.Minecraft import net.minecraft.command.ICommand diff --git a/src/main/kotlin/moe/nea/ledger/LedgerLogger.kt b/src/main/kotlin/moe/nea/ledger/LedgerLogger.kt index 5005040..913d1b5 100644 --- a/src/main/kotlin/moe/nea/ledger/LedgerLogger.kt +++ b/src/main/kotlin/moe/nea/ledger/LedgerLogger.kt @@ -6,7 +6,7 @@ import moe.nea.ledger.database.DBItemEntry import moe.nea.ledger.database.DBLogEntry import moe.nea.ledger.database.Database import moe.nea.ledger.events.ChatReceived -import moe.nea.ledger.utils.Inject +import moe.nea.ledger.utils.di.Inject import net.minecraft.client.Minecraft import net.minecraft.util.ChatComponentText import net.minecraft.util.IChatComponent diff --git a/src/main/kotlin/moe/nea/ledger/LogChatCommand.kt b/src/main/kotlin/moe/nea/ledger/LogChatCommand.kt index 0b49a9a..90b2545 100644 --- a/src/main/kotlin/moe/nea/ledger/LogChatCommand.kt +++ b/src/main/kotlin/moe/nea/ledger/LogChatCommand.kt @@ -1,6 +1,6 @@ package moe.nea.ledger -import moe.nea.ledger.utils.Inject +import moe.nea.ledger.utils.di.Inject import net.minecraft.command.CommandBase import net.minecraft.command.ICommandSender diff --git a/src/main/kotlin/moe/nea/ledger/QueryCommand.kt b/src/main/kotlin/moe/nea/ledger/QueryCommand.kt index e5cbb7f..305069a 100644 --- a/src/main/kotlin/moe/nea/ledger/QueryCommand.kt +++ b/src/main/kotlin/moe/nea/ledger/QueryCommand.kt @@ -6,7 +6,7 @@ import moe.nea.ledger.database.Clause import moe.nea.ledger.database.DBItemEntry import moe.nea.ledger.database.DBLogEntry import moe.nea.ledger.database.Database -import moe.nea.ledger.utils.Inject +import moe.nea.ledger.utils.di.Inject import net.minecraft.command.CommandBase import net.minecraft.command.ICommandSender import net.minecraft.util.ChatComponentText diff --git a/src/main/kotlin/moe/nea/ledger/TelemetryProvider.kt b/src/main/kotlin/moe/nea/ledger/TelemetryProvider.kt index 04f3fd2..d9c7108 100644 --- a/src/main/kotlin/moe/nea/ledger/TelemetryProvider.kt +++ b/src/main/kotlin/moe/nea/ledger/TelemetryProvider.kt @@ -4,8 +4,8 @@ import com.google.gson.JsonArray import com.google.gson.JsonElement import com.google.gson.JsonObject import moe.nea.ledger.gen.BuildConfig -import moe.nea.ledger.utils.DI -import moe.nea.ledger.utils.DIProvider +import moe.nea.ledger.utils.di.DI +import moe.nea.ledger.utils.di.DIProvider import moe.nea.ledger.utils.telemetry.CommonKeys import moe.nea.ledger.utils.telemetry.ContextValue import moe.nea.ledger.utils.telemetry.EventRecorder diff --git a/src/main/kotlin/moe/nea/ledger/modules/AuctionHouseDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/AuctionHouseDetection.kt index 92b659d..d02095d 100644 --- a/src/main/kotlin/moe/nea/ledger/modules/AuctionHouseDetection.kt +++ b/src/main/kotlin/moe/nea/ledger/modules/AuctionHouseDetection.kt @@ -15,7 +15,7 @@ import moe.nea.ledger.getLore import moe.nea.ledger.parseShortNumber import moe.nea.ledger.unformattedString import moe.nea.ledger.useMatcher -import moe.nea.ledger.utils.Inject +import moe.nea.ledger.utils.di.Inject import net.minecraft.client.gui.inventory.GuiChest import net.minecraft.inventory.ContainerChest import net.minecraftforge.fml.common.eventhandler.SubscribeEvent diff --git a/src/main/kotlin/moe/nea/ledger/modules/BankDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/BankDetection.kt index e9a6c26..928d30c 100644 --- a/src/main/kotlin/moe/nea/ledger/modules/BankDetection.kt +++ b/src/main/kotlin/moe/nea/ledger/modules/BankDetection.kt @@ -9,7 +9,7 @@ import moe.nea.ledger.TransactionType import moe.nea.ledger.events.ChatReceived import moe.nea.ledger.parseShortNumber import moe.nea.ledger.useMatcher -import moe.nea.ledger.utils.Inject +import moe.nea.ledger.utils.di.Inject import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import java.util.regex.Pattern diff --git a/src/main/kotlin/moe/nea/ledger/modules/BazaarDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/BazaarDetection.kt index 522beed..0f1fc2c 100644 --- a/src/main/kotlin/moe/nea/ledger/modules/BazaarDetection.kt +++ b/src/main/kotlin/moe/nea/ledger/modules/BazaarDetection.kt @@ -10,7 +10,7 @@ import moe.nea.ledger.TransactionType import moe.nea.ledger.events.ChatReceived import moe.nea.ledger.parseShortNumber import moe.nea.ledger.useMatcher -import moe.nea.ledger.utils.Inject +import moe.nea.ledger.utils.di.Inject import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import java.util.regex.Pattern diff --git a/src/main/kotlin/moe/nea/ledger/modules/BazaarOrderDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/BazaarOrderDetection.kt index 8b33fb1..330ee1d 100644 --- a/src/main/kotlin/moe/nea/ledger/modules/BazaarOrderDetection.kt +++ b/src/main/kotlin/moe/nea/ledger/modules/BazaarOrderDetection.kt @@ -11,7 +11,7 @@ import moe.nea.ledger.events.ChatReceived import moe.nea.ledger.mixin.AccessorGuiEditSign import moe.nea.ledger.parseShortNumber import moe.nea.ledger.useMatcher -import moe.nea.ledger.utils.Inject +import moe.nea.ledger.utils.di.Inject import net.minecraft.client.gui.inventory.GuiEditSign import net.minecraftforge.client.event.GuiScreenEvent import net.minecraftforge.fml.common.eventhandler.SubscribeEvent diff --git a/src/main/kotlin/moe/nea/ledger/modules/BitsDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/BitsDetection.kt index 2872f99..e4c3c98 100644 --- a/src/main/kotlin/moe/nea/ledger/modules/BitsDetection.kt +++ b/src/main/kotlin/moe/nea/ledger/modules/BitsDetection.kt @@ -12,7 +12,7 @@ import moe.nea.ledger.TransactionType import moe.nea.ledger.parseShortNumber import moe.nea.ledger.unformattedString import moe.nea.ledger.useMatcher -import moe.nea.ledger.utils.Inject +import moe.nea.ledger.utils.di.Inject import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import java.time.Instant diff --git a/src/main/kotlin/moe/nea/ledger/modules/BitsShopDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/BitsShopDetection.kt index 8fd4588..d7e0a0d 100644 --- a/src/main/kotlin/moe/nea/ledger/modules/BitsShopDetection.kt +++ b/src/main/kotlin/moe/nea/ledger/modules/BitsShopDetection.kt @@ -13,7 +13,7 @@ import moe.nea.ledger.getLore import moe.nea.ledger.parseShortNumber import moe.nea.ledger.unformattedString import moe.nea.ledger.useMatcher -import moe.nea.ledger.utils.Inject +import moe.nea.ledger.utils.di.Inject import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import java.time.Instant diff --git a/src/main/kotlin/moe/nea/ledger/modules/ChestDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/ChestDetection.kt index 48c040a..cca02e1 100644 --- a/src/main/kotlin/moe/nea/ledger/modules/ChestDetection.kt +++ b/src/main/kotlin/moe/nea/ledger/modules/ChestDetection.kt @@ -7,7 +7,7 @@ import moe.nea.ledger.getDisplayNameU import moe.nea.ledger.getInternalId import moe.nea.ledger.getLore import moe.nea.ledger.unformattedString -import moe.nea.ledger.utils.Inject +import moe.nea.ledger.utils.di.Inject import net.minecraft.init.Blocks import net.minecraft.inventory.Slot import net.minecraft.item.Item diff --git a/src/main/kotlin/moe/nea/ledger/modules/DungeonChestDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/DungeonChestDetection.kt index 4be5228..feb452e 100644 --- a/src/main/kotlin/moe/nea/ledger/modules/DungeonChestDetection.kt +++ b/src/main/kotlin/moe/nea/ledger/modules/DungeonChestDetection.kt @@ -12,7 +12,7 @@ import moe.nea.ledger.events.GuiClickEvent import moe.nea.ledger.getDisplayNameU import moe.nea.ledger.unformattedString import moe.nea.ledger.useMatcher -import moe.nea.ledger.utils.Inject +import moe.nea.ledger.utils.di.Inject import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import java.time.Instant import kotlin.time.Duration.Companion.seconds diff --git a/src/main/kotlin/moe/nea/ledger/modules/KatDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/KatDetection.kt index 4e2e40a..eda5aba 100644 --- a/src/main/kotlin/moe/nea/ledger/modules/KatDetection.kt +++ b/src/main/kotlin/moe/nea/ledger/modules/KatDetection.kt @@ -11,7 +11,7 @@ import moe.nea.ledger.events.ChatReceived import moe.nea.ledger.getInternalId import moe.nea.ledger.getLore import moe.nea.ledger.useMatcher -import moe.nea.ledger.utils.Inject +import moe.nea.ledger.utils.di.Inject import net.minecraftforge.fml.common.eventhandler.SubscribeEvent diff --git a/src/main/kotlin/moe/nea/ledger/modules/KuudraChestDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/KuudraChestDetection.kt index 8d0dc7b..e0e9322 100644 --- a/src/main/kotlin/moe/nea/ledger/modules/KuudraChestDetection.kt +++ b/src/main/kotlin/moe/nea/ledger/modules/KuudraChestDetection.kt @@ -7,7 +7,7 @@ import moe.nea.ledger.LedgerLogger import moe.nea.ledger.TransactionType import moe.nea.ledger.events.GuiClickEvent import moe.nea.ledger.getInternalId -import moe.nea.ledger.utils.Inject +import moe.nea.ledger.utils.di.Inject import net.minecraft.client.Minecraft import net.minecraftforge.fml.common.eventhandler.SubscribeEvent diff --git a/src/main/kotlin/moe/nea/ledger/modules/MinionDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/MinionDetection.kt index 1b48095..6999c7f 100644 --- a/src/main/kotlin/moe/nea/ledger/modules/MinionDetection.kt +++ b/src/main/kotlin/moe/nea/ledger/modules/MinionDetection.kt @@ -14,7 +14,7 @@ import moe.nea.ledger.parseRomanNumber import moe.nea.ledger.parseShortNumber import moe.nea.ledger.unformattedString import moe.nea.ledger.useMatcher -import moe.nea.ledger.utils.Inject +import moe.nea.ledger.utils.di.Inject import net.minecraft.client.gui.inventory.GuiChest import net.minecraft.inventory.ContainerChest import net.minecraftforge.fml.common.eventhandler.SubscribeEvent diff --git a/src/main/kotlin/moe/nea/ledger/modules/NpcDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/NpcDetection.kt index cbafe02..5906562 100644 --- a/src/main/kotlin/moe/nea/ledger/modules/NpcDetection.kt +++ b/src/main/kotlin/moe/nea/ledger/modules/NpcDetection.kt @@ -10,7 +10,7 @@ import moe.nea.ledger.TransactionType import moe.nea.ledger.events.ChatReceived import moe.nea.ledger.parseShortNumber import moe.nea.ledger.useMatcher -import moe.nea.ledger.utils.Inject +import moe.nea.ledger.utils.di.Inject import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import java.util.regex.Pattern diff --git a/src/main/kotlin/moe/nea/ledger/modules/VisitorDetection.kt b/src/main/kotlin/moe/nea/ledger/modules/VisitorDetection.kt index 1df0618..2ee581c 100644 --- a/src/main/kotlin/moe/nea/ledger/modules/VisitorDetection.kt +++ b/src/main/kotlin/moe/nea/ledger/modules/VisitorDetection.kt @@ -14,7 +14,7 @@ import moe.nea.ledger.getLore import moe.nea.ledger.parseShortNumber import moe.nea.ledger.unformattedString import moe.nea.ledger.useMatcher -import moe.nea.ledger.utils.Inject +import moe.nea.ledger.utils.di.Inject import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import java.time.Instant diff --git a/src/main/kotlin/moe/nea/ledger/utils/DI.kt b/src/main/kotlin/moe/nea/ledger/utils/DI.kt deleted file mode 100644 index e998c65..0000000 --- a/src/main/kotlin/moe/nea/ledger/utils/DI.kt +++ /dev/null @@ -1,68 +0,0 @@ -package moe.nea.ledger.utils - -import java.lang.reflect.AnnotatedElement -import java.util.Collections -import java.util.Stack - -@Suppress("UNCHECKED_CAST") -class DI { - private fun internalProvide(type: Class, element: AnnotatedElement? = null): T { - val provider = providers[type] as BaseDIProvider - val context = if (element == null) provider.createEmptyContext() else provider.createContext(element) - val key = Pair(type, context) - val existingValue = values[key] - if (existingValue != null) return existingValue as T - if (type in injectionStack) { - error("Found injection cycle: ${injectionStack.joinToString(" -> ")} -> $type") - } - injectionStack.push(type) - val value = try { - provider.provideWithContext(this, context) - } catch (ex: Exception) { - throw RuntimeException("Could not create instance for type $type", ex) - } - val cycleCheckCookie = injectionStack.pop() - require(cycleCheckCookie == type) { "Unbalanced stack cookie: $cycleCheckCookie != $type" } - values[key] = value - return value - } - - fun provide(type: Class, element: AnnotatedElement? = null): T { - return internalProvide(type, element) - } - - inline fun provide(): T = provide(T::class.java) - - fun register(type: Class, provider: BaseDIProvider) { - providers[type] = provider - } - - fun registerInjectableClasses(vararg type: Class<*>) { - type.forEach { internalRegisterInjectableClass(it) } - } - - private fun internalRegisterInjectableClass(type: Class) { - register(type, DIProvider.fromInjectableClass(type)) - } - - fun instantiateAll() { - providers.keys.forEach { - provide(it, null) - } - } - - fun getAllInstances(): Collection = - Collections.unmodifiableCollection(values.values) - - fun registerSingleton(value: T) { - register(value.javaClass, DIProvider.singeleton(value)) - } - - private val injectionStack: Stack> = Stack() - private val values = mutableMapOf, *>, Any>() - private val providers = mutableMapOf, BaseDIProvider<*, *>>() - - init { - registerSingleton(this) - } -} \ No newline at end of file diff --git a/src/main/kotlin/moe/nea/ledger/utils/DIProvider.kt b/src/main/kotlin/moe/nea/ledger/utils/DIProvider.kt deleted file mode 100644 index 98d1bbc..0000000 --- a/src/main/kotlin/moe/nea/ledger/utils/DIProvider.kt +++ /dev/null @@ -1,51 +0,0 @@ -package moe.nea.ledger.utils - -import java.lang.reflect.AnnotatedElement -import java.lang.reflect.Constructor - -fun interface DIProvider : BaseDIProvider { - override fun provideWithContext(di: DI, context: Unit): T { - return provide(di) - } - - override fun createContext(element: AnnotatedElement) { - } - - override fun createEmptyContext() { - } - - fun provide(di: DI): T - - companion object { - - fun fromInjectableClass(clazz: Class): DIProvider { - @Suppress("UNCHECKED_CAST") - val cons = (clazz.constructors.find { it.getAnnotation(Inject::class.java) != null } - ?: clazz.constructors.find { it.parameterCount == 0 } - ?: error("Could not find DI injection entrypoint for class $clazz")) - as Constructor - return DIProvider { di -> - val typArgs = cons.parameters.map { - di.provide(it.type, it) - }.toTypedArray() - val instance = cons.newInstance(*typArgs) - for (it in clazz.fields) { - if (it.getAnnotation(Inject::class.java) == null) continue - it.set(instance, di.provide(it.type, it)) - } - instance - } - } - - fun singeleton(value: T): DIProvider { - return DIProvider { _ -> value } - } - } - -} - -interface BaseDIProvider { - fun createContext(element: AnnotatedElement): C - fun provideWithContext(di: DI, context: C): T - fun createEmptyContext(): C -} diff --git a/src/main/kotlin/moe/nea/ledger/utils/ErrorUtil.kt b/src/main/kotlin/moe/nea/ledger/utils/ErrorUtil.kt index 9b6a153..4ba313e 100644 --- a/src/main/kotlin/moe/nea/ledger/utils/ErrorUtil.kt +++ b/src/main/kotlin/moe/nea/ledger/utils/ErrorUtil.kt @@ -1,5 +1,6 @@ package moe.nea.ledger.utils +import moe.nea.ledger.utils.di.Inject import moe.nea.ledger.utils.telemetry.ContextValue import moe.nea.ledger.utils.telemetry.EventRecorder import moe.nea.ledger.utils.telemetry.Span diff --git a/src/main/kotlin/moe/nea/ledger/utils/Inject.kt b/src/main/kotlin/moe/nea/ledger/utils/Inject.kt deleted file mode 100644 index 654f77e..0000000 --- a/src/main/kotlin/moe/nea/ledger/utils/Inject.kt +++ /dev/null @@ -1,6 +0,0 @@ -package moe.nea.ledger.utils - -@Retention(AnnotationRetention.RUNTIME) -@Target(AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FIELD) -annotation class Inject( -) diff --git a/src/main/kotlin/moe/nea/ledger/utils/di/DI.kt b/src/main/kotlin/moe/nea/ledger/utils/di/DI.kt new file mode 100644 index 0000000..6940f72 --- /dev/null +++ b/src/main/kotlin/moe/nea/ledger/utils/di/DI.kt @@ -0,0 +1,68 @@ +package moe.nea.ledger.utils.di + +import java.lang.reflect.AnnotatedElement +import java.util.Collections +import java.util.Stack + +@Suppress("UNCHECKED_CAST") +class DI { + private fun internalProvide(type: Class, element: AnnotatedElement? = null): T { + val provider = providers[type] as BaseDIProvider + val context = if (element == null) provider.createEmptyContext() else provider.createContext(element) + val key = Pair(type, context) + val existingValue = values[key] + if (existingValue != null) return existingValue as T + if (type in injectionStack) { + error("Found injection cycle: ${injectionStack.joinToString(" -> ")} -> $type") + } + injectionStack.push(type) + val value = try { + provider.provideWithContext(this, context) + } catch (ex: Exception) { + throw RuntimeException("Could not create instance for type $type", ex) + } + val cycleCheckCookie = injectionStack.pop() + require(cycleCheckCookie == type) { "Unbalanced stack cookie: $cycleCheckCookie != $type" } + values[key] = value + return value + } + + fun provide(type: Class, element: AnnotatedElement? = null): T { + return internalProvide(type, element) + } + + inline fun provide(): T = provide(T::class.java) + + fun register(type: Class, provider: BaseDIProvider) { + providers[type] = provider + } + + fun registerInjectableClasses(vararg type: Class<*>) { + type.forEach { internalRegisterInjectableClass(it) } + } + + private fun internalRegisterInjectableClass(type: Class) { + register(type, DIProvider.fromInjectableClass(type)) + } + + fun instantiateAll() { + providers.keys.forEach { + provide(it, null) + } + } + + fun getAllInstances(): Collection = + Collections.unmodifiableCollection(values.values) + + fun registerSingleton(value: T) { + register(value.javaClass, DIProvider.singeleton(value)) + } + + private val injectionStack: Stack> = Stack() + private val values = mutableMapOf, *>, Any>() + private val providers = mutableMapOf, BaseDIProvider<*, *>>() + + init { + registerSingleton(this) + } +} \ No newline at end of file diff --git a/src/main/kotlin/moe/nea/ledger/utils/di/DIProvider.kt b/src/main/kotlin/moe/nea/ledger/utils/di/DIProvider.kt new file mode 100644 index 0000000..b5ce550 --- /dev/null +++ b/src/main/kotlin/moe/nea/ledger/utils/di/DIProvider.kt @@ -0,0 +1,51 @@ +package moe.nea.ledger.utils.di + +import java.lang.reflect.AnnotatedElement +import java.lang.reflect.Constructor + +fun interface DIProvider : BaseDIProvider { + override fun provideWithContext(di: DI, context: Unit): T { + return provide(di) + } + + override fun createContext(element: AnnotatedElement) { + } + + override fun createEmptyContext() { + } + + fun provide(di: DI): T + + companion object { + + fun fromInjectableClass(clazz: Class): DIProvider { + @Suppress("UNCHECKED_CAST") + val cons = (clazz.constructors.find { it.getAnnotation(Inject::class.java) != null } + ?: clazz.constructors.find { it.parameterCount == 0 } + ?: error("Could not find DI injection entrypoint for class $clazz")) + as Constructor + return DIProvider { di -> + val typArgs = cons.parameters.map { + di.provide(it.type, it) + }.toTypedArray() + val instance = cons.newInstance(*typArgs) + for (it in clazz.fields) { + if (it.getAnnotation(Inject::class.java) == null) continue + it.set(instance, di.provide(it.type, it)) + } + instance + } + } + + fun singeleton(value: T): DIProvider { + return DIProvider { _ -> value } + } + } + +} + +interface BaseDIProvider { + fun createContext(element: AnnotatedElement): C + fun provideWithContext(di: DI, context: C): T + fun createEmptyContext(): C +} diff --git a/src/main/kotlin/moe/nea/ledger/utils/di/Inject.kt b/src/main/kotlin/moe/nea/ledger/utils/di/Inject.kt new file mode 100644 index 0000000..a8fdd87 --- /dev/null +++ b/src/main/kotlin/moe/nea/ledger/utils/di/Inject.kt @@ -0,0 +1,6 @@ +package moe.nea.ledger.utils.di + +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FIELD) +annotation class Inject( +) -- cgit