diff options
author | thedarkcolour <30441001+thedarkcolour@users.noreply.github.com> | 2020-10-18 12:21:34 -0700 |
---|---|---|
committer | thedarkcolour <30441001+thedarkcolour@users.noreply.github.com> | 2020-10-18 12:21:34 -0700 |
commit | 1d4d9787edfea95c3aa23babf1643ce901afa7ac (patch) | |
tree | 933a1876acb75d1351788aee2eca5d1063ba1622 /src | |
parent | e69c00673a0f6bc180d646665fc4973874f13ab8 (diff) | |
download | KotlinForForge-1d4d9787edfea95c3aa23babf1643ce901afa7ac.tar.gz KotlinForForge-1d4d9787edfea95c3aa23babf1643ce901afa7ac.tar.bz2 KotlinForForge-1d4d9787edfea95c3aa23babf1643ce901afa7ac.zip |
Close #8
Diffstat (limited to 'src')
3 files changed, 158 insertions, 27 deletions
diff --git a/src/main/kotlin/thedarkcolour/kotlinforforge/eventbus/KotlinEventBus.kt b/src/main/kotlin/thedarkcolour/kotlinforforge/eventbus/KotlinEventBus.kt index c35c4e9..3f3fb66 100644 --- a/src/main/kotlin/thedarkcolour/kotlinforforge/eventbus/KotlinEventBus.kt +++ b/src/main/kotlin/thedarkcolour/kotlinforforge/eventbus/KotlinEventBus.kt @@ -18,6 +18,9 @@ import java.util.function.Consumer /** @since 1.2.0 * Fixes [addListener] and [addGenericListener] for Kotlin KCallable. + * + * @param builder The BusBuilder used to configure this event bus + * @param synthetic Whether this event bus is just a wrapper for another bus */ public open class KotlinEventBus(builder: BusBuilder, synthetic: Boolean = false) : IEventBus, IEventExceptionHandler { @Suppress("LeakingThis") @@ -305,26 +308,24 @@ public open class KotlinEventBus(builder: BusBuilder, synthetic: Boolean = false */ private fun reflectKotlinSAM(consumer: Consumer<*>): Class<*>? { val clazz = consumer.javaClass + val forgeType = TypeResolver.resolveRawArgument(Consumer::class.java, consumer.javaClass) - when { - clazz.simpleName.contains("$\$Lambda$") -> { - return TypeResolver.resolveRawArgument(Consumer::class.java, consumer.javaClass) - } - clazz.simpleName.contains("\$sam$") -> { - try { - val functionField = clazz.getDeclaredField("function") - functionField.isAccessible = true - val function = functionField[consumer] - - // Function should have two type parameters (parameter type and return type) - return TypeResolver.resolveRawArguments(kotlin.jvm.functions.Function1::class.java, function.javaClass)[0] - } catch (e: NoSuchFieldException) { - // Kotlin SAM interfaces compile to classes with a "function" field - LOGGER.log(Level.FATAL, "Tried to register invalid Kotlin SAM interface: Missing 'function' field") - throw e - } + if (clazz.simpleName.contains("\$sam$")) { + try { + val functionField = clazz.getDeclaredField("function") + functionField.isAccessible = true + val function = functionField[consumer] + + // Function should have two type parameters (parameter type and return type) + return TypeResolver.resolveRawArguments(kotlin.jvm.functions.Function1::class.java, function.javaClass)[0] + } catch (e: NoSuchFieldException) { + // Kotlin SAM interfaces compile to classes with a "function" field + LOGGER.log(Level.FATAL, "Tried to register invalid Kotlin SAM interface: Missing 'function' field") + throw e } - else -> return null + } else { + // Kotlin 1.4 seems to have fixed some of its lambda problems + return forgeType } } diff --git a/src/main/kotlin/thedarkcolour/kotlinforforge/test/TestMod.kt b/src/main/kotlin/thedarkcolour/kotlinforforge/test/TestMod.kt new file mode 100644 index 0000000..01de386 --- /dev/null +++ b/src/main/kotlin/thedarkcolour/kotlinforforge/test/TestMod.kt @@ -0,0 +1,128 @@ +package thedarkcolour.kotlinforforge.test + +import net.minecraftforge.eventbus.api.BusBuilder +import net.minecraftforge.eventbus.api.Event +import net.minecraftforge.eventbus.api.EventPriority +import net.minecraftforge.eventbus.api.GenericEvent +import org.junit.Assert.assertTrue +import thedarkcolour.kotlinforforge.eventbus.KotlinEventBus +import java.util.function.Consumer + +/** + * Uncomment the `@Mod` annotation and uncomment the entry in mods.toml to run the test mod + */ +//@Mod("test_mod") +public class TestMod { + + init { + val l = arrayListOf<Throwable>() + + try { + testAddListenerBridge() + } catch (t: Throwable) { + l.add(t) + } + try { + testFunctionReference() + } catch (t: Throwable) { + l.add(t) + } + try { + testGenericListeners() + } catch (t: Throwable) { + l.add(t) + } + + l.forEach { throwable -> + throwable.printStackTrace() + } + + if (l.isNotEmpty()) { + throw RuntimeException("Test mod did not pass") + } + } + + // Test event class + public open class TestEvent(public var value: String) : Event() + + /** + * Tests the new bridge lambdas introduced in Kotlin 1.4. + */ + private fun testAddListenerBridge() { + val bus = KotlinEventBus(BusBuilder.builder()) + + // Make sure the type checker works properly in Kotlin 1.4 + bus.addListener<TestEvent> { event -> + event.value = "Foo" + } + + // Check that the event posts for added listeners + val event = TestEvent("Bar") + bus.post(event) + assertTrue(event.value == "Foo") + } + + // Test function for function references + private fun exampleFunction(event: TestEvent) { + event.value = "Foo" + } + + /** + * Test that function references work properly in [KotlinEventBus.addListener]. + */ + private fun testFunctionReference() { + val bus = KotlinEventBus(BusBuilder.builder()) + val event = TestEvent("Bar") + + bus.addListener(::exampleFunction) + bus.post(event) + assertTrue(event.value == "Foo") + } + + // generic event + public class TestGenericEvent<T>(type: Class<T>, internal var value: T) : GenericEvent<T>(type) + + // test the function references here as well + private fun functionReference(event: TestGenericEvent<String>) { + event.value = "Far" + } + + // Consumer class + public class EventConsumer : Consumer<TestGenericEvent<String>> { + override fun accept(t: TestGenericEvent<String>) { + t.value = "Jar" + } + } + + /** + * Test that [KotlinEventBus.addGenericListener] respects the generic type + * of an event fired on the [KotlinEventBus] instance. + */ + public fun testGenericListeners() { + // event bus + val bus = KotlinEventBus(BusBuilder.builder()) + + @Suppress("JoinDeclarationAndAssignment") + var fooEvent: TestGenericEvent<String> + + // test fooEvent + fooEvent = TestGenericEvent(String::class.java, "Foo") + bus.addGenericListener(priority = EventPriority.HIGHEST) { e: TestGenericEvent<String> -> + e.value = "Bar" + } + bus.post(fooEvent) + assertTrue(fooEvent.value == "Bar") + + // test consumer subclass + fooEvent = TestGenericEvent(String::class.java, "Foo") + bus.addGenericListener(priority = EventPriority.HIGH, EventConsumer()) + bus.post(fooEvent) + assertTrue(fooEvent.value == "Jar") + + // test barEvent for function references + fooEvent = TestGenericEvent(String::class.java, "Foo") + bus.addGenericListener(priority = EventPriority.NORMAL, ::functionReference) + bus.post(fooEvent) + assertTrue(fooEvent.value == "Far") + } +}
\ No newline at end of file diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 27b9220..e0174e8 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -1,13 +1,7 @@ modLoader="kotlinforforge" # IModLanguageProvider -loaderVersion="[1.4,)" # IModLanguageProvider version +loaderVersion="[1.6,)" # IModLanguageProvider version license="GPL v3.0" -issueTrackerURL="https://github.com/thedarkcolour/KotlinForForge/issues" # Issues page - -description=''' -Kotlin for Forge. Allows mods to use the Kotlin programming language. -''' - # A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. [[dependencies.kotlinforforge]] #optional modId="forge" #mandatory @@ -29,9 +23,17 @@ Kotlin for Forge. Allows mods to use the Kotlin programming language. # --------------------------------------------------------- # # --------------------------------------------------------- # +# UNCOMMENT THIS TO RUN TEST MOD +# [[mods]] +# modId="test_mod" + [[mods]] #mandatory displayName="Kotlin for Forge" # Name of mod modId="kotlinforforge" # Modid -version="1.4.0" # Version of kotlinforforge +version="1.6.2" # Version of kotlinforforge authors="TheDarkColour" # Author -credits="Herobrine knows all." # Credits
\ No newline at end of file +credits="Herobrine knows all." # Credits +description=''' +Kotlin for Forge. Allows mods to use the Kotlin programming language. +''' +issueTrackerURL="https://github.com/thedarkcolour/KotlinForForge/issues" # Issues page
\ No newline at end of file |