Skip to content

Commit

Permalink
Update to kotlin 1.8.10 and remove support for old memory model (#147)
Browse files Browse the repository at this point in the history
Description
This updates to kotlin 1.8.10. In that version, calling freeze now cause compilation errors.
We are now dropping support for old MM

We are also updating various libraries.

Ktlint was updated so this is why there is a lot of code style changes.

Motivation and Context
Old MM has become obsolete in favor of the new MM.

How Has This Been Tested?
I tested it in another project to test ABI compatibility.

Types of changes
 Bug fix (non-breaking change which fixes an issue)
 New feature (non-breaking change which adds functionality)
 Breaking change (fix or feature that would cause existing functionality to change)
Changes are ABI compatible. Old freezing utils were deprecated and will just do nothing.
This is however breaking in the sense that we drop support for old memory model.

New android lifecycle library also as a breaking change but that's not on us.
  • Loading branch information
npresseault authored Mar 2, 2023
1 parent 7bf0ba5 commit ff9756c
Show file tree
Hide file tree
Showing 120 changed files with 284 additions and 440 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
max_line_length = 200

[*.{kt,kts}]
disabled_rules=import-ordering
ktlint_disabled_rules=import-ordering,enum-entry-name-case
30 changes: 26 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,32 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Breaking Changes

- [VMD] ContentDescription is now a property of VMDImageViewModel.
- It does not exist in VMDImage anymore for android
- [VMD-flow] ContentDescription is now a property of VMDImageViewModel.
- It does not exist in VMDImage anymore for android
- [All] Old memory model is no longer supported.

### Deprecation

- [Foundation] `MrFreeze` was deprecated. It is no longer needed in new MM.
- [Streams] `Publisher.threadLocal`, `Publishers.frozenSubject` and `Publishers.frozenBehaviorSubject` operators were deprecated. They are no longer needed in new MM.

### Updates

- Kotlin `1.8.10`
- Jetpack Compose Compiler to `1.4.3`
- Jetpack Compose Runtime to `1.3.3`
- Jetpack Compose UI to `1.3.1`
- Jetpack Compose Material 3 to `1.1.0-alpha07`
- Ktlint to `11.2.0`
- Androidx Lifecycle to `2.6.0-rc01`
- KSP to `1.8.10-1.0.9`
- Android MIN SDK to `24`
- Kotlin Serialization to `1.5.0`
- AtomicFu to `0.20.0`
- Kotlinx Coroutines `1.6.3`

## 4.2.0

- [VMD & VMD-flow] ContentDescription is now a property of VMDImageViewModel.
It does not exist in VMDImage anymore for android

## 4.1.0

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<p>Trikot is a framework that helps building Kotlin Multiplatform applications.<br />iOS, Android and Web are the primary targets.</p>
<a href="https://github.com/mirego/trikot/tags"><img src="https://img.shields.io/github/tag/mirego/trikot.svg?label=latest%20release"></a>
<img src="https://img.shields.io/maven-metadata/v?label=latest%20dev&metadataUrl=https%3A%2F%2Fmirego-maven.s3.amazonaws.com%2Fpublic%2Fcom%2Fmirego%2Ftrikot%2FtrikotFoundation%2Fmaven-metadata.xml" />
<a href="http://kotlinlang.org"><img src="https://img.shields.io/badge/kotlin-1.7.20-blue.svg?logo=kotlin" /></a>
<a href="http://kotlinlang.org"><img src="https://img.shields.io/badge/kotlin-1.8.10-blue.svg?logo=kotlin" /></a>
<a href="https://github.com/mirego/trikot/actions/workflows/ci.yml"><img src="https://github.com/mirego/trikot/actions/workflows/ci.yml/badge.svg" /></a>
<a href="https://github.com/mirego/trikot/actions/workflows/cd.yml"><img src="https://github.com/mirego/trikot/actions/workflows/cd.yml/badge.svg" /></a>
<a href="https://opensource.org/licenses/BSD-3-Clause"><img src="https://img.shields.io/badge/License-BSD_3--Clause-blue.svg" /></a>
Expand Down
2 changes: 1 addition & 1 deletion buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ repositories {
}

dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.20")
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10")
implementation("com.android.tools.build:gradle:7.3.1")
}
24 changes: 12 additions & 12 deletions buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
object Versions {
const val KOTLIN = "1.7.20"
const val ATOMIC_FU = "0.18.5"
const val KOTLIN = "1.8.10"
const val ATOMIC_FU = "0.20.0"
const val ANDROID_GRADLE_PLUGIN = "7.3.1"
const val JETPACK_COMPOSE_COMPILER = "1.3.2"
const val JETPACK_COMPOSE_RUNTIME = "1.3.2"
const val JETPACK_COMPOSE_COMPILER = "1.4.3"
const val JETPACK_COMPOSE_RUNTIME = "1.3.3"
const val JETPACK_COMPOSE_FOUNDATION = "1.3.1"
const val JETPACK_COMPOSE_UI_TOOLING = "1.3.2"
const val JETPACK_COMPOSE_UI_TOOLING = "1.3.3"
const val JETPACK_COMPOSE_MATERIAL = "1.3.1"
const val JETPACK_COMPOSE_MATERIAL_3 = "1.1.0-alpha03"
const val JETPACK_COMPOSE_MATERIAL_3 = "1.1.0-alpha07"
const val COIL = "2.0.0-rc03"
const val KTLINT = "10.3.0"
const val KOTLINX_SERIALIZATION = "1.4.1"
const val KOTLINX_COROUTINES = "1.6.3"
const val KTLINT = "11.2.0"
const val KOTLINX_SERIALIZATION = "1.5.0"
const val KOTLINX_COROUTINES = "1.6.4"
const val KTOR = "2.0.3"
const val KOTLIN_WRAPPERS_EXTENSIONS = "1.0.1-pre.459"
const val ANDROIDX_LIFECYCLE = "2.4.0"
const val ANDROIDX_LIFECYCLE = "2.6.0-rc01"
const val OKIO = "3.2.0"
const val KSP = "1.7.10-1.0.6"
const val KSP = "1.8.10-1.0.9"
const val KOTLIN_POET = "1.12.0"
const val ACCOMPANIST = "0.28.0"

object Android {
const val TARGET_SDK = 33
const val COMPILE_SDK = 33
const val MIN_SDK = 21
const val MIN_SDK = 24
}
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ kotlin.mpp.stability.nowarn=true
org.gradle.parallel=true
kotlin.native.enableDependencyPropagation=false
org.gradle.jvmargs=-Xmx3072m -XX\:+HeapDumpOnOutOfMemoryError -Dfile.encoding\=UTF-8
version=4.2.0
version=4.3.0
android.useAndroidX=true
android.enableJetifier=true
kotlin.code.style=official
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class AnalyticsServiceLogger(private val analyticsService: AnalyticsService) : A
Analytics - Identify user (Service: ${analyticsService.name})
userId: $userId
${properties.toLog()}
""".trimMargin()
""".trimMargin()
)
analyticsService.identifyUser(userId, properties)
}
Expand All @@ -37,7 +37,7 @@ ${properties.toLog()}
"""
Analytics - Increment user properties (Service: ${analyticsService.name})
Incremented Properties: ${incrementalProperties.toLog()}
""".trimMargin()
""".trimMargin()
)

analyticsService.incrementUserProperties(incrementalProperties)
Expand All @@ -54,7 +54,7 @@ Incremented Properties: ${incrementalProperties.toLog()}
"""
Analytics - Set user properties (Service: ${analyticsService.name})
UserProperties Properties: ${properties.toLog()}
""".trimMargin()
""".trimMargin()
)
}

Expand All @@ -80,7 +80,7 @@ Analytics - Track event (Service: ${analyticsService.name})
event: $event
${properties.toLog()}
${superProperties.value.toLog()}
""".trimMargin()
""".trimMargin()
)
analyticsService.trackEvent(event, properties)
}
Expand All @@ -95,7 +95,7 @@ ${superProperties.value.toLog()}
"""
Analytics - SuperProperties updated with $methodName (Service: ${analyticsService.name})
${newProps.toLog()}
""".trimMargin()
""".trimMargin()
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ class MixpanelAnalyticsService(
}

private fun AnalyticsPropertiesType.asJSONProperties(): JSONObject {

return JSONObject().also { props ->
forEach { (type, value) ->
props.put(type, value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class TrikotAttributeProfileService: NSObject, AttributeProfileService {

var trikotCharacteristics = [CBCharacteristic: TrikotAttributeProfileCharacteristic]()

let characteristics: Publisher = frozenBehaviorSubject()
let characteristics: Publisher = behaviorSubject()

init(service: CBService, peripheral: CBPeripheral) {
self.service = service
Expand Down
4 changes: 2 additions & 2 deletions trikot-bluetooth/swift-extensions/TrikotBluetoothDevice.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ class TrikotBluetoothDevice: NSObject, BluetoothDevice, CBPeripheralDelegate {

var physicalAddress: String

var attributeProfileServices: Publisher = frozenBehaviorSubject()
var isConnected: Publisher = frozenBehaviorSubject()
var attributeProfileServices: Publisher = behaviorSubject()
var isConnected: Publisher = behaviorSubject()

var managerIsConnected = false {
didSet {
Expand Down
12 changes: 0 additions & 12 deletions trikot-bluetooth/swift-extensions/TrikotBluetoothExtensions.swift
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
import Foundation
import TRIKOT_FRAMEWORK_NAME

func frozenBehaviorSubject(value: Any? = nil) -> Publisher {
let publisher = Publishers().behaviorSubject(value: value)
MrFreeze().freeze(objectToFreeze: publisher)
return publisher
}

func frozenSubject(value: Any? = nil) -> Publisher {
let publisher = Publishers().publishSubject()
MrFreeze().freeze(objectToFreeze: publisher)
return publisher
}

extension Publisher {
func asBehaviorSubject() -> BehaviorSubject {
return self as! BehaviorSubject
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ public class TrikotBluetoothManager: NSObject, BluetoothManager, CBCentralManage
private let dispatchQueue = DispatchQueue(label: TrikotBluetoothManager.QueueLabel, qos: .background)
private lazy var centralManager = CBCentralManager(delegate: self, queue: dispatchQueue)

private let scanResultpublisher = frozenBehaviorSubject()
private let scanResultpublisher = behaviorSubject()
private let numberOfScanRequest = Atomic<Int>(0)

private var scanResults = [CBPeripheral: TrikotBluetoothScanResult]()
private var connectedDevices = [CBPeripheral: TrikotBluetoothDevice]()
private var delegates = [CBCentralManagerDelegate]()

private let bluetoothStatePublisher: Publisher = frozenBehaviorSubject()
private let bluetoothStatePublisher: Publisher = behaviorSubject()

public lazy var statePublisher = PublisherExtensionsKt.map(bluetoothStatePublisher) { (value: Any) in
guard let centralManagerState = value as? CBManagerState else { return nil }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ class TrikotBluetoothScanResult: NSObject, BluetoothScanResult {
private let centralManager: CBCentralManager
private let peripheral: CBPeripheral
private var lostHeartbeatTimer: Foundation.Timer?
private var manufacturerData = frozenBehaviorSubject()
private var manufacturerData = behaviorSubject()

var bluetoothDevice: TrikotBluetoothDevice?

var name: String

var physicalAddress: String

var rssi: Publisher = frozenBehaviorSubject()
var rssi: Publisher = behaviorSubject()

var onHeartBeatLost: (() -> Void)? {
didSet {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ interface FlowDataSourceRequest {
* Identifier use to save data to cache
*/
val cacheableId: String

/**
* Type of request (See DataSourceRequest.Type)
*/
Expand All @@ -15,6 +16,7 @@ interface FlowDataSourceRequest {
* Use cache if available
*/
USE_CACHE,

/**
* Refresh data and save to cache
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ private class MainDataSource(
private class CacheDataSource(
var readFunction: suspend (request: TestDataSourceRequest) -> DataSourceTestData,
coroutineContext: CoroutineContext,
var clearFunction: suspend () -> Unit = {},
var clearFunction: suspend () -> Unit = {}
) : BaseFlowDataSource<TestDataSourceRequest, DataSourceTestData>(coroutineContext = coroutineContext) {
var internalSaveCount = 0
var internalDeleteCount = 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ interface DataSourceRequest {
* Identifier use to save data to cache
*/
val cacheableId: Any

/**
* Type of request (See DataSourceRequest.Type)
*/
Expand All @@ -15,6 +16,7 @@ interface DataSourceRequest {
* Use cache if available
*/
USE_CACHE,

/**
* Refresh data and save to cache
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import com.mirego.trikot.datasources.testutils.assertPending
import com.mirego.trikot.datasources.testutils.assertValue
import com.mirego.trikot.datasources.testutils.get
import com.mirego.trikot.foundation.concurrent.AtomicReference
import com.mirego.trikot.foundation.concurrent.MrFreeze
import com.mirego.trikot.foundation.concurrent.dispatchQueue.SynchronousDispatchQueue
import com.mirego.trikot.streams.StreamsConfiguration
import com.mirego.trikot.streams.cancellable.CancellableManager
Expand Down Expand Up @@ -227,7 +226,6 @@ class BaseDataSourceTests {
@Test
fun givenNetworkDataWhenRefreshingThenPendingWithCurrentData() {
val networkDataSourceReadPublisher = ReadFromCachePublisher().also {
MrFreeze.freeze(it)
it.dispatchResult(networkResult)
}
val dataSource = BasicDataSource(mutableMapOf(simpleCacheableId to networkDataSourceReadPublisher))
Expand Down
14 changes: 0 additions & 14 deletions trikot-foundation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,6 @@ val otherDate = Date.fromISO8601(isoDate)
otherDate == date // true
```

## Multiplatform freezing

Allow freezing in common code. Does nothing in js and JVM.

```kotlin
freeze(objectToFreeze)
```

In swift, use access freeze via MrFreezeKt class helper to freeze object.

```swift
MrFreezeKt.freeze(objectToFreeze: objectToFreeze)
```

## Dispatch Queues

While waiting for [Sharing of coroutines across threads in Kotlin/Native](https://github.com/Kotlin/kotlinx.coroutines/pull/1648) to work correctly. Trikot.foundation provide a standard Thread model based on queues. When this issue will be resolved, DispatchQueues will be converted to Coroutines.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
package com.mirego.trikot.foundation.concurrent

expect object MrFreeze {
fun <T> freeze(objectToFreeze: T): T
actual fun ensureNeverFrozen(objectToProtect: Any)
@Deprecated("No longer needed in new MM")
object MrFreeze {
@Deprecated(
"freeze is no longer needed in new MM",
replaceWith = ReplaceWith("this")
)
fun <T> freeze(objectToFreeze: T): T = objectToFreeze

@Deprecated(
"ensureNeverFrozen is no longer needed in new MM",
replaceWith = ReplaceWith("this")
)
@Suppress("UNUSED_PARAMETER")
fun ensureNeverFrozen(objectToProtect: Any) {}
}

expect fun <T> freeze(objectToFreeze: T): T
@Deprecated(
"ensureNeverFrozen is no longer needed in new MM",
replaceWith = ReplaceWith("this")
)
fun <T> freeze(objectToFreeze: T): T = objectToFreeze
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.mirego.trikot.foundation.concurrent.dispatchQueue

import com.mirego.trikot.foundation.concurrent.AtomicListReference
import com.mirego.trikot.foundation.concurrent.AtomicReference
import com.mirego.trikot.foundation.concurrent.freeze

/**
* Ensure dispatch blocks are executed sequentially on a dispatch queue.
Expand Down Expand Up @@ -47,7 +46,7 @@ open class SequentialDispatchQueue(override val dispatchQueue: TrikotDispatchQue
}

companion object {
private val NoDispatchBlock = freeze {}
private val SyncDispatchBlock = freeze {}
private val NoDispatchBlock = {}
private val SyncDispatchBlock = {}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,15 @@ package com.mirego.trikot.foundation.concurrent

import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNull

class AtomicReferenceTest {
private val atomicReference = AtomicReference<String?>(null)
private val expectedValue = "expectedValue"

@Test
fun canSetNewNullValueAndReadAfterFreezing() {
atomicReference.compareAndSet(null, expectedValue)
assertEquals(expectedValue, atomicReference.value)
MrFreeze.freeze(atomicReference)
atomicReference.compareAndSet(expectedValue, null)
assertNull(atomicReference.value)
}

@Test
fun canSwapValue() {
assertEquals(expectedValue, atomicReference.compareAndSwap(null, expectedValue))
assertEquals(null, atomicReference.compareAndSwap(expectedValue, null))
freeze(atomicReference)
assertEquals(expectedValue, atomicReference.compareAndSwap(null, expectedValue))
assertEquals(expectedValue, atomicReference.compareAndSwap(null, "other"))
assertEquals("other", atomicReference.compareAndSwap(expectedValue, "other"))
Expand Down
Loading

0 comments on commit ff9756c

Please sign in to comment.