Pair and Triple in public API
PAIR_OR_TRIPLE_PUBLIC_API reports the tuple types Pair and Triple in publicly visible
signatures.
| Diagnostic | PAIR_OR_TRIPLE_PUBLIC_API |
| Default severity | Error |
| Gradle property | pairOrTriplePublicApi |
| Exemption | @IntentionallyPairOrTriple |
What it reports
The check reports Pair and Triple in return types, property types, parameter types, and type
parameter bounds, including their type arguments (like List<Pair<Int, String>>):
@file:JvmName("Locations")/** Returns an unnamed location. */public fun locate(): Pair<Int, Int> = 0 to 0
Rationale
Pair and Triple name their components first/second/third, so a call site reading
point.first or destructuring val (a, b) = point learns nothing about what the values mean.
Worse, the shape is fixed: it can't grow a fourth component or rename a component without
breaking every user in a source-incompatible way, while a purpose-built class can add an
optional property with a default value. See the
Kotlin API guidelines on object-oriented design for data and state.
Don't
@file:JvmName("Geometry")/** Returns unnamed dimensions. */public fun dimensions(): Triple<Int, Int, Int> = Triple(0, 0, 0)/*** Attaches content to an unnamed coordinate pair.** @property position horizontal and vertical anchor coordinates.*/@Pokopublic class Anchor(public val position: Pair<Int, Int>)/** Returns unnamed edges. */public fun edges(): List<Pair<Int, Int>> = emptyList()
Do
@file:JvmName("Geometry")/*** Extents of a three-dimensional object.** @property width horizontal extent in pixels.* @property height vertical extent in pixels.* @property depth front-to-back extent in pixels.*/@Pokopublic class Dimensions(public val width: Int,public val height: Int,public val depth: Int,)/** Returns the dimensions. */public fun dimensions(): Dimensions = Dimensions(0, 0, 0)/*** A position in Cartesian coordinate space.** @property x distance from the vertical axis.* @property y distance from the horizontal axis.*/@Pokopublic class Point(public val x: Int,public val y: Int,)/*** Attaches content to a point in Cartesian space.** @property position point at which the content is anchored.*/@Pokopublic class Anchor(public val position: Point)/** Returns edges. */public fun edges(): List<Point> = emptyList()
Notes
@PublishedApi internaldeclarations are not reported because their tuple types do not cross the supported source API boundary.- A tuple type parameter bound (
<T : Pair<Int, Int>>) is reported too: it constrains every instantiation to the tuple shape, exposing it just like a direct mention. - Extension receivers are not reported:
fun Pair<Int, Int>.manhattanLength(): Intserves a value the user already holds instead of handing out a new tuple. - Overrides are not reported: their signature is fixed by the overridden declaration, which is reported instead.
Exemption
Apply @IntentionallyPairOrTriple on the whole declaration, on a single parameter or type
parameter, or on a type usage, where it covers the annotated type and everything nested in it:
@file:JvmName("Geometry")/** Returns deliberately unnamed dimensions. */@IntentionallyPairOrTriple(reason = ExemptionReason.API_DESIGN)public fun dimensions(): Triple<Int, Int, Int> = Triple(0, 0, 0)/*** Attaches content to a deliberately unnamed coordinate pair.** @property position horizontal and vertical anchor coordinates.*/@Pokopublic class Anchor(public val position: @IntentionallyPairOrTriple(reason = ExemptionReason.API_DESIGN,) Pair<Int, Int>,)/** Returns deliberately unnamed edges. */@IntentionallyPairOrTriple(reason = ExemptionReason.API_DESIGN)public fun edges(): List<Pair<Int, Int>> = emptyList()
Configuration
apiWatchdog {pairOrTriplePublicApi = WatchdogSeverity.WARNING}
With direct compiler invocation:
-P plugin:org.jetbrains.kotlin.library.api.watchdog:diagnosticSeverity=PAIR_OR_TRIPLE_PUBLIC_API:warning