[go: nahoru, domu]

blob: a573176f281e484403ceeb5503d6a6ca42258799 [file] [log] [blame]
/*
* Copyright 2019 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.plugins.kotlin
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.annotation.Config
@RunWith(ComposeRobolectricTestRunner::class)
@Config(
manifest = Config.NONE,
minSdk = 23,
maxSdk = 23
)
class ComposerParamSignatureTests : AbstractCodegenSignatureTest() {
@Test
fun testAnonymousParamNaming(): Unit = validateBytecode(
"""
@Composable
fun Foo(children: @Composable() (a: Int, b: Int) -> Unit) {}
@Composable
fun test() {
Foo { _, _ -> }
}
"""
) {
assert(!it.contains("%anonymous parameter 0%"))
}
@Test
fun testLambdaReorderedParameter(): Unit = checkApi(
"""
@Composable fun Foo(a: String, b: () -> Unit) { }
@Composable fun Example() {
Foo(b={}, a="Hello, world!")
}
""",
"""
public final class TestKt {
public final static Foo(Ljava/lang/String;Lkotlin/jvm/functions/Function0;Landroidx/compose/Composer;)V
public final static Example(Landroidx/compose/Composer;)V
public final static synthetic Foo(Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
public final static synthetic Example()V
final static INNERCLASS TestKt%Foo%1 null null
final static INNERCLASS TestKt%Example%1 null null
final static INNERCLASS TestKt%Example%4 null null
}
final class TestKt%Foo%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(Ljava/lang/String;Lkotlin/jvm/functions/Function0;Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic Ljava/lang/String; %a
private final synthetic Lkotlin/jvm/functions/Function0; %b
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Foo%1 null null
OUTERCLASS TestKt Foo (Ljava/lang/String;Lkotlin/jvm/functions/Function0;Landroidx/compose/Composer;)V
}
final class TestKt%Example%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>()V
public final invoke()V
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Example%1 null null
OUTERCLASS TestKt Example (Landroidx/compose/Composer;)V
}
final class TestKt%Example%4 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Example%4 null null
OUTERCLASS TestKt Example (Landroidx/compose/Composer;)V
}
"""
)
@Test
fun testAmbientCurrent(): Unit = checkApi(
"""
val a = ambientOf { 123 }
@Composable fun Foo() {
val b = a.current
print(b)
}
""",
"""
public final class TestKt {
private final static Landroidx/compose/ProvidableAmbient; a
public final static getA()Landroidx/compose/ProvidableAmbient;
public final static Foo(Landroidx/compose/Composer;)V
public final static synthetic Foo()V
public final static <clinit>()V
final static INNERCLASS TestKt%Foo%1 null null
final static INNERCLASS TestKt%a%1 null null
}
final class TestKt%Foo%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Foo%1 null null
OUTERCLASS TestKt Foo (Landroidx/compose/Composer;)V
}
final class TestKt%a%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>()V
public final invoke()I
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%a%1 null null
OUTERCLASS TestKt <clinit> ()V
}
"""
)
@Test
fun testRemappedTypes(): Unit = checkApi(
"""
class A {
fun makeA(): A { return A() }
fun makeB(): B { return B() }
class B() {
}
}
class C {
fun useAB() {
val a = A()
a.makeA()
a.makeB()
val b = A.B()
}
}
""",
"""
public final class A {
public <init>()V
public final makeA()LA;
public final makeB()LA%B;
public final static INNERCLASS A%B A B
}
public final class A%B {
public <init>()V
public final static INNERCLASS A%B A B
}
public final class C {
public <init>()V
public final useAB()V
}
"""
)
@Test
fun testDataClassHashCode(): Unit = validateBytecode(
"""
data class Foo(
val bar: @Composable() () -> Unit
)
""") {
assert(!it.contains("CHECKCAST kotlin/jvm/functions/Function0"))
}
@Test
fun testCorrectComposerPassed1(): Unit = checkComposerParam(
"""
var a: Composer<*>? = null
fun run() {
a = makeComposer()
invokeComposable(a) {
assertComposer(a)
}
}
"""
)
@Test
fun testSimpleEmits(): Unit = checkApi(
"""
import android.widget.LinearLayout
import android.widget.TextView
@Composable fun Example() {
LinearLayout(id=123) {
TextView(text="Hello World")
}
}
""",
"""
public final class TestKt {
public final static Example(Landroidx/compose/Composer;)V
public final static synthetic Example()V
final static INNERCLASS TestKt%Example%4 null null
}
final class TestKt%Example%4 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Example%4 null null
OUTERCLASS TestKt Example (Landroidx/compose/Composer;)V
}
"""
)
@Test
fun testCorrectComposerPassed2(): Unit = checkComposerParam(
"""
var a: Composer<*>? = null
@Composable fun Foo() {
assertComposer(a)
}
fun run() {
a = makeComposer()
invokeComposable(a) {
Foo()
}
}
"""
)
@Test
fun testCorrectComposerPassed3(): Unit = checkComposerParam(
"""
var a: Composer<*>? = null
var b: Composer<*>? = null
@Composable fun Callback(fn: () -> Unit) {
fn()
}
fun run() {
a = makeComposer()
b = makeComposer()
invokeComposable(a) {
assertComposer(a)
Callback {
invokeComposable(b) {
assertComposer(b)
}
}
}
}
"""
)
@Test
fun testCorrectComposerPassed4(): Unit = checkComposerParam(
"""
var a: Composer<*>? = null
var b: Composer<*>? = null
@Composable fun makeInt(): Int {
assertComposer(a)
return 10
}
@Composable fun WithDefault(x: Int = makeInt()) {}
fun run() {
a = makeComposer()
b = makeComposer()
invokeComposable(a) {
assertComposer(a)
WithDefault()
WithDefault(10)
}
invokeComposable(b) {
assertComposer(b)
WithDefault(10)
}
}
"""
)
@Test
fun testCorrectComposerPassed5(): Unit = checkComposerParam(
"""
var a: Composer<*>? = null
@Composable fun Wrap(children: @Composable() () -> Unit) {
children()
}
fun run() {
a = makeComposer()
invokeComposable(a) {
assertComposer(a)
Wrap {
assertComposer(a)
Wrap {
assertComposer(a)
Wrap {
assertComposer(a)
}
}
}
}
}
"""
)
@Test
fun testCorrectComposerPassed6(): Unit = checkComposerParam(
"""
import android.widget.TextView
fun run() {
invokeComposable(makeComposer()) {
LinearLayout(id=123) {
TextView(text="Hello World")
}
}
}
"""
)
@Test
fun testDefaultParameters(): Unit = checkApi(
"""
@Composable fun Foo(x: Int = 0) {
}
""",
"""
public final class TestKt {
public final static Foo(ILandroidx/compose/Composer;)V
public static synthetic Foo%default(ILandroidx/compose/Composer;ILjava/lang/Object;)V
public final static synthetic Foo(I)V
final static INNERCLASS TestKt%Foo%1 null null
}
final class TestKt%Foo%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(ILandroidx/compose/Composer;)V
public final invoke()V
private final synthetic I %x
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Foo%1 null null
OUTERCLASS TestKt Foo (ILandroidx/compose/Composer;)V
}
"""
)
@Test
fun testDefaultExpressionsWithComposableCall(): Unit = checkApi(
"""
@Composable fun <T> identity(value: T): T = value
@Composable fun Foo(x: Int = identity(20)) {
}
@Composable fun test() {
Foo()
Foo(10)
}
""",
"""
public final class TestKt {
public final static identity(Ljava/lang/Object;Landroidx/compose/Composer;)Ljava/lang/Object;
public final static Foo(ILandroidx/compose/Composer;)V
public static synthetic Foo%default(ILandroidx/compose/Composer;ILjava/lang/Object;)V
public final static test(Landroidx/compose/Composer;)V
public final static synthetic identity(Ljava/lang/Object;)Ljava/lang/Object;
public final static synthetic Foo(I)V
public final static synthetic test()V
final static INNERCLASS TestKt%Foo%1 null null
final static INNERCLASS TestKt%test%5 null null
}
final class TestKt%Foo%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(ILandroidx/compose/Composer;)V
public final invoke()V
private final synthetic I %x
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Foo%1 null null
OUTERCLASS TestKt Foo (ILandroidx/compose/Composer;)V
}
final class TestKt%test%5 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%test%5 null null
OUTERCLASS TestKt test (Landroidx/compose/Composer;)V
}
"""
)
@Test
fun testBasicCallAndParameterUsage(): Unit = checkApi(
"""
@Composable fun Foo(a: Int, b: String) {
print(a)
print(b)
Bar(a, b)
}
@Composable fun Bar(a: Int, b: String) {
print(a)
print(b)
}
""",
"""
public final class TestKt {
public final static Foo(ILjava/lang/String;Landroidx/compose/Composer;)V
public final static Bar(ILjava/lang/String;Landroidx/compose/Composer;)V
public final static synthetic Foo(ILjava/lang/String;)V
public final static synthetic Bar(ILjava/lang/String;)V
final static INNERCLASS TestKt%Foo%3 null null
final static INNERCLASS TestKt%Bar%1 null null
}
final class TestKt%Foo%3 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(ILjava/lang/String;Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic I %a
private final synthetic Ljava/lang/String; %b
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Foo%3 null null
OUTERCLASS TestKt Foo (ILjava/lang/String;Landroidx/compose/Composer;)V
}
final class TestKt%Bar%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(ILjava/lang/String;Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic I %a
private final synthetic Ljava/lang/String; %b
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Bar%1 null null
OUTERCLASS TestKt Bar (ILjava/lang/String;Landroidx/compose/Composer;)V
}
"""
)
@Test
fun testCallFromInlinedLambda(): Unit = checkApi(
"""
@Composable fun Foo() {
listOf(1, 2, 3).forEach { Bar(it) }
}
@Composable fun Bar(a: Int) {}
""",
"""
public final class TestKt {
public final static Foo(Landroidx/compose/Composer;)V
public final static Bar(ILandroidx/compose/Composer;)V
public final static synthetic Foo()V
public final static synthetic Bar(I)V
final static INNERCLASS TestKt%Foo%2 null null
final static INNERCLASS TestKt%Bar%1 null null
}
final class TestKt%Foo%2 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Foo%2 null null
OUTERCLASS TestKt Foo (Landroidx/compose/Composer;)V
}
final class TestKt%Bar%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(ILandroidx/compose/Composer;)V
public final invoke()V
private final synthetic I %a
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Bar%1 null null
OUTERCLASS TestKt Bar (ILandroidx/compose/Composer;)V
}
"""
)
@Test
fun testBasicLambda(): Unit = checkApi(
"""
val foo = @Composable { x: Int -> print(x) }
@Composable fun Bar() {
foo(123)
}
""",
"""
public final class TestKt {
private final static Lkotlin/jvm/functions/Function2; foo
public final static getFoo()Lkotlin/jvm/functions/Function2;
public final static Bar(Landroidx/compose/Composer;)V
public final static synthetic Bar()V
public final static <clinit>()V
final static INNERCLASS TestKt%Bar%3 null null
final static INNERCLASS TestKt%foo%1 null null
}
final class TestKt%Bar%3 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Bar%3 null null
OUTERCLASS TestKt Bar (Landroidx/compose/Composer;)V
}
final class TestKt%foo%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function2 {
synthetic <init>()V
public final invoke(ILandroidx/compose/Composer;)V
public synthetic bridge invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
final static INNERCLASS TestKt%foo%1 null null
OUTERCLASS TestKt <clinit> ()V
}
"""
)
@Test
fun testLocalLambda(): Unit = checkApi(
"""
@Composable fun Bar(children: @Composable() () -> Unit) {
val foo = @Composable { x: Int -> print(x) }
foo(123)
children()
}
""",
"""
public final class TestKt {
public final static Bar(Lkotlin/jvm/functions/Function1;Landroidx/compose/Composer;)V
public final static synthetic Bar(Lkotlin/jvm/functions/Function0;)V
final static INNERCLASS TestKt%Bar%foo%1 null null
final static INNERCLASS TestKt%Bar%5 null null
}
final class TestKt%Bar%foo%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function2 {
synthetic <init>()V
public final invoke(ILandroidx/compose/Composer;)V
public synthetic bridge invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
final static INNERCLASS TestKt%Bar%foo%1 null null
OUTERCLASS TestKt Bar (Lkotlin/jvm/functions/Function1;Landroidx/compose/Composer;)V
}
final class TestKt%Bar%5 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(Lkotlin/jvm/functions/Function1;Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic Lkotlin/jvm/functions/Function1; %children
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Bar%5 null null
OUTERCLASS TestKt Bar (Lkotlin/jvm/functions/Function1;Landroidx/compose/Composer;)V
}
"""
)
@Test
fun testNesting(): Unit = checkApi(
"""
@Composable fun Wrap(children: @Composable() (x: Int) -> Unit) {
children(123)
}
@Composable fun App(x: Int) {
print(x)
Wrap { a ->
print(a)
print(x)
Wrap { b ->
print(x)
print(a)
print(b)
}
}
}
""",
"""
public final class TestKt {
public final static Wrap(Lkotlin/jvm/functions/Function2;Landroidx/compose/Composer;)V
public final static App(ILandroidx/compose/Composer;)V
public final static synthetic Wrap(Lkotlin/jvm/functions/Function1;)V
public final static synthetic App(I)V
final static INNERCLASS TestKt%Wrap%3 null null
final static INNERCLASS TestKt%App%1 null null
final static INNERCLASS TestKt%App%4 null null
}
final class TestKt%Wrap%3 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(Lkotlin/jvm/functions/Function2;Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic Lkotlin/jvm/functions/Function2; %children
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Wrap%3 null null
OUTERCLASS TestKt Wrap (Lkotlin/jvm/functions/Function2;Landroidx/compose/Composer;)V
}
final class TestKt%App%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function2 {
synthetic <init>(I)V
public final invoke(ILandroidx/compose/Composer;)V
private final synthetic I %x
public synthetic bridge invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
final static INNERCLASS TestKt%App%1%invoke%1 null null
final static INNERCLASS TestKt%App%1%invoke%4 null null
final static INNERCLASS TestKt%App%1 null null
OUTERCLASS TestKt App (ILandroidx/compose/Composer;)V
}
final class TestKt%App%1%invoke%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function2 {
synthetic <init>(II)V
public final invoke(ILandroidx/compose/Composer;)V
private final synthetic I %x
private final synthetic I %a
public synthetic bridge invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
final static INNERCLASS TestKt%App%1%invoke%1%invoke%1 null null
final static INNERCLASS TestKt%App%1%invoke%1 null null
final static INNERCLASS TestKt%App%1 null null
OUTERCLASS TestKt%App%1 invoke (ILandroidx/compose/Composer;)V
}
final class TestKt%App%1%invoke%1%invoke%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(LTestKt%App%1%invoke%1;ILandroidx/compose/Composer;II)V
public final invoke()V
private final synthetic LTestKt%App%1%invoke%1; %tmp1_rcvr
private final synthetic I %b
private final synthetic Landroidx/compose/Composer; %%composer
private final synthetic I %x
private final synthetic I %a
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%App%1%invoke%1%invoke%1 null null
final static INNERCLASS TestKt%App%1%invoke%1 null null
final static INNERCLASS TestKt%App%1 null null
OUTERCLASS TestKt%App%1%invoke%1 invoke (ILandroidx/compose/Composer;)V
}
final class TestKt%App%1%invoke%4 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(LTestKt%App%1;ILandroidx/compose/Composer;I)V
public final invoke()V
private final synthetic LTestKt%App%1; %tmp1_rcvr
private final synthetic I %a
private final synthetic Landroidx/compose/Composer; %%composer
private final synthetic I %x
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%App%1%invoke%4 null null
final static INNERCLASS TestKt%App%1 null null
OUTERCLASS TestKt%App%1 invoke (ILandroidx/compose/Composer;)V
}
final class TestKt%App%4 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(ILandroidx/compose/Composer;)V
public final invoke()V
private final synthetic I %x
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%App%4 null null
OUTERCLASS TestKt App (ILandroidx/compose/Composer;)V
}
"""
)
@Test
fun testComposableInterface(): Unit = checkApi(
"""
interface Foo {
@Composable fun bar()
}
class FooImpl : Foo {
@Composable override fun bar() {}
}
""",
"""
public abstract interface Foo {
public abstract bar(Landroidx/compose/Composer;)V
public abstract synthetic bar()V
}
public final class FooImpl implements Foo {
public <init>()V
public bar(Landroidx/compose/Composer;)V
public synthetic bar()V
final static INNERCLASS FooImpl%bar%1 null null
}
final class FooImpl%bar%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(LFooImpl;Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic LFooImpl; %tmp1_rcvr
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS FooImpl%bar%1 null null
OUTERCLASS FooImpl bar (Landroidx/compose/Composer;)V
}
"""
)
@Test
fun testSealedClassEtc(): Unit = checkApi(
"""
sealed class Ambient2<T> {
@Composable
inline val current: T get() = error("")
@Composable fun foo() {}
}
abstract class ProvidableAmbient2<T> : Ambient2<T>() {}
class DynamicProvidableAmbient2<T> : ProvidableAmbient2<T>() {}
class StaticProvidableAmbient2<T> : ProvidableAmbient2<T>() {}
""",
"""
public abstract class Ambient2 {
private <init>()V
public final synthetic getCurrent()Ljava/lang/Object;
public static synthetic current%annotations()V
public final foo(Landroidx/compose/Composer;)V
public final synthetic foo()V
public final getCurrent(Landroidx/compose/Composer;)Ljava/lang/Object;
public synthetic <init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
final static INNERCLASS Ambient2%foo%1 null null
}
final class Ambient2%foo%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(LAmbient2;Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic LAmbient2; %tmp1_rcvr
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS Ambient2%foo%1 null null
OUTERCLASS Ambient2 foo (Landroidx/compose/Composer;)V
}
public abstract class ProvidableAmbient2 extends Ambient2 {
public <init>()V
public static synthetic current%annotations()V
}
public final class DynamicProvidableAmbient2 extends ProvidableAmbient2 {
public <init>()V
public static synthetic current%annotations()V
}
public final class StaticProvidableAmbient2 extends ProvidableAmbient2 {
public <init>()V
public static synthetic current%annotations()V
}
"""
)
@Test
fun testComposableTopLevelProperty(): Unit = checkApi(
"""
@Composable val foo: Int get() { return 123 }
""",
"""
public final class TestKt {
public final static synthetic getFoo()I
public static synthetic foo%annotations()V
public final static getFoo(Landroidx/compose/Composer;)I
}
"""
)
@Test
fun testComposableProperty(): Unit = checkApi(
"""
class Foo {
@Composable val foo: Int get() { return 123 }
}
""",
"""
public final class Foo {
public <init>()V
public final synthetic getFoo()I
public static synthetic foo%annotations()V
public final getFoo(Landroidx/compose/Composer;)I
}
"""
)
@Test
fun testTableLambdaThing(): Unit = validateBytecode(
"""
@Composable
fun Foo() {
val c: @Composable() () -> Unit = with(123) {
val x = @Composable {}
x
}
}
"""
) {
// TODO(lmr): test
}
@Test
fun testDefaultArgs(): Unit = validateBytecode(
"""
@Composable
fun Scaffold(
topAppBar: @Composable() (() -> Unit)? = null
) {}
"""
) {
// TODO(lmr): test
}
@Test
fun testSyntheticAccessFunctions(): Unit = validateBytecode(
"""
class Foo {
@Composable private fun Bar() {}
}
"""
) {
// TODO(lmr): test
}
@Test
fun testLambdaMemoization(): Unit = validateBytecode(
"""
fun subcompose(block: @Composable() () -> Unit) {}
private class Foo {
var children: @Composable() (Double) -> Unit = {}
fun subcompose() {
val constraints = Math.random()
subcompose {
children(constraints)
}
}
}
"""
) {
// TODO(lmr): test
}
@Test
fun testStartRestartGroupsInKickoff(): Unit = validateBytecode(
"""
fun kickoff(block: @Composable() () -> Unit) {}
fun simpleSquareColorAndSizeTest() {
kickoff {
print("abc")
}
}
"""
) { assert(it.contains("INVOKEVIRTUAL androidx/compose/Composer.startRestartGroup")) }
@Test
fun testCustomComposerCall(): Unit = validateBytecode(
"""
class VectorScope(val composer: VectorComposer)
@Composable fun VectorScope.Test(children: @Composable VectorScope.() -> Unit) {
children()
}
internal class AnyApplyAdapter : ApplyAdapter<Any> {
override fun Any.start(instance: Any) {}
override fun Any.insertAt(index: Int, instance: Any) {}
override fun Any.removeAt(index: Int, count: Int) {}
override fun Any.move(from: Int, to: Int, count: Int) {}
override fun Any.end(instance: Any, parent: Any) {}
}
class VectorComposer(
val root: Any,
slotTable: SlotTable,
recomposer: Recomposer
) : Composer<Any>(slotTable, Applier(root, AnyApplyAdapter()), recomposer)
"""
) {
it.contains("INVOKEVIRTUAL androidx/compose/Composer.startGroup")
}
@Test
fun testCallingProperties(): Unit = checkApi(
"""
@Composable val bar: Int get() { return 123 }
@Composable fun Example() {
bar
}
""",
"""
public final class TestKt {
public final static synthetic getBar()I
public static synthetic bar%annotations()V
public final static Example(Landroidx/compose/Composer;)V
public final static synthetic Example()V
public final static getBar(Landroidx/compose/Composer;)I
final static INNERCLASS TestKt%Example%1 null null
}
final class TestKt%Example%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Example%1 null null
OUTERCLASS TestKt Example (Landroidx/compose/Composer;)V
}
"""
)
@Test
fun testAbstractComposable(): Unit = checkApi(
"""
abstract class BaseFoo {
@Composable abstract fun bar()
}
class FooImpl : BaseFoo() {
@Composable override fun bar() {}
}
""",
"""
public abstract class BaseFoo {
public <init>()V
public abstract bar(Landroidx/compose/Composer;)V
public abstract synthetic bar()V
}
public final class FooImpl extends BaseFoo {
public <init>()V
public bar(Landroidx/compose/Composer;)V
public synthetic bar()V
final static INNERCLASS FooImpl%bar%1 null null
}
final class FooImpl%bar%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(LFooImpl;Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic LFooImpl; %tmp1_rcvr
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS FooImpl%bar%1 null null
OUTERCLASS FooImpl bar (Landroidx/compose/Composer;)V
}
"""
)
@Test
fun testLocalClassAndObjectLiterals(): Unit = checkApi(
"""
@Composable
fun Wat() {}
@Composable
fun Foo(x: Int) {
Wat()
@Composable fun goo() { Wat() }
class Bar {
@Composable fun baz() { Wat() }
}
goo()
Bar().baz()
}
""",
"""
public final class TestKt {
public final static Wat(Landroidx/compose/Composer;)V
public final static Foo(ILandroidx/compose/Composer;)V
public final static synthetic Wat()V
public final static synthetic Foo(I)V
private final static Foo%goo(Landroidx/compose/Composer;)V
public final static synthetic access%Foo%goo%0(Landroidx/compose/Composer;)V
final static INNERCLASS TestKt%Wat%1 null null
public final static INNERCLASS TestKt%Foo%Bar null Bar
final static INNERCLASS TestKt%Foo%8 null null
final static INNERCLASS TestKt%Foo%3%3 null null
}
final class TestKt%Wat%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Wat%1 null null
OUTERCLASS TestKt Wat (Landroidx/compose/Composer;)V
}
public final class TestKt%Foo%Bar {
<init>()V
public final baz(Landroidx/compose/Composer;)V
public final synthetic baz()V
final static INNERCLASS TestKt%Foo%Bar%baz%3 null null
public final static INNERCLASS TestKt%Foo%Bar null Bar
OUTERCLASS TestKt Foo (ILandroidx/compose/Composer;)V
}
final class TestKt%Foo%Bar%baz%3 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(LTestKt%Foo%Bar;Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic LTestKt%Foo%Bar; %tmp1_rcvr
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Foo%Bar%baz%3 null null
public final static INNERCLASS TestKt%Foo%Bar null Bar
OUTERCLASS TestKt%Foo%Bar baz (Landroidx/compose/Composer;)V
}
final class TestKt%Foo%8 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(ILandroidx/compose/Composer;)V
public final invoke()V
private final synthetic I %x
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Foo%8 null null
OUTERCLASS TestKt Foo (ILandroidx/compose/Composer;)V
}
final class TestKt%Foo%3%3 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Foo%3%3 null null
OUTERCLASS TestKt Foo%goo (Landroidx/compose/Composer;)V
}
"""
)
@Test
fun testNonComposableCode(): Unit = checkApi(
"""
fun A() {}
val b: Int get() = 123
fun C(x: Int) {
var x = 0
x++
class D {
fun E() { A() }
val F: Int get() = 123
}
val g = object { fun H() {} }
}
fun I(block: () -> Unit) { block() }
fun J() {
I {
I {
A()
}
}
}
""",
"""
public final class TestKt {
public final static A()V
public final static getB()I
public final static C(I)V
public final static I(Lkotlin/jvm/functions/Function0;)V
public final static J()V
public final static INNERCLASS TestKt%C%D null D
public final static INNERCLASS TestKt%C%g%1 null null
final static INNERCLASS TestKt%J%1 null null
}
public final class TestKt%C%D {
<init>()V
public final E()V
public final getF()I
public final static INNERCLASS TestKt%C%D null D
OUTERCLASS TestKt C (I)V
}
public final class TestKt%C%g%1 {
<init>()V
public final H()V
public final static INNERCLASS TestKt%C%g%1 null null
OUTERCLASS TestKt C (I)V
}
final class TestKt%J%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>()V
public final invoke()V
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%J%1%1 null null
final static INNERCLASS TestKt%J%1 null null
OUTERCLASS TestKt J ()V
}
final class TestKt%J%1%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>()V
public final invoke()V
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%J%1%1 null null
final static INNERCLASS TestKt%J%1 null null
OUTERCLASS TestKt%J%1 invoke ()V
}
"""
)
@Test
fun testCircularCall(): Unit = checkApi(
"""
@Composable fun Example() {
Example()
}
""",
"""
public final class TestKt {
public final static Example(Landroidx/compose/Composer;)V
public final static synthetic Example()V
final static INNERCLASS TestKt%Example%3 null null
}
final class TestKt%Example%3 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Example%3 null null
OUTERCLASS TestKt Example (Landroidx/compose/Composer;)V
}
"""
)
@Test
fun testInlineCall(): Unit = checkApi(
"""
@Composable inline fun Example(children: @Composable() () -> Unit) {
children()
}
@Composable fun Test() {
Example {}
}
""",
"""
public final class TestKt {
public final static Example(Lkotlin/jvm/functions/Function1;Landroidx/compose/Composer;)V
public final static Test(Landroidx/compose/Composer;)V
public final static synthetic Example(Lkotlin/jvm/functions/Function0;)V
public final static synthetic Test()V
final static INNERCLASS TestKt%Test%2 null null
}
final class TestKt%Test%2 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Test%2 null null
OUTERCLASS TestKt Test (Landroidx/compose/Composer;)V
}
"""
)
@Test
fun testExtensionSetterEmit(): Unit = checkApi(
"""
import android.widget.TextView
private fun TextView.setRef(ref: (TextView) -> Unit) {}
@Composable
fun Test() {
TextView(ref = { })
}
""",
"""
public final class TestKt {
private final static setRef(Landroid/widget/TextView;Lkotlin/jvm/functions/Function1;)V
public final static Test(Landroidx/compose/Composer;)V
public final static synthetic Test()V
final static INNERCLASS TestKt%Test%1 null null
final static INNERCLASS TestKt%Test%4 null null
}
final class TestKt%Test%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function1 {
synthetic <init>()V
public final invoke(Landroid/widget/TextView;)V
public synthetic bridge invoke(Ljava/lang/Object;)Ljava/lang/Object;
final static INNERCLASS TestKt%Test%1 null null
OUTERCLASS TestKt Test (Landroidx/compose/Composer;)V
}
final class TestKt%Test%4 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>(Landroidx/compose/Composer;)V
public final invoke()V
private final synthetic Landroidx/compose/Composer; %%composer
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%Test%4 null null
OUTERCLASS TestKt Test (Landroidx/compose/Composer;)V
}
"""
)
@Test
fun testDexNaming(): Unit = checkApi(
"""
@Composable
val myProperty: () -> Unit get() {
return { }
}
""",
"""
public final class TestKt {
public final static synthetic getMyProperty()Lkotlin/jvm/functions/Function0;
public static synthetic myProperty%annotations()V
public final static getMyProperty(Landroidx/compose/Composer;)Lkotlin/jvm/functions/Function0;
final static INNERCLASS TestKt%1 null null
}
final class TestKt%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
synthetic <init>()V
public final invoke()V
public synthetic bridge invoke()Ljava/lang/Object;
final static INNERCLASS TestKt%1 null null
OUTERCLASS TestKt getMyProperty (Landroidx/compose/Composer;)Lkotlin/jvm/functions/Function0;
}
"""
)
@Test
fun testInnerClass(): Unit = checkApi(
"""
interface A {
fun b() {}
}
class C {
val foo = 1
inner class D : A {
override fun b() {
print(foo)
}
}
}
""",
"""
public abstract interface A {
public abstract b()V
public final static INNERCLASS A%DefaultImpls A DefaultImpls
}
public final class A%DefaultImpls {
public static b(LA;)V
public final static INNERCLASS A%DefaultImpls A DefaultImpls
}
public final class C {
public <init>()V
private final I foo
public final getFoo()I
public final INNERCLASS C%D C D
}
public final class C%D implements A {
public <init>(LC;)V
public b()V
final synthetic LC; this%0
public final INNERCLASS C%D C D
}
"""
)
}