Skip to content

Commit 0a72005

Browse files
authored
Kotlin: use only immutable collections (#1784)
---------- Motivation ---------- Initially, the mutable collections were introduced. The goal was to provide compatibility with Java and the functional tests for Java contained explicit calls to 'add()' / 'put()' methods. However, it turned out that mutable collections do not make much sense for remaining LIME abstractions. Rationale: 1. When a collection is passed to a function defined in LIME, then it is converted to the corresponding C++ container on JNI bindings layer. The C++ functions receive the parameters by const reference: e.g. 'MutableList<Int>' is converted to 'const std::vector<int>&' -- the C++ data type is immutable. 2. Even when we define a listener (interface or lambda) that can be implemented in Kotlin and later called from C++, the container type passed from C++ to Kotlin will be converted (copied). Therefore, even when the listener modifies the collection passed as parameter, the changes will not be reflected on C++ side. 3. The usage of 'Mutable_' for properties of classes / interfaces can lead to logic errors, because the getter/setter functions for a property are implemented in C++. Please see the snippet below. Given the following class generated for LimeClass with property: ``` class Clazz { // This property is always queried from C++ when we get its value. // The C++ setter is called when we set the value via operator '='. var numbers: MutableList<Int> external get external set } // This code looks natural. // The user may expect that 7 will be present in collection. val c = Clazz() c.numbers.add(7) // The collection is queried again from C++ and the previous change // is not reflected here. println(c.numbers) ``` ---------- Implemented solution ---------- 'KotlinNameResolver' is adjusted to generate immutable collections with usage of JvmSuppressWildcards annotation to handle also open classes. 'KotlinValueResolver' still generates `mutable` dynamic type to ensure that if anyone tries to modify collection from Java for LimeStructure then it is allowed and it does not cause problems. Note: in order to keep the consistency between the way in which the user of the code accesses properties of classes/interfaces and fields of structures, the fields of structures also use immutable collection types. To modify the field the user needs to set the new value of the collection. The compatibility with Java is still preserved because the immutable kotlin.List is still compiled to java.util.List and from Java we can modify its content. Signed-off-by: Patryk Wrobel <[email protected]>
1 parent 7b375de commit 0a72005

File tree

64 files changed

+392
-280
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+392
-280
lines changed

functional-tests/functional/android-kotlin/src/test/kotlin/com/here/android/test/ArraysTest.kt

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class ArraysTest {
3737
val first = "abc"
3838
val second = "def"
3939

40-
val stringList = mutableListOf(first, second)
40+
val stringList = listOf(first, second)
4141
val resultsList = Arrays.reverseStringArray(stringList)
4242

4343
assertEquals(2, resultsList.size)
@@ -50,7 +50,7 @@ class ArraysTest {
5050
val first: Short = 77
5151
val second: Short = 21
5252

53-
val shortList = mutableListOf(first, second)
53+
val shortList = listOf(first, second)
5454
val resultsList = Arrays.reverseArrayInline(shortList)
5555

5656
assertEquals(2, resultsList.size)
@@ -63,7 +63,7 @@ class ArraysTest {
6363
val first: Byte = 55
6464
val second: Byte = 33
6565

66-
val byteList = mutableListOf(first, second)
66+
val byteList = listOf(first, second)
6767
val resultsList = Arrays.reverseInt8Array(byteList)
6868

6969
assertEquals(2, resultsList.size)
@@ -76,7 +76,7 @@ class ArraysTest {
7676
val first: Short = 77
7777
val second: Short = 21
7878

79-
val shortList = mutableListOf(first, second)
79+
val shortList = listOf(first, second)
8080
val resultsList = Arrays.reverseInt16Array(shortList)
8181

8282
assertEquals(2, resultsList.size)
@@ -89,7 +89,7 @@ class ArraysTest {
8989
val first: Int = 57
9090
val second: Int = 23
9191

92-
val intList = mutableListOf(first, second)
92+
val intList = listOf(first, second)
9393
val resultsList = Arrays.reverseInt32Array(intList)
9494

9595
assertEquals(2, resultsList.size)
@@ -102,7 +102,7 @@ class ArraysTest {
102102
val first: Long = 17L
103103
val second: Long = 23L
104104

105-
val longList = mutableListOf(first, second)
105+
val longList = listOf(first, second)
106106
val resultsList = Arrays.reverseInt64Array(longList)
107107

108108
assertEquals(2, resultsList.size)
@@ -115,7 +115,7 @@ class ArraysTest {
115115
val first: Short = 77
116116
val second: Short = 21
117117

118-
val shortList = mutableListOf(first, second)
118+
val shortList = listOf(first, second)
119119
val resultsList = Arrays.reverseUint8Array(shortList)
120120

121121
assertEquals(2, resultsList.size)
@@ -128,7 +128,7 @@ class ArraysTest {
128128
val first: Int = 57
129129
val second: Int = 23
130130

131-
val intList = mutableListOf(first, second)
131+
val intList = listOf(first, second)
132132
val resultsList = Arrays.reverseUint16Array(intList)
133133

134134
assertEquals(2, resultsList.size)
@@ -141,7 +141,7 @@ class ArraysTest {
141141
val first: Long = 17L
142142
val second: Long = 23L
143143

144-
val longList = mutableListOf(first, second)
144+
val longList = listOf(first, second)
145145
val resultsList = Arrays.reverseUint32Array(longList)
146146

147147
assertEquals(2, resultsList.size)
@@ -154,7 +154,7 @@ class ArraysTest {
154154
val first: Long = 17L
155155
val second: Long = 23L
156156

157-
val longList = mutableListOf(first, second)
157+
val longList = listOf(first, second)
158158
val resultsList = Arrays.reverseUint64Array(longList)
159159

160160
assertEquals(2, resultsList.size)
@@ -167,7 +167,7 @@ class ArraysTest {
167167
val first: Float = 77.77f
168168
val second: Float = 23.23f
169169

170-
val floatList = mutableListOf(first, second)
170+
val floatList = listOf(first, second)
171171
val resultsList = Arrays.reverseFloatArray(floatList)
172172

173173
assertEquals(2, resultsList.size)
@@ -180,7 +180,7 @@ class ArraysTest {
180180
val first: Double = 22.22
181181
val second: Double = 66.66
182182

183-
val doubleList = mutableListOf(first, second)
183+
val doubleList = listOf(first, second)
184184
val resultsList = Arrays.reverseDoubleArray(doubleList)
185185

186186
assertEquals(2, resultsList.size)
@@ -190,7 +190,7 @@ class ArraysTest {
190190

191191
@org.junit.Test
192192
fun methodWithBooleanArray() {
193-
val booleanList = mutableListOf<Boolean>(true, true, false)
193+
val booleanList = listOf<Boolean>(true, true, false)
194194
val resultsList = Arrays.reverseBoolArray(booleanList)
195195

196196
assertEquals(3, resultsList.size)
@@ -204,7 +204,7 @@ class ArraysTest {
204204
val first = Arrays.BasicStruct(22.22)
205205
val second = Arrays.BasicStruct(33.33)
206206

207-
val structList = mutableListOf(first, second)
207+
val structList = listOf(first, second)
208208
val resultsList = Arrays.reverseStructArray(structList)
209209

210210
assertEquals(2, resultsList.size)
@@ -214,10 +214,10 @@ class ArraysTest {
214214

215215
@org.junit.Test
216216
fun reverseMapsArray() {
217-
val first = mutableMapOf(32.toShort() to "abc")
218-
val second = mutableMapOf<Short, String>()
217+
val first = mapOf(32.toShort() to "abc")
218+
val second = mapOf<Short, String>()
219219

220-
val input = mutableListOf(first, second)
220+
val input = listOf(first, second)
221221
val result = Arrays.reverseMapsArray(input)
222222

223223
assertEquals(2, result.size)
@@ -227,10 +227,10 @@ class ArraysTest {
227227

228228
@org.junit.Test
229229
fun reverseArrayMapsArray() {
230-
val first = mutableMapOf(42.toShort() to mutableListOf("john", "doe"))
231-
val second = mutableMapOf(44.toShort() to mutableListOf("example", "dot", "com"))
230+
val first = mapOf(42.toShort() to listOf("john", "doe"))
231+
val second = mapOf(44.toShort() to listOf("example", "dot", "com"))
232232

233-
val input = mutableListOf(first, second)
233+
val input = listOf(first, second)
234234
val result = Arrays.reverseArrayMapsArray(input)
235235

236236
assertEquals(2, result.size)
@@ -246,7 +246,7 @@ class ArraysTest {
246246
val second = InstancesFactory.createSimpleInstantiableOne()
247247
second.setStringValue("SECOND STRING")
248248

249-
val instancesArray = mutableListOf(first, second)
249+
val instancesArray = listOf(first, second)
250250
val resultsList = Arrays.reverseExplicitInstancesArray(instancesArray)
251251

252252
assertEquals(2, resultsList.size)
@@ -262,7 +262,7 @@ class ArraysTest {
262262
val second = InstancesFactory.createSimpleInstantiableOne()
263263
second.setStringValue("SECOND STRING")
264264

265-
val instancesArray = mutableListOf(first, second)
265+
val instancesArray = listOf(first, second)
266266
val resultsList: List<SimpleInstantiableOne> = Arrays.reverseImplicitInstancesArray(instancesArray)
267267

268268
assertEquals(2, resultsList.size)
@@ -272,7 +272,7 @@ class ArraysTest {
272272

273273
@org.junit.Test
274274
fun reverseNestedPrimitiveArray() {
275-
val nestedDoubleList = mutableListOf(mutableListOf(11.11, 22.22), mutableListOf(33.33, 44.44))
275+
val nestedDoubleList = listOf(listOf(11.11, 22.22), listOf(33.33, 44.44))
276276
val resultsList = Arrays.reverseNestedPrimitiveArray(nestedDoubleList)
277277

278278
assertEquals(2, resultsList.size)
@@ -290,9 +290,9 @@ class ArraysTest {
290290

291291
@org.junit.Test
292292
fun reverseNestedStructArray() {
293-
val nestedStructList = mutableListOf(
294-
mutableListOf(Arrays.BasicStruct(11.11), Arrays.BasicStruct(22.22)),
295-
mutableListOf(Arrays.BasicStruct(33.33), Arrays.BasicStruct(44.44))
293+
val nestedStructList = listOf(
294+
listOf(Arrays.BasicStruct(11.11), Arrays.BasicStruct(22.22)),
295+
listOf(Arrays.BasicStruct(33.33), Arrays.BasicStruct(44.44))
296296
)
297297

298298
val resultsList = Arrays.reverseNestedStructArray(nestedStructList)
@@ -310,7 +310,7 @@ class ArraysTest {
310310

311311
@org.junit.Test
312312
fun reverseNestedArraysInline() {
313-
val nestedLongList = mutableListOf(mutableListOf(21L, 31L), mutableListOf(45L, 75L))
313+
val nestedLongList = listOf(listOf(21L, 31L), listOf(45L, 75L))
314314
val resultsList = Arrays.reverseNestedArraysInline(nestedLongList)
315315

316316
assertEquals(2, resultsList.size)
@@ -337,30 +337,30 @@ class ArraysTest {
337337
val instance3 = InstancesFactory.createSimpleInstantiableOne()
338338
instance3.setStringValue("Instance 3: STRING")
339339

340-
val instancesArray1 = mutableListOf(instance1, instance2)
341-
val instancesArray2 = mutableListOf(instance3)
342-
val instancesArray3 = mutableListOf<SimpleInstantiableOne>()
340+
val instancesArray1 = listOf(instance1, instance2)
341+
val instancesArray2 = listOf(instance3)
342+
val instancesArray3 = listOf<SimpleInstantiableOne>()
343343

344344
val struct1 = Arrays.FancyStruct(
345-
mutableListOf("struct", "1"),
346-
mutableListOf(1.toShort(), 2.toShort()),
345+
listOf("struct", "1"),
346+
listOf(1.toShort(), 2.toShort()),
347347
instancesArray1
348348
)
349349

350350
val struct2 = Arrays.FancyStruct(
351-
mutableListOf("struct", "2"),
352-
mutableListOf(3.toShort(), 4.toShort()),
351+
listOf("struct", "2"),
352+
listOf(3.toShort(), 4.toShort()),
353353
instancesArray2
354354
)
355355

356356
val struct3 = Arrays.FancyStruct(
357-
mutableListOf("struct", "3"),
358-
mutableListOf(5.toShort(), 6.toShort()),
357+
listOf("struct", "3"),
358+
listOf(5.toShort(), 6.toShort()),
359359
instancesArray3
360360
)
361361

362-
val fancyStructList1 = mutableListOf(struct1, struct2)
363-
val fancyStructList2 = mutableListOf(struct3)
362+
val fancyStructList1 = listOf(struct1, struct2)
363+
val fancyStructList2 = listOf(struct3)
364364
val resultsList = Arrays.mergeArraysOfStructsWithArrays(fancyStructList1, fancyStructList2)
365365

366366
assertEquals(3, resultsList.size)
@@ -381,15 +381,15 @@ class ArraysTest {
381381

382382
@org.junit.Test
383383
fun reverseArrayOfAliases_emptyList() {
384-
val stringList = mutableListOf<String>()
384+
val stringList = listOf<String>()
385385
val resultsList = Arrays.reverseArrayOfAliases(stringList)
386386

387387
assertEquals(0, resultsList.size)
388388
}
389389

390390
@org.junit.Test
391391
fun reverseArrayOfAliases_reversesArray() {
392-
val stringList = mutableListOf("abc", "def")
392+
val stringList = listOf("abc", "def")
393393
val resultsList = Arrays.reverseArrayOfAliases(stringList)
394394

395395
assertEquals(2, resultsList.size)

functional-tests/functional/android-kotlin/src/test/kotlin/com/here/android/test/AttributesTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class AttributesTest {
4545

4646
@org.junit.Test
4747
fun setGetStructAttribute() {
48-
val expectedStruct = Attributes.ExampleStruct(2.71, mutableListOf())
48+
val expectedStruct = Attributes.ExampleStruct(2.71, listOf())
4949
attributes.structAttribute = expectedStruct
5050

5151
val result = attributes.structAttribute

functional-tests/functional/android-kotlin/src/test/kotlin/com/here/android/test/BlobsTest.kt

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,35 +47,35 @@ class BlobsTest {
4747

4848
@org.junit.Test
4949
fun methodWithImplicitArray_emptyArray() {
50-
val uintList: MutableList<Short> = mutableListOf<Short>()
51-
val resultList: MutableList<Short> = ArraysByteBuffer.methodWithImplicitArray(uintList)
50+
val uintList: List<Short> = listOf<Short>()
51+
val resultList: List<Short> = ArraysByteBuffer.methodWithImplicitArray(uintList)
5252

5353
assertEquals(0, resultList.size)
5454
}
5555

5656
@org.junit.Test
5757
fun methodWithImplicitArray_reversesArray() {
58-
val uintList: MutableList<Short> = mutableListOf(1.toShort(), 2.toShort(), 3.toShort())
59-
val resultList: MutableList<Short> = ArraysByteBuffer.methodWithImplicitArray(uintList)
58+
val uintList: List<Short> = listOf(1.toShort(), 2.toShort(), 3.toShort())
59+
val resultList: List<Short> = ArraysByteBuffer.methodWithImplicitArray(uintList)
6060

61-
val expectedResult: MutableList<Short> = mutableListOf(3.toShort(), 2.toShort(), 1.toShort())
61+
val expectedResult: List<Short> = listOf(3.toShort(), 2.toShort(), 1.toShort())
6262
assertEquals(expectedResult, resultList)
6363
}
6464

6565
@org.junit.Test
6666
fun methodWithExplicitArray_emptyArray() {
67-
val uintList: MutableList<Short> = mutableListOf<Short>()
68-
val resultList: MutableList<Short> = ArraysByteBuffer.methodWithExplicitArray(uintList)
67+
val uintList: List<Short> = listOf<Short>()
68+
val resultList: List<Short> = ArraysByteBuffer.methodWithExplicitArray(uintList)
6969

7070
assertEquals(0, resultList.size)
7171
}
7272

7373
@org.junit.Test
7474
fun methodWithExplicitArray_reversesArray() {
75-
val uintList: MutableList<Short> = mutableListOf<Short>(1.toShort(), 2.toShort(), 3.toShort())
76-
val resultList: MutableList<Short> = ArraysByteBuffer.methodWithExplicitArray(uintList)
75+
val uintList: List<Short> = listOf<Short>(1.toShort(), 2.toShort(), 3.toShort())
76+
val resultList: List<Short> = ArraysByteBuffer.methodWithExplicitArray(uintList)
7777

78-
assertEquals(mutableListOf<Short>(3.toShort(), 2.toShort(), 1.toShort()), resultList)
78+
assertEquals(listOf<Short>(3.toShort(), 2.toShort(), 1.toShort()), resultList)
7979
}
8080

8181
@org.junit.Test
@@ -96,34 +96,34 @@ class BlobsTest {
9696

9797
@org.junit.Test
9898
fun methodWithImplicitArrayInStruct_emptyArray() {
99-
val struct = ArraysByteBuffer.StructWithImplicitArray(mutableListOf<Short>())
99+
val struct = ArraysByteBuffer.StructWithImplicitArray(listOf<Short>())
100100
val resultStruct = ArraysByteBuffer.methodWithImplicitArrayInStruct(struct)
101101

102102
assertEquals(0, resultStruct.image.size)
103103
}
104104

105105
@org.junit.Test
106106
fun methodWithImplicitArrayInStruct_reversesArray() {
107-
val struct = ArraysByteBuffer.StructWithImplicitArray(mutableListOf(1.toShort(), 2.toShort(), 3.toShort()))
107+
val struct = ArraysByteBuffer.StructWithImplicitArray(listOf(1.toShort(), 2.toShort(), 3.toShort()))
108108
val resultStruct = ArraysByteBuffer.methodWithImplicitArrayInStruct(struct)
109109

110-
assertEquals(mutableListOf(3.toShort(), 2.toShort(), 1.toShort()), resultStruct.image)
110+
assertEquals(listOf(3.toShort(), 2.toShort(), 1.toShort()), resultStruct.image)
111111
}
112112

113113
@org.junit.Test
114114
fun methodWithExplicitArrayInStruct_emptyArray() {
115-
val struct = ArraysByteBuffer.StructWithExplicitArray(mutableListOf<Short>())
115+
val struct = ArraysByteBuffer.StructWithExplicitArray(listOf<Short>())
116116
val resultStruct = ArraysByteBuffer.methodWithExplicitArrayInStruct(struct)
117117

118118
assertEquals(0, resultStruct.image.size)
119119
}
120120

121121
@org.junit.Test
122122
fun methodWithExplicitArrayInStruct_reversesArray() {
123-
val struct = ArraysByteBuffer.StructWithExplicitArray(mutableListOf(1.toShort(), 2.toShort(), 3.toShort()))
123+
val struct = ArraysByteBuffer.StructWithExplicitArray(listOf(1.toShort(), 2.toShort(), 3.toShort()))
124124
val resultStruct = ArraysByteBuffer.methodWithExplicitArrayInStruct(struct)
125125

126-
assertEquals(mutableListOf(3.toShort(), 2.toShort(), 1.toShort()), resultStruct.image)
126+
assertEquals(listOf(3.toShort(), 2.toShort(), 1.toShort()), resultStruct.image)
127127
}
128128

129129
@org.junit.Test

functional-tests/functional/android-kotlin/src/test/kotlin/com/here/android/test/ConstantsTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ class ConstantsTest {
135135

136136
@org.junit.Test
137137
fun checkMixedConstant() {
138-
val result: MutableMap<MutableList<String>, MutableSet<String>> = CollectionConstants.MIXED_CONSTANT
138+
val result: Map<List<String>, Set<String>> = CollectionConstants.MIXED_CONSTANT
139139
assertEquals(mapOf(listOf("foo") to setOf("bar")), result)
140140
}
141141
}

functional-tests/functional/android-kotlin/src/test/kotlin/com/here/android/test/CppProxyWithComplexListenersTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class CppProxyWithComplexListenersTest {
4040
val kotlinComplexListener: ComplexListener = object: ComplexListener {
4141
override fun onTrajectoryCompleted(
4242
distanceMetric: DistanceMetric,
43-
trajectory: MutableList<NamedPoint3D>,
43+
trajectory: List<NamedPoint3D>,
4444
quality: TrajectoryQuality,
4545
image: ByteArray,
4646
) {
@@ -55,7 +55,7 @@ class CppProxyWithComplexListenersTest {
5555
}
5656
}
5757

58-
val trajectory: MutableList<NamedPoint3D> = mutableListOf(ptOne, ptTwo, ptThree)
58+
val trajectory: List<NamedPoint3D> = listOf(ptOne, ptTwo, ptThree)
5959
val trajectoryQuality: TrajectoryQuality = TrajectoryQuality.TRAJECTORY_AVERAGE
6060

6161
val complexNotifier: ComplexNotifier = ComplexListenerFactory.createComplexNotifier()

0 commit comments

Comments
 (0)