Use reified type parameter for executeCatching; sync / async handlers

The unsafe cast before would throw an exception if any other generic
parameter than `Exception` was used without passing the class reference
explicitly.

It can now also be specified whether the exception handler is to be
executed sync or async, defaulting to sync.
This commit is contained in:
F0Xde
2020-10-18 11:16:03 +02:00
parent b72424d36d
commit 95a6eef6df
2 changed files with 54 additions and 24 deletions

View File

@@ -2,8 +2,6 @@
package net.axay.kspigot.runnables
import net.axay.kspigot.main.KSpigotMainInstance
import org.bukkit.Bukkit
import kotlin.reflect.KClass
abstract class ChainedRunnablePart<T, R>(
@@ -16,13 +14,33 @@ abstract class ChainedRunnablePart<T, R>(
abstract fun execute()
abstract fun <E : Exception> executeCatching(
@Suppress("UNCHECKED_CAST") exceptionClass: KClass<E> = Exception::class as KClass<E>,
exceptionHandler: ((E) -> Unit)? = null
/**
* Begins execution of this chained runnable, catching any exception of
* type [E] and passing it to the optional [exceptionHandler].
*
* @param exceptionSync whether the exception handler should be executed
* synchronously or asynchronously, defaults to `true` (Note that usage of
* any Spigot API functions requires it to be sync)
*/
inline fun <reified E : Exception> executeCatching(
noinline exceptionHandler: ((E) -> Unit)? = null,
exceptionSync: Boolean = true
) {
executeCatchingImpl(E::class, exceptionHandler, exceptionSync)
}
/**
* Has to be public for use in inline function [executeCatching], not
* intended to be used directly.
*/
abstract fun <E : Exception> executeCatchingImpl(
exceptionClass: KClass<E>,
exceptionHandler: ((E) -> Unit)?,
exceptionSync: Boolean
)
protected fun start(data: T) {
this.run {
runTask(sync) {
val result = invoke(data)
next?.start(result)
}
@@ -31,30 +49,28 @@ abstract class ChainedRunnablePart<T, R>(
protected fun <E : Exception> startCatching(
data: T,
exceptionClass: KClass<E>,
exceptionHandler: ((E) -> Unit)?
exceptionHandler: ((E) -> Unit)?,
exceptionSync: Boolean
) {
this.run {
runTask(sync) {
val result = try {
invoke(data)
} catch (e: Exception) {
if (exceptionClass.isInstance(e)) {
@Suppress("UNCHECKED_CAST")
exceptionHandler?.invoke(e as E)
null
if (sync == exceptionSync) {
exceptionHandler?.invoke(e as E)
} else if (exceptionHandler != null) {
runTask(exceptionSync) {
exceptionHandler.invoke(e as E)
}
}
return@runTask
} else throw e
}
if (result != null)
next?.startCatching(result, exceptionClass, exceptionHandler)
next?.startCatching(result, exceptionClass, exceptionHandler, exceptionSync)
}
}
private fun run(realRunnable: () -> Unit) {
if (sync)
Bukkit.getScheduler().runTask(KSpigotMainInstance, realRunnable)
else
Bukkit.getScheduler().runTaskAsynchronously(KSpigotMainInstance, realRunnable)
}
}
class ChainedRunnablePartFirst<R>(
@@ -65,8 +81,11 @@ class ChainedRunnablePartFirst<R>(
override fun execute()
= start(Unit)
override fun <E : Exception> executeCatching(exceptionClass: KClass<E>, exceptionHandler: ((E) -> Unit)?)
= startCatching(Unit, exceptionClass, exceptionHandler)
override fun <E : Exception> executeCatchingImpl(
exceptionClass: KClass<E>, exceptionHandler: ((E) -> Unit)?,
exceptionSync: Boolean
) =
startCatching(Unit, exceptionClass, exceptionHandler, exceptionSync)
override fun invoke(data: Unit) = runnable.invoke()
@@ -81,8 +100,11 @@ class ChainedRunnablePartThen<T, R>(
override fun execute()
= previous.execute()
override fun <E : Exception> executeCatching(exceptionClass: KClass<E>, exceptionHandler: ((E) -> Unit)?)
= previous.executeCatching(exceptionClass, exceptionHandler)
override fun <E : Exception> executeCatchingImpl(
exceptionClass: KClass<E>, exceptionHandler: ((E) -> Unit)?,
exceptionSync: Boolean
) =
previous.executeCatchingImpl(exceptionClass, exceptionHandler, exceptionSync)
override fun invoke(data: T) = runnable.invoke(data)

View File

@@ -104,6 +104,14 @@ fun task(
}
fun runTask(sync: Boolean, runnable: () -> Unit) {
if (sync) {
sync(runnable)
} else {
async(runnable)
}
}
/**
* Starts a synchronous task.
*/