1

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.

임세현
  • 11
  • 2

0 Answers0