Add catchingExceptions method to replace runCatching (#4797)

- Add `runCatchingExceptions` and `mapCatchingExceptions` to replace `runCatching` and `mapCatching`.
- Make `tryOrNull { ... }` catch only exceptions too.
- Apply the changes to the whole project.
- Add new Rust fakes for tests to handle the code that's now unblocked - previously it just threw an `UnsatisfiedLinkError` which we ignored.
- Add a new `detekt-rules` project with a `RunCatchingRule` to prevent `runCatching` and `mapCatching` usages.
This commit is contained in:
Jorge Martin Espinosa 2025-06-04 09:02:26 +02:00 committed by GitHub
parent 7816529fd7
commit efdc10e60a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
144 changed files with 716 additions and 375 deletions

View file

@ -21,7 +21,7 @@ class BlockedUsersStateProvider : PreviewParameterProvider<BlockedUsersState> {
aBlockedUsersState(blockedUsers = emptyList()),
aBlockedUsersState(unblockUserAction = AsyncAction.ConfirmingNoParams),
aBlockedUsersState(unblockUserAction = AsyncAction.Loading),
aBlockedUsersState(unblockUserAction = AsyncAction.Failure(Throwable("Failed to unblock user"))),
aBlockedUsersState(unblockUserAction = AsyncAction.Failure(RuntimeException("Failed to unblock user"))),
aBlockedUsersState(unblockUserAction = AsyncAction.Success(Unit)),
)
}

View file

@ -29,6 +29,7 @@ import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.runCatchingUpdatingState
import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.core.extensions.runCatchingExceptions
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.core.meta.BuildType
import io.element.android.libraries.featureflag.api.Feature
@ -201,8 +202,8 @@ class DeveloperSettingsPresenter @Inject constructor(
}
private fun customElementCallUrlValidator(url: String?): Boolean {
return runCatching {
if (url.isNullOrEmpty()) return@runCatching
return runCatchingExceptions {
if (url.isNullOrEmpty()) return@runCatchingExceptions
val parsedUrl = URL(url)
if (parsedUrl.protocol !in listOf("http", "https")) error("Incorrect protocol")
if (parsedUrl.host.isNullOrBlank()) error("Missing host")

View file

@ -22,6 +22,7 @@ import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.runUpdatingStateNoSuccess
import io.element.android.libraries.core.extensions.runCatchingExceptions
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
@ -209,7 +210,7 @@ class NotificationSettingsPresenter @Inject constructor(
}
private fun CoroutineScope.fixConfigurationMismatch(target: MutableState<NotificationSettingsState.MatrixSettings>) = launch {
runCatching {
runCatchingExceptions {
val groupDefaultMode = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = false, isOneToOne = false).getOrThrow()
val encryptedGroupDefaultMode = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = false).getOrThrow()

View file

@ -23,10 +23,10 @@ open class NotificationSettingsStateProvider : PreviewParameterProvider<Notifica
aValidNotificationSettingsState(systemNotificationsEnabled = false),
aValidNotificationSettingsState(),
aValidNotificationSettingsState(changeNotificationSettingAction = AsyncAction.Loading),
aValidNotificationSettingsState(changeNotificationSettingAction = AsyncAction.Failure(Throwable("error"))),
aValidNotificationSettingsState(changeNotificationSettingAction = AsyncAction.Failure(RuntimeException("error"))),
aValidNotificationSettingsState(
availablePushDistributors = listOf(aDistributor("Firebase")),
changeNotificationSettingAction = AsyncAction.Failure(Throwable("error")),
changeNotificationSettingAction = AsyncAction.Failure(RuntimeException("error")),
),
aValidNotificationSettingsState(availablePushDistributors = listOf(aDistributor("Firebase"))),
aValidNotificationSettingsState(showChangePushProviderDialog = true),

View file

@ -21,7 +21,7 @@ open class EditDefaultNotificationSettingStateProvider : PreviewParameterProvide
anEditDefaultNotificationSettingsState(),
anEditDefaultNotificationSettingsState(isOneToOne = true),
anEditDefaultNotificationSettingsState(changeNotificationSettingAction = AsyncAction.Loading),
anEditDefaultNotificationSettingsState(changeNotificationSettingAction = AsyncAction.Failure(Throwable("error"))),
anEditDefaultNotificationSettingsState(changeNotificationSettingAction = AsyncAction.Failure(RuntimeException("error"))),
anEditDefaultNotificationSettingsState(displayMentionsOnlyDisclaimer = true),
)
}

View file

@ -26,6 +26,7 @@ import io.element.android.libraries.androidutils.file.TemporaryUriDeleter
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.runCatchingUpdatingState
import io.element.android.libraries.core.extensions.runCatchingExceptions
import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.user.MatrixUser
@ -168,7 +169,7 @@ class EditUserProfilePresenter @AssistedInject constructor(
}
private suspend fun updateAvatar(avatarUri: Uri?): Result<Unit> {
return runCatching {
return runCatchingExceptions {
if (avatarUri != null) {
val preprocessed = mediaPreProcessor.process(
uri = avatarUri,