Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial support for tags and extra metadata on components #309

Merged
merged 17 commits into from
Apr 3, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,7 @@ annotation class ShowkaseCodegenMetadata(
val previewParameterName: String = "",
val showkaseStyleName: String = "",
val isDefaultStyle: Boolean = false,
val generatedPropertyName: String = ""
val generatedPropertyName: String = "",
val tags: Array<String> = [],
val extraMetadata: Array<String> = []
)
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,12 @@ package com.airbnb.android.showkase.annotation
* @param defaultStyle Used to represent a composable function is the default style variant of a given
* composable. More information on how Showkase allows you to represent component styles in this section -
* https://github.com/airbnb/Showkase#representing-component-styles-in-showkase
*
* @param tags Various string values that will be propagated to the Showkase browser to allow additional
* filtering or categorization.
* @param extraMetadata Various string values that are **not** used by the standard Showkase browser
* but are still available in the generated `ShowkaseBrowserComponent` object. This may be useful when
* extra data is needed for attributing components during other processes (e.g. static analysis,
* displaying attributions in a custom component browser).
*/
@MustBeDocumented
@Retention(AnnotationRetention.SOURCE)
Expand All @@ -66,5 +71,7 @@ annotation class ShowkaseComposable(
val widthDp: Int = -1,
val heightDp: Int = -1,
val skip: Boolean = false,
val defaultStyle: Boolean = false
val defaultStyle: Boolean = false,
val tags: Array<String> = [],
val extraMetadata: Array<String> = [],
)
Original file line number Diff line number Diff line change
Expand Up @@ -606,5 +606,10 @@ class ShowkaseProcessorTest : BaseProcessorTest() {
modes = listOf(Mode.KSP),
)
}

@Test
fun `top level composable function with showkase and showkaseroot with tags and metadata`() {
compileInputsAndVerifyOutputs()
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public abstract class MyScreenshotTest: ShowkaseScreenshotTest {
name: String,
group: String,
styleName: String?,
tags: List<String>,
extraMetadata: List<String>,
screenshotType: ShowkaseScreenshotType,
screenshotBitmap: Bitmap,
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ public abstract class MyScreenshotTest: ShowkaseScreenshotTest {
name: String,
group: String,
styleName: String?,
tags: List<String>,
extraMetadata: List<String>,
screenshotType: ShowkaseScreenshotType,
screenshotBitmap: Bitmap,
) {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public abstract class MyScreenshotTest: ShowkaseScreenshotTest {
name: String,
group: String,
styleName: String?,
tags: List<String>,
extraMetadata: List<String>,
screenshotType: ShowkaseScreenshotType,
screenshotBitmap: Bitmap,
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public abstract class MyScreenshotTest: ShowkaseScreenshotTest {
name: String,
group: String,
styleName: String?,
tags: List<String>,
extraMetadata: List<String>,
screenshotType: ShowkaseScreenshotType,
screenshotBitmap: Bitmap,
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.airbnb.android.showkase_processor_testing

import com.airbnb.android.showkase.annotation.ShowkaseComposable
import androidx.compose.runtime.Composable
import com.airbnb.android.showkase.annotation.ShowkaseRoot
import com.airbnb.android.showkase.annotation.ShowkaseRootModule

@ShowkaseRoot
public class TestShowkaseRoot: ShowkaseRootModule {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.airbnb.android.showkase_processor_testing

import com.airbnb.android.showkase.annotation.ShowkaseComposable
import androidx.compose.runtime.Composable

@ShowkaseComposable("name", "group", tags = ["tag A", "tag B"], extraMetadata = ["meta A"])
@Composable
public fun TestComposable() {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// This is an auto-generated file. Please do not edit/modify this file.
package com.airbnb.android.showkase

import com.airbnb.android.showkase.`annotation`.ShowkaseCodegenMetadata
import kotlin.Unit

public class ShowkaseMetadata_com_airbnb_android_showkase_processor_testing {
@ShowkaseCodegenMetadata(
showkaseName = "name",
showkaseGroup = "group",
packageName = "com.airbnb.android.showkase_processor_testing",
packageSimpleName = "showkase_processor_testing",
showkaseElementName = "TestComposable",
insideObject = false,
insideWrapperClass = false,
showkaseKDoc = "",
generatedPropertyName = "comairbnbandroidshowkaseprocessortestinggroupname",
showkaseMetadataType = "COMPONENT",
isDefaultStyle = false,
tags = ["tag A", "tag B"],
extraMetadata = ["meta A"],
)
public fun groupname(): Unit {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// This is an auto-generated file. Please do not edit/modify this file.
package com.airbnb.android.showkase_processor_testing

import com.airbnb.android.showkase.`annotation`.ShowkaseRootCodegen
import com.airbnb.android.showkase.models.ShowkaseBrowserColor
import com.airbnb.android.showkase.models.ShowkaseBrowserComponent
import com.airbnb.android.showkase.models.ShowkaseBrowserTypography
import com.airbnb.android.showkase.models.ShowkaseProvider
import kotlin.collections.List

@ShowkaseRootCodegen(
numComposablesWithoutPreviewParameter = 1,
numComposablesWithPreviewParameter = 0,
numColors = 0,
numTypography = 0,
)
public class TestShowkaseRootCodegen : ShowkaseProvider {
public override fun getShowkaseComponents(): List<ShowkaseBrowserComponent> {

return listOf<ShowkaseBrowserComponent>(
comairbnbandroidshowkaseprocessortestinggroupname,
)
}

public override fun getShowkaseColors(): List<ShowkaseBrowserColor> {

return listOf<ShowkaseBrowserColor>(
)
}

public override fun getShowkaseTypography(): List<ShowkaseBrowserTypography> {

return listOf<ShowkaseBrowserTypography>(
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// This is an auto-generated file. Please do not edit/modify this file.
package com.airbnb.android.showkase_processor_testing

import android.content.Context
import android.content.Intent
import com.airbnb.android.showkase.models.Showkase
import com.airbnb.android.showkase.models.ShowkaseElementsMetadata
import com.airbnb.android.showkase.models.ShowkaseProvider
import com.airbnb.android.showkase.ui.ShowkaseBrowserActivity

/**
* Helper function that's autogenerated and gives you an intent to start the ShowkaseBrowser.
*/
public fun Showkase.getBrowserIntent(context: Context): Intent {
val intent = Intent(context, ShowkaseBrowserActivity::class.java)
intent.putExtra("SHOWKASE_ROOT_MODULE",
"com.airbnb.android.showkase_processor_testing.TestShowkaseRoot")
return intent
}

/**
* Helper function that's give's you access to Showkase metadata. This contains data about the
* composables, colors and typography in your codebase that's rendered in showkase.
*/
public fun Showkase.getMetadata(): ShowkaseElementsMetadata {
try {
val showkaseComponentProvider =
Class.forName("com.airbnb.android.showkase_processor_testing.TestShowkaseRootCodegen").newInstance()
as ShowkaseProvider
return showkaseComponentProvider.metadata()
} catch(exception: ClassNotFoundException) {
error("The class wasn't generated correctly. Make sure that you have setup Showkase correctly by following the steps here - https://github.com/airbnb/Showkase#Installation.")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// This is an auto-generated file. Please do not edit/modify this file.
package com.airbnb.android.showkase_processor_testing

import androidx.compose.runtime.Composable
import com.airbnb.android.showkase.models.ShowkaseBrowserComponent

public val comairbnbandroidshowkaseprocessortestinggroupname: ShowkaseBrowserComponent =
ShowkaseBrowserComponent(
group = "group",
componentName = "name",
componentKDoc = "",
componentKey = """com.airbnb.android.showkase_processor_testing_null_group_name_0_null""",
isDefaultStyle = false,
tags = listOf("tag A", "tag B"),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you want the extra metadata to be available here as well no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops I missed that the other classes were internal 🤦

extraMetadata = listOf("meta A"),
component = @Composable { TestComposable() }
)
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public abstract class MyScreenshotTest: ShowkaseScreenshotTest {
name: String,
group: String,
styleName: String?,
tags: List<String>,
extraMetadata: List<String>,
screenshotType: ShowkaseScreenshotType,
screenshotBitmap: Bitmap,
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,8 @@ class ShowkaseProcessor @JvmOverloads constructor(
group = props.showkaseGroup,
name = props.showkaseName,
isDefaultStyle = props.isDefaultStyle,
tags = props.tags.toList(),
extraMetadata = props.extraMetadata.toList()
)
}
private fun getShowkaseRootCodegenOnClassPath(
Expand Down Expand Up @@ -618,7 +620,9 @@ internal data class ShowkaseGeneratedMetadata(
val group: String,
val name: String,
// This property is only used for components
val isDefaultStyle: Boolean = false
val isDefaultStyle: Boolean = false,
val tags: List<String> = emptyList(),
val extraMetadata: List<String> = emptyList()
)

internal enum class ShowkaseGeneratedMetadataType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ internal sealed class ShowkaseMetadata {
val previewParameterProviderType: TypeName? = null,
val previewParameterName: String? = null,
val showkaseStyleName: String? = null,
val isDefaultStyle: Boolean = false
val isDefaultStyle: Boolean = false,
val tags: List<String> = emptyList(),
val extraMetadata: List<String> = emptyList()
) : ShowkaseMetadata()

data class Color(
Expand Down Expand Up @@ -129,7 +131,10 @@ internal fun XAnnotationBox<ShowkaseCodegenMetadata>.toModel(element: XElement):
element = element,
previewParameterProviderType = previewParameterClassType?.typeName?.toKTypeName(),
previewParameterName = props.previewParameterName,
isDefaultStyle = props.isDefaultStyle
isDefaultStyle = props.isDefaultStyle,
tags = props.tags.toList(),
extraMetadata = props.tags.toList()

)
}
ShowkaseMetadataType.COLOR -> {
Expand Down Expand Up @@ -195,6 +200,8 @@ internal fun getShowkaseMetadata(
)
val isDefaultStyle = annotation.value.defaultStyle
val showkaseStyleName = getShowkaseStyleName(annotation.value.styleName, isDefaultStyle)
val tags = annotation.value.tags.toList()
val extraMetadata = annotation.value.extraMetadata.toList()

ShowkaseMetadata.Component(
packageSimpleName = commonMetadata.moduleName,
Expand All @@ -214,6 +221,8 @@ internal fun getShowkaseMetadata(
previewParameterProviderType = previewParameterMetadata?.second,
isDefaultStyle = isDefaultStyle,
componentIndex = showkaseAnnotations.indexOf(annotation),
tags = tags,
extraMetadata = extraMetadata
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class ShowkaseBrowserPropertyWriter(private val environment: XProcessingEnv) {
group = showkaseMetadata.showkaseGroup,
name = showkaseMetadata.showkaseName,
isDefaultStyle = showkaseMetadata.isDefaultStyle,
tags = showkaseMetadata.tags,
extraMetadata = showkaseMetadata.extraMetadata,
)
}

Expand All @@ -64,6 +66,8 @@ class ShowkaseBrowserPropertyWriter(private val environment: XProcessingEnv) {
group = showkaseMetadata.showkaseGroup,
name = showkaseMetadata.showkaseName,
isDefaultStyle = showkaseMetadata.isDefaultStyle,
tags = showkaseMetadata.tags,
extraMetadata = showkaseMetadata.extraMetadata,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ internal class ShowkaseCodegenMetadataWriter(private val environment: XProcessin
showkaseMetadata.showkaseStyleName?.let {
addMember("showkaseStyleName = %S", showkaseMetadata.showkaseStyleName)
}
addStringArrayMember(ShowkaseCodegenMetadata::tags.name, showkaseMetadata.tags)
addStringArrayMember(ShowkaseCodegenMetadata::extraMetadata.name, showkaseMetadata.extraMetadata)
}
}
is ShowkaseMetadata.Color -> {
Expand All @@ -116,4 +118,13 @@ internal class ShowkaseCodegenMetadataWriter(private val environment: XProcessin
annotation.addMember("showkaseMetadataType = %S", ShowkaseMetadataType.TYPOGRAPHY.name)
}
}

private fun AnnotationSpec.Builder.addStringArrayMember(name: String, values: List<String>) {
val valueAsArray = values.joinToString(", ", prefix = "[", postfix = "]") { value ->
"\"$value\""
}
values.takeIf { it.isNotEmpty() }?.let {
addMember("%L = %L", name, valueAsArray)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ internal fun CodeBlock.Builder.addShowkaseBrowserComponent(
showkaseHeightDp?.let { add("\nheightDp = %L,", it) }
showkaseStyleName?.let { add("\nstyleName = %S,", it) }
}

addStringList("tags", showkaseMetadata.tags)
addStringList("extraMetadata", showkaseMetadata.extraMetadata)
add(
composePreviewFunctionLambdaCodeBlock(
showkaseMetadata.packageName,
Expand All @@ -151,6 +152,18 @@ internal fun CodeBlock.Builder.addShowkaseBrowserComponent(
doubleUnindent()
}

/**
* Adds a list of strings to the [name] parameter if the [values] list is not empty.
*/
private fun CodeBlock.Builder.addStringList(name: String, values: List<String>) {
values.takeIf { it.isNotEmpty() }?.let {
val valuesString = it.joinToString(", ", prefix = "listOf(", postfix = ")") { value ->
"\"$value\""
}
add("\n$name = $valuesString,")
}
}

@Suppress("LongParameterList")
internal fun composePreviewFunctionLambdaCodeBlock(
functionPackageName: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ abstract class ShotShowkaseScreenshotTest: ShowkaseScreenshotTest, ScreenshotTes
name: String,
group: String,
styleName: String?,
tags: List<String>,
extraMetadata: List<String>,
screenshotType: ShowkaseScreenshotType,
screenshotBitmap: Bitmap
) {
Expand Down
Loading