From 7358cc5bd62fb012050e5bffcb23f11467a06fd6 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Tue, 17 Jul 2018 17:43:23 +0300 Subject: [PATCH] Fix QuickFix-es with the same family name should be the same class instances (KT-25251) #KT-25251 In Progress --- ...bsoleteExperimentalCoroutinesInspection.kt | 87 +++++++++++-------- 1 file changed, 50 insertions(+), 37 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteExperimentalCoroutinesInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteExperimentalCoroutinesInspection.kt index b0791d314bb..2392aefb679 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteExperimentalCoroutinesInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteExperimentalCoroutinesInspection.kt @@ -55,7 +55,7 @@ class ObsoleteExperimentalCoroutinesInspection : AbstractKotlinInspection(), Cle "Methods are absent in coroutines class since 1.3", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly, - ImportExtensionFunctionFix(fixFqName) + ObsoleteCoroutineUsageFix.createExtensionFix(fixFqName) ) holder.registerProblem(problemDescriptor) @@ -73,7 +73,7 @@ class ObsoleteExperimentalCoroutinesInspection : AbstractKotlinInspection(), Cle "Experimental coroutines usages are obsolete since 1.3", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly, - ObsoleteCoroutineImportFix() + ObsoleteCoroutineUsageFix.createImportFix() ) holder.registerProblem(problemDescriptor) @@ -93,9 +93,6 @@ class ObsoleteExperimentalCoroutinesInspection : AbstractKotlinInspection(), Cle 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, @@ -129,43 +126,59 @@ class ObsoleteExperimentalCoroutinesInspection : AbstractKotlinInspection(), Cle } } - private class ObsoleteCoroutineImportFix : LocalQuickFix { - override fun getFamilyName() = QUICK_FIX_NAME + private class ObsoleteCoroutineUsageFix(val delegate: LocalQuickFix) : LocalQuickFix { + override fun getFamilyName(): String = 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 + delegate.applyFix(project, descriptor) + } - val binding = ObsoleteExperimentalCoroutinesInspection.findBinding(simpleNameExpression) ?: return + companion object { + private const val QUICK_FIX_NAME = "Fix experimental coroutines usage" - if (binding.shouldRemove) { - binding.importDirective.delete() - } else { - simpleNameExpression.mainReference.bindToFqName( - binding.bindTo, shorteningMode = KtSimpleNameReference.ShorteningMode.NO_SHORTENING - ) + fun createImportFix() = ObsoleteCoroutineUsageFix(ObsoleteCoroutineImportFix()) + fun createExtensionFix(fqName: String) = ObsoleteCoroutineUsageFix(ImportExtensionFunctionFix(fqName)) + + 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) + } } } } - - 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) - } - } }