== Why is this an issue?

In Kotlin, nullability is a part of the type system.
By default, any given type `T` is non-nullable.
If you append a "?" to the type, it becomes nullable: `T?`.

When accessing properties or functions of a nullable type, you need to handle the case when the target is `null`.
However, while accessing a non-nullable type, it is redundant to test for `null`, as the compiler statically ensures that the value can never be `null`.
So all the nullability checks on the non-nullable types are considered code smells.

On the other hand, performing a null-check on a value that is always null is equally as redundant.

Here is an example of a non-nullable variable.
`s` is of a type `String` and cannot be `null`.

[source,kotlin]
----
val s: String = ""
----

Here is an example of a nullable variable.
Nullable variables are declared by using the `?`.

[source,kotlin]
----
val s: String? = null
----

Explicit null checks are comparing a result to `null` using `==` or `!=` operators.
In Kotlin, there are various other means of implicitly or explicitly performing a null check or assertion, including the following:

- Safe call operator `?.`
- Elvis operator `?:`
- Not-null assertion operator `!!`
- `requireNotNull` and `checkNotNull` functions

== How to fix it

Avoid using null checks on non-nullable variables and values that are always null.

=== Code examples

If your variable type is non-nullable, any null checks are redundant. For example, `if (s == null) {}`, `requireNotNull(s)` and `checkNotNull(s)` can be dropped from your code.


==== Noncompliant code example

[source,kotlin,diff-id=1,diff-type=noncompliant]
----
val s: String = ""
if (s != null) { doSomething() } // This statement is always true
----

==== Compliant solution

[source,kotlin,diff-id=1,diff-type=compliant]
----
val s: String = ""
doSomething()
----

==== Noncompliant code example

[source,kotlin,diff-id=2,diff-type=noncompliant]
----
fun foo(s: String) {
  if (s == null) { // Noncompliant, `s == null` is always false.
      doSomething()
  }
}
----

==== Compliant solution

[source,kotlin,diff-id=2,diff-type=compliant]
----
fun foo(s: String) {
  doSomething()
}
----

==== Noncompliant code example

[source,kotlin,diff-id=3,diff-type=noncompliant]
----
fun foo(s: String): String {
    return s ?: "" // Noncompliant, ?: is useless and the empty string will never be returned.
}
----

==== Compliant solution

[source,kotlin,diff-id=3,diff-type=compliant]
----
fun foo(s: String): String {
    return s
}
----

If `s` is nullable, the elvis operation makes sense:

[source,kotlin]
----
fun foo(s: String?): String {
    return s ?: ""
}
----

==== Noncompliant code example

[source,kotlin,diff-id=4,diff-type=noncompliant]
----
fun foo(s: String) {
    s!!.doSomething() // Noncompliant, `s` can never be null.
}
----

==== Compliant solution

[source,kotlin,diff-id=4,diff-type=compliant]
----
fun foo(s: String) {
    s.doSomething()
}
----


== Resources

=== Documentation

* https://kotlinlang.org/docs/null-safety.html#nullable-types-and-non-null-types[Kotlin Documentation - Null Safety]
* https://kotlinlang.org/docs/strings.html[Kotlin Documentation - Strings]

=== Articles & blog posts

* https://blog.logrocket.com/complete-guide-null-safety-kotlin/[A complete guide to null safety in Kotlin]
