I am writing my first custom lint-detector for android/compose:
"Don't use the standard button, use our specifically styled custom button"
The detector itself is working as expected:
Lint suppression however doesn't work as expected: "This annotation is not applicable to target 'expression'"
I have to revert to a different scope to get this to work:
How can i fix my lint-rule in such a way, that i can target expressions?
My current (simplified) implementation:
class MissingDefaultDetector : Detector(), SourceCodeScanner {
companion object {
private const val old = "Button"
@JvmField
val ISSUE: Issue = Issue.create(
id = "PreferDefaultComposables",
briefDescription = "Prefer 'DefaultComposables'",
explanation = "The default implementation should be used",
category = Category.CORRECTNESS,
priority = 6,
severity = Severity.WARNING,
implementation = Implementation(
MissingDefaultDetector::class.java,
Scope.JAVA_FILE_SCOPE
)
)
}
override fun getApplicableMethodNames(): List<String> = listOf(old)
override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
context.report(
issue = ISSUE,
scope = node,
location = context.getNameLocation(node),
message = "Prefer our custom version(s) of this component",
)
}
}
The error message "This annotation is not applicable to target 'expression'" means that the @SuppressLint("PreferDefaultComposables") annotation cannot be used on an expression, only on a declaration (such as a class, field, method, or parameter).
In your code, the @SuppressLint("PreferDefaultComposables") annotation is being used on the Button function call. This is not allowed, because the function call is an expression, not a declaration.
To fix this there are two ways
Approach 1 -
@Composable
fun ButtonText() {
// Declare the Button function call inside a lambda expression
@SuppressLint("PreferDefaultComposables")
val button: Unit = Button(onClick = { }) {
Text(text = "Click me")
}
}
Approach 2
@Composable
fun ButtonText() {
@SuppressLint("PreferDefaultComposables")
@Composable
fun InnerButton() {
Button(onClick = { }) {
Text(text = "Click me")
}
}
InnerButton()
}
The default approach will declaring outside or onButtonText function. But your need is to declare inside. Hope these approach helps you