Rework API to invoke composable method

Bug: 239427803
Test: ComposableMethodTest
Relnote: updated API
Change-Id: I64ca0ae49dffb777379fc90d6be8e05a3f89378a
diff --git a/compose/runtime/runtime/api/current.txt b/compose/runtime/runtime/api/current.txt
index f77f754..2c2e001 100644
--- a/compose/runtime/runtime/api/current.txt
+++ b/compose/runtime/runtime/api/current.txt
@@ -761,12 +761,18 @@
 
 package androidx.compose.runtime.reflect {
 
-  public final class ComposableMethodInvokerKt {
-    method @kotlin.jvm.Throws(exceptionClasses=NoSuchMethodException::class) public static java.lang.reflect.Method getDeclaredComposableMethod(Class<?>, String methodName, Class<?>... args) throws java.lang.NoSuchMethodException;
-    method public static java.lang.reflect.Parameter![] getRealParameters(java.lang.reflect.Method);
-    method public static int getRealParametersCount(java.lang.reflect.Method);
-    method public static Object? invokeComposable(java.lang.reflect.Method, androidx.compose.runtime.Composer composer, Object? instance, java.lang.Object?... args);
-    method public static boolean isComposable(java.lang.reflect.Method);
+  public final class ComposableMethod {
+    method public java.lang.reflect.Method asMethod();
+    method public int getParameterCount();
+    method public java.lang.reflect.Parameter![] getParameters();
+    method public operator Object? invoke(androidx.compose.runtime.Composer composer, Object? instance, java.lang.Object?... args);
+    property public final int parameterCount;
+    property public final java.lang.reflect.Parameter![] parameters;
+  }
+
+  public final class ComposableMethodKt {
+    method public static androidx.compose.runtime.reflect.ComposableMethod? asComposableMethod(java.lang.reflect.Method);
+    method @kotlin.jvm.Throws(exceptionClasses=NoSuchMethodException::class) public static androidx.compose.runtime.reflect.ComposableMethod getDeclaredComposableMethod(Class<?>, String methodName, Class<?>... args) throws java.lang.NoSuchMethodException;
   }
 
 }
diff --git a/compose/runtime/runtime/api/public_plus_experimental_current.txt b/compose/runtime/runtime/api/public_plus_experimental_current.txt
index 36d633f..0801888 100644
--- a/compose/runtime/runtime/api/public_plus_experimental_current.txt
+++ b/compose/runtime/runtime/api/public_plus_experimental_current.txt
@@ -826,12 +826,18 @@
 
 package androidx.compose.runtime.reflect {
 
-  public final class ComposableMethodInvokerKt {
-    method @kotlin.jvm.Throws(exceptionClasses=NoSuchMethodException::class) public static java.lang.reflect.Method getDeclaredComposableMethod(Class<?>, String methodName, Class<?>... args) throws java.lang.NoSuchMethodException;
-    method public static java.lang.reflect.Parameter![] getRealParameters(java.lang.reflect.Method);
-    method public static int getRealParametersCount(java.lang.reflect.Method);
-    method public static Object? invokeComposable(java.lang.reflect.Method, androidx.compose.runtime.Composer composer, Object? instance, java.lang.Object?... args);
-    method public static boolean isComposable(java.lang.reflect.Method);
+  public final class ComposableMethod {
+    method public java.lang.reflect.Method asMethod();
+    method public int getParameterCount();
+    method public java.lang.reflect.Parameter![] getParameters();
+    method public operator Object? invoke(androidx.compose.runtime.Composer composer, Object? instance, java.lang.Object?... args);
+    property public final int parameterCount;
+    property public final java.lang.reflect.Parameter![] parameters;
+  }
+
+  public final class ComposableMethodKt {
+    method public static androidx.compose.runtime.reflect.ComposableMethod? asComposableMethod(java.lang.reflect.Method);
+    method @kotlin.jvm.Throws(exceptionClasses=NoSuchMethodException::class) public static androidx.compose.runtime.reflect.ComposableMethod getDeclaredComposableMethod(Class<?>, String methodName, Class<?>... args) throws java.lang.NoSuchMethodException;
   }
 
 }
diff --git a/compose/runtime/runtime/api/restricted_current.txt b/compose/runtime/runtime/api/restricted_current.txt
index f5864c1..f82be3b 100644
--- a/compose/runtime/runtime/api/restricted_current.txt
+++ b/compose/runtime/runtime/api/restricted_current.txt
@@ -789,12 +789,18 @@
 
 package androidx.compose.runtime.reflect {
 
-  public final class ComposableMethodInvokerKt {
-    method @kotlin.jvm.Throws(exceptionClasses=NoSuchMethodException::class) public static java.lang.reflect.Method getDeclaredComposableMethod(Class<?>, String methodName, Class<?>... args) throws java.lang.NoSuchMethodException;
-    method public static java.lang.reflect.Parameter![] getRealParameters(java.lang.reflect.Method);
-    method public static int getRealParametersCount(java.lang.reflect.Method);
-    method public static Object? invokeComposable(java.lang.reflect.Method, androidx.compose.runtime.Composer composer, Object? instance, java.lang.Object?... args);
-    method public static boolean isComposable(java.lang.reflect.Method);
+  public final class ComposableMethod {
+    method public java.lang.reflect.Method asMethod();
+    method public int getParameterCount();
+    method public java.lang.reflect.Parameter![] getParameters();
+    method public operator Object? invoke(androidx.compose.runtime.Composer composer, Object? instance, java.lang.Object?... args);
+    property public final int parameterCount;
+    property public final java.lang.reflect.Parameter![] parameters;
+  }
+
+  public final class ComposableMethodKt {
+    method public static androidx.compose.runtime.reflect.ComposableMethod? asComposableMethod(java.lang.reflect.Method);
+    method @kotlin.jvm.Throws(exceptionClasses=NoSuchMethodException::class) public static androidx.compose.runtime.reflect.ComposableMethod getDeclaredComposableMethod(Class<?>, String methodName, Class<?>... args) throws java.lang.NoSuchMethodException;
   }
 
 }
diff --git a/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/reflect/ComposableMethod.kt b/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/reflect/ComposableMethod.kt
new file mode 100644
index 0000000..d0b63cc
--- /dev/null
+++ b/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/reflect/ComposableMethod.kt
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime.reflect
+
+import androidx.compose.runtime.Composer
+import androidx.compose.runtime.internal.SLOTS_PER_INT
+import java.lang.reflect.Method
+import java.lang.reflect.Modifier
+import java.lang.reflect.Parameter
+import kotlin.math.ceil
+
+private const val BITS_PER_INT = 31
+
+private fun changedParamCount(realValueParams: Int, thisParams: Int): Int {
+    if (realValueParams == 0) return 1
+    val totalParams = realValueParams + thisParams
+    return ceil(
+        totalParams.toDouble() / SLOTS_PER_INT.toDouble()
+    ).toInt()
+}
+
+private fun defaultParamCount(realValueParams: Int): Int {
+    return ceil(
+        realValueParams.toDouble() / BITS_PER_INT.toDouble()
+    ).toInt()
+}
+
+/**
+ * Structure intended to be used exclusively by [getComposableInfo].
+ */
+internal data class ComposableInfo(
+    val isComposable: Boolean,
+    val realParamsCount: Int,
+    val changedParams: Int,
+    val defaultParams: Int
+)
+
+/**
+ * Checks whether the method is Composable function and returns result along with the real
+ * parameters count and changed parameter count (if composable) and packed in a structure.
+ */
+private fun Method.getComposableInfo(): ComposableInfo {
+    val realParamsCount = parameterTypes.indexOfLast { it == Composer::class.java }
+    if (realParamsCount == -1) {
+        return ComposableInfo(false, parameterTypes.size, 0, 0)
+    }
+    val thisParams = if (Modifier.isStatic(this.modifiers)) 0 else 1
+    val changedParams = changedParamCount(realParamsCount, thisParams)
+    val totalParamsWithoutDefaults = realParamsCount +
+        1 + // composer
+        changedParams
+    val totalParams = parameterTypes.size
+    val isDefault = totalParams != totalParamsWithoutDefaults
+    val defaultParams = if (isDefault)
+        defaultParamCount(realParamsCount)
+    else
+        0
+    return ComposableInfo(
+        totalParamsWithoutDefaults + defaultParams == totalParams,
+        realParamsCount,
+        changedParams,
+        defaultParams
+    )
+}
+
+/**
+ * Returns the default value for the [Class] type. This will be 0 for numeric types, false for
+ * boolean and null for object references.
+ */
+private fun Class<*>.getDefaultValue(): Any? = when (name) {
+    "int" -> 0.toInt()
+    "short" -> 0.toShort()
+    "byte" -> 0.toByte()
+    "long" -> 0.toLong()
+    "double" -> 0.toDouble()
+    "float" -> 0.toFloat()
+    "boolean" -> false
+    "char" -> 0.toChar()
+    else -> null
+}
+
+/**
+ * Represents the @Composable method.
+ */
+class ComposableMethod internal constructor(
+    private val method: Method,
+    private val composableInfo: ComposableInfo
+    ) {
+    /**
+     * Returns the backing [Method].
+     */
+    fun asMethod() = method
+
+    /**
+     * Returns the count of method parameters excluding the utility Compose-specific parameters.
+     */
+    val parameterCount
+        get() = composableInfo.realParamsCount
+
+    /**
+     * Returns method parameters excluding the utility Compose-specific parameters.
+     */
+    val parameters: Array<Parameter>
+        @Suppress("ClassVerificationFailure", "NewApi")
+        get() = method.parameters.copyOfRange(0, composableInfo.realParamsCount)
+
+    /**
+     * Calls the Composable method on the given [instance]. If the method accepts default values,
+     * this function will call it with the correct options set.
+     */
+    @Suppress("BanUncheckedReflection", "ListIterator")
+    operator fun invoke(composer: Composer, instance: Any?, vararg args: Any?): Any? {
+        val (_, realParamsCount, changedParams, defaultParams) = composableInfo
+
+        val totalParams = method.parameterTypes.size
+        val changedStartIndex = realParamsCount + 1
+        val defaultStartIndex = changedStartIndex + changedParams
+
+        val defaultsMasks = Array(defaultParams) { index ->
+            val start = index * BITS_PER_INT
+            val end = minOf(start + BITS_PER_INT, realParamsCount)
+            val useDefault =
+                (start until end).map { if (it >= args.size || args[it] == null) 1 else 0 }
+            val mask = useDefault.foldIndexed(0) { i, mask, default -> mask or (default shl i) }
+            mask
+        }
+
+        val arguments = Array(totalParams) { idx ->
+            when (idx) {
+                // pass in "empty" value for all real parameters since we will be using defaults.
+                in 0 until realParamsCount -> args.getOrElse(idx) {
+                    method.parameterTypes[idx].getDefaultValue()
+                }
+                // the composer is the first synthetic parameter
+                realParamsCount -> composer
+                // since this is the root we don't need to be anything unique. 0 should suffice.
+                // changed parameters should be 0 to indicate "uncertain"
+                changedStartIndex -> 1
+                in changedStartIndex + 1 until defaultStartIndex -> 0
+                // Default values mask, all parameters set to use defaults
+                in defaultStartIndex until totalParams -> defaultsMasks[idx - defaultStartIndex]
+                else -> error("Unexpected index")
+            }
+        }
+        return method.invoke(instance, *arguments)
+    }
+
+    override fun equals(other: Any?) = when (other) {
+        is ComposableMethod -> method == other.method
+        else -> false
+    }
+
+    override fun hashCode() = method.hashCode()
+}
+
+fun Method.asComposableMethod(): ComposableMethod? {
+    val composableInfo = getComposableInfo()
+    if (composableInfo.isComposable) {
+        return ComposableMethod(this, composableInfo)
+    }
+    return null
+}
+
+private inline fun <reified T> T.dup(count: Int): Array<T> {
+    return (0 until count).map { this }.toTypedArray()
+}
+
+/**
+ * Find the given @Composable method by name.
+ */
+@Throws(NoSuchMethodException::class)
+fun Class<*>.getDeclaredComposableMethod(methodName: String, vararg args: Class<*>):
+    ComposableMethod {
+    val changedParams = changedParamCount(args.size, 0)
+    val method = try {
+        // without defaults
+        getDeclaredMethod(
+            methodName,
+            *args,
+            Composer::class.java, // composer param
+            *Int::class.java.dup(changedParams) // changed params
+        )
+    } catch (e: ReflectiveOperationException) {
+        val defaultParams = defaultParamCount(args.size)
+        try {
+            getDeclaredMethod(
+                methodName,
+                *args,
+                Composer::class.java, // composer param
+                *Int::class.java.dup(changedParams), // changed param
+                *Int::class.java.dup(defaultParams) // default param
+            )
+        } catch (e2: ReflectiveOperationException) {
+            null
+        }
+    } ?: throw NoSuchMethodException("$name.$methodName")
+
+    return method.asComposableMethod()!!
+}
\ No newline at end of file
diff --git a/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/reflect/ComposableMethodInvoker.kt b/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/reflect/ComposableMethodInvoker.kt
deleted file mode 100644
index 3b7777a..0000000
--- a/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/reflect/ComposableMethodInvoker.kt
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.runtime.reflect
-
-import androidx.compose.runtime.Composer
-import androidx.compose.runtime.internal.SLOTS_PER_INT
-import java.lang.reflect.Method
-import java.lang.reflect.Modifier
-import java.lang.reflect.Parameter
-import kotlin.math.ceil
-
-private inline fun <reified T> T.dup(count: Int): Array<T> {
-    return (0 until count).map { this }.toTypedArray()
-}
-
-/**
- * Find the given @Composable method by name.
- */
-@Throws(NoSuchMethodException::class)
-fun Class<*>.getDeclaredComposableMethod(methodName: String, vararg args: Class<*>): Method {
-    val changedParams = changedParamCount(args.size, 0)
-    val method = try {
-        // without defaults
-        getDeclaredMethod(
-            methodName,
-            *args,
-            Composer::class.java, // composer param
-            *Int::class.java.dup(changedParams) // changed params
-        )
-    } catch (e: ReflectiveOperationException) {
-        val defaultParams = defaultParamCount(args.size)
-        try {
-            getDeclaredMethod(
-                methodName,
-                *args,
-                Composer::class.java, // composer param
-                *Int::class.java.dup(changedParams), // changed param
-                *Int::class.java.dup(defaultParams) // default param
-            )
-        } catch (e2: ReflectiveOperationException) {
-            null
-        }
-    } ?: throw NoSuchMethodException("$name.$methodName")
-
-    return method
-}
-
-/**
- * Returns the default value for the [Class] type. This will be 0 for numeric types, false for
- * boolean and null for object references.
- */
-private fun Class<*>.getDefaultValue(): Any? = when (name) {
-    "int" -> 0.toInt()
-    "short" -> 0.toShort()
-    "byte" -> 0.toByte()
-    "long" -> 0.toLong()
-    "double" -> 0.toDouble()
-    "float" -> 0.toFloat()
-    "boolean" -> false
-    "char" -> 0.toChar()
-    else -> null
-}
-
-/**
- * Structure intended to be used exclusively by [getComposableInfo].
- */
-private data class ComposableInfo(
-    val isComposable: Boolean,
-    val realParamsCount: Int,
-    val changedParams: Int,
-    val defaultParams: Int
-)
-
-/**
- * Checks whether the method is Composable function and returns result along with the real
- * parameters count and changed parameter count (if composable) and packed in a structure.
- */
-private fun Method.getComposableInfo(): ComposableInfo {
-    val realParamsCount = parameterTypes.indexOfLast { it == Composer::class.java }
-    if (realParamsCount == -1) {
-        return ComposableInfo(false, parameterTypes.size, 0, 0)
-    }
-    val thisParams = if (Modifier.isStatic(this.modifiers)) 0 else 1
-    val changedParams = changedParamCount(realParamsCount, thisParams)
-    val totalParamsWithoutDefaults = realParamsCount +
-        1 + // composer
-        changedParams
-    val totalParams = parameterTypes.size
-    val isDefault = totalParams != totalParamsWithoutDefaults
-    val defaultParams = if (isDefault)
-        defaultParamCount(realParamsCount)
-    else
-        0
-    return ComposableInfo(
-        totalParamsWithoutDefaults + defaultParams == totalParams,
-        realParamsCount,
-        changedParams,
-        defaultParams
-    )
-}
-
-/**
- * Calls the Composable method on the given [instance]. If the method accepts default values, this
- * function will call it with the correct options set.
- */
-@Suppress("BanUncheckedReflection", "ListIterator")
-fun Method.invokeComposable(
-    composer: Composer,
-    instance: Any?,
-    vararg args: Any?
-): Any? {
-    val (isComposable, realParamsCount, changedParams, defaultParams) = getComposableInfo()
-
-    check(isComposable)
-
-    val totalParams = parameterTypes.size
-    val changedStartIndex = realParamsCount + 1
-    val defaultStartIndex = changedStartIndex + changedParams
-
-    val defaultsMasks = Array(defaultParams) { index ->
-        val start = index * BITS_PER_INT
-        val end = minOf(start + BITS_PER_INT, realParamsCount)
-        val useDefault =
-            (start until end).map { if (it >= args.size || args[it] == null) 1 else 0 }
-        val mask = useDefault.foldIndexed(0) { i, mask, default -> mask or (default shl i) }
-        mask
-    }
-
-    val arguments = Array(totalParams) { idx ->
-        when (idx) {
-            // pass in "empty" value for all real parameters since we will be using defaults.
-            in 0 until realParamsCount -> args.getOrElse(idx) {
-                parameterTypes[idx].getDefaultValue()
-            }
-            // the composer is the first synthetic parameter
-            realParamsCount -> composer
-            // since this is the root we don't need to be anything unique. 0 should suffice.
-            // changed parameters should be 0 to indicate "uncertain"
-            changedStartIndex -> 1
-            in changedStartIndex + 1 until defaultStartIndex -> 0
-            // Default values mask, all parameters set to use defaults
-            in defaultStartIndex until totalParams -> defaultsMasks[idx - defaultStartIndex]
-            else -> error("Unexpected index")
-        }
-    }
-    return invoke(instance, *arguments)
-}
-
-private const val BITS_PER_INT = 31
-
-private fun changedParamCount(realValueParams: Int, thisParams: Int): Int {
-    if (realValueParams == 0) return 1
-    val totalParams = realValueParams + thisParams
-    return ceil(
-        totalParams.toDouble() / SLOTS_PER_INT.toDouble()
-    ).toInt()
-}
-
-private fun defaultParamCount(realValueParams: Int): Int {
-    return ceil(
-        realValueParams.toDouble() / BITS_PER_INT.toDouble()
-    ).toInt()
-}
-
-/**
- * Returns true if the method is a Composable function and false otherwise.
- */
-val Method.isComposable: Boolean
-    get() = getComposableInfo().isComposable
-
-/**
- * Returns real parameters count for the method, it returns the actual parameters count for the
- * usual methods and for Composable functions it excludes the utility Compose-specific parameters
- * from counting.
- */
-val Method.realParametersCount: Int
-    get() {
-        val (isComposable, realParametersCount, _, _) = getComposableInfo()
-        if (isComposable) {
-            return realParametersCount
-        }
-        return parameterTypes.size
-    }
-
-/**
- * Returns real parameters for the method, it returns the actual parameters for the usual methods
- * and for Composable functions it excludes the utility Compose-specific parameters.
- */
-val Method.realParameters: Array<out Parameter>
-    @Suppress("ClassVerificationFailure", "NewApi")
-    get() {
-        val (isComposable, realParametersCount, _, _) = getComposableInfo()
-        if (isComposable) {
-            return parameters.copyOfRange(0, realParametersCount)
-        }
-        return parameters
-    }
diff --git a/compose/runtime/runtime/src/jvmTest/kotlin/androidx/compose/runtime/reflect/ComposableMethodInvokerTest.kt b/compose/runtime/runtime/src/jvmTest/kotlin/androidx/compose/runtime/reflect/ComposableMethodTest.kt
similarity index 79%
rename from compose/runtime/runtime/src/jvmTest/kotlin/androidx/compose/runtime/reflect/ComposableMethodInvokerTest.kt
rename to compose/runtime/runtime/src/jvmTest/kotlin/androidx/compose/runtime/reflect/ComposableMethodTest.kt
index a976fad..3c92434 100644
--- a/compose/runtime/runtime/src/jvmTest/kotlin/androidx/compose/runtime/reflect/ComposableMethodInvokerTest.kt
+++ b/compose/runtime/runtime/src/jvmTest/kotlin/androidx/compose/runtime/reflect/ComposableMethodTest.kt
@@ -26,9 +26,9 @@
 import androidx.compose.runtime.withRunningRecomposer
 import kotlin.test.Test
 import kotlin.test.assertEquals
-import kotlin.test.assertFalse
 import kotlin.test.assertNotEquals
-import kotlin.test.assertTrue
+import kotlin.test.assertNotNull
+import kotlin.test.assertNull
 import kotlinx.coroutines.runBlocking
 
 @Composable
@@ -209,9 +209,9 @@
     ) { }
 }
 
-class ComposableMethodInvokerTest {
+class ComposableMethodTest {
     private val clazz =
-        Class.forName("androidx.compose.runtime.reflect.ComposableMethodInvokerTestKt")
+        Class.forName("androidx.compose.runtime.reflect.ComposableMethodTestKt")
     private val wrapperClazz =
         Class.forName("androidx.compose.runtime.reflect.ComposablesWrapper")
 
@@ -228,12 +228,12 @@
 
     @Test
     fun test_isComposable_correctly_checks_functions() {
-        assertTrue(composable.isComposable)
-        assertFalse(nonComposable.isComposable)
-        assertFalse(nonComposableWithComposer.isComposable)
-        assertTrue(composableMethod.isComposable)
-        assertFalse(nonComposableMethod.isComposable)
-        assertFalse(nonComposableMethodWithComposer.isComposable)
+        assertNotNull(composable.asComposableMethod())
+        assertNull(nonComposable.asComposableMethod())
+        assertNull(nonComposableWithComposer.asComposableMethod())
+        assertNotNull(composableMethod.asComposableMethod())
+        assertNull(nonComposableMethod.asComposableMethod())
+        assertNull(nonComposableMethodWithComposer.asComposableMethod())
     }
 
     @Throws(NoSuchMethodException::class)
@@ -363,23 +363,19 @@
                 *Array(12) { String::class.java }
             )
 
-        assertEquals(0, function0.realParametersCount)
-        assertEquals(1, function1.realParametersCount)
-        assertEquals(10, function10.realParametersCount)
-        assertEquals(11, function11.realParametersCount)
-        assertEquals(12, function12.realParametersCount)
+        assertEquals(0, function0.parameterCount)
+        assertEquals(1, function1.parameterCount)
+        assertEquals(10, function10.parameterCount)
+        assertEquals(11, function11.parameterCount)
+        assertEquals(12, function12.parameterCount)
 
-        assertEquals(0, method0.realParametersCount)
-        assertEquals(1, method1.realParametersCount)
-        assertEquals(10, method10.realParametersCount)
-        assertEquals(11, method11.realParametersCount)
-        assertEquals(12, method12.realParametersCount)
+        assertEquals(0, method0.parameterCount)
+        assertEquals(1, method1.parameterCount)
+        assertEquals(10, method10.parameterCount)
+        assertEquals(11, method11.parameterCount)
+        assertEquals(12, method12.parameterCount)
 
-        assertEquals(0, nonComposable.realParametersCount)
-        assertEquals(1, nonComposableWithComposer.realParametersCount)
-        assertEquals(0, composableMethod.realParametersCount)
-        assertEquals(0, nonComposableMethod.realParametersCount)
-        assertEquals(1, nonComposableMethodWithComposer.realParametersCount)
+        assertEquals(0, composableMethod.asComposableMethod()!!.parameterCount)
     }
 
     @Suppress("ClassVerificationFailure", "NewApi")
@@ -449,36 +445,32 @@
                 Long::class.java
             )
 
-        assertEquals(0, function0.realParameters.size)
-        assertEquals(1, function1.realParameters.size)
-        assertEquals(10, function10.realParameters.size)
-        assertEquals(11, function11.realParameters.size)
-        assertEquals(12, function12.realParameters.size)
-        assertEquals(12, function12.realParameters.size)
+        assertEquals(0, function0.parameters.size)
+        assertEquals(1, function1.parameters.size)
+        assertEquals(10, function10.parameters.size)
+        assertEquals(11, function11.parameters.size)
+        assertEquals(12, function12.parameters.size)
+        assertEquals(12, function12.parameters.size)
 
-        assertEquals(0, method0.realParameters.size)
-        assertEquals(1, method1.realParameters.size)
-        assertEquals(10, method10.realParameters.size)
-        assertEquals(11, method11.realParameters.size)
-        assertEquals(12, method12.realParameters.size)
+        assertEquals(0, method0.parameters.size)
+        assertEquals(1, method1.parameters.size)
+        assertEquals(10, method10.parameters.size)
+        assertEquals(11, method11.parameters.size)
+        assertEquals(12, method12.parameters.size)
 
-        assertEquals(0, nonComposable.realParameters.size)
-        assertEquals(1, nonComposableWithComposer.realParameters.size)
-        assertEquals(0, composableMethod.realParameters.size)
-        assertEquals(0, nonComposableMethod.realParameters.size)
-        assertEquals(1, nonComposableMethodWithComposer.realParameters.size)
+        assertEquals(0, composableMethod.asComposableMethod()!!.parameters.size)
 
-        assertEquals(6, diffParameters.realParameters.size)
+        assertEquals(6, diffParameters.parameters.size)
         assertEquals(
             listOf(String::class.java, Any::class.java, Int::class.java, Float::class.java,
                 Double::class.java, Long::class.java),
-            diffParameters.realParameters.map { it.type })
+            diffParameters.parameters.map { it.type })
 
-        assertEquals(6, diffParametersMethod.realParameters.size)
+        assertEquals(6, diffParametersMethod.parameters.size)
         assertEquals(
             listOf(String::class.java, Any::class.java, Int::class.java, Float::class.java,
                 Double::class.java, Long::class.java),
-            diffParametersMethod.realParameters.map { it.type })
+            diffParametersMethod.parameters.map { it.type })
     }
 
     private class TestFrameClock : MonotonicFrameClock {
@@ -512,27 +504,29 @@
     fun testInvokeComposableFunctions() {
 
         val composableWithDefaults =
-            clazz.declaredMethods.find { it.name == "composableFunctionWithDefaults" }!!
-        composableWithDefaults.isAccessible = true
+            clazz.declaredMethods
+                .find { it.name == "composableFunctionWithDefaults" }!!
+                .asComposableMethod()!!
+        composableWithDefaults.asMethod().isAccessible = true
 
         val resABAAA = executeWithComposer {
-            composableWithDefaults.invokeComposable(it, null, "a", "b") as String
+            composableWithDefaults.invoke(it, null, "a", "b") as String
         }
 
         val resABCAA = executeWithComposer {
-            composableWithDefaults.invokeComposable(it, null, "a", "b", "c") as String
+            composableWithDefaults.invoke(it, null, "a", "b", "c") as String
         }
 
         val resABCDA = executeWithComposer {
-            composableWithDefaults.invokeComposable(it, null, "a", "b", "c", "d") as String
+            composableWithDefaults.invoke(it, null, "a", "b", "c", "d") as String
         }
 
         val resABCDE = executeWithComposer {
-            composableWithDefaults.invokeComposable(it, null, "a", "b", "c", "d", "e") as String
+            composableWithDefaults.invoke(it, null, "a", "b", "c", "d", "e") as String
         }
 
         val resABADA = executeWithComposer {
-            composableWithDefaults.invokeComposable(it, null, "a", "b", null, "d") as String
+            composableWithDefaults.invoke(it, null, "a", "b", null, "d") as String
         }
 
         assertEquals("abaaa", resABAAA)
@@ -546,30 +540,32 @@
     fun testInvokeComposableMethods() {
 
         val composableWithDefaults =
-            wrapperClazz.declaredMethods.find { it.name == "composableMethodWithDefaults" }!!
-        composableWithDefaults.isAccessible = true
+            wrapperClazz
+                .declaredMethods
+                .find { it.name == "composableMethodWithDefaults" }!!
+                .asComposableMethod()!!
+        composableWithDefaults.asMethod().isAccessible = true
 
         val instance = ComposablesWrapper()
 
         val resABAAA = executeWithComposer {
-            composableWithDefaults.invokeComposable(it, instance, "a", "b") as String
+            composableWithDefaults.invoke(it, instance, "a", "b") as String
         }
 
         val resABCAA = executeWithComposer {
-            composableWithDefaults.invokeComposable(it, instance, "a", "b", "c") as String
+            composableWithDefaults.invoke(it, instance, "a", "b", "c") as String
         }
 
         val resABCDA = executeWithComposer {
-            composableWithDefaults.invokeComposable(it, instance, "a", "b", "c", "d") as String
+            composableWithDefaults.invoke(it, instance, "a", "b", "c", "d") as String
         }
 
         val resABCDE = executeWithComposer {
-            composableWithDefaults
-                .invokeComposable(it, instance, "a", "b", "c", "d", "e") as String
+            composableWithDefaults.invoke(it, instance, "a", "b", "c", "d", "e") as String
         }
 
         val resABADA = executeWithComposer {
-            composableWithDefaults.invokeComposable(it, instance, "a", "b", null, "d") as String
+            composableWithDefaults.invoke(it, instance, "a", "b", null, "d") as String
         }
 
         assertEquals("abaaa", resABAAA)