diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 3e840cb5b..d9acd5f6b 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: # TODO Add 9, 10, 11, 12, and 13 after Kotlin 1.3.60 - java_version: [11] + java_version: [17] steps: - name: Checkout uses: actions/checkout@v2 diff --git a/android/build.gradle b/android/build.gradle.kts similarity index 90% rename from android/build.gradle rename to android/build.gradle.kts index e6ced7596..d3d6284a7 100644 --- a/android/build.gradle +++ b/android/build.gradle.kts @@ -17,7 +17,9 @@ plugins { alias(libs.plugins.android.application) apply false alias(libs.plugins.android.library) apply false alias(libs.plugins.kotlin.android) apply false + alias(libs.plugins.kotlin.symbol.processor) apply false alias(libs.plugins.kotlin.kapt) apply false + alias(libs.plugins.compose.compiler) apply false alias(libs.plugins.maven.publish) apply false alias(libs.plugins.errorprone) apply false alias(libs.plugins.nullaway) apply false diff --git a/android/conventions/build.gradle.kts b/android/conventions/build.gradle.kts index 7a67f3e60..25d7e7f20 100644 --- a/android/conventions/build.gradle.kts +++ b/android/conventions/build.gradle.kts @@ -15,7 +15,7 @@ */ plugins { `kotlin-dsl` - `kotlin-dsl-precompiled-script-plugins` + alias(libs.plugins.spotless) } repositories { diff --git a/android/conventions/src/main/kotlin/Extensions.kt b/android/conventions/src/main/kotlin/Extensions.kt index 16f216f77..66d31eabd 100644 --- a/android/conventions/src/main/kotlin/Extensions.kt +++ b/android/conventions/src/main/kotlin/Extensions.kt @@ -14,8 +14,6 @@ * limitations under the License. */ import com.android.build.gradle.AbstractAppExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.TestedExtension import com.android.build.gradle.api.BaseVariant import net.ltgt.gradle.errorprone.CheckSeverity import net.ltgt.gradle.errorprone.errorprone @@ -23,25 +21,18 @@ import net.ltgt.gradle.nullaway.nullaway fun AbstractAppExtension.errorprone() { applicationVariants.configureEach { errorprone() } - testErrorprone() -} - -fun LibraryExtension.errorprone() { - libraryVariants.configureEach { errorprone() } - testErrorprone() -} - -fun TestedExtension.testErrorprone() { testVariants.configureEach { errorprone() } unitTestVariants.configureEach { errorprone() } } -fun BaseVariant.errorprone() { +private fun BaseVariant.errorprone() { javaCompileProvider.configure { - options.errorprone.nullaway { - severity.set(CheckSeverity.ERROR) - annotatedPackages.add("com.uber") + options.errorprone { + nullaway { + severity.set(CheckSeverity.ERROR) + annotatedPackages.add("com.uber") + } + excludedPaths.set(".*/build/generated/.*") } - options.errorprone.excludedPaths.set(".*/build/generated/.*") } } diff --git a/android/conventions/src/main/kotlin/ribs.kotlin-android-application-conventions.gradle.kts b/android/conventions/src/main/kotlin/ribs.kotlin-android-application-conventions.gradle.kts index fbfd26dec..1e233127d 100644 --- a/android/conventions/src/main/kotlin/ribs.kotlin-android-application-conventions.gradle.kts +++ b/android/conventions/src/main/kotlin/ribs.kotlin-android-application-conventions.gradle.kts @@ -24,40 +24,36 @@ plugins { } kotlin { - jvmToolchain(11) + jvmToolchain(17) } android { - compileSdk = 33 - + compileSdk = 34 defaultConfig { minSdk = 21 - targetSdk = 28 + targetSdk = 34 versionCode = 1 versionName = "1.0" } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + buildFeatures { + buildConfig = true } - // No need for lint. Those are just tutorials. lint { abortOnError = false quiet = true } - buildTypes { debug { matchingFallbacks.add("release") } } - - sourceSets { - getByName("main").java.srcDir("src/main/kotlin") - getByName("test").java.srcDir("src/test/kotlin") - getByName("androidTest").java.srcDir("src/androidTest/kotlin") + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + kotlinOptions { + jvmTarget = "11" } } @@ -71,9 +67,6 @@ androidComponents { tasks.withType().configureEach { compilerOptions { - freeCompilerArgs.addAll( - "-Xjvm-default=all", - "-opt-in=kotlin.RequiresOptIn", - ) + freeCompilerArgs.add("-Xjvm-default=all") } } diff --git a/android/conventions/src/main/kotlin/ribs.kotlin-android-library-conventions.gradle.kts b/android/conventions/src/main/kotlin/ribs.kotlin-android-library-conventions.gradle.kts index b49beb84e..404f77809 100644 --- a/android/conventions/src/main/kotlin/ribs.kotlin-android-library-conventions.gradle.kts +++ b/android/conventions/src/main/kotlin/ribs.kotlin-android-library-conventions.gradle.kts @@ -24,30 +24,28 @@ plugins { } kotlin { - jvmToolchain(8) + jvmToolchain(17) + explicitApi() } android { - compileSdk = 33 + compileSdk = 34 defaultConfig { minSdk = 21 } - // This can be removed on AGP 8.1.0-alpha09 onwards, since we are using JVM Toolchain compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } - buildFeatures { - buildConfig = false + kotlinOptions { + jvmTarget = "11" } - sourceSets { - getByName("main").java.srcDir("src/main/kotlin") - getByName("test").java.srcDir("src/test/kotlin") - getByName("androidTest").java.srcDir("src/androidTest/kotlin") + buildFeatures { + buildConfig = false } testOptions { @@ -67,10 +65,6 @@ androidComponents { tasks.withType().configureEach { compilerOptions { - freeCompilerArgs.addAll( - "-Xexplicit-api=warning", - "-Xjvm-default=all", - "-opt-in=kotlin.RequiresOptIn", - ) + freeCompilerArgs.add("-Xjvm-default=all") } } diff --git a/android/conventions/src/main/kotlin/ribs.kotlin-library-conventions.gradle.kts b/android/conventions/src/main/kotlin/ribs.kotlin-library-conventions.gradle.kts index 0a138b440..7d6cfeef1 100644 --- a/android/conventions/src/main/kotlin/ribs.kotlin-library-conventions.gradle.kts +++ b/android/conventions/src/main/kotlin/ribs.kotlin-library-conventions.gradle.kts @@ -13,18 +13,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.dsl.jvm.JvmTargetValidationMode +import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile + plugins { kotlin("jvm") id("ribs.spotless-convention") } -kotlin { - jvmToolchain(8) - explicitApi() +java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } -tasks.named("compileKotlin", org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask::class.java) { +kotlin { + jvmToolchain(17) + explicitApi() compilerOptions { freeCompilerArgs.add("-Xjvm-default=all") + jvmTarget = JvmTarget.JVM_11 } } + +tasks.withType().configureEach { + jvmTargetValidationMode = JvmTargetValidationMode.WARNING +} diff --git a/android/demos/compose/build.gradle b/android/demos/compose/build.gradle index b7cf81a2e..3a2e74e83 100644 --- a/android/demos/compose/build.gradle +++ b/android/demos/compose/build.gradle @@ -1,6 +1,7 @@ plugins { id("ribs.kotlin-android-application-conventions") - alias(libs.plugins.kotlin.kapt) + alias(libs.plugins.compose.compiler) + alias(libs.plugins.kotlin.symbol.processor) } android { @@ -12,13 +13,14 @@ android { buildFeatures { compose true } - composeOptions { - kotlinCompilerExtensionVersion libs.versions.compose.compiler.get() - } } dependencies { - kapt(libs.motif.compiler) + def composeBom = platform(libs.compose.bom) + implementation(composeBom) + androidTestImplementation(composeBom) + + ksp(libs.motif.compiler) implementation(project(":libraries:rib-android")) implementation(project(":libraries:rib-android-compose")) implementation(project(":libraries:rib-coroutines")) diff --git a/android/demos/memory-leaks/src/main/java/com/uber/rib/SampleApplication.java b/android/demos/memory-leaks/src/main/java/com/uber/rib/SampleApplication.java index 712589905..a8437abb6 100644 --- a/android/demos/memory-leaks/src/main/java/com/uber/rib/SampleApplication.java +++ b/android/demos/memory-leaks/src/main/java/com/uber/rib/SampleApplication.java @@ -16,14 +16,14 @@ package com.uber.rib; import android.app.Application; -import com.squareup.leakcanary.LeakCanary; -import com.squareup.leakcanary.RefWatcher; import com.uber.rib.core.ActivityDelegate; import com.uber.rib.core.HasActivityDelegate; import com.uber.rib.core.RibRefWatcher; -import java.util.concurrent.TimeUnit; +import leakcanary.AppWatcher; +import org.jetbrains.annotations.NotNull; -public class SampleApplication extends Application implements HasActivityDelegate { +public class SampleApplication extends Application + implements HasActivityDelegate, RibRefWatcher.ReferenceWatcher { private SampleActivityDelegate activityDelegate; @@ -31,32 +31,24 @@ public class SampleApplication extends Application implements HasActivityDelegat public void onCreate() { activityDelegate = new SampleActivityDelegate(); super.onCreate(); - if (!LeakCanary.isInAnalyzerProcess(this)) { - // This process is dedicated to LeakCanary for heap analysis. You should not init your app in - // this process. - installLeakCanary(); - } + installLeakCanary(); } /** Install leak canary for both activities and RIBs. */ private void installLeakCanary() { - final RefWatcher refWatcher = - LeakCanary.refWatcher(this).watchDelay(2, TimeUnit.SECONDS).buildAndInstall(); - LeakCanary.install(this); - RibRefWatcher.getInstance() - .setReferenceWatcher( - new RibRefWatcher.ReferenceWatcher() { - @Override - public void watch(Object object) { - refWatcher.watch(object); - } + final RibRefWatcher watcher = RibRefWatcher.getInstance(); + watcher.setReferenceWatcher(this); + watcher.enableLeakCanary(); + } - @Override - public void logBreadcrumb(String eventType, String data, String parent) { - // Ignore for now. Useful for collecting production analytics. - } - }); - RibRefWatcher.getInstance().enableLeakCanary(); + @Override + public void watch(Object objectToWatch) { + AppWatcher.INSTANCE.getObjectWatcher().watch(objectToWatch); + } + + @Override + public void logBreadcrumb(String eventType, @NotNull String data, @NotNull String parent) { + // Ignore for now. Useful for collecting production analytics. } @Override diff --git a/android/demos/rib-workers/build.gradle b/android/demos/rib-workers/build.gradle index 2dbce2cb0..a9c18779e 100644 --- a/android/demos/rib-workers/build.gradle +++ b/android/demos/rib-workers/build.gradle @@ -1,5 +1,7 @@ plugins { id("ribs.kotlin-android-application-errorprone-conventions") + alias(libs.plugins.compose.compiler) + alias(libs.plugins.kotlin.symbol.processor) } android { @@ -11,13 +13,14 @@ android { buildFeatures { compose true } - composeOptions { - kotlinCompilerExtensionVersion libs.versions.compose.compiler.get() - } } dependencies { - kapt(libs.motif.compiler) + def composeBom = platform(libs.compose.bom) + implementation(composeBom) + androidTestImplementation(composeBom) + + ksp(libs.motif.compiler) implementation(project(":libraries:rib-android")) implementation(project(":libraries:rib-android-compose")) implementation(project(":libraries:rib-coroutines")) diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index cf4461f08..364b55317 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -1,42 +1,43 @@ [versions] android-api = "4.1.1.4" -androidx-activity = "1.7.0" -androidx-annotations = "1.1.0" -androidx-appcompat = "1.3.0" -androidx-lifecycle = "2.6.1" -autocommon = "0.8" +androidx-activity = "1.9.2" +androidx-annotations = "1.8.2" +androidx-appcompat = "1.7.0" +androidx-lifecycle = "2.8.3" +autocommon = "0.10" autodispose = "1.4.0" autoservice = "1.0-rc4" -autovalue = "1.7" -checkerqual = "2.5.1" -compose-compiler = "1.4.6" -compose-libraries = "1.4.0" -compose-navigation = "2.4.0-alpha03" -coroutines = "1.7.3" -dagger = "2.43.2" -errorprone = "2.3.3" +autoservice-ksp = "1.2.0" +autovalue = "1.8.1" +checkerqual = "3.42.0" +compose-bom = "2024.09.00" +compose-navigation = "2.8.2" +coroutines = "1.8.0" +dagger = "2.48" +errorprone = "2.23.0" errorprone-javac = "9+181-r4173-1" flipper = "0.93.0" google-java-format = "1.24.0" -gradle-android-plugin = "7.4.2" -gradle-errorprone-plugin = "1.3.0" -gradle-intellij-plugin = "1.15.0" -gradle-maven-publish-plugin = "0.25.2" -gradle-nullaway-plugin = "1.0.2" +gradle-android-plugin = "8.7.0" +gradle-errorprone-plugin = "4.0.1" +gradle-intellij-plugin = "1.17.4" +gradle-maven-publish-plugin = "0.29.0" +gradle-nullaway-plugin = "1.3.0" gradle-spotless-plugin = "6.25.0" -gson = "2.8.7" -guava-android = "27.1-android" -guava-jre = "27.1-jre" +gson = "2.10.1" +guava-android = "31.0.1-android" +guava-jre = "31.0.1-jre" intellij = "2023.2" -javapoet = "1.11.1" +javapoet = "1.13.0" jsr250 = "1.0" -kotlin = "1.8.20" +kotlin = "2.0.0" +ksp = "2.0.0-1.0.24" ktfmt = "0.52" ktlint = "1.3.1" -leakcanary = "1.5.4" -motif = "0.3.4" +leakcanary = "2.14" +motif = "0.4.0-alpha05" percent = "1.0.0" -reactivestreams = "1.0.0" +reactivestreams = "1.0.3" rxandroid2 = "2.1.1" rxbinding = "2.0.0" rxjava2 = "2.2.8" @@ -57,18 +58,20 @@ autodispose-errorprone = { group = "com.uber.autodispose", name = "autodispose-e autodispose-library = { group = "com.uber.autodispose", name = "autodispose", version.ref = "autodispose" } autodispose-lifecycle = { group = "com.uber.autodispose", name = "autodispose-lifecycle", version.ref = "autodispose" } autoservice = { group = "com.google.auto.service", name = "auto-service", version.ref = "autoservice" } +autoservice-ksp = { group = "dev.zacsweers.autoservice", name = "auto-service-ksp", version.ref = "autoservice-ksp" } autovalue-annotations = { group = "com.google.auto.value", name = "auto-value-annotations", version.ref = "autovalue" } autovalue-library = { group = "com.google.auto.value", name = "auto-value", version.ref = "autovalue" } checkerqual = { group = "org.checkerframework", name = "checker-qual", version.ref = "checkerqual" } -compose-animation = { group = "androidx.compose.animation", name = "animation", version.ref = "compose-libraries" } -compose-compiler = { group = "androidx.compose.compiler", name = "compiler", version.ref = "compose-libraries" } -compose-foundation = { group = "androidx.compose.foundation", name = "foundation", version.ref = "compose-libraries" } -compose-material = { group = "androidx.compose.material", name = "material", version.ref = "compose-libraries" } +compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" } +compose-animation = { group = "androidx.compose.animation", name = "animation" } +compose-compiler = { group = "androidx.compose.compiler", name = "compiler" } +compose-foundation = { group = "androidx.compose.foundation", name = "foundation" } +compose-material = { group = "androidx.compose.material", name = "material" } +compose-runtime-rx2 = { group = "androidx.compose.runtime", name = "runtime-rxjava2" } +compose-ui = { group = "androidx.compose.ui", name = "ui" } +compose-uitooling = { group = "androidx.compose.ui", name = "ui-tooling" } +compose-viewmodel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose" } compose-navigation = { group = "androidx.navigation", name = "navigation-compose", version.ref = "compose-navigation" } -compose-runtime-rx2 = { group = "androidx.compose.runtime", name = "runtime-rxjava2", version.ref = "compose-libraries" } -compose-ui = { group = "androidx.compose.ui", name = "ui", version.ref = "compose-libraries" } -compose-uitooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "compose-libraries" } -compose-viewmodel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "compose-libraries" } coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "coroutines" } coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "coroutines" } coroutines-rx2 = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-rx2", version.ref = "coroutines" } @@ -89,7 +92,6 @@ guava-jre = { group = "com.google.guava", name = "guava", version.ref = "guava-j javapoet = { group = "com.squareup", name = "javapoet", version.ref = "javapoet" } javax-inject = { group = "javax.inject", name = "javax.inject", version = "1" } jsr250 = { group = "javax.annotation", name = "jsr250-api", version.ref = "jsr250" } -kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" } leakcanary = { group = "com.squareup.leakcanary", name = "leakcanary-android", version.ref = "leakcanary" } lifecycle-runtime = { group = "androidx.lifecycle", name = "lifecycle-runtime", version.ref = "androidx-lifecycle" } motif-compiler = { group = "com.uber.motif", name = "motif-compiler", version.ref = "motif" } @@ -111,6 +113,8 @@ android-library = { id = "com.android.library", version.ref = "gradle-android-pl errorprone = { id = "net.ltgt.errorprone", version.ref = "gradle-errorprone-plugin" } intellij = { id = "org.jetbrains.intellij", version.ref = "gradle-intellij-plugin" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +kotlin-symbol-processor = { id = "com.google.devtools.ksp", version.ref = "ksp" } +compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } maven-publish = { id = "com.vanniktech.maven.publish", version.ref = "gradle-maven-publish-plugin" } nullaway = { id = "net.ltgt.nullaway", version.ref = "gradle-nullaway-plugin" } diff --git a/android/gradle/test-libs.versions.toml b/android/gradle/test-libs.versions.toml index c0efa0aa8..5e1ba7484 100644 --- a/android/gradle/test-libs.versions.toml +++ b/android/gradle/test-libs.versions.toml @@ -1,10 +1,10 @@ [versions] -compile-testing = "0.17" -coroutines = "1.7.3" -junit = "4.12" +compile-testing = "0.21.0" +coroutines = "1.8.0" +junit = "4.13.2" mockito-kotlin = "4.0.0" -robolectric = "4.4" -truth = "0.43" +robolectric = "4.13" +truth = "1.4.4" [libraries] compile-testing = { group = "com.google.testing.compile", name = "compile-testing", version.ref = "compile-testing" } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 2b6241765..975ee1319 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip diff --git a/android/libraries/rib-android-compose/build.gradle b/android/libraries/rib-android-compose/build.gradle index c444ff3af..d59b56e08 100644 --- a/android/libraries/rib-android-compose/build.gradle +++ b/android/libraries/rib-android-compose/build.gradle @@ -16,6 +16,7 @@ plugins { id("ribs.kotlin-android-library-conventions") alias(libs.plugins.maven.publish) + alias(libs.plugins.compose.compiler) } android { @@ -24,13 +25,13 @@ android { buildFeatures { compose true } - - composeOptions { - kotlinCompilerExtensionVersion libs.versions.compose.compiler.get() - } } dependencies { + def composeBom = platform(libs.compose.bom) + implementation(composeBom) + androidTestImplementation(composeBom) + api(project(":libraries:rib-android")) implementation(libs.compose.foundation) implementation(libs.compose.ui) diff --git a/android/libraries/rib-android-core/build.gradle b/android/libraries/rib-android-core/build.gradle index 9b4758341..d9058ff0e 100644 --- a/android/libraries/rib-android-core/build.gradle +++ b/android/libraries/rib-android-core/build.gradle @@ -27,6 +27,7 @@ dependencies { implementation(libs.javax.inject) implementation(libs.annotation) implementation(libs.appcompat) + implementation(libs.lifecycle.runtime) testImplementation(libs.appcompat) testImplementation(testLibs.robolectric) } diff --git a/android/libraries/rib-android-core/src/main/kotlin/com/uber/rib/core/CoreAppCompatActivity.kt b/android/libraries/rib-android-core/src/main/kotlin/com/uber/rib/core/CoreAppCompatActivity.kt index 5a5641cc3..88bacab73 100644 --- a/android/libraries/rib-android-core/src/main/kotlin/com/uber/rib/core/CoreAppCompatActivity.kt +++ b/android/libraries/rib-android-core/src/main/kotlin/com/uber/rib/core/CoreAppCompatActivity.kt @@ -20,9 +20,9 @@ import android.os.Bundle import androidx.annotation.CallSuper import androidx.annotation.IntRange import androidx.appcompat.app.AppCompatActivity -import androidx.lifecycle.ViewTreeLifecycleOwner -import androidx.lifecycle.ViewTreeViewModelStoreOwner -import androidx.savedstate.ViewTreeSavedStateRegistryOwner +import androidx.lifecycle.setViewTreeLifecycleOwner +import androidx.lifecycle.setViewTreeViewModelStoreOwner +import androidx.savedstate.setViewTreeSavedStateRegistryOwner /** Core Support v7 AppCompat Activity. */ public abstract class CoreAppCompatActivity : AppCompatActivity() { @@ -93,8 +93,8 @@ public abstract class CoreAppCompatActivity : AppCompatActivity() { private fun initViewTreeOwners() { // Set the view tree owners before setting the content view so that the inflation process // and attach listeners will see them already present - ViewTreeLifecycleOwner.set(window.decorView, this) - ViewTreeViewModelStoreOwner.set(window.decorView, this) - ViewTreeSavedStateRegistryOwner.set(window.decorView, this) + window.decorView.setViewTreeLifecycleOwner(this) + window.decorView.setViewTreeViewModelStoreOwner(this) + window.decorView.setViewTreeSavedStateRegistryOwner(this) } } diff --git a/android/libraries/rib-android/src/test/kotlin/com/uber/rib/core/RibActivityTest.kt b/android/libraries/rib-android/src/test/kotlin/com/uber/rib/core/RibActivityTest.kt index 47a138f09..8c04f36fe 100644 --- a/android/libraries/rib-android/src/test/kotlin/com/uber/rib/core/RibActivityTest.kt +++ b/android/libraries/rib-android/src/test/kotlin/com/uber/rib/core/RibActivityTest.kt @@ -20,13 +20,13 @@ import android.content.Intent import android.view.View import android.view.ViewGroup import android.widget.FrameLayout +import androidx.appcompat.R import androidx.lifecycle.findViewTreeLifecycleOwner import androidx.lifecycle.findViewTreeViewModelStoreOwner import androidx.savedstate.findViewTreeSavedStateRegistryOwner import com.google.common.truth.Truth.assertThat import com.uber.autodispose.AutoDispose import com.uber.autodispose.lifecycle.LifecycleEndedException -import com.uber.rib.android.R import com.uber.rib.core.lifecycle.ActivityCallbackEvent import com.uber.rib.core.lifecycle.ActivityCallbackEvent.Companion.create import com.uber.rib.core.lifecycle.ActivityCallbackEvent.SaveInstanceState diff --git a/android/libraries/rib-android/src/test/kotlin/com/uber/rib/core/ViewBuilderTest.kt b/android/libraries/rib-android/src/test/kotlin/com/uber/rib/core/ViewBuilderTest.kt index eaf28eb89..a5ae527c4 100644 --- a/android/libraries/rib-android/src/test/kotlin/com/uber/rib/core/ViewBuilderTest.kt +++ b/android/libraries/rib-android/src/test/kotlin/com/uber/rib/core/ViewBuilderTest.kt @@ -21,8 +21,8 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.FrameLayout +import androidx.appcompat.R import com.google.common.truth.Truth -import com.uber.rib.android.R import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.mock diff --git a/android/libraries/rib-base/build.gradle b/android/libraries/rib-base/build.gradle.kts similarity index 92% rename from android/libraries/rib-base/build.gradle rename to android/libraries/rib-base/build.gradle.kts index fa6cbfaa7..ecad36ad1 100644 --- a/android/libraries/rib-base/build.gradle +++ b/android/libraries/rib-base/build.gradle.kts @@ -15,15 +15,15 @@ */ plugins { id("ribs.kotlin-library-conventions") - alias(libs.plugins.kotlin.kapt) + alias(libs.plugins.kotlin.symbol.processor) alias(libs.plugins.maven.publish) } dependencies { // RIBs themselves don't need to use dagger. But the base library does use dagger // in order to invert a dependency. With a bit of work this could be removed. - kapt(libs.dagger.compiler) - kapt(libs.android.api) + ksp(libs.dagger.compiler) + ksp(libs.android.api) implementation(libs.guava.android) implementation(libs.reactivestreams) @@ -35,7 +35,6 @@ dependencies { implementation(libs.autodispose.coroutines) implementation(libs.coroutines.rx2) - api(libs.kotlin.stdlib) api(libs.coroutines.core) api(project(":libraries:rib-coroutines")) @@ -50,6 +49,6 @@ dependencies { testImplementation(testLibs.mockito.kotlin) testImplementation(testLibs.truth) testImplementation(project(":libraries:rib-test")) { - transitive = false + isTransitive = false } } diff --git a/android/libraries/rib-base/src/main/kotlin/com/uber/rib/core/RibCoroutineWorker.kt b/android/libraries/rib-base/src/main/kotlin/com/uber/rib/core/RibCoroutineWorker.kt index 0848f4b48..785a053bc 100644 --- a/android/libraries/rib-base/src/main/kotlin/com/uber/rib/core/RibCoroutineWorker.kt +++ b/android/libraries/rib-base/src/main/kotlin/com/uber/rib/core/RibCoroutineWorker.kt @@ -113,11 +113,10 @@ public fun CoroutineScope.bind( var bindJob: CompletableJob? = null // A job that completes once worker's onStart completes val unbindJob = launch(context, CoroutineStart.UNDISPATCHED) { - val job = createBindingJob() - bindJob = job + bindJob = createBindingJob() // launch again -- this time, we will dispatch if installed dispatcher // tell us to (CoroutineDispatcher.isDispatchNeeded()). - launch { bindAndAwaitCancellation(worker, job) } + launch { bindAndAwaitCancellation(worker, bindJob) } } // !! is safe here -- outer coroutine was started undispatched. return BindWorkerHandleImpl(bindJob!!, unbindJob) diff --git a/android/libraries/rib-compiler-app/build.gradle b/android/libraries/rib-compiler-app/build.gradle.kts similarity index 83% rename from android/libraries/rib-compiler-app/build.gradle rename to android/libraries/rib-compiler-app/build.gradle.kts index b7fc1d7a0..eeccdaae2 100644 --- a/android/libraries/rib-compiler-app/build.gradle +++ b/android/libraries/rib-compiler-app/build.gradle.kts @@ -34,8 +34,12 @@ dependencies { } // https://code.google.com/p/android/issues/detail?id=64887 -task copyTestResources(type: Copy) { - from "${projectDir}/src/test/resources" - into "${buildDir}/classes/test" +tasks { + register("copyTestResources") { + from("${projectDir}/src/test/resources") + into("${buildDir}/classes/test") + } + processTestResources { + dependsOn("copyTestResources") + } } -processTestResources.dependsOn copyTestResources diff --git a/android/libraries/rib-compiler-test/build.gradle b/android/libraries/rib-compiler-test/build.gradle.kts similarity index 60% rename from android/libraries/rib-compiler-test/build.gradle rename to android/libraries/rib-compiler-test/build.gradle.kts index 23163f44b..0dd44e317 100644 --- a/android/libraries/rib-compiler-test/build.gradle +++ b/android/libraries/rib-compiler-test/build.gradle.kts @@ -1,5 +1,3 @@ -import org.gradle.internal.jvm.Jvm - /* * Copyright (C) 2017. Uber Technologies * @@ -18,7 +16,7 @@ import org.gradle.internal.jvm.Jvm plugins { id("ribs.kotlin-library-conventions") - alias(libs.plugins.kotlin.kapt) + alias(libs.plugins.kotlin.symbol.processor) alias(libs.plugins.maven.publish) } @@ -29,16 +27,26 @@ dependencies { compileOnly(libs.annotation) compileOnly(libs.autoservice) compileOnly(libs.android.api) - kapt(libs.autoservice) + ksp(libs.autoservice.ksp) testImplementation(libs.annotation) testImplementation(testLibs.compile.testing) - testImplementation files("libs/tools.jar") + testImplementation(files("libs/tools.jar")) } // https://code.google.com/p/android/issues/detail?id=64887 -task copyTestResources(type: Copy) { - from "${projectDir}/src/test/resources" - into "${buildDir}/classes/test" +tasks { + register("copyTestResources") { + from("${projectDir}/src/test/resources") + into("${buildDir}/classes/test") + } + processTestResources { + dependsOn("copyTestResources") + } + test { + // See: https://github.com/google/compile-testing/issues/222 + jvmArgs("--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED") + jvmArgs("--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED") + jvmArgs("--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED") + } } -processTestResources.dependsOn copyTestResources diff --git a/android/libraries/rib-coroutines-test/src/main/kotlin/com/uber/rib/core/TestRibDispatchers.kt b/android/libraries/rib-coroutines-test/src/main/kotlin/com/uber/rib/core/TestRibDispatchers.kt index 4e52f80b8..02b6fb11f 100644 --- a/android/libraries/rib-coroutines-test/src/main/kotlin/com/uber/rib/core/TestRibDispatchers.kt +++ b/android/libraries/rib-coroutines-test/src/main/kotlin/com/uber/rib/core/TestRibDispatchers.kt @@ -16,6 +16,7 @@ package com.uber.rib.core import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.MainCoroutineDispatcher import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestCoroutineScheduler @@ -24,6 +25,7 @@ import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.setMain +@OptIn(ExperimentalCoroutinesApi::class) public data class TestRibDispatchers( /** * [TestCoroutineScheduler] to be used by all other [TestDispatcher] when using the default diff --git a/android/libraries/rib-coroutines/src/main/kotlin/com/uber/rib/core/RibDispatchers.kt b/android/libraries/rib-coroutines/src/main/kotlin/com/uber/rib/core/RibDispatchers.kt index 740c4a7ba..f1858c66a 100644 --- a/android/libraries/rib-coroutines/src/main/kotlin/com/uber/rib/core/RibDispatchers.kt +++ b/android/libraries/rib-coroutines/src/main/kotlin/com/uber/rib/core/RibDispatchers.kt @@ -17,7 +17,6 @@ package com.uber.rib.core import kotlin.coroutines.ContinuationInterceptor import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.IO_PARALLELISM_PROPERTY_NAME @@ -53,8 +52,8 @@ public interface RibDispatchersProvider { * The Default [CoroutineDispatcher] that behaves as [Dispatchers.Default]. * * The default [CoroutineDispatcher] that is used by all standard builders like - * [launch][CoroutineScope.launch], [async][CoroutineScope.async], etc if no dispatcher nor any - * other [ContinuationInterceptor] is specified in their context. + * [launch][kotlinx.coroutines.launch], [async][kotlinx.coroutines.async], etc if no dispatcher + * nor any other [ContinuationInterceptor] is specified in their context. * * It is backed by a shared pool of threads on JVM. By default, the maximal level of parallelism * used by this dispatcher is equal to the number of CPU cores, but is at least two. Level of diff --git a/android/libraries/rib-debug-utils/build.gradle.kts b/android/libraries/rib-debug-utils/build.gradle.kts index 4e1668147..dafe03514 100644 --- a/android/libraries/rib-debug-utils/build.gradle.kts +++ b/android/libraries/rib-debug-utils/build.gradle.kts @@ -27,8 +27,6 @@ kotlin { } } } - explicitApi() - jvmToolchain(8) } dependencies { diff --git a/android/libraries/rib-router-navigator/src/main/kotlin/com/uber/rib/core/RouterNavigatorFactory.kt b/android/libraries/rib-router-navigator/src/main/kotlin/com/uber/rib/core/RouterNavigatorFactory.kt index 57afef5e8..51df71894 100644 --- a/android/libraries/rib-router-navigator/src/main/kotlin/com/uber/rib/core/RouterNavigatorFactory.kt +++ b/android/libraries/rib-router-navigator/src/main/kotlin/com/uber/rib/core/RouterNavigatorFactory.kt @@ -32,7 +32,7 @@ public class RouterNavigatorFactory(private val creationStrategy: Strategy?) { * @param [StateT] type for the [RouterNavigator] * @return A new [RouterNavigator] */ - public open fun create( + public fun create( hostRouter: Router<*> ): RouterNavigator = creationStrategy?.create(hostRouter) ?: StackRouterNavigator(hostRouter) diff --git a/android/libraries/rib-router-navigator/src/test/kotlin/com/uber/rib/core/RouterAndStateTest.kt b/android/libraries/rib-router-navigator/src/test/kotlin/com/uber/rib/core/RouterAndStateTest.kt index 38246b0e5..b0b0246f9 100644 --- a/android/libraries/rib-router-navigator/src/test/kotlin/com/uber/rib/core/RouterAndStateTest.kt +++ b/android/libraries/rib-router-navigator/src/test/kotlin/com/uber/rib/core/RouterAndStateTest.kt @@ -52,7 +52,7 @@ class RouterAndStateTest { routerAndState.onPostDetachFromHost(mock(), false) val router2 = routerAndState.router - assertThat(router1).isNotSameAs(router2) + assertThat(router1).isNotSameInstanceAs(router2) } @Test @@ -66,7 +66,7 @@ class RouterAndStateTest { routerAndState.onPostDetachFromHost(mock(), false) val router2 = routerAndState.router - assertThat(router1).isSameAs(router2) + assertThat(router1).isSameInstanceAs(router2) } @Test @@ -80,7 +80,7 @@ class RouterAndStateTest { routerAndState.onPostDetachFromHost(mock(), false) val router2 = routerAndState.router - assertThat(router1).isSameAs(router2) + assertThat(router1).isSameInstanceAs(router2) } @Test @@ -94,7 +94,7 @@ class RouterAndStateTest { routerAndState.onPostDetachFromHost(mock(), false) val router2 = routerAndState.router - assertThat(router1).isSameAs(router2) + assertThat(router1).isSameInstanceAs(router2) } @Test diff --git a/android/libraries/rib-test/build.gradle.kts b/android/libraries/rib-test/build.gradle.kts index e7a22216f..e01b84f21 100644 --- a/android/libraries/rib-test/build.gradle.kts +++ b/android/libraries/rib-test/build.gradle.kts @@ -36,5 +36,4 @@ dependencies { api(testLibs.truth) api(testLibs.mockito.kotlin) api(testLibs.coroutines.test) - implementation(testLibs.mockito.kotlin) } diff --git a/android/libraries/rib-workflow/src/main/kotlin/com/uber/rib/workflow/core/internal/WorkflowFriendModuleApi.kt b/android/libraries/rib-workflow/src/main/kotlin/com/uber/rib/workflow/core/internal/WorkflowFriendModuleApi.kt index 4d55f66a0..26f422d90 100644 --- a/android/libraries/rib-workflow/src/main/kotlin/com/uber/rib/workflow/core/internal/WorkflowFriendModuleApi.kt +++ b/android/libraries/rib-workflow/src/main/kotlin/com/uber/rib/workflow/core/internal/WorkflowFriendModuleApi.kt @@ -20,4 +20,6 @@ package com.uber.rib.workflow.core.internal * * Anything marked with this annotation is not intended for public use. */ -@RequiresOptIn(level = RequiresOptIn.Level.ERROR) internal annotation class WorkflowFriendModuleApi +@Suppress("ExperimentalAnnotationRetention") // false positive +@RequiresOptIn(level = RequiresOptIn.Level.ERROR) +internal annotation class WorkflowFriendModuleApi diff --git a/android/settings.gradle b/android/settings.gradle index 42a33dcc6..9def53541 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -2,12 +2,23 @@ import org.gradle.api.initialization.resolve.RepositoriesMode pluginManagement { repositories { - gradlePluginPortal() - google() + google { + content { + includeGroupByRegex("com\\.android.*") + includeGroupByRegex("com\\.google.*") + includeGroupByRegex("androidx.*") + } + } mavenCentral() + gradlePluginPortal() } } +plugins { + // Provides repository for downloading JDKs. Used by JVM toolchain gradle config. + id("org.gradle.toolchains.foojay-resolver-convention") version("0.8.0") +} + dependencyResolutionManagement { // rib-intellij-plugin project applies the IntelliJ plugin, which applies custom repositories. // Otherwise, this should be FAIL_ON_PROJECT_REPO. diff --git a/android/tooling/rib-intellij-plugin/build.gradle b/android/tooling/rib-intellij-plugin/build.gradle index 077aca802..87466d871 100644 --- a/android/tooling/rib-intellij-plugin/build.gradle +++ b/android/tooling/rib-intellij-plugin/build.gradle @@ -20,12 +20,6 @@ intellij { downloadSources = false } -java { - toolchain { - languageVersion.set(JavaLanguageVersion.of(17)) - } -} - dependencies { testImplementation(project(":libraries:rib-test")) testImplementation(project(":libraries:rib-compiler-test")) diff --git a/android/tooling/rib-intellij-plugin/native/intellij-broadcast-rib/build.gradle b/android/tooling/rib-intellij-plugin/native/intellij-broadcast-rib/build.gradle.kts similarity index 93% rename from android/tooling/rib-intellij-plugin/native/intellij-broadcast-rib/build.gradle rename to android/tooling/rib-intellij-plugin/native/intellij-broadcast-rib/build.gradle.kts index 7ee66ec41..5bc327397 100644 --- a/android/tooling/rib-intellij-plugin/native/intellij-broadcast-rib/build.gradle +++ b/android/tooling/rib-intellij-plugin/native/intellij-broadcast-rib/build.gradle.kts @@ -19,7 +19,11 @@ plugins { } android { - namespace "com.uber.debug.broadcast.rib" + namespace = "com.uber.debug.broadcast.rib" +} + +kotlin { + jvmToolchain(11) } dependencies { diff --git a/android/tooling/rib-intellij-plugin/src/main/kotlin/com/uber/intellij/plugin/android/rib/RibHierarchyBrowser.kt b/android/tooling/rib-intellij-plugin/src/main/kotlin/com/uber/intellij/plugin/android/rib/RibHierarchyBrowser.kt index 6fbf3ad4c..dbe9ef0c7 100644 --- a/android/tooling/rib-intellij-plugin/src/main/kotlin/com/uber/intellij/plugin/android/rib/RibHierarchyBrowser.kt +++ b/android/tooling/rib-intellij-plugin/src/main/kotlin/com/uber/intellij/plugin/android/rib/RibHierarchyBrowser.kt @@ -265,7 +265,7 @@ public class RibHierarchyBrowser( } } - private inner class HelpAction internal constructor() : + private inner class HelpAction : AnAction( IdeBundle.message("action.help"), IdeBundle.message("action.help"), diff --git a/android/tooling/utils/intellij-broadcast-core/src/main/java/com/uber/debug/broadcast/core/DebugBroadcastRequest.java b/android/tooling/utils/intellij-broadcast-core/src/main/java/com/uber/debug/broadcast/core/DebugBroadcastRequest.java index ea9f5d36b..444963f55 100644 --- a/android/tooling/utils/intellij-broadcast-core/src/main/java/com/uber/debug/broadcast/core/DebugBroadcastRequest.java +++ b/android/tooling/utils/intellij-broadcast-core/src/main/java/com/uber/debug/broadcast/core/DebugBroadcastRequest.java @@ -22,6 +22,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.util.Locale; +import java.util.Objects; /** Class representing incoming request to debug broadcast receiver. */ public class DebugBroadcastRequest { @@ -33,17 +34,13 @@ public class DebugBroadcastRequest { private static final String TAG_TEMPLATE = DebugBroadcastReceiver.class.getSimpleName(); private static final Gson GSON = new GsonBuilder().create(); - private int sequence; - private String command; - private @Nullable Bundle extras; + private final int sequence; + private final String command; + private final @Nullable Bundle extras; protected DebugBroadcastRequest(int sequence, @Nullable String command, @Nullable Bundle extras) { this.sequence = sequence; - if (command != null) { - this.command = command; - } else { - this.command = ""; - } + this.command = Objects.requireNonNullElse(command, ""); this.extras = extras; }