171 lines
4.3 KiB
Plaintext

== Why is this an issue?
In Kotlin, `if` and `when` statements are expressions that return a value.
This allows for a more concise and functional programming style with less cognitive complexity,
because it results in fewer return points and fewer variable assignments in a function.
If both branches of an `if` statement end with a `return` statement,
the `if` statement should be used instead as an expression for a `return` statement.
If all branches of an exhaustive `when` statement end with a `return` statement,
the `when` statement should be used instead as an expression for a `return` statement.
A `when` statement is exhaustive when it covers all elements of an enum or features an `else` clause.
=== What is the potential impact?
==== Readability and Understanding
This change makes it easier to understand a function because it will reduce its complexity.
This is because the function now contains fewer return points that the developer needs to keep track of.
== How to fix it
Use the `if` statement as an expression for a `return` statement.
Lift the `return` keyword from the end of the `if` band `else` branch before the `if` keyword.
Use the `when` statement as an expression for a `return` statement.
Lift the `return` keyword from the end of all its case clauses before the `when` keyword.
=== Code examples
==== Noncompliant code example
[source,kotlin,diff-id=1,diff-type=noncompliant]
----
fun returnIfElse(value: Int): String {
// ...
if (value >= 0) { // Noncompliant, every branch contains a return statement
return "positive"
} else {
return "negative"
}
}
----
==== Compliant solution
[source,kotlin,diff-id=1,diff-type=compliant]
----
fun returnIfElse(value: Int): String {
// ...
return if (value >= 0) { // Compliant
"positive"
} else {
"negative"
}
}
----
==== Noncompliant code example
[source,kotlin,diff-id=2,diff-type=noncompliant]
----
fun returnWhenElse(a: Float): Int {
// ...
when { // Noncompliant, every branch of exhaustive `when` contains a return statement
a < 0 -> return -1
a > 0 -> return 1
else -> return 0
}
}
----
==== Compliant solution
[source,kotlin,diff-id=2,diff-type=compliant]
----
fun returnWhenElse(a: Float): Int {
// ...
return when { // Compliant
a < 0 -> -1
a > 0 -> 1
else -> 0
}
}
----
==== Noncompliant code example
[source,kotlin]
----
enum class OneTwoThree {
ONE,
TWO,
THREE
}
----
[source,kotlin,diff-id=3,diff-type=noncompliant]
----
fun returnWhenEnum(oneTwoThree: OneTwoThree): String {
// ...
when(oneTwoThree) { // Noncompliant, every branch of exhaustive `when` contains a return statement
OneTwoThree.ONE -> return "one"
OneTwoThree.TWO -> return "two"
OneTwoThree.THREE -> return "three"
}
}
----
==== Compliant solution
[source,kotlin,diff-id=3,diff-type=compliant]
----
fun returnWhenEnum(oneTwoThree: OneTwoThree): String {
// ...
return when(oneTwoThree) { // Compliant
OneTwoThree.ONE -> "one"
OneTwoThree.TWO -> "two"
OneTwoThree.THREE -> "three"
}
}
----
==== Noncompliant code example
[source,kotlin,diff-id=4,diff-type=noncompliant]
----
fun returnIfElseWithSideEffects(a: Float, b: Float): Int {
// ...
if (a < 0) { // Noncompliant, every branch contains a return statement
foo()
return -1
} else if (a > b) {
bar()
return 1
} else {
return 0
}
}
----
==== Compliant solution
[source,kotlin,diff-id=4,diff-type=compliant]
----
fun returnIfElseWithSideEffects(a: Float, b: Float): Int {
// ...
return if (a < 0) { // Compliant
foo()
-1
} else if (a > b) {
bar()
1
} else {
0
}
}
----
== Resources
=== Documentation
* https://kotlinlang.org/docs/control-flow.html#if-expression[Kotlin Docs, If expression]
* https://kotlinlang.org/docs/control-flow.html#when-expression[Kotlin Docs, When expression]
=== Articles & blog posts
* https://www.baeldung.com/kotlin/if-else-expression[Baeldung, If-Else Expression in Kotlin]
* https://www.baeldung.com/kotlin/when[Baeldung, Guide to the “when{}” Block in Kotlin]
* https://www.sonarsource.com/resources/cognitive-complexity[G. Ann Campbell, Cognitive Complexity]