From f9de91016a3c9cb7b891c54d8b03d7fe478e43d5 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Mon, 9 Jul 2018 13:33:54 +0300 Subject: [PATCH] Inspection for experimental coroutines imports migration (KT-25251) #KT-25251 In Progress --- ...oleteExperimentalCoroutinesInspection.html | 5 + idea/src/META-INF/plugin.xml | 9 + idea/src/META-INF/plugin.xml.172 | 9 + idea/src/META-INF/plugin.xml.173 | 9 + idea/src/META-INF/plugin.xml.182 | 9 + idea/src/META-INF/plugin.xml.as31 | 9 + idea/src/META-INF/plugin.xml.as32 | 9 + ...bsoleteExperimentalCoroutinesInspection.kt | 171 ++++++++++++++++++ .../quickfix/obsoleteCoroutines/.inspection | 1 + .../obsoleteCoroutines/buildSequence.kt | 8 + .../obsoleteCoroutines/buildSequence.kt.after | 7 + .../quickfix/obsoleteCoroutines/resume.kt | 9 + .../obsoleteCoroutines/resume.kt.after | 9 + .../obsoleteCoroutines/resumeWithException.kt | 9 + .../resumeWithException.kt.after | 9 + .../quickfix/obsoleteCoroutines/starImport.kt | 4 + .../obsoleteCoroutines/starImport.kt.after | 4 + .../unresolvedKotlinxImport.kt | 4 + .../unresolvedKotlinxImport.kt.after | 4 + .../QuickFixMultiFileTestGenerated.java | 13 ++ .../QuickFixMultiFileTestGenerated.java.172 | 13 ++ .../idea/quickfix/QuickFixTestGenerated.java | 38 ++++ 22 files changed, 362 insertions(+) create mode 100644 idea/resources/inspectionDescriptions/ObsoleteExperimentalCoroutinesInspection.html create mode 100644 idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteExperimentalCoroutinesInspection.kt create mode 100644 idea/testData/quickfix/obsoleteCoroutines/.inspection create mode 100644 idea/testData/quickfix/obsoleteCoroutines/buildSequence.kt create mode 100644 idea/testData/quickfix/obsoleteCoroutines/buildSequence.kt.after create mode 100644 idea/testData/quickfix/obsoleteCoroutines/resume.kt create mode 100644 idea/testData/quickfix/obsoleteCoroutines/resume.kt.after create mode 100644 idea/testData/quickfix/obsoleteCoroutines/resumeWithException.kt create mode 100644 idea/testData/quickfix/obsoleteCoroutines/resumeWithException.kt.after create mode 100644 idea/testData/quickfix/obsoleteCoroutines/starImport.kt create mode 100644 idea/testData/quickfix/obsoleteCoroutines/starImport.kt.after create mode 100644 idea/testData/quickfix/obsoleteCoroutines/unresolvedKotlinxImport.kt create mode 100644 idea/testData/quickfix/obsoleteCoroutines/unresolvedKotlinxImport.kt.after diff --git a/idea/resources/inspectionDescriptions/ObsoleteExperimentalCoroutinesInspection.html b/idea/resources/inspectionDescriptions/ObsoleteExperimentalCoroutinesInspection.html new file mode 100644 index 00000000000..f0b0060fe63 --- /dev/null +++ b/idea/resources/inspectionDescriptions/ObsoleteExperimentalCoroutinesInspection.html @@ -0,0 +1,5 @@ + + +This inspection reports experimental coroutines usages that are incompatible with Kotlin 1.3+ and should be updated. + + \ No newline at end of file diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 27a16ef9d79..357371848af 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -2918,6 +2918,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. language="kotlin" /> + + diff --git a/idea/src/META-INF/plugin.xml.172 b/idea/src/META-INF/plugin.xml.172 index ecc5a17b8bc..bc4f36e37cd 100644 --- a/idea/src/META-INF/plugin.xml.172 +++ b/idea/src/META-INF/plugin.xml.172 @@ -2915,6 +2915,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. language="kotlin" /> + + diff --git a/idea/src/META-INF/plugin.xml.173 b/idea/src/META-INF/plugin.xml.173 index 31ba66d7720..aa729525a53 100644 --- a/idea/src/META-INF/plugin.xml.173 +++ b/idea/src/META-INF/plugin.xml.173 @@ -2918,6 +2918,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. language="kotlin" /> + + diff --git a/idea/src/META-INF/plugin.xml.182 b/idea/src/META-INF/plugin.xml.182 index d14bc560226..f551fd17f96 100644 --- a/idea/src/META-INF/plugin.xml.182 +++ b/idea/src/META-INF/plugin.xml.182 @@ -2919,6 +2919,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. language="kotlin" /> + + diff --git a/idea/src/META-INF/plugin.xml.as31 b/idea/src/META-INF/plugin.xml.as31 index b011388df1b..f138c9ddd2f 100644 --- a/idea/src/META-INF/plugin.xml.as31 +++ b/idea/src/META-INF/plugin.xml.as31 @@ -2918,6 +2918,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. language="kotlin" /> + + diff --git a/idea/src/META-INF/plugin.xml.as32 b/idea/src/META-INF/plugin.xml.as32 index 6903aa15dca..7ab66c7c4fc 100644 --- a/idea/src/META-INF/plugin.xml.as32 +++ b/idea/src/META-INF/plugin.xml.as32 @@ -2918,6 +2918,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. language="kotlin" /> + + diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteExperimentalCoroutinesInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteExperimentalCoroutinesInspection.kt new file mode 100644 index 00000000000..b0791d314bb --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteExperimentalCoroutinesInspection.kt @@ -0,0 +1,171 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.inspections.migration + +import com.intellij.codeInspection.* +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.project.Project +import com.intellij.psi.search.GlobalSearchScope +import org.jetbrains.kotlin.config.LanguageVersion +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny +import org.jetbrains.kotlin.idea.imports.importableFqName +import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection +import org.jetbrains.kotlin.idea.project.languageVersionSettings +import org.jetbrains.kotlin.idea.references.KtSimpleNameReference +import org.jetbrains.kotlin.idea.references.mainReference +import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors +import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionFqnNameIndex +import org.jetbrains.kotlin.idea.util.ImportInsertHelper +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.parents +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull + +class ObsoleteExperimentalCoroutinesInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): KtVisitorVoid { + return simpleNameExpressionVisitor(fun(simpleNameExpression) { + run { + val versionAtLeast13 = simpleNameExpression.languageVersionSettings.languageVersion >= LanguageVersion.KOTLIN_1_3 + if (!versionAtLeast13 && !ApplicationManager.getApplication().isUnitTestMode) { + return + } + } + + when (simpleNameExpression.text) { + RESUME_MARKER, RESUME_WITH_EXCEPTION_MARKER -> { + simpleNameExpression.parent as? KtCallExpression ?: return + + val descriptor = simpleNameExpression.resolveMainReferenceToDescriptors().firstOrNull() ?: return + val callableDescriptor = descriptor as? CallableDescriptor ?: return + + val resolvedToFqName = callableDescriptor.fqNameOrNull()?.asString() ?: return + val fixFqName = when (resolvedToFqName) { + RESUME_FUNCTION_FQNAME -> RESUME_FUNCTION_FIX_FQNAME + RESUME_WITH_EXCEPTION_FQNAME -> RESUME_WITH_EXCEPTION_FIX_FQNAME + else -> null + } ?: return + + val problemDescriptor = holder.manager.createProblemDescriptor( + simpleNameExpression, + simpleNameExpression, + "Methods are absent in coroutines class since 1.3", + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + isOnTheFly, + ImportExtensionFunctionFix(fixFqName) + ) + + holder.registerProblem(problemDescriptor) + } + + EXPERIMENTAL_COROUTINES_MARKER -> { + val parent = simpleNameExpression.parent as? KtExpression ?: return + val reportExpression = parent as? KtDotQualifiedExpression ?: simpleNameExpression + + findBinding(simpleNameExpression) ?: return + + val problemDescriptor = holder.manager.createProblemDescriptor( + reportExpression, + reportExpression, + "Experimental coroutines usages are obsolete since 1.3", + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + isOnTheFly, + ObsoleteCoroutineImportFix() + ) + + holder.registerProblem(problemDescriptor) + } + } + }) + } + + companion object { + private const val EXPERIMENTAL_COROUTINES_MARKER = "experimental" + + private const val RESUME_MARKER = "resume" + private const val RESUME_FUNCTION_FQNAME = "kotlin.coroutines.experimental.Continuation.resume" + private const val RESUME_FUNCTION_FIX_FQNAME = "kotlin.coroutines.resume" + + private const val RESUME_WITH_EXCEPTION_MARKER = "resumeWithException" + private const val RESUME_WITH_EXCEPTION_FQNAME = "kotlin.coroutines.experimental.Continuation.resumeWithException" + private const val RESUME_WITH_EXCEPTION_FIX_FQNAME = "kotlin.coroutines.resumeWithException" + + // All quick-fixes should have same name to be executable together + private const val QUICK_FIX_NAME = "Fix experimental coroutines usage" + + private class Binding( + val bindTo: FqName, + val shouldRemove: Boolean, + val importDirective: KtImportDirective + ) + + @Suppress("SpellCheckingInspection") + private val PACKAGE_BINDING = mapOf( + "kotlinx.coroutines.experimental" to "kotlinx.coroutines", + "kotlin.coroutines.experimental" to "kotlin.coroutines" + ) + + private val IMPORTS_TO_REMOVE = setOf( + "kotlin.coroutines.experimental.buildSequence" + ) + + private fun findBinding(simpleNameExpression: KtSimpleNameExpression): Binding? { + if (simpleNameExpression.text != EXPERIMENTAL_COROUTINES_MARKER) return null + + val importDirective = simpleNameExpression.parents + .takeWhile { it is KtDotQualifiedExpression || it is KtImportDirective } + .lastOrNull() as? KtImportDirective ?: return null + + val fqNameStr = importDirective.importedFqName?.asString() ?: return null + + val bindEntry = PACKAGE_BINDING.entries.find { (affectedImportPrefix, _) -> + fqNameStr.startsWith(affectedImportPrefix) + } ?: return null + + return Binding(FqName(bindEntry.value), fqNameStr in IMPORTS_TO_REMOVE, importDirective) + } + } + + private class ObsoleteCoroutineImportFix : LocalQuickFix { + override fun getFamilyName() = QUICK_FIX_NAME + + override fun applyFix(project: Project, descriptor: ProblemDescriptor) { + val element = descriptor.psiElement + val simpleNameExpression = when (element) { + is KtSimpleNameExpression -> element + is KtDotQualifiedExpression -> element.selectorExpression as? KtSimpleNameExpression + else -> null + } ?: return + + val binding = ObsoleteExperimentalCoroutinesInspection.findBinding(simpleNameExpression) ?: return + + if (binding.shouldRemove) { + binding.importDirective.delete() + } else { + simpleNameExpression.mainReference.bindToFqName( + binding.bindTo, shorteningMode = KtSimpleNameReference.ShorteningMode.NO_SHORTENING + ) + } + } + } + + private class ImportExtensionFunctionFix(val fqName: String) : LocalQuickFix { + override fun getFamilyName() = QUICK_FIX_NAME + + override fun applyFix(project: Project, descriptor: ProblemDescriptor) { + val element = descriptor.psiElement + element as? KtSimpleNameExpression ?: return + + val importFun = + KotlinTopLevelFunctionFqnNameIndex.getInstance().get(fqName, element.project, GlobalSearchScope.allScope(element.project)) + .asSequence() + .map { it.resolveToDescriptorIfAny() } + .find { it != null && it.importableFqName?.asString() == fqName } ?: return + + ImportInsertHelper.getInstance(element.project).importDescriptor(element.containingKtFile, importFun, false) + } + } +} diff --git a/idea/testData/quickfix/obsoleteCoroutines/.inspection b/idea/testData/quickfix/obsoleteCoroutines/.inspection new file mode 100644 index 00000000000..6c77dc329c6 --- /dev/null +++ b/idea/testData/quickfix/obsoleteCoroutines/.inspection @@ -0,0 +1 @@ +org.jetbrains.kotlin.idea.inspections.migration.ObsoleteExperimentalCoroutinesInspection diff --git a/idea/testData/quickfix/obsoleteCoroutines/buildSequence.kt b/idea/testData/quickfix/obsoleteCoroutines/buildSequence.kt new file mode 100644 index 00000000000..6c0269e1924 --- /dev/null +++ b/idea/testData/quickfix/obsoleteCoroutines/buildSequence.kt @@ -0,0 +1,8 @@ +// "Fix experimental coroutines usage" "true" +// ERROR: Unresolved reference: buildSequence +import kotlin.coroutines.experimental.buildSequence + +fun main(args: Array) { + val lazySeq = buildSequence { + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/obsoleteCoroutines/buildSequence.kt.after b/idea/testData/quickfix/obsoleteCoroutines/buildSequence.kt.after new file mode 100644 index 00000000000..d1b2117b0eb --- /dev/null +++ b/idea/testData/quickfix/obsoleteCoroutines/buildSequence.kt.after @@ -0,0 +1,7 @@ +// "Fix experimental coroutines usage" "true" +// ERROR: Unresolved reference: buildSequence + +fun main(args: Array) { + val lazySeq = buildSequence { + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/obsoleteCoroutines/resume.kt b/idea/testData/quickfix/obsoleteCoroutines/resume.kt new file mode 100644 index 00000000000..4ef619567ae --- /dev/null +++ b/idea/testData/quickfix/obsoleteCoroutines/resume.kt @@ -0,0 +1,9 @@ +// "Fix experimental coroutines usage" "true" +// SHOULD_BE_AVAILABLE_AFTER_EXECUTION +// WITH_RUNTIME + +import kotlin.coroutines.experimental.Continuation + +fun test(con: Continuation) { + con.resume(12) +} \ No newline at end of file diff --git a/idea/testData/quickfix/obsoleteCoroutines/resume.kt.after b/idea/testData/quickfix/obsoleteCoroutines/resume.kt.after new file mode 100644 index 00000000000..4ef619567ae --- /dev/null +++ b/idea/testData/quickfix/obsoleteCoroutines/resume.kt.after @@ -0,0 +1,9 @@ +// "Fix experimental coroutines usage" "true" +// SHOULD_BE_AVAILABLE_AFTER_EXECUTION +// WITH_RUNTIME + +import kotlin.coroutines.experimental.Continuation + +fun test(con: Continuation) { + con.resume(12) +} \ No newline at end of file diff --git a/idea/testData/quickfix/obsoleteCoroutines/resumeWithException.kt b/idea/testData/quickfix/obsoleteCoroutines/resumeWithException.kt new file mode 100644 index 00000000000..a0b8595520b --- /dev/null +++ b/idea/testData/quickfix/obsoleteCoroutines/resumeWithException.kt @@ -0,0 +1,9 @@ +// "Fix experimental coroutines usage" "true" +// SHOULD_BE_AVAILABLE_AFTER_EXECUTION +// WITH_RUNTIME + +import kotlin.coroutines.experimental.Continuation + +fun test(con: Continuation) { + con.resumeWithException(RuntimeException("Haha")) +} \ No newline at end of file diff --git a/idea/testData/quickfix/obsoleteCoroutines/resumeWithException.kt.after b/idea/testData/quickfix/obsoleteCoroutines/resumeWithException.kt.after new file mode 100644 index 00000000000..a0b8595520b --- /dev/null +++ b/idea/testData/quickfix/obsoleteCoroutines/resumeWithException.kt.after @@ -0,0 +1,9 @@ +// "Fix experimental coroutines usage" "true" +// SHOULD_BE_AVAILABLE_AFTER_EXECUTION +// WITH_RUNTIME + +import kotlin.coroutines.experimental.Continuation + +fun test(con: Continuation) { + con.resumeWithException(RuntimeException("Haha")) +} \ No newline at end of file diff --git a/idea/testData/quickfix/obsoleteCoroutines/starImport.kt b/idea/testData/quickfix/obsoleteCoroutines/starImport.kt new file mode 100644 index 00000000000..bef053100b1 --- /dev/null +++ b/idea/testData/quickfix/obsoleteCoroutines/starImport.kt @@ -0,0 +1,4 @@ +// "Fix experimental coroutines usage" "true" +// ERROR: Unresolved reference: coroutines + +import kotlin.coroutines.experimental.* \ No newline at end of file diff --git a/idea/testData/quickfix/obsoleteCoroutines/starImport.kt.after b/idea/testData/quickfix/obsoleteCoroutines/starImport.kt.after new file mode 100644 index 00000000000..ab63b4f7f37 --- /dev/null +++ b/idea/testData/quickfix/obsoleteCoroutines/starImport.kt.after @@ -0,0 +1,4 @@ +// "Fix experimental coroutines usage" "true" +// ERROR: Unresolved reference: coroutines + +import kotlin.coroutines.* \ No newline at end of file diff --git a/idea/testData/quickfix/obsoleteCoroutines/unresolvedKotlinxImport.kt b/idea/testData/quickfix/obsoleteCoroutines/unresolvedKotlinxImport.kt new file mode 100644 index 00000000000..74450e5e68f --- /dev/null +++ b/idea/testData/quickfix/obsoleteCoroutines/unresolvedKotlinxImport.kt @@ -0,0 +1,4 @@ +// "Fix experimental coroutines usage" "true" +// ERROR: Unresolved reference: kotlinx + +import kotlinx.coroutines.experimental.delay \ No newline at end of file diff --git a/idea/testData/quickfix/obsoleteCoroutines/unresolvedKotlinxImport.kt.after b/idea/testData/quickfix/obsoleteCoroutines/unresolvedKotlinxImport.kt.after new file mode 100644 index 00000000000..3af1ea94b1d --- /dev/null +++ b/idea/testData/quickfix/obsoleteCoroutines/unresolvedKotlinxImport.kt.after @@ -0,0 +1,4 @@ +// "Fix experimental coroutines usage" "true" +// ERROR: Unresolved reference: kotlinx + +import kotlinx.coroutines.delay \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java index 209bc3896ea..f7386b0b664 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java @@ -3026,6 +3026,19 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes } } + @TestMetadata("idea/testData/quickfix/obsoleteCoroutines") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ObsoleteCoroutines extends AbstractQuickFixMultiFileTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTestWithExtraFile, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInObsoleteCoroutines() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/obsoleteCoroutines"), Pattern.compile("^(\\w+)\\.((before\\.Main\\.\\w+)|(test))$"), TargetBackend.ANY, true); + } + } + @TestMetadata("idea/testData/quickfix/optimizeImports") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java.172 b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java.172 index d009241d5e8..f1a3cd005ff 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java.172 +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java.172 @@ -1916,6 +1916,19 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes } } + @TestMetadata("idea/testData/quickfix/obsoleteCoroutines") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ObsoleteCoroutines extends AbstractQuickFixMultiFileTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTestWithExtraFile, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInObsoleteCoroutines() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/obsoleteCoroutines"), Pattern.compile("^(\\w+)\\.((before\\.Main\\.\\w+)|(test))$"), TargetBackend.ANY, true); + } + } + @TestMetadata("idea/testData/quickfix/optimizeImports") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 2411a35042c..6cd2aa7a0d0 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -8146,6 +8146,44 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { } } + @TestMetadata("idea/testData/quickfix/obsoleteCoroutines") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ObsoleteCoroutines extends AbstractQuickFixTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInObsoleteCoroutines() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/obsoleteCoroutines"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("buildSequence.kt") + public void testBuildSequence() throws Exception { + runTest("idea/testData/quickfix/obsoleteCoroutines/buildSequence.kt"); + } + + @TestMetadata("resume.kt") + public void testResume() throws Exception { + runTest("idea/testData/quickfix/obsoleteCoroutines/resume.kt"); + } + + @TestMetadata("resumeWithException.kt") + public void testResumeWithException() throws Exception { + runTest("idea/testData/quickfix/obsoleteCoroutines/resumeWithException.kt"); + } + + @TestMetadata("starImport.kt") + public void testStarImport() throws Exception { + runTest("idea/testData/quickfix/obsoleteCoroutines/starImport.kt"); + } + + @TestMetadata("unresolvedKotlinxImport.kt") + public void testUnresolvedKotlinxImport() throws Exception { + runTest("idea/testData/quickfix/obsoleteCoroutines/unresolvedKotlinxImport.kt"); + } + } + @TestMetadata("idea/testData/quickfix/optimizeImports") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)