Skip to content

Commit 871b3c9

Browse files
authored
Don't allow functions in state (airbnb#250)
1 parent b5e921a commit 871b3c9

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-6
lines changed

mvrx/src/main/kotlin/com/airbnb/mvrx/MvRxMutabilityHelper.kt

+11-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package com.airbnb.mvrx
22

3+
import android.util.SparseArray
34
import androidx.collection.ArrayMap
45
import androidx.collection.LongSparseArray
56
import androidx.collection.SparseArrayCompat
6-
import android.util.SparseArray
7+
import kotlin.reflect.KCallable
78
import kotlin.reflect.KClass
89
import kotlin.reflect.KMutableProperty
910
import kotlin.reflect.KProperty1
@@ -27,8 +28,9 @@ private const val IMMUTABLE_MAP_MESSAGE =
2728
internal fun KClass<*>.assertImmutability() {
2829
require(this.isData) { "MvRx state must be a data class!" }
2930

30-
fun KProperty1<*, *>.isSubtype(klass: KClass<*>) =
31-
returnType.isSubtypeOf(klass.starProjectedType)
31+
fun KProperty1<*, *>.isSubtype(vararg classes: KClass<*>): Boolean {
32+
return classes.any { klass -> returnType.isSubtypeOf(klass.starProjectedType) }
33+
}
3234

3335
this.declaredMemberProperties.forEach { prop ->
3436
when {
@@ -37,9 +39,13 @@ internal fun KClass<*>.assertImmutability() {
3739
prop.isSubtype(SparseArray::class) -> "You cannot use SparseArray for ${prop.name}.\n$IMMUTABLE_LIST_MESSAGE"
3840
prop.isSubtype(LongSparseArray::class) -> "You cannot use LongSparseArray for ${prop.name}.\n$IMMUTABLE_LIST_MESSAGE"
3941
prop.isSubtype(SparseArrayCompat::class) -> "You cannot use SparseArrayCompat for ${prop.name}.\n$IMMUTABLE_LIST_MESSAGE"
40-
prop.isSubtype(ArrayMap::class) -> "You cannot use ArrayMap for ${prop.name}.\n$IMMUTABLE_MAP_MESSAGE"
41-
prop.isSubtype(android.util.ArrayMap::class) -> "You cannot use ArrayMap for ${prop.name}.\n$IMMUTABLE_MAP_MESSAGE"
42+
prop.isSubtype(ArrayMap::class, android.util.ArrayMap::class) -> {
43+
"You cannot use ArrayMap for ${prop.name}.\n$IMMUTABLE_MAP_MESSAGE"
44+
}
4245
prop.isSubtype(HashMap::class) -> "You cannot use HashMap for ${prop.name}.\n$IMMUTABLE_MAP_MESSAGE"
46+
prop.isSubtype(Function::class, KCallable::class) -> {
47+
"You cannot use functions inside MvRx state. Only pure data should be represented: ${prop.name}"
48+
}
4349
else -> null
4450
}?.let { throw IllegalArgumentException(it) }
4551
}

mvrx/src/test/kotlin/com/airbnb/mvrx/StateImmutabilityTest.kt

+7-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
package com.airbnb.mvrx
44

5+
import android.util.SparseArray
56
import androidx.collection.ArrayMap
67
import androidx.collection.SparseArrayCompat
7-
import android.util.SparseArray
88
import org.junit.Test
99

1010
class StateImmutabilityTest : BaseTest() {
@@ -68,4 +68,10 @@ class StateImmutabilityTest : BaseTest() {
6868
data class State(val map: SparseArrayCompat<Int> = SparseArrayCompat())
6969
State::class.assertImmutability()
7070
}
71+
72+
@Test(expected = IllegalArgumentException::class)
73+
fun lambda() {
74+
data class State(val func: () -> Unit = {})
75+
State::class.assertImmutability()
76+
}
7177
}

0 commit comments

Comments
 (0)