The Kotlin collections API has methods that allow developers to overcome type-safety restriction of the parameter, such as
Iterable.contains
. When the actual type of the object provided to these methods is not consistent with the target collection’s actual
type, those methods will always return false
or null
. This is most likely unintended and hides a design problem.
This rule raises an issue when the type of the argument of the following APIs is unrelated to the type used for the collection declaration:
-
MutableCollection.remove
-
MutableCollection.removeAll
-
MutableCollection.retainAll
-
Array.contains
-
Array.indexOf
-
Array.lastIndexOf
-
Collection.containsAll
-
Iterable.contains
-
Iterable.indexOf
-
Iterable.lastIndexOf
-
List.indexOf
-
List.lastIndexOf
-
Map.contains
-
Map.containsKey
-
Map.containsValue
-
Map.get
-
MutableMap.remove
Noncompliant code example
fun main(args: Array<String>) {
val map: MutableMap<Int, Any> = mutableMapOf()
map.remove<Any, Any>("42") // Noncompliant; will return 'null' for sure because 'map' is handling only Integer keys
// ...
val list: MutableList<String> = mutableListOf()
val integer = Integer.valueOf(1)
if (list.contains<Any>(integer)) { // Noncompliant; always false.
list.remove<Any>(integer) // Noncompliant; list.add(integer) doesn't compile, so this will always return 'false'
}
}
Compliant solution
fun main(args: Array<String>) {
val map: MutableMap<Int, Any> = mutableMapOf()
map.remove(42)
// ...
val list: MutableList<String> = mutableListOf()
val str = ""
if (list.contains(str)) {
list.remove(str)
}
}