[go: nahoru, domu]

Merge "Add Scaffold content padding lint check" into androidx-main
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/layout/LayoutBasics.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/layout/LayoutBasics.kt
index 443615f..b390058 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/layout/LayoutBasics.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/layout/LayoutBasics.kt
@@ -22,6 +22,7 @@
 
 package androidx.compose.integration.docs.layout
 
+import android.annotation.SuppressLint
 import androidx.compose.foundation.background
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Arrangement
@@ -257,6 +258,7 @@
     }
 }
 
+@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
 private object LayoutBasicsSnippet16 {
     @Composable
     fun HomeScreen(/*...*/) {
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/layout/Material.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/layout/Material.kt
index 3d240ca..67ddde2 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/layout/Material.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/layout/Material.kt
@@ -22,6 +22,7 @@
 
 package androidx.compose.integration.docs.layout
 
+import android.annotation.SuppressLint
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.Spacer
@@ -137,6 +138,7 @@
     }
 }
 
+@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
 private object MaterialSnippet5 {
     @Composable
     fun MyTopAppBar() {
@@ -150,6 +152,7 @@
     }
 }
 
+@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
 private object MaterialSnippet6 {
     @Composable
     fun MyBottomAppBar() {
@@ -163,6 +166,7 @@
     }
 }
 
+@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
 private object MaterialSnippet7 {
     @Composable
     fun MyFAB() {
@@ -178,6 +182,7 @@
     }
 }
 
+@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
 private object MaterialSnippet8 {
     @Composable
     fun MyFAB() {
@@ -195,6 +200,7 @@
     }
 }
 
+@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
 private object MaterialSnippet9 {
     @Composable
     fun MyFAB() {
@@ -215,6 +221,7 @@
     }
 }
 
+@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
 private object MaterialSnippet10 {
     @Composable
     fun MyFAB() {
@@ -241,6 +248,7 @@
     }
 }
 
+@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
 private object MaterialSnippet11 {
     @Composable
     fun MySnackbar() {
@@ -265,6 +273,7 @@
     }
 }
 
+@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
 private object MaterialSnippet12 {
     @Composable
     fun MySnackbar() {
@@ -302,6 +311,7 @@
     }
 }
 
+@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
 private object MaterialSnippet13 {
     @Composable
     fun MyDrawer() {
@@ -317,6 +327,7 @@
     }
 }
 
+@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
 private object MaterialSnippet14 {
     @Composable
     fun MyDrawer() {
@@ -332,6 +343,7 @@
     }
 }
 
+@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
 private object MaterialSnippet15 {
     @Composable
     fun MyDrawer() {
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/navigation/Navigation.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/navigation/Navigation.kt
index 2d9e0c7..0ac03ae 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/navigation/Navigation.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/navigation/Navigation.kt
@@ -22,6 +22,7 @@
 import android.app.PendingIntent
 import android.content.Intent
 import androidx.annotation.StringRes
+import androidx.compose.foundation.layout.padding
 import androidx.compose.material.BottomNavigation
 import androidx.compose.material.BottomNavigationItem
 import androidx.compose.material.Button
@@ -32,6 +33,7 @@
 import androidx.compose.material.icons.filled.Favorite
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
+import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.stringResource
 import androidx.core.app.TaskStackBuilder
@@ -177,9 +179,12 @@
                 }
             }
         }
-    ) {
-
-        NavHost(navController, startDestination = Screen.Profile.route) {
+    ) { innerPadding ->
+        NavHost(
+            navController,
+            startDestination = Screen.Profile.route,
+            modifier = Modifier.padding(innerPadding)
+        ) {
             composable(Screen.Profile.route) { Profile(navController) }
             composable(Screen.FriendsList.route) { FriendsList(navController) }
         }
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/sideeffects/SideEffects.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/sideeffects/SideEffects.kt
index 7429a97..d2f586f 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/sideeffects/SideEffects.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/sideeffects/SideEffects.kt
@@ -21,9 +21,11 @@
 
 package androidx.compose.integration.docs.sideeffects
 
+import android.annotation.SuppressLint
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.items
 import androidx.compose.foundation.lazy.rememberLazyListState
@@ -73,6 +75,7 @@
  * No action required if it's modified.
  */
 
+@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
 @ExperimentalMaterialApi
 private object SideEffectsSnippet1 {
     @Composable
@@ -112,8 +115,8 @@
         // Creates a CoroutineScope bound to the MoviesScreen's lifecycle
         val scope = rememberCoroutineScope()
 
-        Scaffold(scaffoldState = scaffoldState) {
-            Column {
+        Scaffold(scaffoldState = scaffoldState) { innerPadding ->
+            Column(Modifier.padding(innerPadding)) {
                 /* ... */
                 Button(
                     >
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/state/State.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/state/State.kt
index a8ed7dec2..b531c3e4 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/state/State.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/state/State.kt
@@ -192,13 +192,14 @@
             val scaffoldState = rememberScaffoldState()
             val coroutineScope = rememberCoroutineScope()
 
-            Scaffold(scaffoldState = scaffoldState) {
+            Scaffold(scaffoldState = scaffoldState) { innerPadding ->
                 MyContent(
                     showSnackbar = { message ->
                         coroutineScope.launch {
                             scaffoldState.snackbarHostState.showSnackbar(message)
                         }
-                    }
+                    },
+                    modifier = Modifier.padding(innerPadding)
                 )
             }
         }
@@ -261,8 +262,12 @@
                         )
                     }
                 }
-            ) {
-                NavHost(navController = myAppState.navController, "initial") { /* ... */ }
+            ) { innerPadding ->
+                NavHost(
+                    navController = myAppState.navController,
+                    startDestination = "initial",
+                    modifier = Modifier.padding(innerPadding)
+                ) { /* ... */ }
             }
         }
     }
@@ -286,7 +291,7 @@
 private fun MyTheme(content: @Composable () -> Unit) {}
 
 @Composable
-private fun MyContent(showSnackbar: (String) -> Unit) {}
+private fun MyContent(showSnackbar: (String) -> Unit, modifier: Modifier = Modifier) {}
 
 @Composable
 private fun BottomBar(tabs: Unit, navigateToRoute: (String) -> Unit) {}
diff --git a/compose/lint/common/src/main/java/androidx/compose/lint/Names.kt b/compose/lint/common/src/main/java/androidx/compose/lint/Names.kt
index 016e112..7423dbe 100644
--- a/compose/lint/common/src/main/java/androidx/compose/lint/Names.kt
+++ b/compose/lint/common/src/main/java/androidx/compose/lint/Names.kt
@@ -28,6 +28,9 @@
     object AnimationCore {
         val PackageName = Package("androidx.compose.animation.core")
     }
+    object Material {
+        val PackageName = Package("androidx.compose.material")
+    }
     object Runtime {
         val PackageName = Package("androidx.compose.runtime")
 
diff --git a/compose/material/material-lint/src/main/java/androidx/compose/material/lint/ColorsDetector.kt b/compose/material/material-lint/src/main/java/androidx/compose/material/lint/ColorsDetector.kt
index 2f4c445..11cbd84 100644
--- a/compose/material/material-lint/src/main/java/androidx/compose/material/lint/ColorsDetector.kt
+++ b/compose/material/material-lint/src/main/java/androidx/compose/material/lint/ColorsDetector.kt
@@ -19,7 +19,7 @@
 package androidx.compose.material.lint
 
 import androidx.compose.lint.Name
-import androidx.compose.lint.Package
+import androidx.compose.lint.Names
 import androidx.compose.lint.isInPackageName
 import com.android.tools.lint.client.api.UElementHandler
 import com.android.tools.lint.detector.api.Category
@@ -55,7 +55,7 @@
     override fun createUastHandler(context: JavaContext) = object : UElementHandler() {
         override fun visitCallExpression(node: UCallExpression) {
             val method = node.resolve() ?: return
-            if (!method.isInPackageName(MaterialPackageName)) return
+            if (!method.isInPackageName(Names.Material.PackageName)) return
 
             if (node.isConstructorCall()) {
                 if (method.containingClass?.name != Colors.shortName) return
@@ -229,7 +229,6 @@
     "error" to "onError"
 )
 
-private val MaterialPackageName = Package("androidx.compose.material")
-private val LightColors = Name(MaterialPackageName, "lightColors")
-private val DarkColors = Name(MaterialPackageName, "darkColors")
-private val Colors = Name(MaterialPackageName, "Colors")
+private val LightColors = Name(Names.Material.PackageName, "lightColors")
+private val DarkColors = Name(Names.Material.PackageName, "darkColors")
+private val Colors = Name(Names.Material.PackageName, "Colors")
diff --git a/compose/material/material-lint/src/main/java/androidx/compose/material/lint/MaterialIssueRegistry.kt b/compose/material/material-lint/src/main/java/androidx/compose/material/lint/MaterialIssueRegistry.kt
index 4553ca9..75ce926 100644
--- a/compose/material/material-lint/src/main/java/androidx/compose/material/lint/MaterialIssueRegistry.kt
+++ b/compose/material/material-lint/src/main/java/androidx/compose/material/lint/MaterialIssueRegistry.kt
@@ -28,7 +28,8 @@
     override val api = 13
     override val minApi = CURRENT_API
     override val issues get() = listOf(
-        ColorsDetector.ConflictingOnColor
+        ColorsDetector.ConflictingOnColor,
+        ScaffoldPaddingDetector.UnusedMaterialScaffoldPaddingParameter
     )
     override val vendor = Vendor(
         vendorName = "Jetpack Compose",
diff --git a/compose/material/material-lint/src/main/java/androidx/compose/material/lint/ScaffoldPaddingDetector.kt b/compose/material/material-lint/src/main/java/androidx/compose/material/lint/ScaffoldPaddingDetector.kt
new file mode 100644
index 0000000..252ab25
--- /dev/null
+++ b/compose/material/material-lint/src/main/java/androidx/compose/material/lint/ScaffoldPaddingDetector.kt
@@ -0,0 +1,89 @@
+/*
+ * 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.material.lint
+
+import androidx.compose.lint.Name
+import androidx.compose.lint.Names
+import androidx.compose.lint.findUnreferencedParameters
+import androidx.compose.lint.isInPackageName
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.android.tools.lint.detector.api.computeKotlinArgumentMapping
+import com.intellij.psi.PsiMethod
+import java.util.EnumSet
+import org.jetbrains.uast.UCallExpression
+import org.jetbrains.uast.ULambdaExpression
+
+/**
+ * [Detector] that checks `Scaffold` usages for correctness.
+ *
+ * Scaffold provides an padding parameter to the `content` lambda. If this value is unused,
+ * then the content may be obscured by app bars defined by the scaffold.
+ */
+class ScaffoldPaddingDetector : Detector(), SourceCodeScanner {
+    override fun getApplicableMethodNames(): List<String> = listOf(Scaffold.shortName)
+
+    override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
+        if (method.isInPackageName(Names.Material.PackageName)) {
+            val contentArgument = computeKotlinArgumentMapping(node, method)
+                .orEmpty()
+                .filter { (_, parameter) ->
+                    parameter.name == "content"
+                }
+                .keys
+                .filterIsInstance<ULambdaExpression>()
+                .firstOrNull() ?: return
+
+            contentArgument.findUnreferencedParameters().forEach { unreferencedParameter ->
+                val location = unreferencedParameter.parameter
+                    ?.let { context.getLocation(it) }
+                    ?: context.getLocation(contentArgument)
+                val name = unreferencedParameter.name
+                context.report(
+                    UnusedMaterialScaffoldPaddingParameter,
+                    node,
+                    location,
+                    "Content padding parameter $name is not used"
+                )
+            }
+        }
+    }
+
+    companion object {
+        val UnusedMaterialScaffoldPaddingParameter = Issue.create(
+            "UnusedMaterialScaffoldPaddingParameter",
+            "Scaffold content should use the padding provided as a lambda parameter",
+            "The `content` lambda in Scaffold has a padding parameter " +
+                "which will include any inner padding for the content due to app bars. If this " +
+                "parameter is ignored, then content may be obscured by the app bars resulting in " +
+                "visual issues or elements that can't be interacted with.",
+            Category.CORRECTNESS, 3, Severity.ERROR,
+            Implementation(
+                ScaffoldPaddingDetector::class.java,
+                EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES)
+            )
+        )
+    }
+}
+
+private val Scaffold = Name(Names.Material.PackageName, "Scaffold")
\ No newline at end of file
diff --git a/compose/material/material-lint/src/test/java/androidx/compose/material/lint/ScaffoldPaddingDetectorTest.kt b/compose/material/material-lint/src/test/java/androidx/compose/material/lint/ScaffoldPaddingDetectorTest.kt
new file mode 100644
index 0000000..88b9576
--- /dev/null
+++ b/compose/material/material-lint/src/test/java/androidx/compose/material/lint/ScaffoldPaddingDetectorTest.kt
@@ -0,0 +1,305 @@
+/*
+ * 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.
+ */
+
+@file:Suppress("UnstableApiUsage")
+
+package androidx.compose.material.lint
+
+import androidx.compose.lint.test.Stubs
+import androidx.compose.lint.test.compiledStub
+import com.android.tools.lint.checks.infrastructure.LintDetectorTest
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+/* ktlint-disable max-line-length */
+@RunWith(JUnit4::class)
+
+/**
+ * Test for [ScaffoldPaddingDetector].
+ */
+class ScaffoldPaddingDetectorTest : LintDetectorTest() {
+    override fun getDetector(): Detector = ScaffoldPaddingDetector()
+
+    override fun getIssues(): MutableList<Issue> =
+        mutableListOf(ScaffoldPaddingDetector.UnusedMaterialScaffoldPaddingParameter)
+
+    private val PaddingValuesStub = compiledStub(
+        filename = "Padding.kt",
+        filepath = "androidx/compose/foundation/layout",
+        checksum = 0xeedd3f96,
+        """
+
+            package androidx.compose.foundation.layout
+
+            import androidx.compose.ui.Modifier
+
+            interface PaddingValues
+
+        """,
+        """
+        META-INF/main.kotlin_module:
+        H4sIAAAAAAAAAGNgYGBmYGBgBGI2BijgUueSTMxLKcrPTKnQS87PLcgvTtXL
+        TSxJLcpMzBHiCk5OTEvLz0nxLuHi5WJOy88XYgtJLS7xLlFi0GIAACJwI+tQ
+        AAAA
+        """,
+        """
+        androidx/compose/foundation/layout/PaddingValues.class:
+        H4sIAAAAAAAAAJVOTUvDQBB9s9Gkxq9ULdQ/YdrizZMXIVBRFHrJaZtsyzbp
+        rnQ3pd76uzxIz/4ocVL9A87Amzfz4L35+v74BHCLHmEgTbmyutykhV2+WafS
+        mW1MKb22Jq3lu218+izLUpv5RNaNchGIkCzkWrJs5unTdKEKHyEgdMeV9bU2
+        6aPyki3kHUEs1wFnUQthCyBQxfeNbrcBs3JI6O22nVj0RSwSZrP+bjsSA2rF
+        EWE0/u+THMw58d/tpvK8vNpmVagHXSvC9UtjvF6qiXZ6Wqt7Y6zfu7mQM3GA
+        3xK43OMFrngO2fKQO8wRZIgydDIcIWaK4wwnOM1BDmc4zyEcEofuD692uKBp
+        AQAA
+        """
+
+    )
+
+    // Simplified Scaffold.kt stubs
+    private val ScaffoldStub = compiledStub(
+        filename = "Scaffold.kt",
+        filepath = "androidx/compose/material",
+        checksum = 0x2dde3750,
+        """
+            package androidx.compose.material
+
+            import androidx.compose.foundation.layout.PaddingValues
+            import androidx.compose.runtime.Composable
+            import androidx.compose.ui.Modifier
+
+            @Composable
+            fun Scaffold(
+                modifier: Modifier = Modifier,
+                topBar: @Composable () -> Unit = {},
+                bottomBar: @Composable () -> Unit = {},
+                content: @Composable (PaddingValues) -> Unit
+            ) {}
+
+        """,
+        """
+        META-INF/main.kotlin_module:
+        H4sIAAAAAAAAAGNgYGBmYGBgBGI2BijgUueSTMxLKcrPTKnQS87PLcgvTtXL
+        TSxJLcpMzBHiCk5OTEvLz0nxLuHi5WJOy88XYgtJLS7xLlFi0GIAACJwI+tQ
+        AAAA
+        """,
+        """
+        androidx/compose/material/ScaffoldKt$Scaffold$1.class:
+        H4sIAAAAAAAAAKVU604TQRT+Zlt6xxZEuYj3qi0o2+LdNiSEQNxQMLHYxPBr
+        2t3C0N1Z091t8B8P4RP4BKKJJJoY4k8fynhmaQ2GiBo32bMn53zfmXOb/fb9
+        0xcA9/CEQefS7LrC3NVbrvPK9Szd4b7VFdzW6y3ebru2uernB2q+HAdjWK11
+        XN8WUt/pObqQhJeEr3GnafLKcV87kC1fuNLTV/paqTrwv5DCryxUGKZ+HyyO
+        KMOl0wPGEWOIVQWFW2CIFIoNhmjBKDYySCCVwhDSZPC3hcdQrv1juZReTMie
+        27EYxgrF2g7vcd3mckt/1tyxWn4lgyySKWgYYUgfqyyOswwJY72+sbi+tMww
+        /EvZGZzD+STGME6gassOk1f5hqGmlPtMkrRphpEBcc3yucl9TilpTi9CA2RK
+        xJQAA+soJULOXaG0EmlmmWH6cC+ROtxLaTmNPrnDvSmtxJ6mvr6NaQlNYeYp
+        8SqXrnztuIFHLaRg+b9pUxy3GXI/e2VabR7YPsObwskuB0Jfc03RFlb3Twvy
+        n/5yxTg5JbUMc9Cp0kG6cx3KNLrkmjTY0Zrb4naDU31N29pQgiFbE9JaD5ym
+        1e1bMoaUVnfJ5p5n0S5ll2XLdj0ht2gy267JkKyLLcn9oEvgVN0Nui1rRSjm
+        5PNA+sKxGsITFGpRStfnYdoo0ZSHqON0rzCpxk6ji9JLq0CWedLyhGBq0DOR
+        A2T2w2HfJZk5smI45IyoPewzZkMMvQqs0T1XMGVIHyOyI2JukYi5PnFe7ZE6
+        fOYjRt9j4t0p/ET/4ASlPTh4nNDqSX+G9vIAFz7g4n5oGMJ9kimCHQEm8CCs
+        8w7V/zA8JIJH4beMx+Gvia49sS5vImLgioGrBq7hukHNuGHgJm5tgnkooEh+
+        DzMeZj1kfwB7t1DT1wQAAA==
+        """,
+        """
+        androidx/compose/material/ScaffoldKt$Scaffold$2.class:
+        H4sIAAAAAAAAAKVU604TQRT+Zlt6WYotiHIR71VbULatd9uQECJxQ8HEYhPD
+        r2l3C0O3s6a72+A/HsIn8AlEE0k0McSfPpTxzNIqhogaN9mzJ+d835lzm/36
+        7eNnAHfwiMHg0uq6wtoxmm7npevZRof7dldwx6g1eavlOtaKnx2o2VIcjGGl
+        2nZ9R0hju9cxhCS8JHyVdxoWLx/1tQLZ9IUrPWO5rxUqA/9zKfzyQplh+vfB
+        4ogyXDg5YBwxhlhFULgFhkguX2eI5sx8PYUEdB1DGCaDvyU8hmL1H8ul9GJC
+        9ty2zTCey1e3eY8bDpebxtPGtt30yymkkdShYZRh+EhlcZxmSJhrtfXFtaXH
+        DCO/lJ3CGZxNYhwTBKo0nTB5lW8Yalq5TyVJm2EYHRBXbZ9b3OeUktbpRWiA
+        TImYEmBgbaVEyLkjlFYgzSoyzBzsJvSDXV3LaPTJHOxOawX2RP/yJqYlNIUp
+        UeIVLl35quMGHrWQgmX/pk1x3GTI/OiVZbd44PgMr3PHuxwIY9W1REvY3T8t
+        yH/6i2Xz+JTUMszDoEoH6c63KdPokmvRYMeqbpM7dU71NRx7XQmGdFVIey3o
+        NOxu35IypbS7Sw73PJt2Kf1YNh3XE3KTJrPlWgzJmtiU3A+6BNZrbtBt2stC
+        MaeeBdIXHbsuPEGhFqV0fR6mjQJNeYg6TvcKU2rsNLoovbQKZCmRliUEU4Oe
+        jewjtRcO+zbJ1KEVIyFnVO1hnzEXYuhVYI3uuYKxkPKTyA6JmUUiZvrEktoj
+        dfjsB4y9w+TbE/iJ/sEJSntw8ASh1TP8CdqLfZx7j/N7oWEId0nqBDsETOJe
+        WOctqv9+eEgED8JvEQ/DXxNde2Jd3EDExCUTl01cwVWTmnHNxHXc2ADzkEOe
+        /B5mPcx5SH8Hm6I3JNcEAAA=
+        """,
+        """
+        androidx/compose/material/ScaffoldKt.class:
+        H4sIAAAAAAAAAMVVS3PbVBT+rl+SFSd1lThN3BJK49I0jyo25elQSE3Titim
+        g9tssrqWZaNYusrokSkbJgx/gQ1b/gGsOiwYD0v+BX+E6ZFshzTupGTKDAvd
+        e173nO+ce+7Rn3//9juAu2gwlLjoeK7VeaYZrnPo+qbm8MD0LG5rLYN3u67d
+        2Q0kMIb8AT/ims1FT/uqfWAaJE0yyGMrhu9X6hPOQktruB2ra5letd53A9sS
+        2sGRo3VDYQSWK3xtZ0RtvqG+XL29x/DXm2HYGuufCiuo3vtvzctbG5Pgum4o
+        OjxSU2m/dcNAe8w7HUv09rgdmn71TIQox5uTXrxQBJZjarWY523brDIs112v
+        px2YQdvjFuHgQrgBH2JqukEztG2ykp1RbWQoDEunMrAENYKgRtBF4JEDy/Al
+        5BgKxjem0R95eMw97phkyHBrpX62RaqnJK3ISY8yyGEGlxRMI8+QCdzD+5xi
+        qwzZthsErhOzcwyS4RIAEciYJ1znXyvD9dd1z2tNymSSH3dzqWN2eWgHDD/+
+        z12tTxY1aoJr54GS8BaVM2oGLsgJw/k5lE4sqzm8jetZLOEdBu3fjIbSScXK
+        EpapnfRm68l2s/aAoTwZ9HwHFP0m3s2ihFsvd+Ir6ibh9oURViSsXRxWJYa1
+        kcU67uSQRkZBApsMl8c31zADTk+YU/8knKMkTVYWLZloAQPrR0SClM+siKKj
+        iU6Z4YfB8Q1lcKwk8ol4WzjZ4k9OjOni0/zguJjYZBVZJmOikpVZolLFaTWl
+        knwz/cfPmYSciaXShPRKXi7OxjJlpMkONY+kCEqFRSjVcTanX8yEMHojlYsP
+        MYapcTnv9OlNpWpux2S4VLeE2Qydtuk9iWZWFNA1uL3H6TKIHwmzLasneBB6
+        RF/9ejjpdHFk+Rapt/8ZavQzO6s9mU4vmU23Am70G/xwFCCnC2F6NZv7vklq
+        peWGnmHuWJFuceRybyIcytQHqeiOaV+MGoO4GnF8JF9cVaee4/KaOkvrulqg
+        dUO9Qusv8ZEvoh6hyi/QOHxA9OrwEBSSIKZU+lhMzdGXiKl5FJHETuxBwsOR
+        D5n2R5E+RUw2brszaz6Lq7hGdITQoVAZ2iuFVOq7n6D8ihsDLO0WUukhtzLA
+        ar2QkoacRlxjdW194znKQ+g6rWkkZ6an4yyWCAkoiETYZ2gvYIpCZbGMHGWV
+        Jbxfkl6lg6U4swV6SsN9N3Z3H3Xa6wSuQm7f20dSx10d7+v4AB/q+Agf6/gE
+        1X0wH1v4dB9TPtI+7vlQfCz4UH185kP2Medj3sfnPrZfADvMWafjCAAA
+        """
+    )
+
+    @Test
+    fun unreferencedParameters() {
+        lint().files(
+            kotlin(
+                """
+                package foo
+
+                import androidx.compose.material.*
+                import androidx.compose.runtime.*
+                import androidx.compose.ui.*
+
+                @Composable
+                fun Test() {
+                    Scaffold { /**/ }
+                    Scaffold(Modifier) { /**/ }
+                    Scaffold(Modifier, topBar = {}, bottomBar = {}) { /**/ }
+                    Scaffold(Modifier, topBar = {}, bottomBar = {}, content = { /**/ })
+                    Scaffold(Modifier, topBar = {}, bottomBar = {}) { _ -> /**/ }
+                    Scaffold(Modifier, topBar = {}, bottomBar = {}) { innerPadding -> /**/ }
+                }
+            """
+            ),
+            PaddingValuesStub,
+            ScaffoldStub,
+            Stubs.Modifier,
+            Stubs.Composable
+        )
+            .run()
+            .expect(
+                """
+src/foo/test.kt:10: Error: Content padding parameter it is not used [UnusedMaterialScaffoldPaddingParameter]
+                    Scaffold { /**/ }
+                             ~~~~~~~~
+src/foo/test.kt:11: Error: Content padding parameter it is not used [UnusedMaterialScaffoldPaddingParameter]
+                    Scaffold(Modifier) { /**/ }
+                                       ~~~~~~~~
+src/foo/test.kt:12: Error: Content padding parameter it is not used [UnusedMaterialScaffoldPaddingParameter]
+                    Scaffold(Modifier, topBar = {}, bottomBar = {}) { /**/ }
+                                                                    ~~~~~~~~
+src/foo/test.kt:13: Error: Content padding parameter it is not used [UnusedMaterialScaffoldPaddingParameter]
+                    Scaffold(Modifier, topBar = {}, bottomBar = {}, content = { /**/ })
+                                                                              ~~~~~~~~
+src/foo/test.kt:14: Error: Content padding parameter _ is not used [UnusedMaterialScaffoldPaddingParameter]
+                    Scaffold(Modifier, topBar = {}, bottomBar = {}) { _ -> /**/ }
+                                                                      ~
+src/foo/test.kt:15: Error: Content padding parameter innerPadding is not used [UnusedMaterialScaffoldPaddingParameter]
+                    Scaffold(Modifier, topBar = {}, bottomBar = {}) { innerPadding -> /**/ }
+                                                                      ~~~~~~~~~~~~
+6 errors, 0 warnings
+            """
+            )
+    }
+
+    @Test
+    fun unreferencedParameter_shadowedNames() {
+        lint().files(
+            kotlin(
+                """
+                package foo
+
+                import androidx.compose.material.*
+                import androidx.compose.runtime.*
+                import androidx.compose.ui.*
+
+                val foo = false
+
+                @Composable
+                fun Test() {
+                    Scaffold {
+                        foo.let {
+                            // These `it`s refer to the `let`, not the `Scaffold`, so we
+                            // should still report an error
+                            it.let {
+                                if (it) { /**/ } else { /**/ }
+                            }
+                        }
+                    }
+                    Scaffold(Modifier, topBar = {}, bottomBar = {}) { innerPadding ->
+                        foo.let { innerPadding ->
+                            // These `innerPadding`s refer to the `let`, not the `Scaffold`, so we
+                            // should still report an error
+                            innerPadding.let {
+                                if (innerPadding) { /**/ } else { /**/ }
+                            }
+                        }
+                    }
+                }
+            """
+            ),
+            PaddingValuesStub,
+            ScaffoldStub,
+            Stubs.Modifier,
+            Stubs.Composable
+        )
+            .run()
+            .expect(
+                """
+src/foo/test.kt:12: Error: Content padding parameter it is not used [UnusedMaterialScaffoldPaddingParameter]
+                    Scaffold {
+                             ^
+src/foo/test.kt:21: Error: Content padding parameter innerPadding is not used [UnusedMaterialScaffoldPaddingParameter]
+                    Scaffold(Modifier, topBar = {}, bottomBar = {}) { innerPadding ->
+                                                                      ~~~~~~~~~~~~
+2 errors, 0 warnings
+            """
+            )
+    }
+
+    @Test
+    fun noErrors() {
+        lint().files(
+            kotlin(
+                """
+                package foo
+
+                import androidx.compose.material.*
+                import androidx.compose.runtime.*
+                import androidx.compose.ui.*
+
+                @Composable
+                fun Test() {
+                    Scaffold {
+                        it
+                    }
+                    Scaffold(Modifier, topBar = {}, bottomBar = {}) { innerPadding ->
+                        innerPadding
+                    }
+                }
+        """
+            ),
+            PaddingValuesStub,
+            ScaffoldStub,
+            Stubs.Modifier,
+            Stubs.Composable
+        )
+            .run()
+            .expectClean()
+    }
+}
+/* ktlint-enable max-line-length */
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/keyinput/InterceptEnterToSendMessageDemo.kt b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/keyinput/InterceptEnterToSendMessageDemo.kt
index 52bcfa6..3c839a9 100644
--- a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/keyinput/InterceptEnterToSendMessageDemo.kt
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/keyinput/InterceptEnterToSendMessageDemo.kt
@@ -52,8 +52,8 @@
     val scaffoldState = rememberScaffoldState()
     val coroutineScope = rememberCoroutineScope()
     var textFieldValue by remember { mutableStateOf(TextFieldValue("")) }
-    Scaffold(scaffoldState = scaffoldState) {
-        Column {
+    Scaffold(scaffoldState = scaffoldState) { innerPadding ->
+        Column(Modifier.padding(innerPadding)) {
             Text(
                 text = "Use a physical keyboard with this demo. As you enter text into this " +
                     "textfield, notice how the enter key is intercepted to show a snackbar." +
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/modifier/CommunicatingModifierDemo.kt b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/modifier/CommunicatingModifierDemo.kt
index 8bc83e7f..6e04d4c 100644
--- a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/modifier/CommunicatingModifierDemo.kt
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/modifier/CommunicatingModifierDemo.kt
@@ -64,10 +64,11 @@
             }
     }
 
-    Scaffold(scaffoldState = scaffoldState) {
+    Scaffold(scaffoldState = scaffoldState) { innerPadding ->
         Column(
             Modifier
                 .background(Gray)
+                .padding(innerPadding)
                 .modifierLocalProvider(ModifierLocalColor) { "Gray" }
         ) {
             Text("Click the red box to read the parent's ModifierLocalColor")