Dispatchers IO is now considered non-blocking context

See BlockingMethodInNonBlockingContextInspection
This commit is contained in:
Nikita Katkov
2018-12-06 16:59:15 +03:00
committed by Mikhail Glukhikh
parent 3b33d3e58d
commit 297054037c
5 changed files with 42 additions and 10 deletions
@@ -24,9 +24,9 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getParameterForArgument
import org.jetbrains.kotlin.resolve.calls.checkers.isRestrictsSuspensionReceiver
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
class CoroutineNonBlockingContextChecker : NonBlockingContextChecker {
override fun isApplicable(file: PsiFile): Boolean {
@@ -45,10 +45,11 @@ class CoroutineNonBlockingContextChecker : NonBlockingContextChecker {
val callExpression = PsiTreeUtil.getParentOfType(containingArgument, KtCallExpression::class.java) ?: return false
val call = callExpression.resolveToCall(BodyResolveMode.PARTIAL) ?: return false
val hasBlockingAnnotation = call.getFirstArgument()?.resolveToCall()
?.resultingDescriptor?.annotations?.hasAnnotation(FqName(BLOCKING_CONTEXT_ANNOTATION))
if (hasBlockingAnnotation == true)
return false
val argumentDescriptor = call.getFirstArgument()?.resolveToCall()?.resultingDescriptor
val hasBlockingAnnotation = argumentDescriptor?.annotations?.hasAnnotation(FqName(BLOCKING_CONTEXT_ANNOTATION))
if (hasBlockingAnnotation == true) return false
val isIoDispatcherUsed = argumentDescriptor?.fqNameOrNull()?.asString() == IO_DISPATCHER_FQN
if (isIoDispatcherUsed) return false
val parameterForArgument = call.getParameterForArgument(containingArgument) ?: return false
val type = parameterForArgument.returnType ?: return false
@@ -69,5 +70,6 @@ class CoroutineNonBlockingContextChecker : NonBlockingContextChecker {
companion object {
private const val BLOCKING_CONTEXT_ANNOTATION = "org.jetbrains.annotations.BlockingContext"
private const val IO_DISPATCHER_FQN = "kotlinx.coroutines.Dispatchers.IO"
}
}
@@ -2,7 +2,6 @@
import kotlin.coroutines.*
import org.jetbrains.annotations.BlockingContext
import kotlin.coroutines.experimental.buildSequence
import java.lang.Thread.sleep
suspend fun testFunction() {
@@ -0,0 +1,28 @@
@file:Suppress("UNUSED_PARAMETER")
package kotlinx.coroutines
import java.lang.Thread.sleep
suspend fun withIoDispatcher() {
withContext(Dispatchers.IO) {
//no warning since IO dispatcher type used
Thread.sleep(42)
}
withContext(Dispatchers.Default) {
Thread.<warning descr="Inappropriate blocking method call">sleep</warning>(1)
}
}
class CoroutineDispatcher()
object Dispatchers {
val IO: kotlinx.coroutines.CoroutineDispatcher = TODO()
val Default: kotlinx.coroutines.CoroutineDispatcher = TODO()
}
suspend fun <T> withContext(
context: CoroutineDispatcher,
f: suspend () -> T
) {
TODO()
}
@@ -10,11 +10,9 @@ import com.intellij.testFramework.LightProjectDescriptor
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.idea.test.configureCompilerOptions
class CoroutineNonBlockingontextDetectionTest: KotlinLightCodeInsightFixtureTestCase() {
override fun getTestDataPath(): String
= PluginTestCaseBase.getTestDataPathBase() + "/inspections/blockingCallsDetection"
class CoroutineNonBlockingContextDetectionTest : KotlinLightCodeInsightFixtureTestCase() {
override fun getTestDataPath(): String = PluginTestCaseBase.getTestDataPathBase() + "/inspections/blockingCallsDetection"
override fun getProjectDescriptor(): LightProjectDescriptor = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
@@ -43,4 +41,9 @@ class CoroutineNonBlockingontextDetectionTest: KotlinLightCodeInsightFixtureTest
myFixture.configureByFile("NestedFunctionsInsideSuspendLambda.kt")
myFixture.testHighlighting(true, false, false, "NestedFunctionsInsideSuspendLambda.kt")
}
fun testDispatchersTypeDetection() {
myFixture.configureByFile("DispatchersTypeCheck.kt")
myFixture.testHighlighting(true, false, false, "DispatchersTypeCheck.kt")
}
}