Browse Source

Upgrade Kotlin to v2.0 (#3594)

* Bump Kotlin to v2.0

* Fix lots of issues due to the upgrade: lint issues, function signature incompatibilities, broken tests, etc.

---------

Co-authored-by: Benoit Marty <benoit@matrix.org>
pull/3642/head
Jorge Martin Espinosa 1 week ago committed by GitHub
parent
commit
366db4791b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      .idea/kotlinc.xml
  2. 2
      appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt
  3. 22
      build.gradle.kts
  4. 5
      features/cachecleaner/api/build.gradle.kts
  5. 7
      features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt
  6. 5
      features/enterprise/impl/build.gradle.kts
  7. 5
      features/ftue/test/build.gradle.kts
  8. 4
      features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt
  9. 4
      features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt
  10. 1
      features/licenses/impl/build.gradle.kts
  11. 2
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/WebViewMessageInterceptor.kt
  12. 5
      features/migration/impl/build.gradle.kts
  13. 1
      features/roomdirectory/impl/build.gradle.kts
  14. 1
      features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTest.kt
  15. 6
      gradle/libs.versions.toml
  16. 5
      libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/bottomsheet/CustomSheetState.kt
  17. 5
      libraries/mediapickers/api/build.gradle.kts
  18. 5
      libraries/mediapickers/test/build.gradle.kts
  19. 2
      libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/FakeUnifiedPushNewGatewayHandler.kt
  20. 4
      libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt
  21. 1
      plugins/build.gradle.kts
  22. 8
      plugins/src/main/kotlin/extension/CommonExtension.kt
  23. 3
      plugins/src/main/kotlin/io.element.android-compose-application.gradle.kts
  24. 3
      plugins/src/main/kotlin/io.element.android-compose-library.gradle.kts
  25. 27
      tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/LambdaRecorder.kt
  26. 2
      tools/detekt/detekt.yml
  27. 5
      tools/lint/lint.xml

2
.idea/kotlinc.xml

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="KotlinJpsPluginSettings"> <component name="KotlinJpsPluginSettings">
<option name="version" value="1.9.25" /> <option name="version" value="2.0.20" />
</component> </component>
</project> </project>

2
appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt

@ -478,7 +478,7 @@ class LoggedInPresenterTest {
distributors = listOf(Distributor("aDistributorValue1", "aDistributorName1")), distributors = listOf(Distributor("aDistributorValue1", "aDistributorName1")),
currentDistributor = { null }, currentDistributor = { null },
), ),
registerWithLambda: suspend (MatrixClient, PushProvider, Distributor) -> Result<Unit> = { _, _, _ -> registerWithLambda: (MatrixClient, PushProvider, Distributor) -> Result<Unit> = { _, _, _ ->
Result.success(Unit) Result.success(Unit)
}, },
selectPushProviderLambda: (MatrixClient, PushProvider) -> Unit = { _, _ -> lambdaError() }, selectPushProviderLambda: (MatrixClient, PushProvider) -> Unit = { _, _ -> lambdaError() },

22
build.gradle.kts

@ -18,6 +18,7 @@ plugins {
alias(libs.plugins.android.application) apply false alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false alias(libs.plugins.android.library) apply false
alias(libs.plugins.kotlin.android) apply false alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.compose.compiler) apply false
alias(libs.plugins.ksp) apply false alias(libs.plugins.ksp) apply false
alias(libs.plugins.anvil) apply false alias(libs.plugins.anvil) apply false
alias(libs.plugins.kotlin.jvm) apply false alias(libs.plugins.kotlin.jvm) apply false
@ -82,20 +83,15 @@ allprojects {
} }
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> { tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
compilerOptions {
// Warnings are potential errors, so stop ignoring them // Warnings are potential errors, so stop ignoring them
// This is disabled by default, but the CI will enforce this. // This is disabled by default, but the CI will enforce this.
// You can override by passing `-PallWarningsAsErrors=true` in the command line // You can override by passing `-PallWarningsAsErrors=true` in the command line
// Or add a line with "allWarningsAsErrors=true" in your ~/.gradle/gradle.properties file // Or add a line with "allWarningsAsErrors=true" in your ~/.gradle/gradle.properties file
kotlinOptions.allWarningsAsErrors = project.properties["allWarningsAsErrors"] == "true" allWarningsAsErrors = project.properties["allWarningsAsErrors"] == "true"
kotlinOptions {
/*
// Uncomment to suppress Compose Kotlin compiler compatibility warning // Uncomment to suppress Compose Kotlin compiler compatibility warning
freeCompilerArgs += listOf( // freeCompilerArgs.addAll(listOf("-P", "plugin:androidx.compose.compiler.plugins.kotlin:suppressKotlinVersionCompatibilityCheck=true"))
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:suppressKotlinVersionCompatibilityCheck=true"
)
*/
} }
} }
} }
@ -192,20 +188,24 @@ subprojects {
subprojects { subprojects {
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach { tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions { compilerOptions {
if (project.findProperty("composeCompilerReports") == "true") { if (project.findProperty("composeCompilerReports") == "true") {
freeCompilerArgs += listOf( freeCompilerArgs.addAll(
listOf(
"-P", "-P",
"plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" + "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" +
"${project.layout.buildDirectory.asFile.get().absolutePath}/compose_compiler" "${project.layout.buildDirectory.asFile.get().absolutePath}/compose_compiler"
) )
)
} }
if (project.findProperty("composeCompilerMetrics") == "true") { if (project.findProperty("composeCompilerMetrics") == "true") {
freeCompilerArgs += listOf( freeCompilerArgs.addAll(
listOf(
"-P", "-P",
"plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" + "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" +
"${project.layout.buildDirectory.asFile.get().absolutePath}/compose_compiler" "${project.layout.buildDirectory.asFile.get().absolutePath}/compose_compiler"
) )
)
} }
} }
} }

5
features/cachecleaner/api/build.gradle.kts

@ -1,3 +1,5 @@
import extension.setupAnvil
/* /*
* Copyright 2023, 2024 New Vector Ltd. * Copyright 2023, 2024 New Vector Ltd.
* *
@ -7,13 +9,14 @@
plugins { plugins {
id("io.element.android-library") id("io.element.android-library")
alias(libs.plugins.anvil)
} }
android { android {
namespace = "io.element.android.features.cachecleaner.api" namespace = "io.element.android.features.cachecleaner.api"
} }
setupAnvil()
dependencies { dependencies {
implementation(projects.libraries.architecture) implementation(projects.libraries.architecture)
implementation(libs.androidx.startup) implementation(libs.androidx.startup)

7
features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt

@ -109,12 +109,7 @@ class CallScreenPresenterTest {
assertThat(initialState.isInWidgetMode).isTrue() assertThat(initialState.isInWidgetMode).isTrue()
assertThat(widgetProvider.getWidgetCalled).isTrue() assertThat(widgetProvider.getWidgetCalled).isTrue()
assertThat(widgetDriver.runCalledCount).isEqualTo(1) assertThat(widgetDriver.runCalledCount).isEqualTo(1)
// Called several times because of the recomposition analyticsLambda.assertions().isCalledOnce().with(value(MobileScreen.ScreenName.RoomCall))
analyticsLambda.assertions().isCalledExactly(2)
.withSequence(
listOf(value(MobileScreen.ScreenName.RoomCall)),
listOf(value(MobileScreen.ScreenName.RoomCall))
)
sendCallNotificationIfNeededLambda.assertions().isCalledOnce() sendCallNotificationIfNeededLambda.assertions().isCalledOnce()
} }
} }

5
features/enterprise/impl/build.gradle.kts

@ -1,3 +1,5 @@
import extension.setupAnvil
/* /*
* Copyright 2024 New Vector Ltd. * Copyright 2024 New Vector Ltd.
* *
@ -6,13 +8,14 @@
*/ */
plugins { plugins {
id("io.element.android-library") id("io.element.android-library")
alias(libs.plugins.anvil)
} }
android { android {
namespace = "io.element.android.features.enterprise.impl" namespace = "io.element.android.features.enterprise.impl"
} }
setupAnvil()
dependencies { dependencies {
implementation(projects.anvilannotations) implementation(projects.anvilannotations)
api(projects.features.enterprise.api) api(projects.features.enterprise.api)

5
features/ftue/test/build.gradle.kts

@ -1,3 +1,5 @@
import extension.setupAnvil
/* /*
* Copyright 2024 New Vector Ltd. * Copyright 2024 New Vector Ltd.
* *
@ -7,7 +9,6 @@
plugins { plugins {
id("io.element.android-compose-library") id("io.element.android-compose-library")
alias(libs.plugins.anvil)
id("kotlin-parcelize") id("kotlin-parcelize")
} }
@ -15,6 +16,8 @@ android {
namespace = "io.element.android.features.ftue.test" namespace = "io.element.android.features.ftue.test"
} }
setupAnvil()
dependencies { dependencies {
implementation(projects.features.ftue.api) implementation(projects.features.ftue.api)
implementation(projects.tests.testutils) implementation(projects.tests.testutils)

4
features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt

@ -99,7 +99,7 @@ class AcceptDeclineInvitePresenterTest {
InternalAcceptDeclineInviteEvents.ConfirmDeclineInvite InternalAcceptDeclineInviteEvents.ConfirmDeclineInvite
) )
} }
skipItems(1) skipItems(2)
awaitItem().also { state -> awaitItem().also { state ->
assertThat(state.declineAction).isInstanceOf(AsyncAction.Failure::class.java) assertThat(state.declineAction).isInstanceOf(AsyncAction.Failure::class.java)
state.eventSink( state.eventSink(
@ -147,7 +147,7 @@ class AcceptDeclineInvitePresenterTest {
InternalAcceptDeclineInviteEvents.ConfirmDeclineInvite InternalAcceptDeclineInviteEvents.ConfirmDeclineInvite
) )
} }
skipItems(1) skipItems(2)
awaitItem().also { state -> awaitItem().also { state ->
assertThat(state.declineAction).isInstanceOf(AsyncAction.Success::class.java) assertThat(state.declineAction).isInstanceOf(AsyncAction.Success::class.java)
} }

4
features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt

@ -338,11 +338,15 @@ class JoinRoomPresenterTest {
awaitItem().also { state -> awaitItem().also { state ->
state.eventSink(JoinRoomEvents.KnockRoom) state.eventSink(JoinRoomEvents.KnockRoom)
} }
assertThat(awaitItem().knockAction).isEqualTo(AsyncAction.Loading)
awaitItem().also { state -> awaitItem().also { state ->
assertThat(state.knockAction).isEqualTo(AsyncAction.Success(Unit)) assertThat(state.knockAction).isEqualTo(AsyncAction.Success(Unit))
fakeKnockRoom.lambda = knockRoomFailure fakeKnockRoom.lambda = knockRoomFailure
state.eventSink(JoinRoomEvents.KnockRoom) state.eventSink(JoinRoomEvents.KnockRoom)
} }
assertThat(awaitItem().knockAction).isEqualTo(AsyncAction.Loading)
awaitItem().also { state -> awaitItem().also { state ->
assertThat(state.knockAction).isInstanceOf(AsyncAction.Failure::class.java) assertThat(state.knockAction).isInstanceOf(AsyncAction.Failure::class.java)
} }

1
features/licenses/impl/build.gradle.kts

@ -10,7 +10,6 @@ import extension.setupAnvil
plugins { plugins {
id("io.element.android-compose-library") id("io.element.android-compose-library")
id("kotlin-parcelize") id("kotlin-parcelize")
alias(libs.plugins.anvil)
alias(libs.plugins.kotlin.serialization) alias(libs.plugins.kotlin.serialization)
} }

2
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/WebViewMessageInterceptor.kt

@ -51,7 +51,7 @@ class WebViewMessageInterceptor(
} }
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean { override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
request ?: return super.shouldOverrideUrlLoading(view, request) request ?: return false
// Load the URL in a Chrome Custom Tab, and return true to cancel the load // Load the URL in a Chrome Custom Tab, and return true to cancel the load
onOpenExternalUrl(request.url.toString()) onOpenExternalUrl(request.url.toString())
return true return true

5
features/migration/impl/build.gradle.kts

@ -1,3 +1,5 @@
import extension.setupAnvil
/* /*
* Copyright 2024 New Vector Ltd. * Copyright 2024 New Vector Ltd.
* *
@ -7,13 +9,14 @@
plugins { plugins {
id("io.element.android-compose-library") id("io.element.android-compose-library")
alias(libs.plugins.anvil)
} }
android { android {
namespace = "io.element.android.features.migration.impl" namespace = "io.element.android.features.migration.impl"
} }
setupAnvil()
dependencies { dependencies {
implementation(projects.features.migration.api) implementation(projects.features.migration.api)
implementation(projects.libraries.architecture) implementation(projects.libraries.architecture)

1
features/roomdirectory/impl/build.gradle.kts

@ -9,7 +9,6 @@ import extension.setupAnvil
plugins { plugins {
id("io.element.android-compose-library") id("io.element.android-compose-library")
alias(libs.plugins.anvil)
id("kotlin-parcelize") id("kotlin-parcelize")
} }

1
features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTest.kt

@ -343,6 +343,7 @@ class VerifySelfSessionPresenterTest {
skipItems(1) skipItems(1)
val initialItem = awaitItem() val initialItem = awaitItem()
initialItem.eventSink(VerifySelfSessionViewEvents.SignOut) initialItem.eventSink(VerifySelfSessionViewEvents.SignOut)
assertThat(awaitItem().signOutAction.isLoading()).isTrue()
val finalItem = awaitItem() val finalItem = awaitItem()
assertThat(finalItem.signOutAction.isSuccess()).isTrue() assertThat(finalItem.signOutAction.isSuccess()).isTrue()
assertThat(finalItem.signOutAction.dataOrNull()).isEqualTo("aUrl") assertThat(finalItem.signOutAction.dataOrNull()).isEqualTo("aUrl")

6
gradle/libs.versions.toml

@ -4,9 +4,9 @@
[versions] [versions]
# Project # Project
android_gradle_plugin = "8.7.0" android_gradle_plugin = "8.7.0"
kotlin = "1.9.25" kotlin = "2.0.20"
kotlinpoetKsp = "1.18.1" kotlinpoetKsp = "1.18.1"
ksp = "1.9.25-1.0.20" ksp = "2.0.20-1.0.25"
firebaseAppDistribution = "5.0.0" firebaseAppDistribution = "5.0.0"
# AndroidX # AndroidX
@ -62,6 +62,7 @@ kover = "0.8.3"
[libraries] [libraries]
# Project # Project
android_gradle_plugin = { module = "com.android.tools.build:gradle", version.ref = "android_gradle_plugin" } android_gradle_plugin = { module = "com.android.tools.build:gradle", version.ref = "android_gradle_plugin" }
compose_compiler_plugin = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" }
# https://developer.android.com/studio/write/java8-support#library-desugaring-versions # https://developer.android.com/studio/write/java8-support#library-desugaring-versions
android_desugar = "com.android.tools:desugar_jdk_libs:2.1.2" android_desugar = "com.android.tools:desugar_jdk_libs:2.1.2"
anvil_gradle_plugin = { module = "dev.zacsweers.anvil:gradle-plugin", version.ref = "anvil" } anvil_gradle_plugin = { module = "dev.zacsweers.anvil:gradle-plugin", version.ref = "anvil" }
@ -238,3 +239,4 @@ firebaseAppDistribution = { id = "com.google.firebase.appdistribution", version.
knit = { id = "org.jetbrains.kotlinx.knit", version = "0.5.0" } knit = { id = "org.jetbrains.kotlinx.knit", version = "0.5.0" }
sonarqube = "org.sonarqube:5.1.0.4882" sonarqube = "org.sonarqube:5.1.0.4882"
licensee = "app.cash.licensee:1.11.0" licensee = "app.cash.licensee:1.11.0"
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }

5
libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/bottomsheet/CustomSheetState.kt

@ -7,7 +7,6 @@
package io.element.android.libraries.designsystem.theme.components.bottomsheet package io.element.android.libraries.designsystem.theme.components.bottomsheet
import androidx.compose.animation.core.DecayAnimationSpec
import androidx.compose.animation.core.SpringSpec import androidx.compose.animation.core.SpringSpec
import androidx.compose.animation.core.exponentialDecay import androidx.compose.animation.core.exponentialDecay
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
@ -296,13 +295,9 @@ internal object AnchoredDraggableDefaults {
/** /**
* The default animation used by [AnchoredDraggableState]. * The default animation used by [AnchoredDraggableState].
*/ */
@get:ExperimentalMaterial3Api
@Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
@ExperimentalMaterial3Api @ExperimentalMaterial3Api
val SnapAnimationSpec = SpringSpec<Float>() val SnapAnimationSpec = SpringSpec<Float>()
@get:ExperimentalMaterial3Api
@Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
@ExperimentalMaterial3Api @ExperimentalMaterial3Api
val DecayAnimationSpec = exponentialDecay<Float>() val DecayAnimationSpec = exponentialDecay<Float>()
} }

5
libraries/mediapickers/api/build.gradle.kts

@ -1,3 +1,5 @@
import extension.setupAnvil
/* /*
* Copyright 2023, 2024 New Vector Ltd. * Copyright 2023, 2024 New Vector Ltd.
* *
@ -7,9 +9,10 @@
plugins { plugins {
id("io.element.android-compose-library") id("io.element.android-compose-library")
alias(libs.plugins.anvil)
} }
setupAnvil()
android { android {
namespace = "io.element.android.libraries.mediapickers.api" namespace = "io.element.android.libraries.mediapickers.api"

5
libraries/mediapickers/test/build.gradle.kts

@ -1,3 +1,5 @@
import extension.setupAnvil
/* /*
* Copyright 2023, 2024 New Vector Ltd. * Copyright 2023, 2024 New Vector Ltd.
* *
@ -7,9 +9,10 @@
plugins { plugins {
id("io.element.android-compose-library") id("io.element.android-compose-library")
alias(libs.plugins.anvil)
} }
setupAnvil()
android { android {
namespace = "io.element.android.libraries.mediapickers.test" namespace = "io.element.android.libraries.mediapickers.test"

2
libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/FakeUnifiedPushNewGatewayHandler.kt

@ -10,7 +10,7 @@ package io.element.android.libraries.pushproviders.unifiedpush
import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaError
class FakeUnifiedPushNewGatewayHandler( class FakeUnifiedPushNewGatewayHandler(
private val handleResult: suspend (String, String, String) -> Result<Unit> = { _, _, _ -> lambdaError() }, private val handleResult: (String, String, String) -> Result<Unit> = { _, _, _ -> lambdaError() },
) : UnifiedPushNewGatewayHandler { ) : UnifiedPushNewGatewayHandler {
override suspend fun handle(endpoint: String, pushGateway: String, clientSecret: String): Result<Unit> { override suspend fun handle(endpoint: String, pushGateway: String, clientSecret: String): Result<Unit> {
return handleResult(endpoint, pushGateway, clientSecret) return handleResult(endpoint, pushGateway, clientSecret)

4
libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt

@ -9,6 +9,7 @@ package io.element.android.libraries.roomselect.impl
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -22,6 +23,7 @@ import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
import io.element.android.libraries.matrix.ui.model.SelectRoomInfo import io.element.android.libraries.matrix.ui.model.SelectRoomInfo
import io.element.android.libraries.roomselect.api.RoomSelectMode import io.element.android.libraries.roomselect.api.RoomSelectMode
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
@ -50,7 +52,7 @@ class RoomSelectPresenter @AssistedInject constructor(
val roomSummaryDetailsList by dataSource.roomInfoList.collectAsState(initial = persistentListOf()) val roomSummaryDetailsList by dataSource.roomInfoList.collectAsState(initial = persistentListOf())
val searchResults by remember { val searchResults by remember<State<SearchBarResultState<ImmutableList<SelectRoomInfo>>>> {
derivedStateOf { derivedStateOf {
when { when {
roomSummaryDetailsList.isNotEmpty() -> SearchBarResultState.Results(roomSummaryDetailsList.toImmutableList()) roomSummaryDetailsList.isNotEmpty() -> SearchBarResultState.Results(roomSummaryDetailsList.toImmutableList())

1
plugins/build.gradle.kts

@ -24,4 +24,5 @@ dependencies {
implementation(libs.autonomousapps.dependencyanalysis.plugin) implementation(libs.autonomousapps.dependencyanalysis.plugin)
implementation(libs.anvil.gradle.plugin) implementation(libs.anvil.gradle.plugin)
implementation(libs.ksp.gradle.plugin) implementation(libs.ksp.gradle.plugin)
implementation(libs.compose.compiler.plugin)
} }

8
plugins/src/main/kotlin/extension/CommonExtension.kt

@ -10,7 +10,6 @@ package extension
import Versions import Versions
import com.android.build.api.dsl.CommonExtension import com.android.build.api.dsl.CommonExtension
import isEnterpriseBuild import isEnterpriseBuild
import org.gradle.accessors.dm.LibrariesForLibs
import org.gradle.api.Project import org.gradle.api.Project
import java.io.File import java.io.File
@ -44,21 +43,18 @@ fun CommonExtension<*, *, *, *, *, *>.androidConfig(project: Project) {
} }
checkDependencies = false checkDependencies = false
abortOnError = true abortOnError = true
ignoreTestSources = true
ignoreTestFixturesSources = true ignoreTestFixturesSources = true
checkGeneratedSources = false checkGeneratedSources = false
} }
} }
fun CommonExtension<*, *, *, *, *, *>.composeConfig(libs: LibrariesForLibs) { fun CommonExtension<*, *, *, *, *, *>.composeConfig() {
buildFeatures { buildFeatures {
compose = true compose = true
} }
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.composecompiler.get()
}
packaging { packaging {
resources.excludes.apply { resources.excludes.apply {
add("META-INF/AL2.0") add("META-INF/AL2.0")

3
plugins/src/main/kotlin/io.element.android-compose-application.gradle.kts

@ -19,11 +19,12 @@ plugins {
id("com.android.application") id("com.android.application")
id("kotlin-android") id("kotlin-android")
id("com.autonomousapps.dependency-analysis") id("com.autonomousapps.dependency-analysis")
id("org.jetbrains.kotlin.plugin.compose")
} }
android { android {
androidConfig(project) androidConfig(project)
composeConfig(libs) composeConfig()
compileOptions { compileOptions {
isCoreLibraryDesugaringEnabled = true isCoreLibraryDesugaringEnabled = true
} }

3
plugins/src/main/kotlin/io.element.android-compose-library.gradle.kts

@ -19,11 +19,12 @@ plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("com.autonomousapps.dependency-analysis") id("com.autonomousapps.dependency-analysis")
id("org.jetbrains.kotlin.plugin.compose")
} }
android { android {
androidConfig(project) androidConfig(project)
composeConfig(libs) composeConfig()
compileOptions { compileOptions {
isCoreLibraryDesugaringEnabled = true isCoreLibraryDesugaringEnabled = true
} }

27
tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/LambdaRecorder.kt

@ -7,6 +7,8 @@
package io.element.android.tests.testutils.lambda package io.element.android.tests.testutils.lambda
import kotlinx.coroutines.runBlocking
/** /**
* A recorder that can be used to record the parameters of lambda invocation. * A recorder that can be used to record the parameters of lambda invocation.
*/ */
@ -93,21 +95,21 @@ inline fun <reified R> lambdaAnyRecorder(
class LambdaNoParamRecorder<out R>(ensureNeverCalled: Boolean, val block: () -> R) : LambdaRecorder(ensureNeverCalled), () -> R { class LambdaNoParamRecorder<out R>(ensureNeverCalled: Boolean, val block: () -> R) : LambdaRecorder(ensureNeverCalled), () -> R {
override fun invoke(): R { override fun invoke(): R {
onInvoke() onInvoke()
return block() return runBlocking { block() }
} }
} }
class LambdaOneParamRecorder<in T, out R>(ensureNeverCalled: Boolean, val block: (T) -> R) : LambdaRecorder(ensureNeverCalled), (T) -> R { class LambdaOneParamRecorder<in T, out R>(ensureNeverCalled: Boolean, val block: (T) -> R) : LambdaRecorder(ensureNeverCalled), (T) -> R {
override fun invoke(p: T): R { override fun invoke(p: T): R {
onInvoke(p) onInvoke(p)
return block(p) return runBlocking { block(p) }
} }
} }
class LambdaTwoParamsRecorder<in T1, in T2, out R>(ensureNeverCalled: Boolean, val block: (T1, T2) -> R) : LambdaRecorder(ensureNeverCalled), (T1, T2) -> R { class LambdaTwoParamsRecorder<in T1, in T2, out R>(ensureNeverCalled: Boolean, val block: (T1, T2) -> R) : LambdaRecorder(ensureNeverCalled), (T1, T2) -> R {
override fun invoke(p1: T1, p2: T2): R { override fun invoke(p1: T1, p2: T2): R {
onInvoke(p1, p2) onInvoke(p1, p2)
return block(p1, p2) return runBlocking { block(p1, p2) }
} }
} }
@ -116,7 +118,7 @@ class LambdaThreeParamsRecorder<in T1, in T2, in T3, out R>(ensureNeverCalled: B
), (T1, T2, T3) -> R { ), (T1, T2, T3) -> R {
override fun invoke(p1: T1, p2: T2, p3: T3): R { override fun invoke(p1: T1, p2: T2, p3: T3): R {
onInvoke(p1, p2, p3) onInvoke(p1, p2, p3)
return block(p1, p2, p3) return runBlocking { block(p1, p2, p3) }
} }
} }
@ -125,16 +127,19 @@ class LambdaFourParamsRecorder<in T1, in T2, in T3, in T4, out R>(ensureNeverCal
), (T1, T2, T3, T4) -> R { ), (T1, T2, T3, T4) -> R {
override fun invoke(p1: T1, p2: T2, p3: T3, p4: T4): R { override fun invoke(p1: T1, p2: T2, p3: T3, p4: T4): R {
onInvoke(p1, p2, p3, p4) onInvoke(p1, p2, p3, p4)
return block(p1, p2, p3, p4) return runBlocking { block(p1, p2, p3, p4) }
} }
} }
class LambdaFiveParamsRecorder<in T1, in T2, in T3, in T4, in T5, out R>(ensureNeverCalled: Boolean, val block: (T1, T2, T3, T4, T5) -> R) : LambdaRecorder( class LambdaFiveParamsRecorder<in T1, in T2, in T3, in T4, in T5, out R>(
ensureNeverCalled: Boolean,
val block: (T1, T2, T3, T4, T5) -> R,
) : LambdaRecorder(
ensureNeverCalled ensureNeverCalled
), (T1, T2, T3, T4, T5) -> R { ), (T1, T2, T3, T4, T5) -> R {
override fun invoke(p1: T1, p2: T2, p3: T3, p4: T4, p5: T5): R { override fun invoke(p1: T1, p2: T2, p3: T3, p4: T4, p5: T5): R {
onInvoke(p1, p2, p3, p4, p5) onInvoke(p1, p2, p3, p4, p5)
return block(p1, p2, p3, p4, p5) return runBlocking { block(p1, p2, p3, p4, p5) }
} }
} }
@ -144,7 +149,7 @@ class LambdaSixParamsRecorder<in T1, in T2, in T3, in T4, in T5, in T6, out R>(
) : LambdaRecorder(ensureNeverCalled), (T1, T2, T3, T4, T5, T6) -> R { ) : LambdaRecorder(ensureNeverCalled), (T1, T2, T3, T4, T5, T6) -> R {
override fun invoke(p1: T1, p2: T2, p3: T3, p4: T4, p5: T5, p6: T6): R { override fun invoke(p1: T1, p2: T2, p3: T3, p4: T4, p5: T5, p6: T6): R {
onInvoke(p1, p2, p3, p4, p5, p6) onInvoke(p1, p2, p3, p4, p5, p6)
return block(p1, p2, p3, p4, p5, p6) return runBlocking { block(p1, p2, p3, p4, p5, p6) }
} }
} }
@ -154,7 +159,7 @@ class LambdaSevenParamsRecorder<in T1, in T2, in T3, in T4, in T5, in T6, in T7,
) : LambdaRecorder(ensureNeverCalled), (T1, T2, T3, T4, T5, T6, T7) -> R { ) : LambdaRecorder(ensureNeverCalled), (T1, T2, T3, T4, T5, T6, T7) -> R {
override fun invoke(p1: T1, p2: T2, p3: T3, p4: T4, p5: T5, p6: T6, p7: T7): R { override fun invoke(p1: T1, p2: T2, p3: T3, p4: T4, p5: T5, p6: T6, p7: T7): R {
onInvoke(p1, p2, p3, p4, p5, p6, p7) onInvoke(p1, p2, p3, p4, p5, p6, p7)
return block(p1, p2, p3, p4, p5, p6, p7) return runBlocking { block(p1, p2, p3, p4, p5, p6, p7) }
} }
} }
@ -164,7 +169,7 @@ class LambdaEightParamsRecorder<in T1, in T2, in T3, in T4, in T5, in T6, in T7,
) : LambdaRecorder(ensureNeverCalled), (T1, T2, T3, T4, T5, T6, T7, T8) -> R { ) : LambdaRecorder(ensureNeverCalled), (T1, T2, T3, T4, T5, T6, T7, T8) -> R {
override fun invoke(p1: T1, p2: T2, p3: T3, p4: T4, p5: T5, p6: T6, p7: T7, p8: T8): R { override fun invoke(p1: T1, p2: T2, p3: T3, p4: T4, p5: T5, p6: T6, p7: T7, p8: T8): R {
onInvoke(p1, p2, p3, p4, p5, p6, p7, p8) onInvoke(p1, p2, p3, p4, p5, p6, p7, p8)
return block(p1, p2, p3, p4, p5, p6, p7, p8) return runBlocking { block(p1, p2, p3, p4, p5, p6, p7, p8) }
} }
} }
@ -174,7 +179,7 @@ class LambdaNineParamsRecorder<in T1, in T2, in T3, in T4, in T5, in T6, in T7,
) : LambdaRecorder(ensureNeverCalled), (T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R { ) : LambdaRecorder(ensureNeverCalled), (T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R {
override fun invoke(p1: T1, p2: T2, p3: T3, p4: T4, p5: T5, p6: T6, p7: T7, p8: T8, p9: T9): R { override fun invoke(p1: T1, p2: T2, p3: T3, p4: T4, p5: T5, p6: T6, p7: T7, p8: T8, p9: T9): R {
onInvoke(p1, p2, p3, p4, p5, p6, p7, p8, p9) onInvoke(p1, p2, p3, p4, p5, p6, p7, p8, p9)
return block(p1, p2, p3, p4, p5, p6, p7, p8, p9) return runBlocking { block(p1, p2, p3, p4, p5, p6, p7, p8, p9) }
} }
} }

2
tools/detekt/detekt.yml

@ -3,7 +3,7 @@
style: style:
AlsoCouldBeApply: AlsoCouldBeApply:
active: true active: true
OptionalWhenBraces: BracesOnWhenStatements:
active: false active: false
CascadingCallWrapping: CascadingCallWrapping:
active: true active: true

5
tools/lint/lint.xml

@ -117,4 +117,9 @@
<!-- Compose --> <!-- Compose -->
<issue id="UnnecessaryComposedModifier" severity="error" /> <issue id="UnnecessaryComposedModifier" severity="error" />
<!-- There seems to be an issue with this check, it flags lots of false positives. -->
<!-- See https://issuetracker.google.com/issues/349411310 -->
<!-- TODO: check again in the near future. -->
<issue id="ProduceStateDoesNotAssignValue" severity="ignore" />
</lint> </lint>

Loading…
Cancel
Save