Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f944dbe1 authored by Daniel Akinola's avatar Daniel Akinola Committed by Android (Google) Code Review
Browse files

Merge "Allow @Application Context & @GlobalConfig Configuration Classes past...

Merge "Allow @Application Context & @GlobalConfig Configuration Classes past ShadeDisplayAware linter" into main
parents 1aa05225 b651b139
Loading
Loading
Loading
Loading
+49 −23
Original line number Original line Diff line number Diff line
@@ -25,6 +25,7 @@ import com.android.tools.lint.detector.api.JavaContext
import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.SourceCodeScanner
import com.android.tools.lint.detector.api.SourceCodeScanner
import com.intellij.psi.PsiParameter
import org.jetbrains.uast.UClass
import org.jetbrains.uast.UClass
import org.jetbrains.uast.getContainingUFile
import org.jetbrains.uast.getContainingUFile


@@ -40,14 +41,8 @@ class ShadeDisplayAwareDetector : Detector(), SourceCodeScanner {
                    if (!isInRelevantShadePackage(node)) continue
                    if (!isInRelevantShadePackage(node)) continue
                    if (IGNORED_PACKAGES.contains(node.qualifiedName)) continue
                    if (IGNORED_PACKAGES.contains(node.qualifiedName)) continue


                    // Check the any context-dependent parameter to see if it has @ShadeDisplayAware
                    // annotation
                    for (parameter in constructor.parameterList.parameters) {
                    for (parameter in constructor.parameterList.parameters) {
                        val shouldReport =
                        if (parameter.shouldReport()) {
                            CONTEXT_DEPENDENT_SHADE_CLASSES.contains(
                                parameter.type.canonicalText
                            ) && !parameter.hasAnnotation(SHADE_DISPLAY_AWARE_ANNOTATION)
                        if (shouldReport) {
                            context.report(
                            context.report(
                                issue = ISSUE,
                                issue = ISSUE,
                                scope = parameter.declarationScope,
                                scope = parameter.declarationScope,
@@ -62,20 +57,35 @@ class ShadeDisplayAwareDetector : Detector(), SourceCodeScanner {


    companion object {
    companion object {
        private const val INJECT_ANNOTATION = "javax.inject.Inject"
        private const val INJECT_ANNOTATION = "javax.inject.Inject"
        private const val APPLICATION_ANNOTATION =
            "com.android.systemui.dagger.qualifiers.Application"
        private const val GLOBAL_CONFIG_ANNOTATION = "com.android.systemui.common.ui.GlobalConfig"
        private const val SHADE_DISPLAY_AWARE_ANNOTATION =
        private const val SHADE_DISPLAY_AWARE_ANNOTATION =
            "com.android.systemui.shade.ShadeDisplayAware"
            "com.android.systemui.shade.ShadeDisplayAware"


        private const val CONTEXT = "android.content.Context"
        private const val WINDOW_MANAGER = "android.view.WindowManager"
        private const val LAYOUT_INFLATER = "android.view.LayoutInflater"
        private const val RESOURCES = "android.content.res.Resources"
        private const val CONFIG_STATE = "com.android.systemui.common.ui.ConfigurationState"
        private const val CONFIG_CONTROLLER =
            "com.android.systemui.statusbar.policy.ConfigurationController"
        private const val CONFIG_INTERACTOR =
            "com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor"

        private val CONTEXT_DEPENDENT_SHADE_CLASSES =
        private val CONTEXT_DEPENDENT_SHADE_CLASSES =
            setOf(
            setOf(
                "android.content.Context",
                CONTEXT,
                "android.view.WindowManager",
                WINDOW_MANAGER,
                "android.view.LayoutInflater",
                LAYOUT_INFLATER,
                "android.content.res.Resources",
                RESOURCES,
                "com.android.systemui.common.ui.ConfigurationState",
                CONFIG_STATE,
                "com.android.systemui.statusbar.policy.ConfigurationController",
                CONFIG_CONTROLLER,
                "com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor",
                CONFIG_INTERACTOR,
            )
            )


        private val CONFIG_CLASSES = setOf(CONFIG_STATE, CONFIG_CONTROLLER, CONFIG_INTERACTOR)

        private val SHADE_WINDOW_PACKAGES =
        private val SHADE_WINDOW_PACKAGES =
            listOf(
            listOf(
                "com.android.systemui.biometrics",
                "com.android.systemui.biometrics",
@@ -93,6 +103,22 @@ class ShadeDisplayAwareDetector : Detector(), SourceCodeScanner {
                "com.android.systemui.qs.customize.TileAdapter",
                "com.android.systemui.qs.customize.TileAdapter",
            )
            )


        private fun PsiParameter.shouldReport(): Boolean {
            val className = type.canonicalText

            // check if the parameter is a context-dependent class relevant to shade
            if (className !in CONTEXT_DEPENDENT_SHADE_CLASSES) return false
            // check if it has @ShadeDisplayAware
            if (hasAnnotation(SHADE_DISPLAY_AWARE_ANNOTATION)) return false
            // check if its a @Application-annotated Context
            if (className == CONTEXT && hasAnnotation(APPLICATION_ANNOTATION)) return false
            // check if its a @GlobalConfig-annotated ConfigurationState, ConfigurationController
            // or ConfigurationInteractor
            if (className in CONFIG_CLASSES && hasAnnotation(GLOBAL_CONFIG_ANNOTATION)) return false

            return true
        }

        private fun isInRelevantShadePackage(node: UClass): Boolean {
        private fun isInRelevantShadePackage(node: UClass): Boolean {
            val packageName = node.getContainingUFile()?.packageName
            val packageName = node.getContainingUFile()?.packageName
            if (packageName.isNullOrBlank()) return false
            if (packageName.isNullOrBlank()) return false
@@ -102,15 +128,15 @@ class ShadeDisplayAwareDetector : Detector(), SourceCodeScanner {
        }
        }


        private fun reportMsg(className: String) =
        private fun reportMsg(className: String) =
            """UI elements of the shade window
            "UI elements of the shade window should use " +
              |should use ShadeDisplayAware-annotated $className, as the shade might move between windows, and only
                "ShadeDisplayAware-annotated $className, as the shade might move between windows, " +
              |@ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
                "and only @ShadeDisplayAware resources are updated with the new configuration " +
              |might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
                "correctly. Failures to do so might result in wrong dimensions for shade window " +
              |If the usage of $className is not related to display specific configuration or UI, then there is
                "classes (e.g. using the wrong density or theme). If the usage of $className is " +
              |technically no need to use the annotation, and you can annotate the class with
                "not related to display specific configuration or UI, then there is technically " +
              |@SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")
                "no need to use the annotation, and you can annotate the class with " +
              |"""
                "@SuppressLint(\"ShadeDisplayAwareContextChecker\")/" +
                .trimMargin()
                "@Suppress(\"ShadeDisplayAwareContextChecker\")".trimMargin()


        @JvmField
        @JvmField
        val ISSUE: Issue =
        val ISSUE: Issue =
+85 −9
Original line number Original line Diff line number Diff line
@@ -63,6 +63,26 @@ class ShadeDisplayAwareDetectorTest : SystemUILintDetectorTest() {
            )
            )
            .indented()
            .indented()


    private val applicationStub: TestFile =
        kotlin(
                """
                package com.android.systemui.dagger.qualifiers

                @Retention(AnnotationRetention.RUNTIME) annotation class Application
                """
            )
            .indented()

    private val globalConfigStub: TestFile =
        kotlin(
                """
                package com.android.systemui.common.ui

                @Retention(AnnotationRetention.RUNTIME) annotation class GlobalConfig
                """
            )
            .indented()

    private val configStateStub: TestFile =
    private val configStateStub: TestFile =
        kotlin(
        kotlin(
                """
                """
@@ -98,6 +118,8 @@ class ShadeDisplayAwareDetectorTest : SystemUILintDetectorTest() {
            injectStub,
            injectStub,
            qsContext,
            qsContext,
            shadeDisplayAwareStub,
            shadeDisplayAwareStub,
            applicationStub,
            globalConfigStub,
            configStateStub,
            configStateStub,
            configControllerStub,
            configControllerStub,
            configInteractorStub,
            configInteractorStub,
@@ -258,6 +280,60 @@ class ShadeDisplayAwareDetectorTest : SystemUILintDetectorTest() {
            .expectClean()
            .expectClean()
    }
    }


    @Test
    fun injectedConstructor_inRelevantPackage_withApplicationAnnotatedContext() {
        lint()
            .files(
                TestFiles.kotlin(
                    """
                        package com.android.systemui.shade.example

                        import javax.inject.Inject
                        import android.content.Context
                        import com.android.systemui.dagger.qualifiers.Application

                        class ExampleClass
                            @Inject
                            constructor(@Application private val context: Context)
                    """
                        .trimIndent()
                ),
                *androidStubs,
                *otherStubs,
            )
            .issues(ShadeDisplayAwareDetector.ISSUE)
            .testModes(TestMode.DEFAULT)
            .run()
            .expectClean()
    }

    @Test
    fun injectedConstructor_inRelevantPackage_withGlobalConfigAnnotatedConfigurationClass() {
        lint()
            .files(
                TestFiles.kotlin(
                    """
                        package com.android.systemui.shade.example

                        import javax.inject.Inject
                        import com.android.systemui.common.ui.ConfigurationState
                        import com.android.systemui.common.ui.GlobalConfig

                        class ExampleClass
                            @Inject
                            constructor(@GlobalConfig private val configState: ConfigurationState)
                    """
                        .trimIndent()
                ),
                *androidStubs,
                *otherStubs,
            )
            .issues(ShadeDisplayAwareDetector.ISSUE)
            .testModes(TestMode.DEFAULT)
            .run()
            .expectClean()
    }

    @Test
    @Test
    fun injectedConstructor_notInRelevantPackage_withRelevantParameter_withoutAnnotation() {
    fun injectedConstructor_notInRelevantPackage_withRelevantParameter_withoutAnnotation() {
        lint()
        lint()
@@ -363,13 +439,13 @@ class ShadeDisplayAwareDetectorTest : SystemUILintDetectorTest() {
    }
    }


    private fun errorMsgString(lineNumber: Int, className: String) =
    private fun errorMsgString(lineNumber: Int, className: String) =
        """
        "src/com/android/systemui/shade/example/ExampleClass.kt:$lineNumber: Error: UI elements of " +
        src/com/android/systemui/shade/example/ExampleClass.kt:$lineNumber: Error: UI elements of the shade window
            "the shade window should use ShadeDisplayAware-annotated $className, as the shade " +
        should use ShadeDisplayAware-annotated $className, as the shade might move between windows, and only
            "might move between windows, and only @ShadeDisplayAware resources are updated with " +
        @ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so
            "the new configuration correctly. Failures to do so might result in wrong dimensions " +
        might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme).
            "for shade window classes (e.g. using the wrong density or theme). If the usage of " +
        If the usage of $className is not related to display specific configuration or UI, then there is
            "$className is not related to display specific configuration or UI, then there is " +
        technically no need to use the annotation, and you can annotate the class with
            "technically no need to use the annotation, and you can annotate the class with " +
        @SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")
            "@SuppressLint(\"ShadeDisplayAwareContextChecker\")" +
    """
            "/@Suppress(\"ShadeDisplayAwareContextChecker\")"
}
}
+199 −3

File changed.

Preview size limit exceeded, changes collapsed.