blob: fe408f3e973c54b209e0e8bd7c446ea90424057e [file] [log] [blame]
/*
* Copyright 2020 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.compiler.plugins.kotlin
import org.intellij.lang.annotations.Language
import org.junit.Test
class StabilityPropagationTransformTests : ComposeIrTransformTest() {
private fun stabilityPropagation(
@Language("kotlin")
unchecked: String,
@Language("kotlin")
checked: String,
expectedTransformed: String,
dumpTree: Boolean = false
) = verifyComposeIrTransform(
"""
import androidx.compose.runtime.Composable
$checked
""".trimIndent(),
expectedTransformed,
"""
import androidx.compose.runtime.Composable
$unchecked
""".trimIndent(),
dumpTree = dumpTree
)
@Test
fun testPassingLocalKnownStable(): Unit = stabilityPropagation(
"""
class Foo(val foo: Int)
@Composable fun A(x: Any) {}
""",
"""
import androidx.compose.runtime.remember
@Composable
fun Test(x: Foo) {
A(x)
A(Foo(0))
A(remember { Foo(0) })
}
""",
"""
@Composable
fun Test(x: Foo, %composer: Composer?, %changed: Int) {
if (isTraceInProgress()) {
traceEventStart(<>)
}
%composer = %composer.startRestartGroup(<>)
sourceInformation(%composer, "C(Test)<A(x)>,<A(Foo(...>,<rememb...>,<A(reme...>:Test.kt")
val %dirty = %changed
if (%changed and 0b1110 === 0) {
%dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
}
if (%dirty and 0b1011 !== 0b0010 || !%composer.skipping) {
A(x, %composer, 0b1110 and %dirty)
A(Foo(0), %composer, 0)
A(remember({
val tmp0_return = Foo(0)
tmp0_return
}, %composer, 0), %composer, 0b0110)
} else {
%composer.skipToGroupEnd()
}
%composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
Test(x, %composer, %changed or 0b0001)
}
if (isTraceInProgress()) {
traceEventEnd()
}
}
"""
)
@Test
fun testPassingLocalKnownUnstable(): Unit = stabilityPropagation(
"""
class Foo(var foo: Int)
@Composable fun A(x: Any) {}
""",
"""
import androidx.compose.runtime.remember
@Composable
fun Test(x: Foo) {
A(x)
A(Foo(0))
A(remember { Foo(0) })
}
""",
"""
@Composable
fun Test(x: Foo, %composer: Composer?, %changed: Int) {
if (isTraceInProgress()) {
traceEventStart(<>)
}
%composer = %composer.startRestartGroup(<>)
sourceInformation(%composer, "C(Test)<A(x)>,<A(Foo(...>,<rememb...>,<A(reme...>:Test.kt")
A(x, %composer, 0b1000)
A(Foo(0), %composer, 0b1000)
A(remember({
val tmp0_return = Foo(0)
tmp0_return
}, %composer, 0), %composer, 0b1000)
%composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
Test(x, %composer, %changed or 0b0001)
}
if (isTraceInProgress()) {
traceEventEnd()
}
}
"""
)
@Test
fun testListOfMarkedAsStable(): Unit = stabilityPropagation(
"""
@Composable fun A(x: Any) {}
""",
"""
@Composable
fun Example() {
A(listOf("a"))
}
""",
"""
@Composable
fun Example(%composer: Composer?, %changed: Int) {
if (isTraceInProgress()) {
traceEventStart(<>)
}
%composer = %composer.startRestartGroup(<>)
sourceInformation(%composer, "C(Example)<A(list...>:Test.kt")
if (%changed !== 0 || !%composer.skipping) {
A(listOf("a"), %composer, 0)
} else {
%composer.skipToGroupEnd()
}
%composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
Example(%composer, %changed or 0b0001)
}
if (isTraceInProgress()) {
traceEventEnd()
}
}
"""
)
}