diff --git a/plugins/kotlin/code-insight/inspections-shared/resources/kotlin.code-insight.inspections.shared.xml b/plugins/kotlin/code-insight/inspections-shared/resources/kotlin.code-insight.inspections.shared.xml
index 3f073398e11c..0f481436d1be 100644
--- a/plugins/kotlin/code-insight/inspections-shared/resources/kotlin.code-insight.inspections.shared.xml
+++ b/plugins/kotlin/code-insight/inspections-shared/resources/kotlin.code-insight.inspections.shared.xml
@@ -97,6 +97,14 @@
language="kotlin"
key="inspection.redundant.setter.display.name" bundle="messages.KotlinBundle"/>
+
+
? {
+ val newExpression = psiFactory.createExpressionByPattern("$0.$1()", this, name)
+ val fragment = KtPsiFactory(project).createExpressionCodeFragment(newExpression.text, context)
+ val expression = fragment.firstChild as? KtExpression ?: return null
+ return expression.resolveCall()?.successfulFunctionCallOrNull()
+ }
+
+ context(KtAnalysisSession)
+ private fun KtForExpression.isSuspendingLoopOrUnresolved(): Boolean {
+ val loopRangeExpression = loopRange ?: return true
+ val psiFactory = KtPsiFactory(project)
+ val iteratorFunction = loopRangeExpression.resolveMemberFunction("iterator", psiFactory) ?: return true
+ if (iteratorFunction.partiallyAppliedSymbol.symbol.isSuspendSymbol()) {
+ return true
+ }
+ val functionsToCheck = listOf("hasNext", "next")
+ for (f in functionsToCheck) {
+ val iteratorExpression = psiFactory.createExpressionByPattern("$0.iterator()", loopRangeExpression)
+ val resolvedFunction = iteratorExpression.resolveMemberFunction(f, psiFactory, loopRangeExpression) ?: return true
+ if (resolvedFunction.partiallyAppliedSymbol.symbol.isSuspendSymbol()) {
+ return true
+ }
+ }
+ return false
+ }
+
+ context(KtAnalysisSession)
+ private fun KtCallInfo.isExternalSuspendOrUnresolved(selfSymbol: KtFunctionSymbol): Boolean {
+ val functionCall = successfulCallOrNull>() ?: return true
+ val symbol = functionCall.partiallyAppliedSymbol.symbol // Recursive call to itself, ignore
+ if (symbol == selfSymbol) return false
+ if (symbol.isSuspendSymbol()) return true
+
+ return if (functionCall is KtCompoundVariableAccessCall) {
+ val compoundAccessSymbol = functionCall.compoundAccess.operationPartiallyAppliedSymbol.symbol
+ if (compoundAccessSymbol == selfSymbol) return false
+ compoundAccessSymbol.isSuspendSymbol()
+ } else {
+ false
+ }
+ }
+
+ context(KtAnalysisSession)
+ private fun KtNamedFunction.hasSuspendOrUnresolvedCall(functionSymbol: KtFunctionSymbol): Boolean {
+ return anyDescendantOfType { expression ->
+ if (expression == this) return@anyDescendantOfType false
+ if (expression is KtForExpression) {
+ return@anyDescendantOfType expression.isSuspendingLoopOrUnresolved()
+ }
+ // If resolveCall returns null, we skip it (likely block/function/etc., not an actual expression we want to analyze)
+ val resolvedCall = expression.resolveCall()
+ ?: return@anyDescendantOfType false
+ // If we cannot resolve to anything or a singular call, then we do not know if this might be suspending or not
+ if (resolvedCall is KtErrorCallInfo) {
+ return@anyDescendantOfType true
+ }
+ resolvedCall.isExternalSuspendOrUnresolved(functionSymbol)
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/k1/test/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/SharedK1InspectionTestGenerated.java b/plugins/kotlin/code-insight/inspections-shared/tests/k1/test/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/SharedK1InspectionTestGenerated.java
index fef21e33fbdc..df227fa0cd2b 100644
--- a/plugins/kotlin/code-insight/inspections-shared/tests/k1/test/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/SharedK1InspectionTestGenerated.java
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/k1/test/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/SharedK1InspectionTestGenerated.java
@@ -229,6 +229,23 @@ public abstract class SharedK1InspectionTestGenerated extends AbstractSharedK1In
}
}
+ @RunWith(JUnit3RunnerWithInners.class)
+ @TestMetadata("../testData/inspections/redundantSuspendModifier")
+ public abstract static class RedundantSuspendModifier extends AbstractSharedK1InspectionTest {
+ @RunWith(JUnit3RunnerWithInners.class)
+ @TestMetadata("../testData/inspections/redundantSuspendModifier/inspectionData")
+ public static class InspectionData extends AbstractSharedK1InspectionTest {
+ private void runTest(String testDataFilePath) throws Exception {
+ KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
+ }
+
+ @TestMetadata("inspections.test")
+ public void testInspections_test() throws Exception {
+ runTest("../testData/inspections/redundantSuspendModifier/inspectionData/inspections.test");
+ }
+ }
+ }
+
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("../testData/inspections/removeSetterParameterType")
public abstract static class RemoveSetterParameterType extends AbstractSharedK1InspectionTest {
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/k1/test/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/SharedK1LocalInspectionTestGenerated.java b/plugins/kotlin/code-insight/inspections-shared/tests/k1/test/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/SharedK1LocalInspectionTestGenerated.java
index ced6f84d3cdd..64ef7cf30227 100644
--- a/plugins/kotlin/code-insight/inspections-shared/tests/k1/test/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/SharedK1LocalInspectionTestGenerated.java
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/k1/test/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/SharedK1LocalInspectionTestGenerated.java
@@ -987,6 +987,134 @@ public abstract class SharedK1LocalInspectionTestGenerated extends AbstractShare
}
}
+ @RunWith(JUnit3RunnerWithInners.class)
+ @TestMetadata("../testData/inspectionsLocal/redundantSuspend")
+ public static class RedundantSuspend extends AbstractSharedK1LocalInspectionTest {
+ private void runTest(String testDataFilePath) throws Exception {
+ KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
+ }
+
+ @TestMetadata("actual.kt")
+ public void testActual() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/actual.kt");
+ }
+
+ @TestMetadata("coroutineContext.kt")
+ public void testCoroutineContext() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/coroutineContext.kt");
+ }
+
+ @TestMetadata("interface.kt")
+ public void testInterface() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/interface.kt");
+ }
+
+ @TestMetadata("interfaceNoBody.kt")
+ public void testInterfaceNoBody() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/interfaceNoBody.kt");
+ }
+
+ @TestMetadata("invokeOperator.kt")
+ public void testInvokeOperator() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/invokeOperator.kt");
+ }
+
+ @TestMetadata("invokingByQualified.kt")
+ public void testInvokingByQualified() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/invokingByQualified.kt");
+ }
+
+ @TestMetadata("lambdaCall.kt")
+ public void testLambdaCall() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/lambdaCall.kt");
+ }
+
+ @TestMetadata("nonSuspendingLoop.kt")
+ public void testNonSuspendingLoop() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/nonSuspendingLoop.kt");
+ }
+
+ @TestMetadata("nonSuspendingLoopExtensionProperty.kt")
+ public void testNonSuspendingLoopExtensionProperty() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopExtensionProperty.kt");
+ }
+
+ @TestMetadata("nonSuspendingLoopIteratorOtherClass.kt")
+ public void testNonSuspendingLoopIteratorOtherClass() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopIteratorOtherClass.kt");
+ }
+
+ @TestMetadata("nonSuspendingLoopLocalExtensionProperty.kt")
+ public void testNonSuspendingLoopLocalExtensionProperty() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopLocalExtensionProperty.kt");
+ }
+
+ @TestMetadata("nullableFunctionType.kt")
+ public void testNullableFunctionType() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/nullableFunctionType.kt");
+ }
+
+ @TestMetadata("operator.kt")
+ public void testOperator() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/operator.kt");
+ }
+
+ @TestMetadata("operatorAssignment.kt")
+ public void testOperatorAssignment() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/operatorAssignment.kt");
+ }
+
+ @TestMetadata("override.kt")
+ public void testOverride() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/override.kt");
+ }
+
+ @TestMetadata("parenthesized.kt")
+ public void testParenthesized() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/parenthesized.kt");
+ }
+
+ @TestMetadata("recursiveCall.kt")
+ public void testRecursiveCall() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/recursiveCall.kt");
+ }
+
+ @TestMetadata("recursiveOperator.kt")
+ public void testRecursiveOperator() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/recursiveOperator.kt");
+ }
+
+ @TestMetadata("recursiveOperatorAssignment.kt")
+ public void testRecursiveOperatorAssignment() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/recursiveOperatorAssignment.kt");
+ }
+
+ @TestMetadata("selfCallWithDifferentReceiver.kt")
+ public void testSelfCallWithDifferentReceiver() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/selfCallWithDifferentReceiver.kt");
+ }
+
+ @TestMetadata("suspendingLoop.kt")
+ public void testSuspendingLoop() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/suspendingLoop.kt");
+ }
+
+ @TestMetadata("suspendingLoopExtensionProperty.kt")
+ public void testSuspendingLoopExtensionProperty() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/suspendingLoopExtensionProperty.kt");
+ }
+
+ @TestMetadata("suspendingLoopIteratorOtherClass.kt")
+ public void testSuspendingLoopIteratorOtherClass() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/suspendingLoopIteratorOtherClass.kt");
+ }
+
+ @TestMetadata("suspendingLoopLocalExtensionProperty.kt")
+ public void testSuspendingLoopLocalExtensionProperty() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/suspendingLoopLocalExtensionProperty.kt");
+ }
+ }
+
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("../testData/inspectionsLocal/redundantValueArgument")
public static class RedundantValueArgument extends AbstractSharedK1LocalInspectionTest {
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/k2/test/org/jetbrains/kotlin/idea/k2/codeInsight/inspections/shared/SharedK2InspectionTestGenerated.java b/plugins/kotlin/code-insight/inspections-shared/tests/k2/test/org/jetbrains/kotlin/idea/k2/codeInsight/inspections/shared/SharedK2InspectionTestGenerated.java
index d8b4607ce728..c5a0071c5798 100644
--- a/plugins/kotlin/code-insight/inspections-shared/tests/k2/test/org/jetbrains/kotlin/idea/k2/codeInsight/inspections/shared/SharedK2InspectionTestGenerated.java
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/k2/test/org/jetbrains/kotlin/idea/k2/codeInsight/inspections/shared/SharedK2InspectionTestGenerated.java
@@ -229,6 +229,23 @@ public abstract class SharedK2InspectionTestGenerated extends AbstractSharedK2In
}
}
+ @RunWith(JUnit3RunnerWithInners.class)
+ @TestMetadata("../testData/inspections/redundantSuspendModifier")
+ public abstract static class RedundantSuspendModifier extends AbstractSharedK2InspectionTest {
+ @RunWith(JUnit3RunnerWithInners.class)
+ @TestMetadata("../testData/inspections/redundantSuspendModifier/inspectionData")
+ public static class InspectionData extends AbstractSharedK2InspectionTest {
+ private void runTest(String testDataFilePath) throws Exception {
+ KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
+ }
+
+ @TestMetadata("inspections.test")
+ public void testInspections_test() throws Exception {
+ runTest("../testData/inspections/redundantSuspendModifier/inspectionData/inspections.test");
+ }
+ }
+ }
+
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("../testData/inspections/removeSetterParameterType")
public abstract static class RemoveSetterParameterType extends AbstractSharedK2InspectionTest {
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/k2/test/org/jetbrains/kotlin/idea/k2/codeInsight/inspections/shared/SharedK2LocalInspectionTestGenerated.java b/plugins/kotlin/code-insight/inspections-shared/tests/k2/test/org/jetbrains/kotlin/idea/k2/codeInsight/inspections/shared/SharedK2LocalInspectionTestGenerated.java
index 954f2c66be62..4a157dde1092 100644
--- a/plugins/kotlin/code-insight/inspections-shared/tests/k2/test/org/jetbrains/kotlin/idea/k2/codeInsight/inspections/shared/SharedK2LocalInspectionTestGenerated.java
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/k2/test/org/jetbrains/kotlin/idea/k2/codeInsight/inspections/shared/SharedK2LocalInspectionTestGenerated.java
@@ -987,6 +987,134 @@ public abstract class SharedK2LocalInspectionTestGenerated extends AbstractShare
}
}
+ @RunWith(JUnit3RunnerWithInners.class)
+ @TestMetadata("../testData/inspectionsLocal/redundantSuspend")
+ public static class RedundantSuspend extends AbstractSharedK2LocalInspectionTest {
+ private void runTest(String testDataFilePath) throws Exception {
+ KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
+ }
+
+ @TestMetadata("actual.kt")
+ public void testActual() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/actual.kt");
+ }
+
+ @TestMetadata("coroutineContext.kt")
+ public void testCoroutineContext() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/coroutineContext.kt");
+ }
+
+ @TestMetadata("interface.kt")
+ public void testInterface() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/interface.kt");
+ }
+
+ @TestMetadata("interfaceNoBody.kt")
+ public void testInterfaceNoBody() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/interfaceNoBody.kt");
+ }
+
+ @TestMetadata("invokeOperator.kt")
+ public void testInvokeOperator() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/invokeOperator.kt");
+ }
+
+ @TestMetadata("invokingByQualified.kt")
+ public void testInvokingByQualified() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/invokingByQualified.kt");
+ }
+
+ @TestMetadata("lambdaCall.kt")
+ public void testLambdaCall() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/lambdaCall.kt");
+ }
+
+ @TestMetadata("nonSuspendingLoop.kt")
+ public void testNonSuspendingLoop() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/nonSuspendingLoop.kt");
+ }
+
+ @TestMetadata("nonSuspendingLoopExtensionProperty.kt")
+ public void testNonSuspendingLoopExtensionProperty() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopExtensionProperty.kt");
+ }
+
+ @TestMetadata("nonSuspendingLoopIteratorOtherClass.kt")
+ public void testNonSuspendingLoopIteratorOtherClass() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopIteratorOtherClass.kt");
+ }
+
+ @TestMetadata("nonSuspendingLoopLocalExtensionProperty.kt")
+ public void testNonSuspendingLoopLocalExtensionProperty() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopLocalExtensionProperty.kt");
+ }
+
+ @TestMetadata("nullableFunctionType.kt")
+ public void testNullableFunctionType() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/nullableFunctionType.kt");
+ }
+
+ @TestMetadata("operator.kt")
+ public void testOperator() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/operator.kt");
+ }
+
+ @TestMetadata("operatorAssignment.kt")
+ public void testOperatorAssignment() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/operatorAssignment.kt");
+ }
+
+ @TestMetadata("override.kt")
+ public void testOverride() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/override.kt");
+ }
+
+ @TestMetadata("parenthesized.kt")
+ public void testParenthesized() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/parenthesized.kt");
+ }
+
+ @TestMetadata("recursiveCall.kt")
+ public void testRecursiveCall() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/recursiveCall.kt");
+ }
+
+ @TestMetadata("recursiveOperator.kt")
+ public void testRecursiveOperator() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/recursiveOperator.kt");
+ }
+
+ @TestMetadata("recursiveOperatorAssignment.kt")
+ public void testRecursiveOperatorAssignment() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/recursiveOperatorAssignment.kt");
+ }
+
+ @TestMetadata("selfCallWithDifferentReceiver.kt")
+ public void testSelfCallWithDifferentReceiver() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/selfCallWithDifferentReceiver.kt");
+ }
+
+ @TestMetadata("suspendingLoop.kt")
+ public void testSuspendingLoop() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/suspendingLoop.kt");
+ }
+
+ @TestMetadata("suspendingLoopExtensionProperty.kt")
+ public void testSuspendingLoopExtensionProperty() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/suspendingLoopExtensionProperty.kt");
+ }
+
+ @TestMetadata("suspendingLoopIteratorOtherClass.kt")
+ public void testSuspendingLoopIteratorOtherClass() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/suspendingLoopIteratorOtherClass.kt");
+ }
+
+ @TestMetadata("suspendingLoopLocalExtensionProperty.kt")
+ public void testSuspendingLoopLocalExtensionProperty() throws Exception {
+ runTest("../testData/inspectionsLocal/redundantSuspend/suspendingLoopLocalExtensionProperty.kt");
+ }
+ }
+
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("../testData/inspectionsLocal/redundantValueArgument")
public static class RedundantValueArgument extends AbstractSharedK2LocalInspectionTest {
diff --git a/plugins/kotlin/idea/tests/testData/inspections/redundantSuspendModifier/inspectionData/expected.xml b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspections/redundantSuspendModifier/inspectionData/expected.xml
similarity index 100%
rename from plugins/kotlin/idea/tests/testData/inspections/redundantSuspendModifier/inspectionData/expected.xml
rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspections/redundantSuspendModifier/inspectionData/expected.xml
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspections/redundantSuspendModifier/inspectionData/inspections.test b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspections/redundantSuspendModifier/inspectionData/inspections.test
new file mode 100644
index 000000000000..3ecd4c147804
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspections/redundantSuspendModifier/inspectionData/inspections.test
@@ -0,0 +1,2 @@
+// INSPECTION_CLASS: org.jetbrains.kotlin.idea.codeInsight.inspections.shared.RedundantSuspendModifierInspection
+// K2_INSPECTION_CLASS: org.jetbrains.kotlin.idea.codeInsight.inspections.shared.RedundantSuspendModifierInspection
diff --git a/plugins/kotlin/idea/tests/testData/inspections/redundantSuspendModifier/operators.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspections/redundantSuspendModifier/operators.kt
similarity index 100%
rename from plugins/kotlin/idea/tests/testData/inspections/redundantSuspendModifier/operators.kt
rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspections/redundantSuspendModifier/operators.kt
diff --git a/plugins/kotlin/idea/tests/testData/inspections/redundantSuspendModifier/test.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspections/redundantSuspendModifier/test.kt
similarity index 100%
rename from plugins/kotlin/idea/tests/testData/inspections/redundantSuspendModifier/test.kt
rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspections/redundantSuspendModifier/test.kt
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/.inspection b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/.inspection
new file mode 100644
index 000000000000..8ff5c3987ad6
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/.inspection
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.codeInsight.inspections.shared.RedundantSuspendModifierInspection
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/actual.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/actual.kt
similarity index 100%
rename from plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/actual.kt
rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/actual.kt
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/coroutineContext.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/coroutineContext.kt
similarity index 100%
rename from plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/coroutineContext.kt
rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/coroutineContext.kt
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/interface.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/interface.kt
new file mode 100644
index 000000000000..62e2e66ea46e
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/interface.kt
@@ -0,0 +1,7 @@
+// PROBLEM: none
+
+interface Suspended {
+ suspend fun bar() {
+
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/interfaceNoBody.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/interfaceNoBody.kt
new file mode 100644
index 000000000000..c71ad9e9dffa
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/interfaceNoBody.kt
@@ -0,0 +1,6 @@
+// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+// PROBLEM: none
+
+interface Suspended {
+ suspend fun bar()
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/invokeOperator.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/invokeOperator.kt
similarity index 100%
rename from plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/invokeOperator.kt
rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/invokeOperator.kt
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/invokingByQualified.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/invokingByQualified.kt
similarity index 100%
rename from plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/invokingByQualified.kt
rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/invokingByQualified.kt
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/lambdaCall.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/lambdaCall.kt
similarity index 100%
rename from plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/lambdaCall.kt
rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/lambdaCall.kt
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoop.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoop.kt
new file mode 100644
index 000000000000..45a90b76dada
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoop.kt
@@ -0,0 +1,11 @@
+class Iterable {
+ operator fun iterator() = this
+ operator fun hasNext(): Boolean = false
+ operator fun next(): Int = 0
+}
+
+suspend fun foo() {
+ val iterable = Iterable()
+ for (x in iterable) {
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoop.kt.after b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoop.kt.after
new file mode 100644
index 000000000000..d61eb718f82e
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoop.kt.after
@@ -0,0 +1,11 @@
+class Iterable {
+ operator fun iterator() = this
+ operator fun hasNext(): Boolean = false
+ operator fun next(): Int = 0
+}
+
+fun foo() {
+ val iterable = Iterable()
+ for (x in iterable) {
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopExtensionProperty.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopExtensionProperty.kt
new file mode 100644
index 000000000000..82278465357d
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopExtensionProperty.kt
@@ -0,0 +1,12 @@
+class SIterable {
+}
+
+operator fun SIterable.iterator() = this
+operator fun SIterable.hasNext(): Boolean = false
+operator fun SIterable.next(): Int = 0
+
+suspend fun foo() {
+ val iterable = SIterable()
+ for (x in iterable) {
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopExtensionProperty.kt.after b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopExtensionProperty.kt.after
new file mode 100644
index 000000000000..7f2521f30564
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopExtensionProperty.kt.after
@@ -0,0 +1,12 @@
+class SIterable {
+}
+
+operator fun SIterable.iterator() = this
+operator fun SIterable.hasNext(): Boolean = false
+operator fun SIterable.next(): Int = 0
+
+fun foo() {
+ val iterable = SIterable()
+ for (x in iterable) {
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopIteratorOtherClass.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopIteratorOtherClass.kt
new file mode 100644
index 000000000000..a913e8f7e392
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopIteratorOtherClass.kt
@@ -0,0 +1,14 @@
+class OtherIterator {
+ operator fun hasNext(): Boolean = false
+ operator fun next(): Int = 0
+}
+
+class SIterable {
+ operator fun iterator() = OtherIterator()
+}
+
+suspend fun foo() {
+ val iterable = SIterable()
+ for (x in iterable) {
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopIteratorOtherClass.kt.after b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopIteratorOtherClass.kt.after
new file mode 100644
index 000000000000..2252c2d902c1
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopIteratorOtherClass.kt.after
@@ -0,0 +1,14 @@
+class OtherIterator {
+ operator fun hasNext(): Boolean = false
+ operator fun next(): Int = 0
+}
+
+class SIterable {
+ operator fun iterator() = OtherIterator()
+}
+
+fun foo() {
+ val iterable = SIterable()
+ for (x in iterable) {
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopLocalExtensionProperty.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopLocalExtensionProperty.kt
new file mode 100644
index 000000000000..c6e70926772e
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopLocalExtensionProperty.kt
@@ -0,0 +1,12 @@
+class SIterable {
+}
+
+suspend fun foo() {
+ operator fun SIterable.iterator() = this
+ operator fun SIterable.hasNext(): Boolean = false
+ operator fun SIterable.next(): Int = 0
+
+ val iterable = SIterable()
+ for (x in iterable) {
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopLocalExtensionProperty.kt.after b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopLocalExtensionProperty.kt.after
new file mode 100644
index 000000000000..54adf890cc56
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nonSuspendingLoopLocalExtensionProperty.kt.after
@@ -0,0 +1,12 @@
+class SIterable {
+}
+
+fun foo() {
+ operator fun SIterable.iterator() = this
+ operator fun SIterable.hasNext(): Boolean = false
+ operator fun SIterable.next(): Int = 0
+
+ val iterable = SIterable()
+ for (x in iterable) {
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/nullableFunctionType.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nullableFunctionType.kt
similarity index 100%
rename from plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/nullableFunctionType.kt
rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/nullableFunctionType.kt
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/operator.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/operator.kt
new file mode 100644
index 000000000000..c0471f7f03b4
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/operator.kt
@@ -0,0 +1,9 @@
+// PROBLEM: none
+
+class A(val x: Int) {
+ suspend operator fun plus(a: A): A = A(1)
+}
+
+suspend fun foo(a1: A, a2: A): A {
+ return a1 + a2
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/operatorAssignment.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/operatorAssignment.kt
new file mode 100644
index 000000000000..ba3e10a51233
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/operatorAssignment.kt
@@ -0,0 +1,10 @@
+// PROBLEM: none
+
+class A(val x: Int) {
+ suspend operator fun plus(a: A): A = A(1)
+}
+
+suspend fun foo(a1: A, a2: A) {
+ var a = a1
+ a += a2
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/override.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/override.kt
similarity index 100%
rename from plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/override.kt
rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/override.kt
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/parenthesized.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/parenthesized.kt
similarity index 100%
rename from plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/parenthesized.kt
rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/parenthesized.kt
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/recursiveCall.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/recursiveCall.kt
similarity index 100%
rename from plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/recursiveCall.kt
rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/recursiveCall.kt
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/recursiveCall.kt.after b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/recursiveCall.kt.after
similarity index 100%
rename from plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/recursiveCall.kt.after
rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/recursiveCall.kt.after
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/recursiveOperator.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/recursiveOperator.kt
new file mode 100644
index 000000000000..ddac84bb01a4
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/recursiveOperator.kt
@@ -0,0 +1,5 @@
+class A(val x: Int) {
+ suspend operator fun plus(a: A): A {
+ return a + a
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/recursiveOperator.kt.after b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/recursiveOperator.kt.after
new file mode 100644
index 000000000000..921644f6ca2d
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/recursiveOperator.kt.after
@@ -0,0 +1,5 @@
+class A(val x: Int) {
+ operator fun plus(a: A): A {
+ return a + a
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/recursiveOperatorAssignment.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/recursiveOperatorAssignment.kt
new file mode 100644
index 000000000000..850ced8ff117
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/recursiveOperatorAssignment.kt
@@ -0,0 +1,7 @@
+class A(val x: Int) {
+ suspend operator fun plus(a: A): A {
+ var a = a
+ a += a
+ return a
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/recursiveOperatorAssignment.kt.after b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/recursiveOperatorAssignment.kt.after
new file mode 100644
index 000000000000..2db3b890d9e7
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/recursiveOperatorAssignment.kt.after
@@ -0,0 +1,7 @@
+class A(val x: Int) {
+ operator fun plus(a: A): A {
+ var a = a
+ a += a
+ return a
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/selfCallWithDifferentReceiver.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/selfCallWithDifferentReceiver.kt
similarity index 100%
rename from plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/selfCallWithDifferentReceiver.kt
rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/selfCallWithDifferentReceiver.kt
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/selfCallWithDifferentReceiver.kt.after b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/selfCallWithDifferentReceiver.kt.after
similarity index 100%
rename from plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/selfCallWithDifferentReceiver.kt.after
rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/selfCallWithDifferentReceiver.kt.after
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/suspendingLoop.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/suspendingLoop.kt
new file mode 100644
index 000000000000..6d6fe0e4faf0
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/suspendingLoop.kt
@@ -0,0 +1,13 @@
+// PROBLEM: none
+
+class SIterable {
+ operator fun iterator() = this
+ suspend operator fun hasNext(): Boolean = false
+ suspend operator fun next(): Int = 0
+}
+
+suspend fun foo() {
+ val iterable = SIterable()
+ for (x in iterable) {
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/suspendingLoopExtensionProperty.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/suspendingLoopExtensionProperty.kt
new file mode 100644
index 000000000000..041d893b63aa
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/suspendingLoopExtensionProperty.kt
@@ -0,0 +1,15 @@
+// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+// PROBLEM: none
+
+class SIterable {
+}
+
+operator fun SIterable.iterator() = this
+suspend operator fun SIterable.hasNext(): Boolean = false
+suspend operator fun SIterable.next(): Int = 0
+
+suspend fun foo() {
+ val iterable = SIterable()
+ for (x in iterable) {
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/suspendingLoopIteratorOtherClass.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/suspendingLoopIteratorOtherClass.kt
new file mode 100644
index 000000000000..7081c75db56a
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/suspendingLoopIteratorOtherClass.kt
@@ -0,0 +1,17 @@
+// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+// PROBLEM: none
+
+class OtherIterator {
+ suspend operator fun hasNext(): Boolean = false
+ suspend operator fun next(): Int = 0
+}
+
+class SIterable {
+ operator fun iterator() = OtherIterator()
+}
+
+suspend fun foo() {
+ val iterable = SIterable()
+ for (x in iterable) {
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/suspendingLoopLocalExtensionProperty.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/suspendingLoopLocalExtensionProperty.kt
new file mode 100644
index 000000000000..ab4dc507033e
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/redundantSuspend/suspendingLoopLocalExtensionProperty.kt
@@ -0,0 +1,15 @@
+// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+// PROBLEM: none
+
+class SIterable {
+}
+
+suspend fun foo() {
+ operator fun SIterable.iterator() = this
+ suspend operator fun SIterable.hasNext(): Boolean = false
+ suspend operator fun SIterable.next(): Int = 0
+
+ val iterable = SIterable()
+ for (x in iterable) {
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantSuspendModifierInspection.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantSuspendModifierInspection.kt
deleted file mode 100644
index b3810c037351..000000000000
--- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantSuspendModifierInspection.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
-
-package org.jetbrains.kotlin.idea.inspections
-
-import com.intellij.codeInspection.IntentionWrapper
-import com.intellij.codeInspection.LocalInspectionToolSession
-import com.intellij.codeInspection.ProblemsHolder
-import com.intellij.psi.PsiElementVisitor
-import org.jetbrains.kotlin.config.LanguageFeature
-import org.jetbrains.kotlin.descriptors.Modality
-import org.jetbrains.kotlin.diagnostics.Errors
-import org.jetbrains.kotlin.idea.base.resources.KotlinBundle
-import org.jetbrains.kotlin.idea.base.projectStructure.languageVersionSettings
-import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent
-import org.jetbrains.kotlin.idea.highlighter.SuspendCallKind
-import org.jetbrains.kotlin.idea.highlighter.getSuspendCallKind
-import org.jetbrains.kotlin.idea.quickfix.RemoveModifierFixBase
-import org.jetbrains.kotlin.lexer.KtTokens
-import org.jetbrains.kotlin.psi.KtExpression
-import org.jetbrains.kotlin.psi.KtNamedFunction
-import org.jetbrains.kotlin.psi.namedFunctionVisitor
-import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
-import org.jetbrains.kotlin.psi.psiUtil.isAncestor
-import org.jetbrains.kotlin.resolve.BindingContext
-import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
-import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall
-
-import org.jetbrains.kotlin.idea.codeinsight.api.classic.inspections.AbstractKotlinInspection
-
-class RedundantSuspendModifierInspection : AbstractKotlinInspection() {
- override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
- return namedFunctionVisitor(fun(function) {
- if (!function.languageVersionSettings.supportsFeature(LanguageFeature.Coroutines)) return
-
- val suspendModifier = function.modifierList?.getModifier(KtTokens.SUSPEND_KEYWORD) ?: return
- if (!function.hasBody()) return
- if (function.hasModifier(KtTokens.OVERRIDE_KEYWORD) || function.hasModifier(KtTokens.ACTUAL_KEYWORD)) return
-
- val context = function.analyzeWithContent()
- val descriptor = context[BindingContext.FUNCTION, function] ?: return
- if (descriptor.modality == Modality.OPEN) return
-
- if (function.hasSuspendCalls(context)) return
-
- if (function.hasAnyUnresolvedCalls(context)) return
-
- holder.registerProblem(
- suspendModifier,
- KotlinBundle.message("redundant.suspend.modifier"),
- IntentionWrapper(RemoveModifierFixBase(function, KtTokens.SUSPEND_KEYWORD, isRedundant = true).asIntention())
- )
- })
- }
-
- private fun KtNamedFunction.hasAnyUnresolvedCalls(context: BindingContext): Boolean {
- return context.diagnostics.any {
- it.factory == Errors.UNRESOLVED_REFERENCE && this.isAncestor(it.psiElement)
- }
- }
-
- private fun KtNamedFunction.hasSuspendCalls(bindingContext: BindingContext): Boolean {
- val selfDescriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, this] ?: return false
-
- return anyDescendantOfType { expression ->
- val kind = getSuspendCallKind(expression, bindingContext) ?: return@anyDescendantOfType false
- if (kind is SuspendCallKind.FunctionCall) {
- val resolvedCall = kind.element.getResolvedCall(bindingContext)
- if (resolvedCall != null) {
- val isSelfCall = when (resolvedCall) {
- is VariableAsFunctionResolvedCall -> selfDescriptor == resolvedCall.functionCall.candidateDescriptor.original
- else -> selfDescriptor == resolvedCall.candidateDescriptor.original
- }
-
- if (isSelfCall) {
- return@anyDescendantOfType false
- }
- }
- }
-
- return@anyDescendantOfType true
- }
- }
-}
diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/InspectionTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/InspectionTestGenerated.java
index 85eb709c477e..79fd7b344b29 100644
--- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/InspectionTestGenerated.java
+++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/InspectionTestGenerated.java
@@ -273,11 +273,6 @@ public abstract class InspectionTestGenerated extends AbstractInspectionTest {
runTest("testData/inspections/redundantSamConstructor/inspectionData/inspections.test");
}
- @TestMetadata("redundantSuspendModifier/inspectionData/inspections.test")
- public void testRedundantSuspendModifier_inspectionData_Inspections_test() throws Exception {
- runTest("testData/inspections/redundantSuspendModifier/inspectionData/inspections.test");
- }
-
@TestMetadata("redundantUnitReturnType/inspectionData/inspections.test")
public void testRedundantUnitReturnType_inspectionData_Inspections_test() throws Exception {
runTest("testData/inspections/redundantUnitReturnType/inspectionData/inspections.test");
diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
index 6b7d4bcebcd4..1ec441e8c3df 100644
--- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
+++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
@@ -10492,64 +10492,6 @@ public abstract class LocalInspectionTestGenerated extends AbstractLocalInspecti
}
}
- @RunWith(JUnit3RunnerWithInners.class)
- @TestMetadata("testData/inspectionsLocal/redundantSuspend")
- public static class RedundantSuspend extends AbstractLocalInspectionTest {
- private void runTest(String testDataFilePath) throws Exception {
- KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
- }
-
- @TestMetadata("actual.kt")
- public void testActual() throws Exception {
- runTest("testData/inspectionsLocal/redundantSuspend/actual.kt");
- }
-
- @TestMetadata("coroutineContext.kt")
- public void testCoroutineContext() throws Exception {
- runTest("testData/inspectionsLocal/redundantSuspend/coroutineContext.kt");
- }
-
- @TestMetadata("invokeOperator.kt")
- public void testInvokeOperator() throws Exception {
- runTest("testData/inspectionsLocal/redundantSuspend/invokeOperator.kt");
- }
-
- @TestMetadata("invokingByQualified.kt")
- public void testInvokingByQualified() throws Exception {
- runTest("testData/inspectionsLocal/redundantSuspend/invokingByQualified.kt");
- }
-
- @TestMetadata("lambdaCall.kt")
- public void testLambdaCall() throws Exception {
- runTest("testData/inspectionsLocal/redundantSuspend/lambdaCall.kt");
- }
-
- @TestMetadata("nullableFunctionType.kt")
- public void testNullableFunctionType() throws Exception {
- runTest("testData/inspectionsLocal/redundantSuspend/nullableFunctionType.kt");
- }
-
- @TestMetadata("override.kt")
- public void testOverride() throws Exception {
- runTest("testData/inspectionsLocal/redundantSuspend/override.kt");
- }
-
- @TestMetadata("parenthesized.kt")
- public void testParenthesized() throws Exception {
- runTest("testData/inspectionsLocal/redundantSuspend/parenthesized.kt");
- }
-
- @TestMetadata("recursiveCall.kt")
- public void testRecursiveCall() throws Exception {
- runTest("testData/inspectionsLocal/redundantSuspend/recursiveCall.kt");
- }
-
- @TestMetadata("selfCallWithDifferentReceiver.kt")
- public void testSelfCallWithDifferentReceiver() throws Exception {
- runTest("testData/inspectionsLocal/redundantSuspend/selfCallWithDifferentReceiver.kt");
- }
- }
-
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("testData/inspectionsLocal/redundantUnitExpression")
public static class RedundantUnitExpression extends AbstractLocalInspectionTest {
diff --git a/plugins/kotlin/idea/tests/testData/inspections/redundantSuspendModifier/inspectionData/inspections.test b/plugins/kotlin/idea/tests/testData/inspections/redundantSuspendModifier/inspectionData/inspections.test
deleted file mode 100644
index f87aff072708..000000000000
--- a/plugins/kotlin/idea/tests/testData/inspections/redundantSuspendModifier/inspectionData/inspections.test
+++ /dev/null
@@ -1 +0,0 @@
-// INSPECTION_CLASS: org.jetbrains.kotlin.idea.inspections.RedundantSuspendModifierInspection
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/.inspection b/plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/.inspection
deleted file mode 100644
index 434360ce1f69..000000000000
--- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/redundantSuspend/.inspection
+++ /dev/null
@@ -1 +0,0 @@
-org.jetbrains.kotlin.idea.inspections.RedundantSuspendModifierInspection
\ No newline at end of file
diff --git a/plugins/kotlin/k2-fe10-bindings/resources/META-INF/fe10Binding.xml b/plugins/kotlin/k2-fe10-bindings/resources/META-INF/fe10Binding.xml
index 54a25d4dbb33..b92e35666267 100644
--- a/plugins/kotlin/k2-fe10-bindings/resources/META-INF/fe10Binding.xml
+++ b/plugins/kotlin/k2-fe10-bindings/resources/META-INF/fe10Binding.xml
@@ -215,14 +215,6 @@
language="kotlin"
key="inspection.redundant.object.type.check.display.name" bundle="messages.KotlinBundle"/>
-
-
-
-