diff --git a/detekt-core/src/main/resources/default-detekt-config.yml b/detekt-core/src/main/resources/default-detekt-config.yml index 7615608ce32..3e738fc22ca 100644 --- a/detekt-core/src/main/resources/default-detekt-config.yml +++ b/detekt-core/src/main/resources/default-detekt-config.yml @@ -175,6 +175,7 @@ complexity: ignoreDeprecated: false ignorePrivate: false ignoreOverridden: false + ignoreAnnotatedFunctions: [] coroutines: active: true diff --git a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/TooManyFunctions.kt b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/TooManyFunctions.kt index e528b08ea0f..35e27c61fef 100644 --- a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/TooManyFunctions.kt +++ b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/TooManyFunctions.kt @@ -63,6 +63,9 @@ class TooManyFunctions(config: Config = Config.empty) : Rule(config) { @Configuration("ignore overridden functions") private val ignoreOverridden: Boolean by config(false) + @Configuration("ignore functions annotated with these annotations") + private val ignoreAnnotatedFunctions: List by config(emptyList()) + private var amountOfTopLevelFunctions: Int = 0 override fun visitKtFile(file: KtFile) { @@ -163,6 +166,7 @@ class TooManyFunctions(config: Config = Config.empty) : Rule(config) { ignoreDeprecated && function.hasAnnotation(DEPRECATED) -> true ignorePrivate && function.isPrivate() -> true ignoreOverridden && function.isOverride() -> true + ignoreAnnotatedFunctions.any { function.hasAnnotation(it) } -> true else -> false } diff --git a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/TooManyFunctionsSpec.kt b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/TooManyFunctionsSpec.kt index fea85459e61..3ca17d67d1c 100644 --- a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/TooManyFunctionsSpec.kt +++ b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/TooManyFunctionsSpec.kt @@ -14,6 +14,7 @@ private const val THRESHOLD_IN_ENUMS = "thresholdInEnums" private const val IGNORE_DEPRECATED = "ignoreDeprecated" private const val IGNORE_PRIVATE = "ignorePrivate" private const val IGNORE_OVERRIDDEN = "ignoreOverridden" +private const val IGNORE_ANNOTATED_FUNCTIONS = "ignoreAnnotatedFunctions" class TooManyFunctionsSpec { val rule = TooManyFunctions( @@ -250,4 +251,61 @@ class TooManyFunctionsSpec { assertThat(configuredRule.compileAndLint(code)).hasSize(1) } } + + @Test + fun `should not count functions included in ignoreAnnotatedFunctions`() { + val rule = TooManyFunctions( + TestConfig( + THRESHOLD_IN_CLASSES to "2", + THRESHOLD_IN_ENUMS to "2", + THRESHOLD_IN_FILES to "2", + THRESHOLD_IN_INTERFACES to "2", + THRESHOLD_IN_OBJECTS to "2", + IGNORE_ANNOTATED_FUNCTIONS to listOf("Preview"), + ) + ) + + val code = """ + annotation class Preview + class A { + fun a() = Unit + @Preview + fun b() = Unit + @Preview + fun c() = Unit + } + """.trimIndent() + + val findings = rule.compileAndLint(code) + assertThat(findings).isEmpty() + } + + @Test + fun `should trigger when there are too many non-annotated functions`() { + val rule = TooManyFunctions( + TestConfig( + THRESHOLD_IN_CLASSES to "2", + THRESHOLD_IN_ENUMS to "2", + THRESHOLD_IN_FILES to "2", + THRESHOLD_IN_INTERFACES to "2", + THRESHOLD_IN_OBJECTS to "2", + IGNORE_ANNOTATED_FUNCTIONS to listOf("Preview"), + ) + ) + + val code = """ + annotation class Preview + class A { + fun a() = Unit + fun b() = Unit + @Preview + fun c() = Unit + @Preview + fun d() = Unit + } + """.trimIndent() + + val findings = rule.compileAndLint(code) + assertThat(findings).hasSize(1) + } } diff --git a/website/docs/introduction/compose.md b/website/docs/introduction/compose.md index b0a25fa0d55..1efe7dba7c0 100644 --- a/website/docs/introduction/compose.md +++ b/website/docs/introduction/compose.md @@ -100,3 +100,15 @@ private fun FooLazyColumnPreview() { // Violation for FooLazyColumnPreview() #### Recommended configuration * Set `ignoreAnnotated` to `['Preview']` +* +### TooManyFunctions for Compose + +See [TooManyFunctions](/docs/rules/complexity/#toomanyfunctions). + +detekt may flag files with many composable preview functions, i.e. those marked with `@Preview`, +as having too many functions. Since preview functions do not contribute to complexity, this might not be +desired. + +#### Recommended configuration + +* Set `ignoreAnnotatedFunctions` to `['Preview']`