I'd like to know how to check the annotation in Custom Lint

151 Views Asked by At

We are making custom lint for the purpose of applying them to the Android project.

The problematic part is the lint that requires the use of NamedArgument in the Composable function.

                        @Composable
                        fun MyComposable(
                            a: String,
                            b: Int,
                            onClick: () -> Unit = {},
                        ) {}

                        @Composable
                        fun success1() {
                            MyComposable(
                                a = "success",
                                b = 1,
                            ) {

                            }
                        }

I was thinking about how to determine if MyComposable is @Composable when calling MyComposable in the success1 function in the following cases:

class NamedArgumentDetector : Detector(), SourceCodeScanner {

override fun getApplicableUastTypes() = listOf(
    UExpression::class.java,
)

override fun createUastHandler(context: JavaContext) = object : UElementHandler() {
    override fun visitExpression(node: UExpression) {
        if (node !is KotlinUFunctionCallExpression || !node.isInvokedWithinComposable()) return

        val firstMethodName = node.methodName?.first() ?: return
        if (firstMethodName !in 'A'..'Z') return

        val lastArgumentIndex = node.valueArguments.lastIndex
        node.valueArguments.fastForEachIndexed { index, argument ->
            if (index == lastArgumentIndex && argument is KotlinULambdaExpression) return

            val expressionSourcePsi = argument.sourcePsi

            val argumentParent = expressionSourcePsi?.node?.treeParent ?: return

            val argumentFirstChildNode = argumentParent.firstChildNode
            val argumentParentFirstChildNode = argumentParent.treeParent.firstChildNode

            if (!(
                argumentFirstChildNode.isValueArgumentName() ||
                        argumentParentFirstChildNode.isValueArgumentName()
            )
            ) {
                context.report(
                    issue = NamedArgumentIssue,
                    scope = expressionSourcePsi,
                    location = context.getLocation(expressionSourcePsi),
                    message = Explanation,
                )
                return
            }
        }
    }
}

private fun ASTNode.isValueArgumentName() =
    this.elementType == VALUE_ARGUMENT_NAME

}

Detector code. In the example above, we were able to check whether success1 invokes Composable, but I can't think of a way to check whether MyComposable called by success1 is a Composable function.

I would appreciate it if you let me know if there is a way to check.

0

There are 0 best solutions below