From ecbc7c6d88ba147e037b5407d7a4dc9720286ffc Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Wed, 26 Oct 2022 17:59:44 +0900 Subject: [PATCH] UseArrayLiteralsInAnnotations: fix false negative with primitive array factory calls (#5482) --- .../style/UseArrayLiteralsInAnnotations.kt | 36 +++++++++++++++++-- .../UseArrayLiteralsInAnnotationsSpec.kt | 35 ++++++++++++++++++ 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseArrayLiteralsInAnnotations.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseArrayLiteralsInAnnotations.kt index 29f91e5f7bc..1a6bd1cccbf 100644 --- a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseArrayLiteralsInAnnotations.kt +++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseArrayLiteralsInAnnotations.kt @@ -8,7 +8,12 @@ import io.gitlab.arturbosch.detekt.api.Issue import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity import io.gitlab.arturbosch.detekt.api.internal.ActiveByDefault +import io.gitlab.arturbosch.detekt.rules.safeAs import org.jetbrains.kotlin.psi.KtAnnotationEntry +import org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.KtPrimaryConstructor +import org.jetbrains.kotlin.psi.psiUtil.containingClass /** * This rule detects annotations which use the arrayOf(...) syntax instead of the array literal [...] syntax. @@ -34,14 +39,39 @@ class UseArrayLiteralsInAnnotations(config: Config = Config.empty) : Rule(config override fun visitAnnotationEntry(annotationEntry: KtAnnotationEntry) { for (argument in annotationEntry.valueArguments) { - val expr = argument.getArgumentExpression()?.text ?: continue - if (expr.startsWith(LONG_ANNOTATION_LITERAL_FORM)) { + if (argument.getArgumentExpression().isArrayOfFunctionCall()) { report(CodeSmell(issue, Entity.from(argument.asElement()), issue.description)) } } } + override fun visitPrimaryConstructor(constructor: KtPrimaryConstructor) { + if (constructor.containingClass()?.isAnnotation() != true) return + for (parameter in constructor.valueParameters) { + val defaultValue = parameter.defaultValue ?: continue + if (defaultValue.isArrayOfFunctionCall()) { + report(CodeSmell(issue, Entity.from(defaultValue), issue.description)) + } + } + } + + private fun KtExpression?.isArrayOfFunctionCall(): Boolean = + this?.safeAs()?.calleeExpression?.text in arrayOfFunctions + companion object { - const val LONG_ANNOTATION_LITERAL_FORM = "arrayOf(" + private val arrayOfFunctions = listOf( + "boolean", + "char", + "byte", + "short", + "int", + "long", + "float", + "double", + "ubyte", + "ushort", + "uint", + "ulong", + ).map { "${it}ArrayOf" }.toSet() + "arrayOf" } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseArrayLiteralsInAnnotationsSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseArrayLiteralsInAnnotationsSpec.kt index a43b625b5fb..145aa49edaf 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseArrayLiteralsInAnnotationsSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseArrayLiteralsInAnnotationsSpec.kt @@ -22,6 +22,41 @@ class UseArrayLiteralsInAnnotationsSpec { assertThat(findings).hasSize(1) } + @Test + fun `finds intArrayOf usage`() { + val code = """ + annotation class Test(val values: IntArray) + + @Test(intArrayOf(1, 2)) + fun test() {} + """.trimIndent() + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(1) + } + + @Test + fun `finds longArrayOf usage`() { + val code = """ + annotation class Test(val values: LongArray) + + @Test(longArrayOf(1, 2)) + fun test() {} + """.trimIndent() + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(1) + } + + @Test + fun `finds arrayOf usage as default value`() { + val code = """ + annotation class Test(val s: Array = arrayOf("a", "b")) + """.trimIndent() + subject.compileAndLint(code) + assertThat(subject.findings) + .hasSize(1) + .hasTextLocations(45 to 62) + } + @Test @DisplayName("expects [] syntax") fun expectsBracketSyntax() {