From 063b9deffe9bb006c9677eb38a48bd7ae340934e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Odin=20Asbj=C3=B8rnsen?= Date: Tue, 4 Apr 2023 22:13:12 +0200 Subject: [PATCH] Handle private previews for Custom annotations (#313) * Handle private previews for Custom annotations The validation was not quite handled for the custom annotation processing steps and it had not passed the flag since it had a default argument. * Add comment to test and fix spelling misstake --- .../android/showkasesample/CustomShape.kt | 8 +++ showkase-browser-testing/build.gradle | 4 ++ .../ShowkaseBrowserTest.kt | 35 +++++++++++++ .../TestComposables.kt | 6 +++ .../ShowkaseProcessorTest.kt | 7 +++ .../input/Composables.kt | 19 +++++++ ...owkase_processor_testing_devicepreviews.kt | 19 +++++++ .../showkase/processor/ShowkaseProcessor.kt | 50 ++++++++++++------- 8 files changed, 129 insertions(+), 19 deletions(-) create mode 100644 showkase-processor-testing/src/test/resources/ShowkaseProcessorTest/composable_function_with_private_custom_preview_annotation_compiles_with_flag/input/Composables.kt create mode 100644 showkase-processor-testing/src/test/resources/ShowkaseProcessorTest/composable_function_with_private_custom_preview_annotation_compiles_with_flag/output/ShowkaseMetadata_showkase_com_airbnb_android_showkase_processor_testing_devicepreviews.kt diff --git a/sample/src/main/java/com/airbnb/android/showkasesample/CustomShape.kt b/sample/src/main/java/com/airbnb/android/showkasesample/CustomShape.kt index e8eaa0fba..9873c75be 100644 --- a/sample/src/main/java/com/airbnb/android/showkasesample/CustomShape.kt +++ b/sample/src/main/java/com/airbnb/android/showkasesample/CustomShape.kt @@ -33,3 +33,11 @@ fun CustomRoundedSquareWithText() { Text("This is a rounded square!") } } + +@FontPreview +@Composable +private fun PrivateCustomRoundedSquareWithText() { + Box(Modifier.size(100.dp).clip(RoundedCornerShape(8.dp))) { + Text("This is a private rounded square!") + } +} diff --git a/showkase-browser-testing/build.gradle b/showkase-browser-testing/build.gradle index 82490e224..9d3ed709b 100644 --- a/showkase-browser-testing/build.gradle +++ b/showkase-browser-testing/build.gradle @@ -3,12 +3,16 @@ apply plugin: 'kotlin-android' if (project.hasProperty('useKsp')) { apply plugin: 'com.google.devtools.ksp' + ksp { + arg("skipPrivatePreviews", "true") + } } else { apply plugin: 'kotlin-kapt' kapt { correctErrorTypes = true arguments { arg("multiPreviewType", "com.airbnb.android.submodule.showkasesample.LocalePreview") + arg("skipPrivatePreviews", "true") } } } diff --git a/showkase-browser-testing/src/androidTest/java/com/airbnb/android/showkase_browser_testing/ShowkaseBrowserTest.kt b/showkase-browser-testing/src/androidTest/java/com/airbnb/android/showkase_browser_testing/ShowkaseBrowserTest.kt index 4920d201d..fef34b0c4 100644 --- a/showkase-browser-testing/src/androidTest/java/com/airbnb/android/showkase_browser_testing/ShowkaseBrowserTest.kt +++ b/showkase-browser-testing/src/androidTest/java/com/airbnb/android/showkase_browser_testing/ShowkaseBrowserTest.kt @@ -816,4 +816,39 @@ class ShowcaseBrowserTest { } } + + // We have enabled private preview compiler flag so this test + // should test that we can have private methods annotated with custom annotations + // and that they will not show in the application. + @Test + fun customAnnotatedPrivateComposablesShouldCompileButNotShow() { + + composeTestRule.apply { + + verifyLandingScreen( + components = componentSize, + typography = 13, + colors = 4, + ) + // Tap on the "Components" row + clickRowWithText("Components ($componentSize)") + + waitForIdle() + + onRoot().performTouchInput { + swipeUp() + } + + waitForIdle() + + val composables = if (BuildConfig.IS_RUNNING_KSP) 3 else 1 + + clickRowWithText("LocalePreview ($composables)") + + onNodeWithText("Private Text Composable").assertDoesNotExist() + + waitForIdle() + + } + } } diff --git a/showkase-browser-testing/src/main/java/com/airbnb/android/showkase_browser_testing/TestComposables.kt b/showkase-browser-testing/src/main/java/com/airbnb/android/showkase_browser_testing/TestComposables.kt index 82a316254..093c25d4f 100644 --- a/showkase-browser-testing/src/main/java/com/airbnb/android/showkase_browser_testing/TestComposables.kt +++ b/showkase-browser-testing/src/main/java/com/airbnb/android/showkase_browser_testing/TestComposables.kt @@ -114,5 +114,11 @@ fun PreviewEnglishText() { BasicText(text = "Some text In locale") } +@EnglishLocalePreview +@Composable +private fun PrivateTextComposable() { + BasicText(text = "Private Text Composable") +} + @ShowkaseRoot class MyRootModule: ShowkaseRootModule diff --git a/showkase-processor-testing/src/test/java/com/airbnb/android/showkase_processor_testing/ShowkaseProcessorTest.kt b/showkase-processor-testing/src/test/java/com/airbnb/android/showkase_processor_testing/ShowkaseProcessorTest.kt index 928ee0157..a97cc08eb 100644 --- a/showkase-processor-testing/src/test/java/com/airbnb/android/showkase_processor_testing/ShowkaseProcessorTest.kt +++ b/showkase-processor-testing/src/test/java/com/airbnb/android/showkase_processor_testing/ShowkaseProcessorTest.kt @@ -611,5 +611,12 @@ class ShowkaseProcessorTest : BaseProcessorTest() { fun `top level composable function with showkase and showkaseroot with tags and metadata`() { compileInputsAndVerifyOutputs() } + + @Test + fun `composable function with private custom preview annotation compiles with flag`() { + val options = mutableMapOf() + options["skipPrivatePreviews"] = "true" + compileInputsAndVerifyOutputs(options = options) + } } diff --git a/showkase-processor-testing/src/test/resources/ShowkaseProcessorTest/composable_function_with_private_custom_preview_annotation_compiles_with_flag/input/Composables.kt b/showkase-processor-testing/src/test/resources/ShowkaseProcessorTest/composable_function_with_private_custom_preview_annotation_compiles_with_flag/input/Composables.kt new file mode 100644 index 000000000..69a251cb2 --- /dev/null +++ b/showkase-processor-testing/src/test/resources/ShowkaseProcessorTest/composable_function_with_private_custom_preview_annotation_compiles_with_flag/input/Composables.kt @@ -0,0 +1,19 @@ +package com.airbnb.android.showkase_processor_testing + +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview + + +@Preview( + name = "large Screen", + group = "device", +) +public annotation class DevicePreviews + +public class Composables { + + @DevicePreviews + @Composable + private fun Component() { + } +} diff --git a/showkase-processor-testing/src/test/resources/ShowkaseProcessorTest/composable_function_with_private_custom_preview_annotation_compiles_with_flag/output/ShowkaseMetadata_showkase_com_airbnb_android_showkase_processor_testing_devicepreviews.kt b/showkase-processor-testing/src/test/resources/ShowkaseProcessorTest/composable_function_with_private_custom_preview_annotation_compiles_with_flag/output/ShowkaseMetadata_showkase_com_airbnb_android_showkase_processor_testing_devicepreviews.kt new file mode 100644 index 000000000..9ece7a520 --- /dev/null +++ b/showkase-processor-testing/src/test/resources/ShowkaseProcessorTest/composable_function_with_private_custom_preview_annotation_compiles_with_flag/output/ShowkaseMetadata_showkase_com_airbnb_android_showkase_processor_testing_devicepreviews.kt @@ -0,0 +1,19 @@ +// This is an auto-generated file. Please do not edit/modify this file. +package com.airbnb.android.showkase + +import com.airbnb.android.showkase.`annotation`.ShowkaseMultiPreviewCodegenMetadata +import kotlin.Unit + +public class ShowkaseMetadata_showkase_com_airbnb_android_showkase_processor_testing_devicepreviews + { + @ShowkaseMultiPreviewCodegenMetadata( + previewName = "large Screen", + previewGroup = "device", + supportTypeQualifiedName = "com.airbnb.android.showkase_processor_testing.DevicePreviews", + showkaseWidth = -1, + showkaseHeight = -1, + packageName = "com.airbnb.android.showkase_processor_testing", + ) + public fun Preview_0(): Unit { + } +} diff --git a/showkase-processor/src/main/java/com/airbnb/android/showkase/processor/ShowkaseProcessor.kt b/showkase-processor/src/main/java/com/airbnb/android/showkase/processor/ShowkaseProcessor.kt index b9ecd1b7f..f55f9b9df 100644 --- a/showkase-processor/src/main/java/com/airbnb/android/showkase/processor/ShowkaseProcessor.kt +++ b/showkase-processor/src/main/java/com/airbnb/android/showkase/processor/ShowkaseProcessor.kt @@ -26,11 +26,11 @@ import com.airbnb.android.showkase.processor.models.getShowkaseMetadataFromPrevi import com.airbnb.android.showkase.processor.models.getShowkaseTypographyMetadata import com.airbnb.android.showkase.processor.writer.PaparazziShowkaseScreenshotTestWriter import com.airbnb.android.showkase.processor.writer.ShowkaseBrowserProperties +import com.airbnb.android.showkase.processor.writer.ShowkaseBrowserPropertyWriter import com.airbnb.android.showkase.processor.writer.ShowkaseBrowserWriter import com.airbnb.android.showkase.processor.writer.ShowkaseBrowserWriter.Companion.CODEGEN_AUTOGEN_CLASS_NAME import com.airbnb.android.showkase.processor.writer.ShowkaseCodegenMetadataWriter import com.airbnb.android.showkase.processor.writer.ShowkaseExtensionFunctionsWriter -import com.airbnb.android.showkase.processor.writer.ShowkaseBrowserPropertyWriter import com.airbnb.android.showkase.processor.writer.ShowkaseScreenshotTestWriter import com.google.devtools.ksp.processing.SymbolProcessor import com.google.devtools.ksp.processing.SymbolProcessorEnvironment @@ -137,7 +137,11 @@ class ShowkaseProcessor @JvmOverloads constructor( ShowkaseBrowserWriter(environment).writeCustomAnnotationElementToMetadata( element ) - return@mapNotNull processCustomAnnotation(roundEnvironment, element) + return@mapNotNull processCustomAnnotation( + skipPrivatePreviews = skipPrivatePreviews, + roundEnvironment = roundEnvironment, + annotation = element + ) } val skipElement = showkaseValidator.validateComponentElementOrSkip( element, @@ -154,6 +158,7 @@ class ShowkaseProcessor @JvmOverloads constructor( } private fun processCustomAnnotation( + skipPrivatePreviews: Boolean, roundEnvironment: XRoundEnv, annotation: XTypeElement? = null ): Set { @@ -166,17 +171,20 @@ class ShowkaseProcessor @JvmOverloads constructor( annotatedElements.map { annotatedElement -> if (!showkaseValidator.checkElementIsAnnotationClass(annotatedElement)) { - showkaseValidator.validateComponentElementOrSkip( + val skipable = showkaseValidator.validateComponentElementOrSkip( element = annotatedElement, annotationName = supportedType, + skipPrivatePreviews = skipPrivatePreviews ) - components.addAll( - getShowkaseMetadataFromCustomAnnotation( - element = annotatedElement, - showkaseValidator = showkaseValidator, - supportedType.getCustomAnnotationSimpleName(), - ).toSet() - ) + if (!skipable) { + components.addAll( + getShowkaseMetadataFromCustomAnnotation( + element = annotatedElement, + showkaseValidator = showkaseValidator, + supportedType.getCustomAnnotationSimpleName(), + ).toSet() + ) + } } } } @@ -193,6 +201,7 @@ class ShowkaseProcessor @JvmOverloads constructor( // from the annotation from classpath. We use the fields from the classpath annotation to build // common data for the ShowkaseMetadata. + val skipPrivatePreviews = environment.options["skipPrivatePreviews"] == "true" // Supported annotations from classpath val supportedCustomPreview = mutableSetOf() environment.getTypeElementsFromPackage(CODEGEN_PACKAGE_NAME) @@ -223,19 +232,22 @@ class ShowkaseProcessor @JvmOverloads constructor( roundEnvironment .getElementsAnnotatedWith(customPreviewMetadata.supportTypeQualifiedName) .mapIndexed elementRoot@{ elementIndex, xElement -> - showkaseValidator.validateComponentElementOrSkip( + val skippable = showkaseValidator.validateComponentElementOrSkip( xElement, customPreviewMetadata.supportTypeQualifiedName, + skipPrivatePreviews = skipPrivatePreviews ) - components.add( - getShowkaseMetadata( - xElement = xElement, - customPreviewMetadata = customPreviewMetadata, - elementIndex = elementIndex, - index = index, - showkaseValidator = showkaseValidator + if (!skippable) { + components.add( + getShowkaseMetadata( + xElement = xElement, + customPreviewMetadata = customPreviewMetadata, + elementIndex = elementIndex, + index = index, + showkaseValidator = showkaseValidator + ) ) - ) + } } }