All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.freya022.botcommands.internal.utils.StackUtils.kt Maven / Gradle / Ivy

package io.github.freya022.botcommands.internal.utils

import io.github.freya022.botcommands.api.core.annotations.IgnoreStackFrame
import io.github.freya022.botcommands.api.core.utils.simpleNestedName
import java.lang.StackWalker.StackFrame

@RequiresOptIn("Make sure internal classes are ignored", level = RequiresOptIn.Level.WARNING)
internal annotation class StackSensitive

internal val stackWalker: StackWalker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)

@PublishedApi
internal fun currentFrame(): StackFrame {
    return stackWalker.walk { stream ->
        stream
            // Filter out the synthetic method responsible for creating default parameters
            .filter { !it.methodName.endsWith("\$default") }
            .skip(1)
            .findFirst().get()
    }
}

/**
 * - 0 to find the direct caller
 * - 1 to find the caller of the caller
 */
@StackSensitive
internal fun findCaller(skip: Long = 0): StackFrame {
    return stackWalker.walk { stream ->
        stream
            // Filter out the synthetic method responsible for creating default parameters
            .filter { !it.methodName.endsWith("\$default") }
            // Skip this method + the method calling this
            .skip(2 + skip)
            .filter { !it.declaringClass.isAnnotationPresent(IgnoreStackFrame::class.java) }
            .findFirst().get()
    }
}

val StackFrame.sourceFile: String
    get() = fileName
        ?: declaringClass.sourceFileOrNull
        ?: buildString {
            append("${declaringClass.canonicalName.split('.').first { it.any(Char::isUpperCase) }}.")
            if (declaringClass.isAnnotationPresent(Metadata::class.java)) {
                append("kt")
            } else {
                append("java")
            }
        }

@PublishedApi
internal fun StackFrame.toSignature() = "${declaringClass.simpleNestedName}.${methodName.substringBefore('$')} ($sourceFile:$lineNumber)"




© 2015 - 2025 Weber Informatics LLC | Privacy Policy