171 lines
4.3 KiB
Plaintext
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] |