mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2024-12-23 08:30:44 +00:00
Merge pull request #4947 from Isira-Seneviratne/Convert_ExceptionUtils_to_extensions
Rewrite ExceptionUtils methods as extension functions.
This commit is contained in:
commit
9ee7740fcc
@ -32,11 +32,11 @@ import org.acra.config.CoreConfiguration;
|
||||
import org.acra.config.CoreConfigurationBuilder;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||
import org.schabi.newpipe.ktx.ExceptionUtils;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.ErrorInfo;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
import org.schabi.newpipe.settings.SettingsActivity;
|
||||
import org.schabi.newpipe.util.ExceptionUtils;
|
||||
import org.schabi.newpipe.util.Localization;
|
||||
import org.schabi.newpipe.util.ServiceHelper;
|
||||
import org.schabi.newpipe.util.StateSaver;
|
||||
|
@ -22,10 +22,10 @@ import org.schabi.newpipe.ReCaptchaActivity;
|
||||
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
|
||||
import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException;
|
||||
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
||||
import org.schabi.newpipe.ktx.ExceptionUtils;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.ErrorInfo;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
import org.schabi.newpipe.util.ExceptionUtils;
|
||||
import org.schabi.newpipe.util.InfoCache;
|
||||
|
||||
import java.util.Collections;
|
||||
|
@ -51,6 +51,7 @@ import org.schabi.newpipe.extractor.services.peertube.linkHandler.PeertubeSearch
|
||||
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory;
|
||||
import org.schabi.newpipe.fragments.BackPressable;
|
||||
import org.schabi.newpipe.fragments.list.BaseListFragment;
|
||||
import org.schabi.newpipe.ktx.ExceptionUtils;
|
||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.ErrorInfo;
|
||||
@ -58,7 +59,6 @@ import org.schabi.newpipe.report.UserAction;
|
||||
import org.schabi.newpipe.util.AnimationUtils;
|
||||
import org.schabi.newpipe.util.Constants;
|
||||
import org.schabi.newpipe.util.DeviceUtils;
|
||||
import org.schabi.newpipe.util.ExceptionUtils;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.ServiceHelper;
|
||||
|
75
app/src/main/java/org/schabi/newpipe/ktx/Throwable.kt
Normal file
75
app/src/main/java/org/schabi/newpipe/ktx/Throwable.kt
Normal file
@ -0,0 +1,75 @@
|
||||
@file:JvmName("ExceptionUtils")
|
||||
|
||||
package org.schabi.newpipe.ktx
|
||||
|
||||
import java.io.IOException
|
||||
import java.io.InterruptedIOException
|
||||
|
||||
/**
|
||||
* @return if throwable is related to Interrupted exceptions, or one of its causes is.
|
||||
*/
|
||||
val Throwable.isInterruptedCaused: Boolean
|
||||
get() = hasExactCause(InterruptedIOException::class.java, InterruptedException::class.java)
|
||||
|
||||
/**
|
||||
* @return if throwable is related to network issues, or one of its causes is.
|
||||
*/
|
||||
val Throwable.isNetworkRelated: Boolean
|
||||
get() = hasAssignableCause<IOException>()
|
||||
|
||||
/**
|
||||
* Calls [hasCause] with the `checkSubtypes` parameter set to false.
|
||||
*/
|
||||
fun Throwable.hasExactCause(vararg causesToCheck: Class<*>) = hasCause(false, *causesToCheck)
|
||||
|
||||
/**
|
||||
* Calls [hasCause] with a reified [Throwable] type.
|
||||
*/
|
||||
inline fun <reified T : Throwable> Throwable.hasExactCause() = hasExactCause(T::class.java)
|
||||
|
||||
/**
|
||||
* Calls [hasCause] with the `checkSubtypes` parameter set to true.
|
||||
*/
|
||||
fun Throwable?.hasAssignableCause(vararg causesToCheck: Class<*>) = hasCause(true, *causesToCheck)
|
||||
|
||||
/**
|
||||
* Calls [hasCause] with a reified [Throwable] type.
|
||||
*/
|
||||
inline fun <reified T : Throwable> Throwable?.hasAssignableCause() = hasAssignableCause(T::class.java)
|
||||
|
||||
/**
|
||||
* Check if the throwable has some cause from the causes to check, or is itself in it.
|
||||
*
|
||||
* If `checkIfAssignable` is true, not only the exact type will be considered equals, but also its subtypes.
|
||||
*
|
||||
* @param checkSubtypes if subtypes are also checked.
|
||||
* @param causesToCheck an array of causes to check.
|
||||
*
|
||||
* @see Class.isAssignableFrom
|
||||
*/
|
||||
tailrec fun Throwable?.hasCause(checkSubtypes: Boolean, vararg causesToCheck: Class<*>): Boolean {
|
||||
if (this == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if throwable is a subtype of any of the causes to check
|
||||
causesToCheck.forEach { causeClass ->
|
||||
if (checkSubtypes) {
|
||||
if (causeClass.isAssignableFrom(this.javaClass)) {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
if (causeClass == this.javaClass) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val currentCause: Throwable? = cause
|
||||
// Check if cause is not pointing to the same instance, to avoid infinite loops.
|
||||
if (this !== currentCause) {
|
||||
return currentCause.hasCause(checkSubtypes, *causesToCheck)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
@ -50,13 +50,13 @@ import org.schabi.newpipe.database.feed.model.FeedGroupEntity
|
||||
import org.schabi.newpipe.extractor.ListInfo
|
||||
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem
|
||||
import org.schabi.newpipe.ktx.isNetworkRelated
|
||||
import org.schabi.newpipe.local.feed.FeedDatabaseManager
|
||||
import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.ErrorResultEvent
|
||||
import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.ProgressEvent
|
||||
import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.SuccessResultEvent
|
||||
import org.schabi.newpipe.local.feed.service.FeedEventManager.postEvent
|
||||
import org.schabi.newpipe.local.subscription.SubscriptionManager
|
||||
import org.schabi.newpipe.util.ExceptionUtils
|
||||
import org.schabi.newpipe.util.ExtractorHelper
|
||||
import java.io.IOException
|
||||
import java.time.OffsetDateTime
|
||||
@ -344,7 +344,7 @@ class FeedLoadService : Service() {
|
||||
|
||||
error is IOException -> throw error
|
||||
cause is IOException -> throw cause
|
||||
ExceptionUtils.isNetworkRelated(error) -> throw IOException(error)
|
||||
error.isNetworkRelated -> throw IOException(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,11 +36,11 @@ import androidx.core.app.ServiceCompat;
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
|
||||
import org.schabi.newpipe.ktx.ExceptionUtils;
|
||||
import org.schabi.newpipe.local.subscription.SubscriptionManager;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.ErrorInfo;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
import org.schabi.newpipe.util.ExceptionUtils;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Collections;
|
||||
|
@ -35,8 +35,8 @@ import org.schabi.newpipe.database.subscription.SubscriptionEntity;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.channel.ChannelInfo;
|
||||
import org.schabi.newpipe.extractor.subscription.SubscriptionItem;
|
||||
import org.schabi.newpipe.ktx.ExceptionUtils;
|
||||
import org.schabi.newpipe.util.Constants;
|
||||
import org.schabi.newpipe.util.ExceptionUtils;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -1,86 +0,0 @@
|
||||
package org.schabi.newpipe.util
|
||||
|
||||
import java.io.IOException
|
||||
import java.io.InterruptedIOException
|
||||
|
||||
class ExceptionUtils {
|
||||
companion object {
|
||||
/**
|
||||
* @return if throwable is related to Interrupted exceptions, or one of its causes is.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isInterruptedCaused(throwable: Throwable): Boolean {
|
||||
return hasExactCause(
|
||||
throwable,
|
||||
InterruptedIOException::class.java,
|
||||
InterruptedException::class.java
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if throwable is related to network issues, or one of its causes is.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isNetworkRelated(throwable: Throwable): Boolean {
|
||||
return hasAssignableCause(
|
||||
throwable,
|
||||
IOException::class.java
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls [hasCause] with the `checkSubtypes` parameter set to false.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun hasExactCause(throwable: Throwable, vararg causesToCheck: Class<*>): Boolean {
|
||||
return hasCause(throwable, false, *causesToCheck)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls [hasCause] with the `checkSubtypes` parameter set to true.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun hasAssignableCause(throwable: Throwable?, vararg causesToCheck: Class<*>): Boolean {
|
||||
return hasCause(throwable, true, *causesToCheck)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if throwable has some cause from the causes to check, or is itself in it.
|
||||
*
|
||||
* If `checkIfAssignable` is true, not only the exact type will be considered equals, but also its subtypes.
|
||||
*
|
||||
* @param throwable throwable that will be checked.
|
||||
* @param checkSubtypes if subtypes are also checked.
|
||||
* @param causesToCheck an array of causes to check.
|
||||
*
|
||||
* @see Class.isAssignableFrom
|
||||
*/
|
||||
@JvmStatic
|
||||
tailrec fun hasCause(throwable: Throwable?, checkSubtypes: Boolean, vararg causesToCheck: Class<*>): Boolean {
|
||||
if (throwable == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if throwable is a subtype of any of the causes to check
|
||||
causesToCheck.forEach { causeClass ->
|
||||
if (checkSubtypes) {
|
||||
if (causeClass.isAssignableFrom(throwable.javaClass)) {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
if (causeClass == throwable.javaClass) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val currentCause: Throwable? = throwable.cause
|
||||
// Check if cause is not pointing to the same instance, to avoid infinite loops.
|
||||
if (throwable !== currentCause) {
|
||||
return hasCause(currentCause, checkSubtypes, *causesToCheck)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
@ -58,6 +58,7 @@ import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExt
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor;
|
||||
import org.schabi.newpipe.ktx.ExceptionUtils;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.ErrorInfo;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
|
@ -0,0 +1,67 @@
|
||||
package org.schabi.newpipe.ktx
|
||||
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import java.io.IOException
|
||||
import java.io.InterruptedIOException
|
||||
import java.net.SocketException
|
||||
import javax.net.ssl.SSLException
|
||||
|
||||
class ThrowableExtensionsTest {
|
||||
@Test fun `assignable causes`() {
|
||||
assertTrue(Throwable().hasAssignableCause<Throwable>())
|
||||
assertTrue(Exception().hasAssignableCause<Exception>())
|
||||
assertTrue(IOException().hasAssignableCause<Exception>())
|
||||
|
||||
assertTrue(IOException().hasAssignableCause<IOException>())
|
||||
assertTrue(Exception(SocketException()).hasAssignableCause<IOException>())
|
||||
assertTrue(Exception(IllegalStateException()).hasAssignableCause<RuntimeException>())
|
||||
assertTrue(Exception(Exception(IOException())).hasAssignableCause<IOException>())
|
||||
assertTrue(Exception(IllegalStateException(Exception(IOException()))).hasAssignableCause<IOException>())
|
||||
assertTrue(Exception(IllegalStateException(Exception(SocketException()))).hasAssignableCause<IOException>())
|
||||
assertTrue(Exception(IllegalStateException(Exception(SSLException("IO")))).hasAssignableCause<IOException>())
|
||||
assertTrue(Exception(IllegalStateException(Exception(InterruptedIOException()))).hasAssignableCause<IOException>())
|
||||
assertTrue(Exception(IllegalStateException(Exception(InterruptedIOException()))).hasAssignableCause<RuntimeException>())
|
||||
|
||||
assertTrue(IllegalStateException().hasAssignableCause<Throwable>())
|
||||
assertTrue(IllegalStateException().hasAssignableCause<Exception>())
|
||||
assertTrue(Exception(IllegalStateException(Exception(InterruptedIOException()))).hasAssignableCause<InterruptedIOException>())
|
||||
}
|
||||
|
||||
@Test fun `no assignable causes`() {
|
||||
assertFalse(Throwable().hasAssignableCause<Exception>())
|
||||
assertFalse(Exception().hasAssignableCause<IOException>())
|
||||
assertFalse(Exception(IllegalStateException()).hasAssignableCause<IOException>())
|
||||
assertFalse(Exception(NullPointerException()).hasAssignableCause<IOException>())
|
||||
assertFalse(Exception(IllegalStateException(Exception(Exception()))).hasAssignableCause<IOException>())
|
||||
assertFalse(Exception(IllegalStateException(Exception(SocketException()))).hasAssignableCause<InterruptedIOException>())
|
||||
assertFalse(Exception(IllegalStateException(Exception(InterruptedIOException()))).hasAssignableCause<InterruptedException>())
|
||||
}
|
||||
|
||||
@Test fun `exact causes`() {
|
||||
assertTrue(Throwable().hasExactCause<Throwable>())
|
||||
assertTrue(Exception().hasExactCause<Exception>())
|
||||
|
||||
assertTrue(IOException().hasExactCause<IOException>())
|
||||
assertTrue(Exception(SocketException()).hasExactCause<SocketException>())
|
||||
assertTrue(Exception(Exception(IOException())).hasExactCause<IOException>())
|
||||
assertTrue(Exception(IllegalStateException(Exception(IOException()))).hasExactCause<IOException>())
|
||||
assertTrue(Exception(IllegalStateException(Exception(SocketException()))).hasExactCause<SocketException>())
|
||||
assertTrue(Exception(IllegalStateException(Exception(SSLException("IO")))).hasExactCause<SSLException>())
|
||||
assertTrue(Exception(IllegalStateException(Exception(InterruptedIOException()))).hasExactCause<InterruptedIOException>())
|
||||
assertTrue(Exception(IllegalStateException(Exception(InterruptedIOException()))).hasExactCause<IllegalStateException>())
|
||||
}
|
||||
|
||||
@Test fun `no exact causes`() {
|
||||
assertFalse(Throwable().hasExactCause<Exception>())
|
||||
assertFalse(Exception().hasExactCause<Throwable>())
|
||||
|
||||
assertFalse(SocketException().hasExactCause<IOException>())
|
||||
assertFalse(IllegalStateException().hasExactCause<RuntimeException>())
|
||||
assertFalse(Exception(SocketException()).hasExactCause<IOException>())
|
||||
assertFalse(Exception(IllegalStateException(Exception(IOException()))).hasExactCause<RuntimeException>())
|
||||
assertFalse(Exception(IllegalStateException(Exception(SocketException()))).hasExactCause<IOException>())
|
||||
assertFalse(Exception(IllegalStateException(Exception(InterruptedIOException()))).hasExactCause<IOException>())
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
package org.schabi.newpipe.util
|
||||
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.schabi.newpipe.util.ExceptionUtils.Companion.hasAssignableCause
|
||||
import org.schabi.newpipe.util.ExceptionUtils.Companion.hasExactCause
|
||||
import java.io.IOException
|
||||
import java.io.InterruptedIOException
|
||||
import java.net.SocketException
|
||||
import javax.net.ssl.SSLException
|
||||
|
||||
class ExceptionUtilsTest {
|
||||
@Test fun `assignable causes`() {
|
||||
assertTrue(hasAssignableCause(Throwable(), Throwable::class.java))
|
||||
assertTrue(hasAssignableCause(Exception(), Exception::class.java))
|
||||
assertTrue(hasAssignableCause(IOException(), Exception::class.java))
|
||||
|
||||
assertTrue(hasAssignableCause(IOException(), IOException::class.java))
|
||||
assertTrue(hasAssignableCause(Exception(SocketException()), IOException::class.java))
|
||||
assertTrue(hasAssignableCause(Exception(IllegalStateException()), RuntimeException::class.java))
|
||||
assertTrue(hasAssignableCause(Exception(Exception(IOException())), IOException::class.java))
|
||||
assertTrue(hasAssignableCause(Exception(IllegalStateException(Exception(IOException()))), IOException::class.java))
|
||||
assertTrue(hasAssignableCause(Exception(IllegalStateException(Exception(SocketException()))), IOException::class.java))
|
||||
assertTrue(hasAssignableCause(Exception(IllegalStateException(Exception(SSLException("IO")))), IOException::class.java))
|
||||
assertTrue(hasAssignableCause(Exception(IllegalStateException(Exception(InterruptedIOException()))), IOException::class.java))
|
||||
assertTrue(hasAssignableCause(Exception(IllegalStateException(Exception(InterruptedIOException()))), RuntimeException::class.java))
|
||||
|
||||
assertTrue(hasAssignableCause(IllegalStateException(), Throwable::class.java))
|
||||
assertTrue(hasAssignableCause(IllegalStateException(), Exception::class.java))
|
||||
assertTrue(hasAssignableCause(Exception(IllegalStateException(Exception(InterruptedIOException()))), InterruptedIOException::class.java))
|
||||
}
|
||||
|
||||
@Test fun `no assignable causes`() {
|
||||
assertFalse(hasAssignableCause(Throwable(), Exception::class.java))
|
||||
assertFalse(hasAssignableCause(Exception(), IOException::class.java))
|
||||
assertFalse(hasAssignableCause(Exception(IllegalStateException()), IOException::class.java))
|
||||
assertFalse(hasAssignableCause(Exception(NullPointerException()), IOException::class.java))
|
||||
assertFalse(hasAssignableCause(Exception(IllegalStateException(Exception(Exception()))), IOException::class.java))
|
||||
assertFalse(hasAssignableCause(Exception(IllegalStateException(Exception(SocketException()))), InterruptedIOException::class.java))
|
||||
assertFalse(hasAssignableCause(Exception(IllegalStateException(Exception(InterruptedIOException()))), InterruptedException::class.java))
|
||||
}
|
||||
|
||||
@Test fun `exact causes`() {
|
||||
assertTrue(hasExactCause(Throwable(), Throwable::class.java))
|
||||
assertTrue(hasExactCause(Exception(), Exception::class.java))
|
||||
|
||||
assertTrue(hasExactCause(IOException(), IOException::class.java))
|
||||
assertTrue(hasExactCause(Exception(SocketException()), SocketException::class.java))
|
||||
assertTrue(hasExactCause(Exception(Exception(IOException())), IOException::class.java))
|
||||
assertTrue(hasExactCause(Exception(IllegalStateException(Exception(IOException()))), IOException::class.java))
|
||||
assertTrue(hasExactCause(Exception(IllegalStateException(Exception(SocketException()))), SocketException::class.java))
|
||||
assertTrue(hasExactCause(Exception(IllegalStateException(Exception(SSLException("IO")))), SSLException::class.java))
|
||||
assertTrue(hasExactCause(Exception(IllegalStateException(Exception(InterruptedIOException()))), InterruptedIOException::class.java))
|
||||
assertTrue(hasExactCause(Exception(IllegalStateException(Exception(InterruptedIOException()))), IllegalStateException::class.java))
|
||||
}
|
||||
|
||||
@Test fun `no exact causes`() {
|
||||
assertFalse(hasExactCause(Throwable(), Exception::class.java))
|
||||
assertFalse(hasExactCause(Exception(), Throwable::class.java))
|
||||
|
||||
assertFalse(hasExactCause(SocketException(), IOException::class.java))
|
||||
assertFalse(hasExactCause(IllegalStateException(), RuntimeException::class.java))
|
||||
assertFalse(hasExactCause(Exception(SocketException()), IOException::class.java))
|
||||
assertFalse(hasExactCause(Exception(IllegalStateException(Exception(IOException()))), RuntimeException::class.java))
|
||||
assertFalse(hasExactCause(Exception(IllegalStateException(Exception(SocketException()))), IOException::class.java))
|
||||
assertFalse(hasExactCause(Exception(IllegalStateException(Exception(InterruptedIOException()))), IOException::class.java))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user