Louis Pullen-Freilich | 0f84a10 | 2021-03-16 22:41:00 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2021 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | @file:Suppress("UnstableApiUsage") |
| 18 | |
| 19 | package androidx.compose.animation.core.lint |
| 20 | |
Louis Pullen-Freilich | cafae15 | 2021-06-02 21:40:39 +0100 | [diff] [blame] | 21 | import androidx.compose.lint.test.Stubs |
Louis Pullen-Freilich | baed27e | 2023-01-19 20:35:46 +0000 | [diff] [blame] | 22 | import androidx.compose.lint.test.bytecodeStub |
Louis Pullen-Freilich | 0f84a10 | 2021-03-16 22:41:00 +0000 | [diff] [blame] | 23 | import com.android.tools.lint.checks.infrastructure.LintDetectorTest |
| 24 | import com.android.tools.lint.detector.api.Detector |
| 25 | import com.android.tools.lint.detector.api.Issue |
| 26 | import org.junit.Test |
| 27 | import org.junit.runner.RunWith |
| 28 | import org.junit.runners.JUnit4 |
| 29 | |
| 30 | /* ktlint-disable max-line-length */ |
| 31 | @RunWith(JUnit4::class) |
| 32 | |
Louis Pullen-Freilich | 0f84a10 | 2021-03-16 22:41:00 +0000 | [diff] [blame] | 33 | /** |
| 34 | * Test for [TransitionDetector]. |
| 35 | */ |
| 36 | class TransitionDetectorTest : LintDetectorTest() { |
| 37 | override fun getDetector(): Detector = TransitionDetector() |
| 38 | |
| 39 | override fun getIssues(): MutableList<Issue> = |
| 40 | mutableListOf(TransitionDetector.UnusedTransitionTargetStateParameter) |
| 41 | |
| 42 | // Simplified Transition.kt stubs |
Louis Pullen-Freilich | baed27e | 2023-01-19 20:35:46 +0000 | [diff] [blame] | 43 | private val TransitionStub = bytecodeStub( |
Louis Pullen-Freilich | cafae15 | 2021-06-02 21:40:39 +0100 | [diff] [blame] | 44 | filename = "Transition.kt", |
| 45 | filepath = "androidx/compose/animation/core", |
Louis Pullen-Freilich | e0a9476 | 2023-11-27 17:52:24 +0900 | [diff] [blame^] | 46 | checksum = 0x7997109d, |
Louis Pullen-Freilich | 0f84a10 | 2021-03-16 22:41:00 +0000 | [diff] [blame] | 47 | """ |
| 48 | package androidx.compose.animation.core |
| 49 | |
| 50 | import androidx.compose.runtime.Composable |
| 51 | |
| 52 | class Transition<S> { |
| 53 | class Segment<S> |
| 54 | } |
| 55 | |
| 56 | @Composable |
| 57 | inline fun <S> Transition<S>.animateFloat( |
| 58 | noinline transitionSpec: @Composable Transition.Segment<S>.() -> Unit = {}, |
| 59 | label: String = "FloatAnimation", |
| 60 | targetValueByState: @Composable (state: S) -> Float |
| 61 | ): Float = 5f |
Louis Pullen-Freilich | cafae15 | 2021-06-02 21:40:39 +0100 | [diff] [blame] | 62 | """, |
| 63 | """ |
Louis Pullen-Freilich | 9675ba2 | 2021-08-10 00:37:06 +0100 | [diff] [blame] | 64 | META-INF/main.kotlin_module: |
Louis Pullen-Freilich | e0a9476 | 2023-11-27 17:52:24 +0900 | [diff] [blame^] | 65 | H4sIAAAAAAAA/2NgYGBmYGBgBGJOBijg0ueST8xLKcrPTKnQS87PLcgvTtVL |
| 66 | zMvMTSzJzM8DihSlCvGEFCXmFWeCBLxLuHi5mNPy84XYQlKLS7xLlBi0GAD5 |
| 67 | +CagWAAAAA== |
Louis Pullen-Freilich | cafae15 | 2021-06-02 21:40:39 +0100 | [diff] [blame] | 68 | """, |
| 69 | """ |
| 70 | androidx/compose/animation/core/Transition$Segment.class: |
Louis Pullen-Freilich | e0a9476 | 2023-11-27 17:52:24 +0900 | [diff] [blame^] | 71 | H4sIAAAAAAAA/5VRTW/TQBB9u3bixnWpW74SvqGVKDngNqqEBFUlqIRkyYCE |
| 72 | q1xy2sSrdBt7jbybqsf8Fv4BJyQOKOLIj0KMTSQkuMDlzbw3M7tvZ7//+PIV |
| 73 | wCF2GQZCZ1WpsstoUhYfSiMjoVUhrCo1KZWMTiuhjar5biqnhdTWA2PYO0qf |
| 74 | J+fiQkS50NPo3fhcTuyL478lhvBPzYPL0D5SWtljBmfvyTBAG56PFtYYXHum |
| 75 | DMNh8v/O6LKtZFbaXOnojbQiE1aQxosLh97LaujUAAY2I/1S1WyfsuyA4fFy |
| 76 | Efi8y/3lwuchwXLRXS767hoL2YDv81etbx/bPHTq9gGdkLL6oP6/2/TQY/BW |
| 77 | Xhk2fleezoi7J2UmGTYTpeXbeTGW1akY56RsJ+VE5ENRqZqvxCDWWlYnuTBG |
| 78 | 0ro6qZpqYecVlfy0nFcT+VrVfb33c21VIYfKKBp8qXVpG3cGB+C08tU+6h8g |
| 79 | vEssajjQ6n9G5xMlHPcI243o4T5h8KsBPtYpunhA6JPGcQu30cPDZsrBoybe |
| 80 | wQ7FZ1QPaGZjBCfGlRibMUJsUYrtGFdxbQRmcB03RnAN1g1uGnQNvJ/VVf1q |
| 81 | rwIAAA== |
Louis Pullen-Freilich | cafae15 | 2021-06-02 21:40:39 +0100 | [diff] [blame] | 82 | """, |
| 83 | """ |
Louis Pullen-Freilich | 9675ba2 | 2021-08-10 00:37:06 +0100 | [diff] [blame] | 84 | androidx/compose/animation/core/Transition.class: |
Louis Pullen-Freilich | e0a9476 | 2023-11-27 17:52:24 +0900 | [diff] [blame^] | 85 | H4sIAAAAAAAA/41RTW/TQBB9u3HsxE1bt3wlfEN7KBHCbcQpVJWgEpIlAxKu |
| 86 | cslpE6/Sbew18m6qHvNb+AeckDigiCM/CjE2kZDgUll6M+/tvNnZ8c9f374D |
| 87 | eIl9hr7QaVmo9CqcFvmnwshQaJULqwpNSinDs1JooyrugTEcHCfD+EJcijAT |
| 88 | ehZ+mFzIqX118r/EEPyreXAY3GOllT1haBw8G3XgwvPRRIvBsefKMDyPrz8R |
| 89 | XbITzwubKR2+k1akwgrSeH7ZoPexCtoVgIHNSb9SFTukLD2im1bLLZ93ub9a |
| 90 | +jyooMW7q2Xfaa2WARvwQz5kzpvmj88uDxqVZ0BtElZ18xI5y6W2DIPrT7u/ |
| 91 | Nnm4y7D5V38xpz7OaZFKhu1Yafl+kU9keSYmGSm7cTEV2UiUquJrsRNpLcvT |
| 92 | TBgjaWftRM20sIuSjvykWJRT+VZVdb2PC21VLkfKKDK+1rqw9WwGR+C09/Vy |
| 93 | qt9A+IBYWHOg2f+K9hdKOB4SurXo4hFh508BfGxQdPCY0CftHtX26HtSuxp4 |
| 94 | Wsf72KM4pPMOeTbHaETYirAdIcAOpdiNcAM3x2AGt3B7jKbBhsEdg66BZ9D7 |
| 95 | DXTP2E6vAgAA |
Louis Pullen-Freilich | 9675ba2 | 2021-08-10 00:37:06 +0100 | [diff] [blame] | 96 | """, |
| 97 | """ |
Louis Pullen-Freilich | cafae15 | 2021-06-02 21:40:39 +0100 | [diff] [blame] | 98 | androidx/compose/animation/core/TransitionKt$animateFloat$1.class: |
Louis Pullen-Freilich | e0a9476 | 2023-11-27 17:52:24 +0900 | [diff] [blame^] | 99 | H4sIAAAAAAAA/81WX1MbVRT/3U0gyZLyJ6V/AEUssYWAXYLYKkmxkRJZCSk2 |
| 100 | kRmHp5vkNixs7nZ2Nxl846EfwU/gJ2h1xjo64zA++qEcz91sKbHRFnzxIfee |
| 101 | e875nX855yR//PnLbwBWUGXIcdlwHatxZNSd1hPHEwaXVov7liOJ4wqj6nLp |
| 102 | Weq95ae7MlG0He6nszEwhqelQ8e3LWkcdFqGJX3hSm4bJd6qNXjurOxxW9aV |
| 103 | Gc8ohlQ2X3p77+mKaLaE9PPVSm7t1PDX0vLpyTD5z1HEEGWY/vdIYhhkGMxb |
| 104 | ZG6NITI3v8sQnTPnd5OIQ9cxgCFi+PuWx3DvHFG/VjMKddCSHedQMNydu0D+ |
| 105 | ORVa/iLIbuUUfLbkuE3jQPg1l1tUBi6l4/NuScqOX27bNsWpp1W+aUmvOC73 |
| 106 | lvC0xKb0XTJh1b0YrjBcqe+L+mFoY4e7vCVIkeHWXOmAd7hhc9k0HtYORN3P |
| 107 | neFUlJFmTpX7Gq7ruIoJhpWLVIfhZh9X86+zGJbPbz6Gd5MYwagODe8xDJ3p |
| 108 | whjeZ4ib5Uq1UF7fYLjU06JJzCKdwA18wKA9yTKk+kUUz9ftoAVV1yWUk4wC |
| 109 | DieIWmQYe2lyW/i8wX1OEK3VidAsM3Uk1AEGdqiICAmPLEU9I6pBPldOjof1 |
| 110 | k2NdG9WC67q6Rk+OJ7UldiMaJ1rLxFPRlLapLUU29d+/H9TiUYVdplTzXDry |
| 111 | 25bT9mhAlJMKw+J5BiGGewzjPdPQEI952/YZvjtPP79pq/RprDchzD4tU0zi |
| 112 | M9xnyLx9ZDF8zhALe4Va4JXk9iG9M31XZcVpu3XxQNTazY0jXxCAUmQY6HC7 |
| 113 | TUviaWW7sKP3WNK3AjN6pjLzkirqCzPZmV6t/7Cl9ExJz85mF7N3Vone0Gn3 |
| 114 | rTsNodrWqXN7l7sWr9miqg6GkZIlRbndqgk35CQqVlNyv+0SnX7Ulr7VEqbs |
| 115 | WJ5F4tO1UHi1dhiSppTCXbe55wl6jmzIuu149OVRs+87DVpH3UIVLeVgvF/V |
| 116 | GCZCX7tdTz0Opv4exxkpsjRhA9TV9JOGCTVyNDZRomkM6TTplSYNanwMZqIv |
| 117 | kHweDNqXdCa7XFwKMGNqOyASIHKE0OiOLaTGf8akgmjYCpTpR4CACn61qxLC |
| 118 | FXUZUyQvBdpj2FY8mjakgNECWX8njOd+aD2ZWTjB9E+Y+QE3n/W4QI+L5KmL |
| 119 | JG5hLsht/jS7a4EOMPQrtG9eYOFHfPg8jKdMZ4rE01jHAypOV3ECD4MSraEQ |
| 120 | xhrBTnBv4Cu6/xdti0cUySqleJu+XGMPERNLJrImlvGRSf9/PjZxB3f3wDx8 |
| 121 | gk/3MOBh1UPOQ97DlEfFrhB+mPBF+nwR6G3+BSprltw9CQAA |
Louis Pullen-Freilich | cafae15 | 2021-06-02 21:40:39 +0100 | [diff] [blame] | 122 | """, |
| 123 | """ |
Louis Pullen-Freilich | 9675ba2 | 2021-08-10 00:37:06 +0100 | [diff] [blame] | 124 | androidx/compose/animation/core/TransitionKt.class: |
Louis Pullen-Freilich | e0a9476 | 2023-11-27 17:52:24 +0900 | [diff] [blame^] | 125 | H4sIAAAAAAAA/8VWz1PbVhD+nizbsjFgFKDgJG5KnAQIRMZQt40dGkKhqDFO |
| 126 | pqZcOHQe9sMRyBIjyUxy6dBe+g/0klunhx576CnTQ4ch00v/pk6nK2EbgztD |
| 127 | 3EsP2h9v3367+96+tf/8+7ffASzhOcMct2qObdRealW7cWi7QuOW0eCeYVu0 |
| 128 | 4ghty+GWa/j6Uy8KxpDc50dcM7lV157t7osqrYYYEmduYt20ucfw7XTp3YEL |
| 129 | pQPbMw1L2z9qaHtNq+ovutp6S1oolM5DVjzHsOpXesysM/xVrDwsXU62sNxP |
| 130 | ZsWtSmH5qmDF+T4QMxVRbwjLu4j8lWV4vtpvncV5gunyCk6fgPzy7/Rm5TQt |
| 131 | z2gIbTXQ+a4pCgy3S7ZT1/aFt+twg8C5ZdkePwtUtr1y0zRpV6TovTDcZQVx |
| 132 | hnRXUoblCcfipqZbfsauUXWjSDCMVV+I6kHL/zl3eEPQRoZ7071X0lv2zHYC |
| 133 | QxiOYxBJhiGvc3yVQ1FVoDKETb4rTAWjDKrHnbrwtrnZFE9eVSh3oWBcfvwj |
| 134 | wDCSMTJ7mYvNyXRyyvj1XDLM9dO0DLeu6kIK01sbw2h31ExN7PGmSdF/+J/f |
| 135 | jN57M34fFfqZEBcONLMQxQcMil6ubK2UV9cYHvVRYQ9YIYHbyMQwhTsXe/Bf |
| 136 | ioniHvVN4LjSDqBghuFm771/3cwtdS5hpH1Km8LjNe5xui+pcRSiecl8EvMJ |
| 137 | 9RU78AWJjC8NX8qSVFtg+OPkOBc/OY5LyWjAJqQ2C76k1JGDTUMdqyKlvOTJ |
| 138 | cUrKsilZOTlOSrOKKqvShpQN5TJKPCmn0mpcba9FfJ6NZsOnP0UkRQloLKco |
| 139 | UjJOEAO5u8lEakq9po5sSGRLKIOqogypsqJMDweerO25cfq98vYNOzk+/U6K |
| 140 | xsPK6etclvnF5FhQZ8Vv4taZdHf20n8YeuSWbmOtvfQEmW2rDbr16tAfR+Pt |
| 141 | DZ2hUSZGBtkiTg/f9R84Q67/8FE8Zph9d78onjBEW84Mg+eWBweky6t2jRIZ |
| 142 | LhmWKDcbu8LZ8keqf152lZvb3DF8vbUYqxh1i3tNh+TrX54NYt06MlyDzCvn |
| 143 | M5chc9naOYkL2wZp0lUPNvlhK0BCtyzhrJrcdQWZ4xW76VTFuuHbJluQ2z3h |
| 144 | sAAJst/TxCcRRoS0ddIOSQ8TT8+qA28wcl+9RnROHSM6r75HNJSX1YlfAr/P |
| 145 | iUaoWa5jGBvBP4swySHCSwXYadJuBDHSUHGTdvrSKH1SII3TWgh6gBXFFy00 |
| 146 | hfhT+iZlUmLBq7tEkzG8j1sk+wn/TM4R4vkxWf7mNeK/4u4Jpktjcpi0iDq7 |
| 147 | eWUhIZSIypCGYkFJqQBvgFLyf40GMEY/RxPEF7vKXOwqM4/7rTLznTLznTLz |
| 148 | rTJD2CRNpbUVrOIz8p4KfCZRDg5gDc+I75D3HOHP7yCk44EOTUcWCzpyWNQp |
| 149 | 8oe0wSXMj3aQdOlR4GMXn7i44UJ18dBFIVhRXBRdjAbyuItHLpZdfPoPx8wC |
| 150 | mQAKAAA= |
Louis Pullen-Freilich | 0f84a10 | 2021-03-16 22:41:00 +0000 | [diff] [blame] | 151 | """ |
| 152 | ) |
| 153 | |
| 154 | @Test |
| 155 | fun unreferencedParameters() { |
| 156 | lint().files( |
| 157 | kotlin( |
| 158 | """ |
| 159 | package foo |
| 160 | |
| 161 | import androidx.compose.animation.core.* |
| 162 | import androidx.compose.runtime.* |
| 163 | |
| 164 | val transition = Transition<Boolean>() |
| 165 | |
| 166 | var foo = false |
| 167 | |
| 168 | @Composable |
| 169 | fun Test() { |
| 170 | transition.animateFloat { if (foo) 1f else 0f } |
| 171 | transition.animateFloat(targetValueByState = { if (foo) 1f else 0f }) |
| 172 | transition.animateFloat { param -> if (foo) 1f else 0f } |
| 173 | transition.animateFloat(targetValueByState = { param -> if (foo) 1f else 0f }) |
| 174 | transition.animateFloat { _ -> if (foo) 1f else 0f } |
| 175 | transition.animateFloat(targetValueByState = { _ -> if (foo) 1f else 0f }) |
| 176 | } |
| 177 | """ |
| 178 | ), |
| 179 | TransitionStub, |
Louis Pullen-Freilich | cafae15 | 2021-06-02 21:40:39 +0100 | [diff] [blame] | 180 | Stubs.Composable |
Louis Pullen-Freilich | 0f84a10 | 2021-03-16 22:41:00 +0000 | [diff] [blame] | 181 | ) |
| 182 | .run() |
| 183 | .expect( |
| 184 | """ |
| 185 | src/foo/test.kt:13: Error: Target state parameter it is not used [UnusedTransitionTargetStateParameter] |
| 186 | transition.animateFloat { if (foo) 1f else 0f } |
| 187 | ~~~~~~~~~~~~~~~~~~~~~~~ |
| 188 | src/foo/test.kt:14: Error: Target state parameter it is not used [UnusedTransitionTargetStateParameter] |
| 189 | transition.animateFloat(targetValueByState = { if (foo) 1f else 0f }) |
| 190 | ~~~~~~~~~~~~~~~~~~~~~~~ |
| 191 | src/foo/test.kt:15: Error: Target state parameter param is not used [UnusedTransitionTargetStateParameter] |
| 192 | transition.animateFloat { param -> if (foo) 1f else 0f } |
| 193 | ~~~~~ |
| 194 | src/foo/test.kt:16: Error: Target state parameter param is not used [UnusedTransitionTargetStateParameter] |
| 195 | transition.animateFloat(targetValueByState = { param -> if (foo) 1f else 0f }) |
| 196 | ~~~~~ |
| 197 | src/foo/test.kt:17: Error: Target state parameter _ is not used [UnusedTransitionTargetStateParameter] |
| 198 | transition.animateFloat { _ -> if (foo) 1f else 0f } |
| 199 | ~ |
| 200 | src/foo/test.kt:18: Error: Target state parameter _ is not used [UnusedTransitionTargetStateParameter] |
| 201 | transition.animateFloat(targetValueByState = { _ -> if (foo) 1f else 0f }) |
| 202 | ~ |
| 203 | 6 errors, 0 warnings |
| 204 | """ |
| 205 | ) |
| 206 | } |
| 207 | |
| 208 | @Test |
| 209 | fun unreferencedParameter_shadowedNames() { |
| 210 | lint().files( |
| 211 | kotlin( |
| 212 | """ |
| 213 | package foo |
| 214 | |
| 215 | import androidx.compose.animation.core.* |
| 216 | import androidx.compose.runtime.* |
| 217 | |
| 218 | val transition = Transition<Boolean>() |
| 219 | |
| 220 | var foo = false |
| 221 | |
| 222 | @Composable |
| 223 | fun Test() { |
| 224 | transition.animateFloat { |
| 225 | foo.let { |
Louis Pullen-Freilich | 087f445 | 2021-03-22 21:26:17 +0000 | [diff] [blame] | 226 | // These `it`s refer to the `let`, not the `animateFloat`, so we |
Louis Pullen-Freilich | 0f84a10 | 2021-03-16 22:41:00 +0000 | [diff] [blame] | 227 | // should still report an error |
| 228 | it.let { |
| 229 | if (it) 1f else 0f |
| 230 | } |
| 231 | } |
| 232 | } |
| 233 | transition.animateFloat { param -> |
| 234 | foo.let { param -> |
Louis Pullen-Freilich | 087f445 | 2021-03-22 21:26:17 +0000 | [diff] [blame] | 235 | // This `param` refers to the `let`, not the `animateFloat`, so we |
Louis Pullen-Freilich | 0f84a10 | 2021-03-16 22:41:00 +0000 | [diff] [blame] | 236 | // should still report an error |
| 237 | if (param) 1f else 0f |
| 238 | } |
| 239 | } |
| 240 | } |
| 241 | """ |
| 242 | ), |
| 243 | TransitionStub, |
Louis Pullen-Freilich | cafae15 | 2021-06-02 21:40:39 +0100 | [diff] [blame] | 244 | Stubs.Composable |
Louis Pullen-Freilich | 0f84a10 | 2021-03-16 22:41:00 +0000 | [diff] [blame] | 245 | ) |
| 246 | .run() |
| 247 | .expect( |
| 248 | """ |
| 249 | src/foo/test.kt:13: Error: Target state parameter it is not used [UnusedTransitionTargetStateParameter] |
| 250 | transition.animateFloat { |
| 251 | ^ |
| 252 | src/foo/test.kt:22: Error: Target state parameter param is not used [UnusedTransitionTargetStateParameter] |
| 253 | transition.animateFloat { param -> |
| 254 | ~~~~~ |
| 255 | 2 errors, 0 warnings |
| 256 | """ |
| 257 | ) |
| 258 | } |
| 259 | |
| 260 | @Test |
| 261 | fun noErrors() { |
| 262 | lint().files( |
| 263 | kotlin( |
| 264 | """ |
| 265 | package foo |
| 266 | |
| 267 | import androidx.compose.animation.core.* |
| 268 | import androidx.compose.runtime.* |
| 269 | |
| 270 | val transition = Transition<Boolean>() |
| 271 | |
| 272 | var foo = false |
| 273 | |
| 274 | @Composable |
| 275 | fun Test() { |
| 276 | transition.animateFloat { if (it) 1f else 0f } |
| 277 | transition.animateFloat(targetValueByState = { if (it) 1f else 0f }) |
| 278 | transition.animateFloat { param -> if (param) 1f else 0f } |
| 279 | transition.animateFloat(targetValueByState = { param -> if (param) 1f else 0f }) |
| 280 | transition.animateFloat { param -> |
| 281 | foo.let { |
| 282 | it.let { |
| 283 | if (param && it) 1f else 0f |
| 284 | } |
| 285 | } |
| 286 | } |
| 287 | transition.animateFloat { |
| 288 | foo.let { param -> |
| 289 | param.let { param -> |
| 290 | if (param && it) 1f else 0f |
| 291 | } |
| 292 | } |
| 293 | } |
| 294 | |
| 295 | transition.animateFloat { |
| 296 | foo.run { |
| 297 | run { |
| 298 | if (this && it) 1f else 0f |
| 299 | } |
| 300 | } |
| 301 | } |
| 302 | |
Louis Pullen-Freilich | 087f445 | 2021-03-22 21:26:17 +0000 | [diff] [blame] | 303 | fun multipleParameterLambda(lambda: (Boolean, Boolean) -> Float): Float |
Louis Pullen-Freilich | 0f84a10 | 2021-03-16 22:41:00 +0000 | [diff] [blame] | 304 | = lambda(true, true) |
| 305 | |
| 306 | transition.animateFloat { |
| 307 | multipleParameterLambda { _, _ -> |
| 308 | multipleParameterLambda { param1, _ -> |
| 309 | if (param1 && it) 1f else 0f |
| 310 | } |
| 311 | } |
| 312 | } |
| 313 | } |
| 314 | """ |
| 315 | ), |
| 316 | TransitionStub, |
Louis Pullen-Freilich | cafae15 | 2021-06-02 21:40:39 +0100 | [diff] [blame] | 317 | Stubs.Composable |
Louis Pullen-Freilich | 0f84a10 | 2021-03-16 22:41:00 +0000 | [diff] [blame] | 318 | ) |
| 319 | .run() |
| 320 | .expectClean() |
| 321 | } |
| 322 | } |
| 323 | /* ktlint-enable max-line-length */ |