From 87bbac9d43e15557a2ff0dc3254fd41a9d5639e1 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Wed, 7 Feb 2018 15:24:40 +0300 Subject: [PATCH] Take coroutineContext into account in RedundantSuspendModifierInspection #KT-22651: Fixed --- .../backend/common/commonCoroutineCodegenUtil.kt | 5 ----- .../kotlin/codegen/coroutines/coroutineCodegenUtil.kt | 1 + .../jetbrains/kotlin/codegen/inline/InlineCodegen.kt | 2 +- .../resolve/calls/checkers/coroutineCallChecker.kt | 10 ++++++++++ .../highlighter/KotlinSuspendCallLineMarkerProvider.kt | 10 ++++++---- .../redundantSuspend/coroutineContext.kt | 8 ++++++++ .../idea/inspections/LocalInspectionTestGenerated.java | 6 ++++++ .../functions/factories/CoroutineContextFIF.kt | 2 +- 8 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 idea/testData/inspectionsLocal/redundantSuspend/coroutineContext.kt diff --git a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/commonCoroutineCodegenUtil.kt b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/commonCoroutineCodegenUtil.kt index 813c92c7f2f..ddc581db9f4 100644 --- a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/commonCoroutineCodegenUtil.kt +++ b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/commonCoroutineCodegenUtil.kt @@ -58,11 +58,6 @@ fun FunctionDescriptor.getBuiltInSuspendCoroutineOrReturn() = .getContributedFunctions(SUSPEND_COROUTINE_OR_RETURN_NAME, NoLookupLocation.FROM_BACKEND) .singleOrNull() -fun FunctionDescriptor.isBuiltInCoroutineContext(): Boolean { - val fqNameSafe = (this as? PropertyGetterDescriptor)?.correspondingProperty?.fqNameSafe - return fqNameSafe == COROUTINE_CONTEXT_1_2_20_FQ_NAME || fqNameSafe == COROUTINE_CONTEXT_FQ_NAME -} - fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(): Boolean { if (name != SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME) return false val original = module.getPackage(COROUTINES_INTRINSICS_PACKAGE_FQ_NAME).memberScope diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt index 5e914767b32..5856b1a3ccf 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtPsiFactory import org.jetbrains.kotlin.resolve.* +import org.jetbrains.kotlin.resolve.calls.checkers.isBuiltInCoroutineContext import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt index 6a1a8161292..1cea6afb8fe 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt @@ -18,7 +18,6 @@ package org.jetbrains.kotlin.codegen.inline import com.intellij.psi.PsiElement import com.intellij.util.ArrayUtil -import org.jetbrains.kotlin.backend.common.isBuiltInCoroutineContext import org.jetbrains.kotlin.backend.common.isBuiltInIntercepted import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment import org.jetbrains.kotlin.codegen.* @@ -41,6 +40,7 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert +import org.jetbrains.kotlin.resolve.calls.checkers.isBuiltInCoroutineContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.resolve.inline.InlineUtil.isInlinableParameterExpression diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt index 2e28c3cea01..84113077221 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt @@ -23,8 +23,10 @@ import org.jetbrains.kotlin.coroutines.hasSuspendFunctionType import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtThisExpression @@ -47,6 +49,14 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs val COROUTINE_CONTEXT_1_2_20_FQ_NAME = DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME.child(Name.identifier("coroutineContext")) val COROUTINE_CONTEXT_FQ_NAME = DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("coroutineContext")) +fun FqName.isBuiltInCorouineContext() = + this == COROUTINE_CONTEXT_1_2_20_FQ_NAME || this == COROUTINE_CONTEXT_FQ_NAME + +fun FunctionDescriptor.isBuiltInCoroutineContext() = + (this as? PropertyGetterDescriptor)?.correspondingProperty?.fqNameSafe?.isBuiltInCorouineContext() == true + +fun PropertyDescriptor.isBuiltInCoroutineContext() = this.fqNameSafe.isBuiltInCorouineContext() + object CoroutineSuspendCallChecker : CallChecker { private val ALLOWED_SCOPE_KINDS = setOf(LexicalScopeKind.FUNCTION_INNER_SCOPE, LexicalScopeKind.FUNCTION_HEADER_FOR_DESTRUCTURING) diff --git a/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinSuspendCallLineMarkerProvider.kt b/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinSuspendCallLineMarkerProvider.kt index a0f03bfca46..82f064cfda1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinSuspendCallLineMarkerProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinSuspendCallLineMarkerProvider.kt @@ -13,6 +13,7 @@ import com.intellij.openapi.editor.markup.GutterIconRenderer import com.intellij.openapi.progress.ProgressManager import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors import org.jetbrains.kotlin.descriptors.accessors import org.jetbrains.kotlin.idea.KotlinIcons @@ -22,6 +23,7 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext.* import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.resolve.calls.checkers.isBuiltInCoroutineContext import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode class KotlinSuspendCallLineMarkerProvider : LineMarkerProvider { @@ -68,7 +70,7 @@ class KotlinSuspendCallLineMarkerProvider : LineMarkerProvider { } private fun KtExpression.isValidCandidateExpression(): Boolean { - if (this is KtOperationReferenceExpression || this is KtForExpression || this is KtProperty) return true + if (this is KtOperationReferenceExpression || this is KtForExpression || this is KtProperty || this is KtNameReferenceExpression) return true val parent = parent if (parent is KtCallExpression && parent.calleeExpression == this) return true return false @@ -94,14 +96,14 @@ fun KtExpression.hasSuspendCalls(bindingContext: BindingContext = analyze(BodyRe val delegatedFunctionDescriptor = bindingContext[DELEGATED_PROPERTY_RESOLVED_CALL, accessor]?.resultingDescriptor delegatedFunctionDescriptor?.isSuspend == true } - } - else { + } else { false } } else -> { val resolvedCall = getResolvedCall(bindingContext) - (resolvedCall?.resultingDescriptor as? FunctionDescriptor)?.isSuspend == true + (resolvedCall?.resultingDescriptor as? FunctionDescriptor)?.isSuspend == true || + (resolvedCall?.resultingDescriptor as? PropertyDescriptor)?.isBuiltInCoroutineContext() == true } } } diff --git a/idea/testData/inspectionsLocal/redundantSuspend/coroutineContext.kt b/idea/testData/inspectionsLocal/redundantSuspend/coroutineContext.kt new file mode 100644 index 00000000000..b56255283b7 --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantSuspend/coroutineContext.kt @@ -0,0 +1,8 @@ +// PROBLEM: none +// WITH_RUNTIME + +import kotlin.coroutines.experimental.coroutineContext + +suspend fun test() { + coroutineContext +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index 9b2a9a2fc31..3893ff7335a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -2961,6 +2961,12 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/redundantSuspend"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true); } + @TestMetadata("coroutineContext.kt") + public void testCoroutineContext() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantSuspend/coroutineContext.kt"); + doTest(fileName); + } + @TestMetadata("getterDelegate.kt") public void testGetterDelegate() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantSuspend/getterDelegate.kt"); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/CoroutineContextFIF.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/CoroutineContextFIF.kt index 700345f0f00..899054120fd 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/CoroutineContextFIF.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/CoroutineContextFIF.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories -import org.jetbrains.kotlin.backend.common.isBuiltInCoroutineContext import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.js.backend.ast.JsExpression @@ -30,6 +29,7 @@ import org.jetbrains.kotlin.js.translate.utils.JsAstUtils import org.jetbrains.kotlin.js.translate.utils.TranslationUtils import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.calls.checkers.isBuiltInCoroutineContext import org.jetbrains.kotlin.resolve.inline.InlineStrategy object CoroutineContextFIF : FunctionIntrinsicFactory {