76 lines
2.4 KiB
Plaintext
76 lines
2.4 KiB
Plaintext
== Why is this an issue?
|
|
|
|
The primary purpose of classes that implement indexed access operators is that of element access,
|
|
like this is the case for arrays, lists, maps, or sets.
|
|
When a class implements indexed access operators, they should be used as operators instead of calling them as functions,
|
|
because this is the intention of the designer of the API.
|
|
|
|
=== What is the potential impact?
|
|
|
|
==== Readability and Understanding
|
|
|
|
This change makes it easier to understand what a function does,
|
|
because the semantics of indexed access operators is evident to the reader,
|
|
while for a function call, the reader would need to know what the called function does.
|
|
|
|
==== Java interop
|
|
|
|
The issue is also raised when Java API is used as a Kotlin compiler treats all `get(.)` methods as possible index access operators. Use `CompletableFuture[timeout, unit]` instead of `CompletableFuture.get(timeout, unit)` when accessing Java's `CompletableFuture`.
|
|
|
|
|
|
== How to fix it
|
|
|
|
Replace `instance.get(index)` with `instance[index]`.
|
|
|
|
Replace `instance.set(index, value)` with `instance[index] = value`.
|
|
|
|
This also works with multi-index access operators.
|
|
|
|
=== Code examples
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,kotlin]
|
|
----
|
|
interface Grid {
|
|
operator fun get(row: Int, column: Int): Int
|
|
operator fun set(row: Int, column: Int, value: Int)
|
|
}
|
|
----
|
|
|
|
[source,kotlin,diff-id=1,diff-type=noncompliant]
|
|
----
|
|
fun indexedAccess(list: MutableList<Int>, map: MutableMap<String, Int>, grid: Grid) {
|
|
list.get(1) // Noncompliant
|
|
list.set(1, 42) // Noncompliant
|
|
map.get("b") // Noncompliant
|
|
map.set("b", 42) // Noncompliant
|
|
grid.get(1, 2) // Noncompliant
|
|
grid.set(1, 2, 42) // Noncompliant
|
|
}
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,kotlin,diff-id=1,diff-type=compliant]
|
|
----
|
|
fun indexedAccess(list: MutableList<Int>, map: MutableMap<String, Int>, grid: Grid) {
|
|
list[1] // Compliant
|
|
list[1] = 42 // Compliant
|
|
map["b"] // Compliant
|
|
map["b"] = 42 // Compliant
|
|
grid[1, 2] // Compliant
|
|
grid[1, 2] = 42 // Compliant
|
|
list.getOrNull(2) // Compliant, because function is not an operator
|
|
list.getOrElse(3) {42} // Compliant, because function is not an operator
|
|
map.getValue("a") // Compliant, because function is not an operator
|
|
map.getOrElse("c") {42} // Compliant, because function is not an operator
|
|
}
|
|
----
|
|
|
|
== Resources
|
|
|
|
=== Documentation
|
|
|
|
* https://kotlinlang.org/docs/operator-overloading.html#indexed-access-operator[Kotlin Docs, Indexed access operator]
|