All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.airbnb.paris.processor.models.StyleableInfo.kt Maven / Gradle / Ivy
package com.airbnb.paris.processor.models
import com.airbnb.paris.annotations.Styleable
import com.airbnb.paris.processor.ParisProcessor
import com.airbnb.paris.processor.framework.WithSkyProcessor
import javax.annotation.processing.RoundEnvironment
import javax.lang.model.element.Element
import javax.lang.model.element.TypeElement
internal class StyleableInfoExtractor(override val processor: ParisProcessor) : WithSkyProcessor {
private val mutableModels = mutableListOf()
val models get() = mutableModels.toList()
fun process(
roundEnv: RoundEnvironment,
classesToStyleableChildInfo: Map>,
classesToBeforeStyleInfo: Map>,
classesToAfterStyleInfo: Map>,
classesToAttrsInfo: Map>,
classesToStylesInfo: Map>
): List {
val styleableElements = roundEnv.getElementsAnnotatedWith(Styleable::class.java)
val classesMissingStyleableAnnotation =
(classesToStyleableChildInfo + classesToAttrsInfo + classesToStylesInfo)
.filter { (`class`, _) -> `class` !in styleableElements }
.keys
if (classesMissingStyleableAnnotation.isNotEmpty()) {
logError(classesMissingStyleableAnnotation.first()) {
"Uses @Attr, @StyleableChild and/or @Style but is not annotated with @Styleable."
}
}
return styleableElements
.mapNotNull {
fromElement(
it as TypeElement,
classesToStyleableChildInfo[it] ?: emptyList(),
classesToBeforeStyleInfo[it] ?: emptyList(),
classesToAfterStyleInfo[it] ?: emptyList(),
classesToAttrsInfo[it] ?: emptyList(),
classesToStylesInfo[it] ?: emptyList()
)
}
.also {
mutableModels.addAll(it)
}
}
private fun fromElement(
element: TypeElement,
styleableChildren: List,
beforeStyles: List,
afterStyles: List,
attrs: List,
styles: List
): StyleableInfo? {
val baseStyleableInfo = BaseStyleableInfoExtractor(processor).fromElement(element)
if (baseStyleableInfo.styleableResourceName.isEmpty() && (attrs.isNotEmpty() || styleableChildren.isNotEmpty())) {
logError(element) {
"@Styleable is missing its value parameter (@Attr or @StyleableChild won't work otherwise)."
}
return null
}
if (baseStyleableInfo.styleableResourceName.isNotEmpty() && styleableChildren.isEmpty() && attrs.isEmpty()) {
logWarning {
"No need to specify the @Styleable value parameter if no class members are annotated with @Attr."
}
}
return StyleableInfo(
processor,
element,
styleableChildren,
beforeStyles,
afterStyles,
attrs,
styles,
baseStyleableInfo
)
}
}
/**
* If [styleableResourceName] isn't empty then at least one of [styleableChildren] or [attrs] won't be
* empty either
*/
internal class StyleableInfo(
override val processor: ParisProcessor,
val element: TypeElement,
val styleableChildren: List,
val beforeStyles: List,
val afterStyles: List,
val attrs: List,
val styles: List,
baseStyleableInfo: BaseStyleableInfo
) : BaseStyleableInfo(baseStyleableInfo), WithSkyProcessor {
/**
* Applies lower camel case formatting
*/
fun attrResourceNameToCamelCase(name: String): String {
val prefix = "${styleableResourceName}_"
if (!name.startsWith(prefix)) {
logError(element) {
"Attribute \"$name\" does not belong to styleable declaration \"$styleableResourceName\"."
}
}
val formattedName = name.removePrefix("${styleableResourceName}_")
.removePrefix("android_")
return formattedName
.foldRightIndexed("") { index, c, acc ->
if (c == '_') {
acc
} else {
if (index == 0 || formattedName[index - 1] != '_') {
c + acc
} else {
c.toUpperCase() + acc
}
}
}.decapitalize()
}
}