diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/blockingCallsDetection/CoroutineNonBlockingContextChecker.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/blockingCallsDetection/CoroutineNonBlockingContextChecker.kt
index 28c33e0ef98..983d5b66b56 100644
--- a/idea/src/org/jetbrains/kotlin/idea/inspections/blockingCallsDetection/CoroutineNonBlockingContextChecker.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/inspections/blockingCallsDetection/CoroutineNonBlockingContextChecker.kt
@@ -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"
}
}
\ No newline at end of file
diff --git a/idea/testData/inspections/blockingCallsDetection/ContextCheck.kt b/idea/testData/inspections/blockingCallsDetection/ContextCheck.kt
index 7a5656eced5..09e6f088768 100644
--- a/idea/testData/inspections/blockingCallsDetection/ContextCheck.kt
+++ b/idea/testData/inspections/blockingCallsDetection/ContextCheck.kt
@@ -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() {
diff --git a/idea/testData/inspections/blockingCallsDetection/DispatchersTypeCheck.kt b/idea/testData/inspections/blockingCallsDetection/DispatchersTypeCheck.kt
new file mode 100644
index 00000000000..3d1071a062e
--- /dev/null
+++ b/idea/testData/inspections/blockingCallsDetection/DispatchersTypeCheck.kt
@@ -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.sleep(1)
+ }
+}
+
+class CoroutineDispatcher()
+object Dispatchers {
+ val IO: kotlinx.coroutines.CoroutineDispatcher = TODO()
+ val Default: kotlinx.coroutines.CoroutineDispatcher = TODO()
+}
+
+suspend fun withContext(
+ context: CoroutineDispatcher,
+ f: suspend () -> T
+) {
+ TODO()
+}
\ No newline at end of file
diff --git a/idea/testData/inspections/blockingCallsDetection/DispatchersTypeCheck.kt.182 b/idea/testData/inspections/blockingCallsDetection/DispatchersTypeCheck.kt.182
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/CoroutineNonBlockingontextDetectionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/inspections/CoroutineNonBlockingontextDetectionTest.kt
index a5c8a189bda..de5b5db5404 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/inspections/CoroutineNonBlockingontextDetectionTest.kt
+++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/CoroutineNonBlockingontextDetectionTest.kt
@@ -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")
+ }
}
\ No newline at end of file