diff --git a/build.gradle.kts b/build.gradle.kts index c261d9c..84d806a 100755 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ plugins { } group = "pw.aru.psi" -version = "1.5" +version = "1.6" //Repositories and Dependencies repositories { diff --git a/src/main/kotlin/pw/aru/psi/bootstrap/CommandBootstrap.kt b/src/main/kotlin/pw/aru/psi/bootstrap/CommandBootstrap.kt index 5a36708..69418f0 100644 --- a/src/main/kotlin/pw/aru/psi/bootstrap/CommandBootstrap.kt +++ b/src/main/kotlin/pw/aru/psi/bootstrap/CommandBootstrap.kt @@ -17,7 +17,6 @@ import pw.aru.psi.executor.service.TaskExecutorService import pw.aru.psi.logging.DiscordLogger import pw.aru.utils.Colors import pw.aru.utils.extensions.lang.allOf -import pw.aru.utils.extensions.lang.classOf import pw.aru.utils.extensions.lib.field import java.time.OffsetDateTime @@ -58,7 +57,7 @@ class CommandBootstrap(private val scanResult: ScanResult, private val kodein: K .loadClasses(ICommand::class.java) .forEach { try { - val meta = it.getAnnotation(classOf()) + val meta = it.getAnnotation(Command::class.java) val command = kodein.jitInstance(it) registry.register(meta.value.toList(), command) processExecutable(command) @@ -144,11 +143,11 @@ class CommandBootstrap(private val scanResult: ScanResult, private val kodein: K private fun processExecutable(it: Any) { if (it is Executable) { when { - it.javaClass.isAnnotationPresent(classOf()) -> { - val meta = it.javaClass.getAnnotation(classOf()) + it.javaClass.isAnnotationPresent(RunEvery::class.java) -> { + val meta = it.javaClass.getAnnotation(RunEvery::class.java) tasks.task(meta.amount, meta.unit, meta.initialDelay, it.simpleName + meta, it::run) } - it.javaClass.isAnnotationPresent(classOf()) -> { + it.javaClass.isAnnotationPresent(RunAtStartup::class.java) -> { tasks.queue("${it.simpleName}@RunAtStartup", it::run) } else -> { diff --git a/src/main/kotlin/pw/aru/psi/commands/manager/CommandRegistry.kt b/src/main/kotlin/pw/aru/psi/commands/manager/CommandRegistry.kt index ab4be34..478c03e 100755 --- a/src/main/kotlin/pw/aru/psi/commands/manager/CommandRegistry.kt +++ b/src/main/kotlin/pw/aru/psi/commands/manager/CommandRegistry.kt @@ -2,7 +2,6 @@ package pw.aru.psi.commands.manager import mu.KLogging import pw.aru.psi.commands.ICommand -import pw.aru.utils.extensions.lang.classOf class CommandRegistry { interface Listener { @@ -15,8 +14,8 @@ class CommandRegistry { companion object : KLogging() { private val helpInterfaces = listOf( - classOf(), - classOf() + ICommand.HelpDialogProvider::class.java, + ICommand.HelpDialog::class.java ) val NOOP_LISTENER = object : Listener { diff --git a/src/main/kotlin/pw/aru/psi/exported/exported.kt b/src/main/kotlin/pw/aru/psi/exported/exported.kt index b866741..2af35b4 100644 --- a/src/main/kotlin/pw/aru/psi/exported/exported.kt +++ b/src/main/kotlin/pw/aru/psi/exported/exported.kt @@ -10,4 +10,4 @@ package pw.aru.psi.exported /** * Psi Version */ -const val psi_version = "1.5" \ No newline at end of file +const val psi_version = "1.6" \ No newline at end of file diff --git a/src/main/kotlin/pw/aru/utils/extensions/lang/Collections.kt b/src/main/kotlin/pw/aru/utils/extensions/lang/Collections.kt new file mode 100755 index 0000000..98de708 --- /dev/null +++ b/src/main/kotlin/pw/aru/utils/extensions/lang/Collections.kt @@ -0,0 +1,41 @@ +@file:Suppress("NOTHING_TO_INLINE") +@file:JvmName("LangExt") +@file:JvmMultifileClass + +package pw.aru.utils.extensions.lang + +fun List.bestSplit(minSize: Int, maxSize: Int): List> { + return when { + size < maxSize -> listOf(this) + else -> chunked((minSize..maxSize).minBy { it - size % it } ?: (minSize + maxSize) / 2) + } +} + +fun Iterable>.roundRobinFlatten(): List { + val result = ArrayList() + val iterators = mapTo(ArrayList(), Iterable::iterator) + + while (iterators.isNotEmpty()) { + val i = iterators.iterator() + while (i.hasNext()) { + val ii = i.next() + if (ii.hasNext()) { + result.add(ii.next()) + } else { + i.remove() + } + } + } + + return result +} + +inline fun Map.ifContains(k: K, function: (V) -> Unit) { + if (containsKey(k)) function(get(k)!!) +} + +inline fun List.randomOrNull(): E? = if (isEmpty()) null else random() + +inline fun Array.randomOrNull(): E? = if (isEmpty()) null else random() + +inline fun randomOf(vararg objects: E): E = objects.random() diff --git a/src/main/kotlin/pw/aru/utils/extensions/lang/Conditions.kt b/src/main/kotlin/pw/aru/utils/extensions/lang/Conditions.kt new file mode 100644 index 0000000..7192b63 --- /dev/null +++ b/src/main/kotlin/pw/aru/utils/extensions/lang/Conditions.kt @@ -0,0 +1,11 @@ +@file:Suppress("NOTHING_TO_INLINE") +@file:JvmName("LangExt") +@file:JvmMultifileClass + +package pw.aru.utils.extensions.lang + +inline fun anyOf(vararg cases: Boolean) = cases.any { it } + +inline fun allOf(vararg cases: Boolean) = cases.all { it } + +inline fun noneOf(vararg cases: Boolean) = cases.none { it } diff --git a/src/main/kotlin/pw/aru/utils/extensions/lang/Environiment.kt b/src/main/kotlin/pw/aru/utils/extensions/lang/Environiment.kt new file mode 100644 index 0000000..8e98712 --- /dev/null +++ b/src/main/kotlin/pw/aru/utils/extensions/lang/Environiment.kt @@ -0,0 +1,12 @@ +package pw.aru.utils.extensions.lang + +import kotlin.properties.ReadOnlyProperty +import kotlin.reflect.KProperty + +object Environiment : ReadOnlyProperty { + private val env by lazy { System.getenv() } + + override fun getValue(thisRef: Any?, property: KProperty<*>): String { + return env.get(property.name) ?: throw IllegalStateException("No environment property ${property.name}") + } +} diff --git a/src/main/kotlin/pw/aru/utils/extensions/lang/Functions.kt b/src/main/kotlin/pw/aru/utils/extensions/lang/Functions.kt new file mode 100755 index 0000000..4ddecfe --- /dev/null +++ b/src/main/kotlin/pw/aru/utils/extensions/lang/Functions.kt @@ -0,0 +1,11 @@ +@file:Suppress("NOTHING_TO_INLINE") +@file:JvmName("LangExt") +@file:JvmMultifileClass + +package pw.aru.utils.extensions.lang + +inline fun T.applyOn(thisObj: U, block: U.() -> Unit): T { + thisObj.block() + return this +} + diff --git a/src/main/kotlin/pw/aru/utils/extensions/lang/Futures.kt b/src/main/kotlin/pw/aru/utils/extensions/lang/Futures.kt new file mode 100644 index 0000000..a84c0c8 --- /dev/null +++ b/src/main/kotlin/pw/aru/utils/extensions/lang/Futures.kt @@ -0,0 +1,50 @@ +@file:Suppress("NOTHING_TO_INLINE") +@file:JvmName("LangExt") +@file:JvmMultifileClass + +package pw.aru.utils.extensions.lang + +import java.util.concurrent.CompletableFuture +import java.util.concurrent.CompletionStage +import java.util.concurrent.Future +import kotlin.reflect.KProperty + +@JvmName("futureValue") +fun Future.value(): V = get() + +@JvmName("completionValue") +fun CompletionStage.value(): V = stageToFuture().join() + +@JvmName("futureCompletionValue") +fun T.value(): V where T : Future, T : CompletionStage = get() + +@JvmName("futureGetValue") +operator fun Future.getValue(r: Any?, p: KProperty<*>): V = get() + +@JvmName("completionGetValue") +operator fun CompletionStage.getValue(r: Any?, p: KProperty<*>): V = stageToFuture().join() + +@JvmName("futureCompletionGetValue") +operator fun T.getValue(r: Any?, p: KProperty<*>): V where T : Future, T : CompletionStage = get() + +private fun CompletionStage.stageToFuture(): CompletableFuture { + return if (this is CompletableFuture<*>) { + this as CompletableFuture + } else { + toCompletableFuture() + } +} + +fun Array>.awaitAll(): CompletionStage { + return CompletableFuture.allOf( + *map { it.stageToFuture() } + .toTypedArray() + ) +} + +fun Collection>.awaitAll(): CompletionStage { + return CompletableFuture.allOf( + *map { it.stageToFuture() } + .toTypedArray() + ) +} diff --git a/src/main/kotlin/pw/aru/utils/extensions/lang/JavaHttpClient.kt b/src/main/kotlin/pw/aru/utils/extensions/lang/JavaHttpClient.kt old mode 100755 new mode 100644 index ffa9f52..3663e4c --- a/src/main/kotlin/pw/aru/utils/extensions/lang/JavaHttpClient.kt +++ b/src/main/kotlin/pw/aru/utils/extensions/lang/JavaHttpClient.kt @@ -1,20 +1,23 @@ +@file:Suppress("NOTHING_TO_INLINE") +@file:JvmName("LangExt") +@file:JvmMultifileClass + package pw.aru.utils.extensions.lang import java.net.http.HttpClient import java.net.http.HttpRequest import java.net.http.HttpResponse +import java.net.http.HttpResponse.BodyHandler import java.util.concurrent.CompletableFuture +import java.net.http.HttpRequest.newBuilder as requestBuilder + +private typealias RequestBuilder = HttpRequest.Builder.() -> Unit +private typealias CompletableResponse = CompletableFuture> -fun HttpClient.send( - bodyHandler: HttpResponse.BodyHandler, - block: HttpRequest.Builder.() -> Unit -): HttpResponse { - return send(HttpRequest.newBuilder().also(block).build(), bodyHandler) +inline fun HttpClient.send(bodyHandler: BodyHandler, block: RequestBuilder): HttpResponse { + return send(requestBuilder().also(block).build(), bodyHandler) } -fun HttpClient.sendAsync( - bodyHandler: HttpResponse.BodyHandler, - block: HttpRequest.Builder.() -> Unit -): CompletableFuture> { - return sendAsync(HttpRequest.newBuilder().also(block).build(), bodyHandler) +inline fun HttpClient.sendAsync(bodyHandler: BodyHandler, block: RequestBuilder): CompletableResponse { + return sendAsync(requestBuilder().also(block).build(), bodyHandler) } diff --git a/src/main/kotlin/pw/aru/utils/extensions/lang/KotlinStdLib.kt b/src/main/kotlin/pw/aru/utils/extensions/lang/KotlinStdLib.kt deleted file mode 100755 index 17ac8ee..0000000 --- a/src/main/kotlin/pw/aru/utils/extensions/lang/KotlinStdLib.kt +++ /dev/null @@ -1,173 +0,0 @@ -@file:Suppress("NOTHING_TO_INLINE") -@file:JvmName("Extensions") -@file:JvmMultifileClass - -package pw.aru.utils.extensions.lang - -import java.util.concurrent.* -import java.util.concurrent.atomic.AtomicLong -import kotlin.concurrent.thread -import kotlin.properties.ReadOnlyProperty -import kotlin.random.Random -import kotlin.reflect.KProperty - -val environment = object : ReadOnlyProperty { - private val env by lazy { System.getenv() } - - override fun getValue(thisRef: Any?, property: KProperty<*>): String { - return env.get(property.name) ?: throw IllegalStateException("No environment property ${property.name}") - } -} - -inline fun classOf() = T::class.java - -@JvmName("futureGet") -inline operator fun Future.invoke(): V = get() - -@JvmName("completionGet") -inline operator fun CompletionStage.invoke(): V = toCompletableFuture().get() - -@JvmName("futureCompletionGet") -inline operator fun T.invoke(): V where T : Future, T : CompletionStage = get() - - -@JvmName("futureGetValue") -inline operator fun Future.getValue(r: Any?, p: KProperty<*>): V = get() - -@JvmName("completionGetValue") -inline operator fun CompletionStage.getValue(r: Any?, p: KProperty<*>): V = toCompletableFuture().join() - -@JvmName("futureCompletionGetValue") -inline operator fun T.getValue(r: Any?, p: KProperty<*>): V where T : Future, T : CompletionStage = get() - -private fun CompletionStage.stageToFuture(): CompletableFuture { - return if (this is CompletableFuture<*>) { - this as CompletableFuture - } else { - toCompletableFuture() - } -} - -fun Array>.awaitAll(): CompletionStage { - return CompletableFuture.allOf( - *map { it.stageToFuture() } - .toTypedArray() - ) -} - -fun Collection>.awaitAll(): CompletionStage { - return CompletableFuture.allOf( - *map { it.stageToFuture() } - .toTypedArray() - ) -} - -inline fun Map.ifContains(k: K, function: (V) -> Unit) { - if (containsKey(k)) function(get(k)!!) -} - -inline fun anyOf(vararg cases: Boolean) = cases.any { it } - -inline fun allOf(vararg cases: Boolean) = cases.all { it } - -inline fun noneOf(vararg cases: Boolean) = cases.none { it } - -inline fun multiline(vararg lines: String) = lines.joinToString("\n") - -fun threadFactory( - isDaemon: Boolean = false, - contextClassLoader: ClassLoader? = null, - nameFormat: String? = null, - priority: Int = -1 -): ThreadFactory { - val count = if (nameFormat != null) AtomicLong(0) else null - return ThreadFactory { - thread(false, isDaemon, contextClassLoader, nameFormat?.format(count!!.getAndIncrement()), priority, it::run) - } -} - - -fun threadGroupBasedFactory(name: String): (Runnable) -> Thread { - val group = ThreadGroup(name) - val count = AtomicLong(0) - - return { - object : Thread(group, "$name-${count.getAndIncrement()}") { - override fun run() { - it.run() - } - } - } -} - - -inline fun Semaphore.acquiring(permits: Int = 1, run: () -> T): T { - acquire(permits) - try { - return run() - } finally { - release(permits) - } -} - -inline fun T.applyOn(thisObj: U, block: U.() -> Unit): T { - thisObj.block() - return this -} - -inline fun handlers( - crossinline success: (T) -> Unit = {}, - crossinline failure: (Throwable) -> Unit = {} -): (T, Throwable?) -> Unit = { obj, t -> - if (t != null) { - failure(t) - } else { - success(obj) - } -} - -inline fun Any.format(s: String): String = s.format(this) - -inline operator fun Appendable.plusAssign(other: CharSequence) { - append(other) -} - -inline operator fun Appendable.plusAssign(other: Char) { - append(other) -} - - -inline fun List.random(): E = this[randomIndex(this.size)] - -inline fun List.randomOrNull(): E? = this.getOrNull(randomIndex(this.size)) - -inline fun Array.random(): E = this[randomIndex(this.size)] - -inline fun Array.randomOrNull(): E? = this.getOrNull(randomIndex(this.size)) - -inline fun randomOf(vararg objects: E): E = objects.random() - -@PublishedApi -internal inline fun randomIndex(max: Int): Int { - return if (max == 0) 0 else Random.nextInt(max) -} - -fun Iterable>.roundRobinFlatten(): List { - val result = ArrayList() - val iterators = mapTo(ArrayList(), Iterable::iterator) - val toRemove = ArrayList>() - - while (iterators.isNotEmpty()) { - for (iterator in iterators) { - if (iterator.hasNext()) { - result.add(iterator.next()) - } else { - toRemove.add(iterator) - } - } - iterators.removeAll(toRemove) - toRemove.clear() - } - - return result -} diff --git a/src/main/kotlin/pw/aru/utils/extensions/lang/Locks.kt b/src/main/kotlin/pw/aru/utils/extensions/lang/Locks.kt new file mode 100644 index 0000000..ce204c3 --- /dev/null +++ b/src/main/kotlin/pw/aru/utils/extensions/lang/Locks.kt @@ -0,0 +1,16 @@ +@file:Suppress("NOTHING_TO_INLINE") +@file:JvmName("LangExt") +@file:JvmMultifileClass + +package pw.aru.utils.extensions.lang + +import java.util.concurrent.Semaphore + +inline fun Semaphore.acquiring(permits: Int = 1, run: () -> T): T { + acquire(permits) + try { + return run() + } finally { + release(permits) + } +} diff --git a/src/main/kotlin/pw/aru/utils/extensions/lang/String.Manipulation.kt b/src/main/kotlin/pw/aru/utils/extensions/lang/String.Manipulation.kt deleted file mode 100755 index 61a1f43..0000000 --- a/src/main/kotlin/pw/aru/utils/extensions/lang/String.Manipulation.kt +++ /dev/null @@ -1,12 +0,0 @@ -@file:Suppress("NOTHING_TO_INLINE") -@file:JvmName("Extensions") -@file:JvmMultifileClass - -package pw.aru.utils.extensions.lang - - -fun String.initials(): String = filter(Char::isUpperCase) - -fun String.limit(size: Int): String { - return if (length <= size) this else substring(0, size - 3) + "..." -} diff --git a/src/main/kotlin/pw/aru/utils/extensions/lang/Strings.kt b/src/main/kotlin/pw/aru/utils/extensions/lang/Strings.kt new file mode 100755 index 0000000..4f6ea49 --- /dev/null +++ b/src/main/kotlin/pw/aru/utils/extensions/lang/Strings.kt @@ -0,0 +1,23 @@ +@file:Suppress("NOTHING_TO_INLINE") +@file:JvmName("LangExt") +@file:JvmMultifileClass + +package pw.aru.utils.extensions.lang + +fun String.initials(): String = filter(Char::isUpperCase) + +fun String.limit(size: Int): String { + return if (length <= size) this else substring(0, size - 3) + "..." +} + +inline fun multiline(vararg lines: String) = lines.joinToString("\n") + +inline fun Any.format(s: String): String = s.format(this) + +inline operator fun Appendable.plusAssign(other: CharSequence) { + append(other) +} + +inline operator fun Appendable.plusAssign(other: Char) { + append(other) +} diff --git a/src/main/kotlin/pw/aru/utils/extensions/lang/String.Replacing.kt b/src/main/kotlin/pw/aru/utils/extensions/lang/StringsReplacing.kt similarity index 98% rename from src/main/kotlin/pw/aru/utils/extensions/lang/String.Replacing.kt rename to src/main/kotlin/pw/aru/utils/extensions/lang/StringsReplacing.kt index 1a1c8bd..ae3e0cd 100755 --- a/src/main/kotlin/pw/aru/utils/extensions/lang/String.Replacing.kt +++ b/src/main/kotlin/pw/aru/utils/extensions/lang/StringsReplacing.kt @@ -1,5 +1,5 @@ @file:Suppress("NOTHING_TO_INLINE") -@file:JvmName("Extensions") +@file:JvmName("LangExt") @file:JvmMultifileClass package pw.aru.utils.extensions.lang diff --git a/src/main/kotlin/pw/aru/utils/extensions/lang/String.Splitting.kt b/src/main/kotlin/pw/aru/utils/extensions/lang/StringsSplitting.kt similarity index 98% rename from src/main/kotlin/pw/aru/utils/extensions/lang/String.Splitting.kt rename to src/main/kotlin/pw/aru/utils/extensions/lang/StringsSplitting.kt index 217d272..3b4770a 100755 --- a/src/main/kotlin/pw/aru/utils/extensions/lang/String.Splitting.kt +++ b/src/main/kotlin/pw/aru/utils/extensions/lang/StringsSplitting.kt @@ -1,12 +1,11 @@ @file:Suppress("NOTHING_TO_INLINE") -@file:JvmName("Extensions") +@file:JvmName("LangExt") @file:JvmMultifileClass package pw.aru.utils.extensions.lang import java.util.* - fun String.smartSplit( maxLength: Int = 2000, vararg policy: SplitPolicy = arrayOf(SplitPolicy.ANYWHERE) diff --git a/src/main/kotlin/pw/aru/utils/extensions/lang/ThreadFactories.kt b/src/main/kotlin/pw/aru/utils/extensions/lang/ThreadFactories.kt new file mode 100644 index 0000000..e078cc9 --- /dev/null +++ b/src/main/kotlin/pw/aru/utils/extensions/lang/ThreadFactories.kt @@ -0,0 +1,39 @@ +@file:Suppress("NOTHING_TO_INLINE") +@file:JvmName("LangExt") +@file:JvmMultifileClass + +package pw.aru.utils.extensions.lang + +import java.util.concurrent.ThreadFactory +import java.util.concurrent.atomic.AtomicLong +import kotlin.concurrent.thread + +fun threadFactory( + isDaemon: Boolean = false, + contextClassLoader: ClassLoader? = null, + nameFormat: String? = null, + priority: Int = -1 +): ThreadFactory { + val count = if (nameFormat != null) AtomicLong(0) else null + return ThreadFactory { + thread(false, isDaemon, contextClassLoader, nameFormat?.format(count!!.getAndIncrement()), priority, it::run) + } +} + +fun threadGroupBasedFactory( + name: String, + isDaemon: Boolean = false, + contextClassLoader: ClassLoader? = null, + priority: Int = -1 +): ThreadFactory { + val group = ThreadGroup(name) + val count = AtomicLong(0) + + return ThreadFactory { + Thread(group, it, "$name-${count.getAndIncrement()}").also { thread -> + if (isDaemon) thread.isDaemon = true + if (priority > 0) thread.priority = priority + if (contextClassLoader != null) thread.contextClassLoader = contextClassLoader + } + } +} diff --git a/src/main/kotlin/pw/aru/utils/extensions/lang/JavaLang.kt b/src/main/kotlin/pw/aru/utils/extensions/lang/Throwables.kt old mode 100755 new mode 100644 similarity index 65% rename from src/main/kotlin/pw/aru/utils/extensions/lang/JavaLang.kt rename to src/main/kotlin/pw/aru/utils/extensions/lang/Throwables.kt index a5919da..d7684d8 --- a/src/main/kotlin/pw/aru/utils/extensions/lang/JavaLang.kt +++ b/src/main/kotlin/pw/aru/utils/extensions/lang/Throwables.kt @@ -1,18 +1,11 @@ @file:Suppress("NOTHING_TO_INLINE") -@file:JvmName("Extensions") +@file:JvmName("LangExt") @file:JvmMultifileClass package pw.aru.utils.extensions.lang -import ch.qos.logback.core.helpers.ThrowableToStringArray - - -fun List.split(minSize: Int, maxSize: Int): List> { - return when { - size < maxSize -> listOf(this) - else -> chunked((minSize..maxSize).minBy { it - size % it } ?: (minSize + maxSize) / 2) - } -} +import java.io.PrintWriter +import java.io.StringWriter fun Throwable.simpleName(): String { var c: Class<*>? = javaClass @@ -44,4 +37,6 @@ fun Throwable.especializationName(): String { return "Throwable" } -fun Throwable.stackTraceToString() = ThrowableToStringArray.convert(this).joinToString("\n") +fun Throwable.stackTraceToString(): String { + return StringWriter().also { printStackTrace(PrintWriter(it, true)) }.toString() +} \ No newline at end of file diff --git a/src/main/kotlin/pw/aru/utils/extensions/lang/ToString.kt b/src/main/kotlin/pw/aru/utils/extensions/lang/ToString.kt index f7580b1..f3aee85 100755 --- a/src/main/kotlin/pw/aru/utils/extensions/lang/ToString.kt +++ b/src/main/kotlin/pw/aru/utils/extensions/lang/ToString.kt @@ -1,5 +1,5 @@ @file:Suppress("NOTHING_TO_INLINE") -@file:JvmName("Extensions") +@file:JvmName("LangExt") @file:JvmMultifileClass package pw.aru.utils.extensions.lang