From ad5fe749c82ca69efb422c3769463a67cf004b7c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 11:10:49 +0100 Subject: [PATCH] Create rule S6527: Function chain using "filter" should be simplified (#1645) Co-authored-by: Marco Kaufmann Co-authored-by: Angelo Buono --- rules/S6527/kotlin/metadata.json | 25 +++++++++++++++ rules/S6527/kotlin/rule.adoc | 52 ++++++++++++++++++++++++++++++++ rules/S6527/metadata.json | 2 ++ 3 files changed, 79 insertions(+) create mode 100644 rules/S6527/kotlin/metadata.json create mode 100644 rules/S6527/kotlin/rule.adoc create mode 100644 rules/S6527/metadata.json diff --git a/rules/S6527/kotlin/metadata.json b/rules/S6527/kotlin/metadata.json new file mode 100644 index 0000000000..08029fd69e --- /dev/null +++ b/rules/S6527/kotlin/metadata.json @@ -0,0 +1,25 @@ +{ + "title": "Function chain using \"filter\" should be simplified", + "type": "CODE_SMELL", + "code": { + "impacts": { + "MAINTAINABILITY": "LOW" + }, + "attribute": "EFFICIENT" + }, + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5min" + }, + "tags": [ + ], + "defaultSeverity": "Major", + "ruleSpecification": "RSPEC-6527", + "sqKey": "S6527", + "scope": "All", + "defaultQualityProfiles": [ + "Sonar way" + ], + "quickfix": "unknown" +} diff --git a/rules/S6527/kotlin/rule.adoc b/rules/S6527/kotlin/rule.adoc new file mode 100644 index 0000000000..40c8bac703 --- /dev/null +++ b/rules/S6527/kotlin/rule.adoc @@ -0,0 +1,52 @@ +== Why is this an issue? + +The `filter(predicate)` function is used to extract a subset of elements from a collection that match a given predicate. +Many collection functions such as `any()`, `count()`, `first()`, and more, come with an optional condition predicate. + +It is not recommended to invoke the `filter(predicate)` function prior to these terminal operations. +Instead, the predicate variant of the terminal operation should be used as a replacement. + +=== What is the potential impact? + +Using `filter(predicate)` before terminal operations can result in unnecessary iterations over the collection, which could negatively impact the performance of the code, especially with large collections. By directly using the predicate variant of the function, you can streamline the code and improve its efficiency and readability. + +== How to fix it + +Replace the `filter(predicate)` call with the predicate variant of the terminal operation. +As of Kotlin API version 1.8, the list of terminal operations supporting a predicate is: + +* `any()` +* `none()` +* `count()` +* `first()`, `firstOrNull()` +* `last()`, `lastOrNull()` +* `single()`, `singleOrNull()` + +=== Code examples + +==== Noncompliant code example + +[source,kotlin,diff-id=1,diff-type=noncompliant] +---- +val list = listOf(5,2,9,6,8,2,5,7,3) +val hasElementsGreater5 = list.filter { it > 5 }.any() // Noncompliant +val countElementsGreater5 = list.filter { it > 5 }.count() // Noncompliant +val lastElementGreater5 = list.filter { it > 5 }.lastOrNull() // Noncompliant +---- + +==== Compliant solution + +[source,kotlin,diff-id=1,diff-type=compliant] +---- +val list = listOf(5,2,9,6,8,2,5,7,3) +val hasElementsGreater5 = list.any { it > 5 } // Compliant +val countElementsGreater5 = list.count { it > 5 } // Compliant +val lastElementGreater5 = list.lastOrNull { it > 5 } // Compliant +---- + +== Resources + +=== Documentation + +* https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/[Kotlin API Docs, Package kotlin.collections] + diff --git a/rules/S6527/metadata.json b/rules/S6527/metadata.json new file mode 100644 index 0000000000..2c63c08510 --- /dev/null +++ b/rules/S6527/metadata.json @@ -0,0 +1,2 @@ +{ +}