47

Update

How can I get function name which is currently being execute using Kotlin?

I'm trying to get the function name of the function which is currently being execute as below but it's always coming as null

val funName = Object().`class`.enclosingMethod?.name;
android.weasel
  • 3,343
  • 1
  • 30
  • 41
Suryakant Sharma
  • 3,852
  • 1
  • 25
  • 47

2 Answers2

54

I found one of the way:-

val name = object : Any() {

}.javaClass.enclosingMethod.name

Above code can also be refine as -

val name = object{}.javaClass.enclosingMethod.name

Edit because incorrect duplicate flag prevents a new answer:

A more Java way is this:

Thread.currentThread().stackTrace[1].methodName

but it takes ~47ms on my system compared with ~13ms for the object() based one: nearly 4 times slower.

android.weasel
  • 3,343
  • 1
  • 30
  • 41
Suryakant Sharma
  • 3,852
  • 1
  • 25
  • 47
  • 4
    to be safe: object{}.javaClass.enclosingMethod?.name – Bart Burg Mar 25 '19 at 10:18
  • 1
    object{}.javaClass.enclosingMethod worked in Kotlin 1.2.x, but seems to no longer work in Kotlin 1.3.50 – GreenSaguaro Nov 20 '19 at 22:59
  • The stackTrace method will not work on overriden methods. Try running that code in an Activity's onCreate and it will return a method called "getStackTrace". Running enclosingMethod in onCreate will also return null. – Johann Nov 25 '19 at 11:34
  • Can you get function argument values as well? – Oleg Yablokov Oct 07 '20 at 08:21
  • Use "Thread.currentThread().stackTrace[3].methodName" if you have a Log method and want the name of the parent method. – Cosmin Jan 11 '21 at 11:24
  • works on kotlin 1.6.10, so comment by @GreenSaguaro does not seem to apply (anymore) – Catweazle Feb 28 '22 at 14:36
  • Both approaches are tricky. There might not be a class for Kotlin functions defined at file level, and the thread stack deep might vary. – Mister Smith Aug 12 '22 at 12:24
25

There's also another option if you don't need the name to be discovered dynamically at runtime:

instance::method.name

Check below example on https://pl.kotl.in/1ZcxQP4b3:

fun main() {
    val test = Test()
    test.methodA()
    println("The name of method is ${test::methodA.name}")
}

class Test {
    fun methodA() {
        println("Executing method ${this::methodA.name}")
        println("Executing method ${::methodA.name} - without explicit this")
    }
}

After executing main() you will see:

Executing method methodA
Executing method methodA - without explicit this
The name of method is methodA

This way you can leverage all the "IDE intelligence" (renaming, searching for occurrences, etc.) but what's important, all occurrences of instance::method.name are replaced by Kotlin to ordinary strings during compilation. If you decompile Kotlin-generated bytecode, you'll see:

public final void main() {
    Test test = new Test();
    test.methodA();
    String var2 = "The name of method is " + "methodA"; // <--- ordinary string, no reflection etc.
    boolean var3 = false;
    System.out.println(var2);
}
dominik
  • 2,404
  • 2
  • 29
  • 33