@file:OptIn(ExperimentalContracts::class) package moe.nea.firmament.util import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract import moe.nea.firmament.Firmament @Suppress("NOTHING_TO_INLINE") // Suppressed since i want the logger to not pick up the ErrorUtil stack-frame object ErrorUtil { var aggressiveErrors = run { TestUtil.isInTest || Firmament.DEBUG || ErrorUtil::class.java.desiredAssertionStatus() } inline fun softCheck(message: String, check: Boolean) { if (!check) softError(message) } inline fun lazyCheck(message: String, func: () -> Boolean) { contract { callsInPlace(func, InvocationKind.AT_MOST_ONCE) } if (!aggressiveErrors) return if (func()) return error(message) } inline fun softError(message: String, exception: Throwable) { if (aggressiveErrors) throw IllegalStateException(message, exception) else logError(message, exception) } fun logError(message: String, exception: Throwable) { Firmament.logger.error(message, exception) } fun logError(message: String) { Firmament.logger.error(message) } inline fun softError(message: String) { if (aggressiveErrors) error(message) else logError(message) } fun Result.intoCatch(message: String): Catch { return this.map { Catch.succeed(it) }.getOrElse { softError(message, it) Catch.fail(it) } } class Catch private constructor(val value: T?, val exc: Throwable?) { fun orNull(): T? = value inline fun or(block: (exc: Throwable) -> T): T { contract { callsInPlace(block, InvocationKind.AT_MOST_ONCE) } if (exc != null) return block(exc) @Suppress("UNCHECKED_CAST") return value as T } companion object { fun fail(exception: Throwable): Catch = Catch(null, exception) fun succeed(value: T): Catch = Catch(value, null) } } inline fun catch(message: String, block: () -> T): Catch { try { return Catch.succeed(block()) } catch (exc: Throwable) { softError(message, exc) return Catch.fail(exc) } } inline fun notNullOr(nullable: T?, message: String, orElse: () -> T): T { contract { callsInPlace(orElse, InvocationKind.AT_MOST_ONCE) } if (nullable == null) { softError(message) return orElse() } return nullable } fun softUserError(string: String) { if (TestUtil.isInTest) error(string) MC.sendChat(tr("firmament.usererror", "Firmament encountered a user caused error: $string")) } }