diff --git a/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/internal/Signatures.kt b/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/internal/Signatures.kt index 117100b1985e..a52675736f09 100644 --- a/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/internal/Signatures.kt +++ b/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/internal/Signatures.kt @@ -92,21 +92,15 @@ private fun buildClassSignature(classOrObject: KtClassOrObject): String { } private fun buildFunctionSignature(element: KtNamedFunction): String { - var methodStart = 0 - element.docComment?.let { - methodStart = it.endOffset - it.startOffset - } - var methodEnd = element.endOffset - element.startOffset - val typeReference = element.typeReference - if (typeReference != null) { - methodEnd = typeReference.endOffset - element.startOffset + val startOffset = element.startOffset + val endOffset = if (element.typeReference != null) { + element.typeReference!!.endOffset } else { - element.valueParameterList?.let { - methodEnd = it.endOffset - element.startOffset - } + element.valueParameterList?.endOffset ?: 0 } - require(methodStart < methodEnd) { - "Error building function signature with range $methodStart - $methodEnd for element: ${element.text}" + + require(startOffset < endOffset) { + "Error building function signature with range $startOffset - $endOffset for element: ${element.text}" } - return element.text.substring(methodStart, methodEnd) + return element.text.substring(0, endOffset - startOffset) } diff --git a/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/internal/SignaturesSpec.kt b/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/internal/SignaturesSpec.kt new file mode 100644 index 000000000000..d201277fcaaa --- /dev/null +++ b/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/internal/SignaturesSpec.kt @@ -0,0 +1,128 @@ +package io.gitlab.arturbosch.detekt.api.internal + +import io.gitlab.arturbosch.detekt.api.Debt +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.test.compileAndLint +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatThrownBy +import org.jetbrains.kotlin.psi.KtNamedFunction +import org.junit.jupiter.api.Test + +class SignaturesSpec { + private var result = "" + private val subject = TestRule { result = it } + + @Test + fun `function with type reference`() { + subject.compileAndLint(functionWithTypeReference()) + assertThat(result).isEqualTo(signatureWithTypeReference()) + } + + @Test + fun `function without type reference`() { + subject.compileAndLint(functionWithoutTypeReference()) + assertThat(result).isEqualTo(signatureWithoutTypeReference()) + } + + @Test + fun `function throws exception`() { + assertThatThrownBy { + subject.compileAndLint(functionWontCompile()) + } + .isInstanceOf(IllegalArgumentException::class.java) + .hasMessageContaining("Error building function signature") + } +} + +private class TestRule(val block: (String) -> Unit) : Rule() { + override val issue = Issue(javaClass.simpleName, Severity.CodeSmell, "", Debt.TWENTY_MINS) + + override fun visitNamedFunction(function: KtNamedFunction) { + block(function.buildFullSignature()) + } +} + +private fun signatureWithTypeReference() = """ + Test.kt${'$'}TestClass.Companion${'$'}@JvmStatic @Parameterized.Parameters(name = "parameterName") /** * Function KDoc */ fun data(): List> +""".trimIndent() + +private fun signatureWithoutTypeReference() = """ + Test.kt${'$'}TestClass.Companion${'$'}@JvmStatic @Parameterized.Parameters(name = "parameterName") /** * Function KDoc */ fun data() +""".trimIndent() + +private fun functionWithTypeReference() = """ + @RunWith(Parameterized::class) + class TestClass { + companion object { + @JvmStatic + @Parameterized.Parameters(name = "parameterName") + /** + * Function KDoc + */ + fun data(): List> = + /** + * more description + * more description + * more description + * more description + * more description + */ + listOf( + arrayOf(1, 2, 3, 4), + arrayOf(11, 22, 33, 44) + ) + } + } +""".trimIndent() + +private fun functionWithoutTypeReference() = """ + @RunWith(Parameterized::class) + class TestClass { + companion object { + @JvmStatic + @Parameterized.Parameters(name = "parameterName") + /** + * Function KDoc + */ + fun data() = + /** + * more description + * more description + * more description + * more description + * more description + */ + listOf( + arrayOf(1, 2, 3, 4), + arrayOf(11, 22, 33, 44) + ) + } + } +""".trimIndent() + +private fun functionWontCompile() = """ + @RunWith(Parameterized.class) + class TestClass { + companion object { + @JvmStatic + @Parameterized.Parameters(name = "parameterName") + /** + * Function KDoc + */ + fun data() = + /** + * more description + * more description + * more description + * more description + * more description + */ + listOf( + arrayOf(1, 2, 3, 4), + arrayOf(11, 22, 33, 44) + ) + } + } +""".trimIndent()