From 9bb159d4bc96e4d42ba6befe68b21f9a50ec41c6 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Wed, 14 Oct 2015 22:35:56 +0300 Subject: [PATCH] Code simplifications --- .../quickfix/MapPlatformClassToKotlinFix.kt | 139 ++++++++---------- .../kotlin/idea/quickfix/QuickFixRegistrar.kt | 2 +- 2 files changed, 62 insertions(+), 79 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/MapPlatformClassToKotlinFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/MapPlatformClassToKotlinFix.kt index af5d0670973..1cda2fb32c6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/MapPlatformClassToKotlinFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/MapPlatformClassToKotlinFix.kt @@ -26,17 +26,20 @@ import com.intellij.openapi.project.Project import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile -import com.intellij.psi.util.PsiTreeUtil import com.intellij.refactoring.rename.inplace.MyLookupExpression import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully -import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil +import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType +import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import java.util.* class MapPlatformClassToKotlinFix( @@ -57,28 +60,27 @@ class MapPlatformClassToKotlinFix( override fun getFamilyName() = "Change to Kotlin class" public override fun invoke(project: Project, editor: Editor?, file: JetFile) { - val context = file.analyzeFully() - val diagnostics = context.diagnostics + val bindingContext = file.analyzeFully() + val imports = ArrayList() val usages = ArrayList() - for (diagnostic in diagnostics) { + for (diagnostic in bindingContext.diagnostics) { if (diagnostic.factory !== Errors.PLATFORM_CLASS_MAPPED_TO_KOTLIN) continue + val refExpr = getImportOrUsageFromDiagnostic(diagnostic) ?: continue - val descriptor = resolveToClass(refExpr, context) - if (descriptor == null || descriptor != platformClass) continue - val imp = PsiTreeUtil.getParentOfType(refExpr, JetImportDirective::class.java) - if (imp == null) { - val type = PsiTreeUtil.getParentOfType(refExpr, JetUserType::class.java) ?: continue - usages.add(type) - } else { - imports.add(imp) + if (resolveToClass(refExpr, bindingContext) != platformClass) continue + + val import = refExpr.getStrictParentOfType() + if (import != null) { + imports.add(import) + } + else { + usages.add(refExpr.getStrictParentOfType() ?: continue) } } - for (imp in imports) { - imp.delete() - } + imports.forEach { it.delete() } if (usages.isEmpty()) { // if we are not going to replace any usages, there's no reason to continue at all @@ -97,7 +99,7 @@ class MapPlatformClassToKotlinFix( } private fun replaceUsagesWithFirstClass(project: Project, usages: List): List { - val replacementClass = possibleClasses.iterator().next() + val replacementClass = possibleClasses.first() val replacementClassName = replacementClass.name.asString() val replacedElements = ArrayList() for (usage in usages) { @@ -113,81 +115,62 @@ class MapPlatformClassToKotlinFix( return replacedElements } - companion object { - private val PRIMARY_USAGE = "PrimaryUsage" - private val OTHER_USAGE = "OtherUsage" + private val PRIMARY_USAGE = "PrimaryUsage" + private val OTHER_USAGE = "OtherUsage" - private fun buildAndShowTemplate( - project: Project, editor: Editor, file: PsiFile, - replacedElements: Collection, options: LinkedHashSet) { - PsiDocumentManager.getInstance(project).commitAllDocuments() - PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document) + private fun buildAndShowTemplate( + project: Project, editor: Editor, file: PsiFile, + replacedElements: Collection, options: LinkedHashSet + ) { + PsiDocumentManager.getInstance(project).commitAllDocuments() + PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document) - val primaryReplacedExpression = replacedElements.iterator().next() + val primaryReplacedExpression = replacedElements.iterator().next() - val caretModel = editor.caretModel - val oldOffset = caretModel.offset - caretModel.moveToOffset(file.node.startOffset) + val caretModel = editor.caretModel + val oldOffset = caretModel.offset + caretModel.moveToOffset(file.node.startOffset) - val builder = TemplateBuilderImpl(file) - val expression = MyLookupExpression(primaryReplacedExpression.text, options, null, null, false, "Choose an appropriate Kotlin class") + val builder = TemplateBuilderImpl(file) + val expression = MyLookupExpression(primaryReplacedExpression.text, options, null, null, false, "Choose an appropriate Kotlin class") - builder.replaceElement(primaryReplacedExpression, PRIMARY_USAGE, expression, true) - for (replacedExpression in replacedElements) { - if (replacedExpression === primaryReplacedExpression) continue - builder.replaceElement(replacedExpression, OTHER_USAGE, PRIMARY_USAGE, false) + builder.replaceElement(primaryReplacedExpression, PRIMARY_USAGE, expression, true) + for (replacedExpression in replacedElements) { + if (replacedExpression === primaryReplacedExpression) continue + builder.replaceElement(replacedExpression, OTHER_USAGE, PRIMARY_USAGE, false) + } + + TemplateManager.getInstance(project).startTemplate(editor, builder.buildInlineTemplate(), object : TemplateEditingAdapter() { + override fun templateFinished(template: Template?, brokenOff: Boolean) { + caretModel.moveToOffset(oldOffset) } - TemplateManager.getInstance(project).startTemplate(editor, builder.buildInlineTemplate(), object : TemplateEditingAdapter() { - override fun templateFinished(template: Template?, brokenOff: Boolean) { - caretModel.moveToOffset(oldOffset) - } - }) + }) + } + + companion object : JetSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): IntentionAction? { + val typeExpr = getImportOrUsageFromDiagnostic(diagnostic) ?: return null + + val context = typeExpr.analyze() + val platformClass = resolveToClass(typeExpr, context) ?: return null + + val possibleClasses = Errors.PLATFORM_CLASS_MAPPED_TO_KOTLIN.cast(diagnostic).a + return MapPlatformClassToKotlinFix(typeExpr, platformClass, possibleClasses) } private fun getImportOrUsageFromDiagnostic(diagnostic: Diagnostic): JetReferenceExpression? { - val imp = QuickFixUtil.getParentElementOfType(diagnostic, JetImportDirective::class.java) - val typeExpr: JetReferenceExpression? - if (imp == null) { - val type = QuickFixUtil.getParentElementOfType(diagnostic, JetUserType::class.java) ?: return null - typeExpr = type.referenceExpression - } else { - val importRef = imp.importedReference - if (importRef == null || importRef !is JetDotQualifiedExpression) return null - val refExpr = (importRef as JetDotQualifiedExpression?)?.getSelectorExpression() - if (refExpr == null || refExpr !is JetReferenceExpression) return null - typeExpr = refExpr + val import = diagnostic.psiElement.getNonStrictParentOfType() + return if (import != null) { + import.importedReference?.getQualifiedElementSelector() as? JetReferenceExpression } - return typeExpr - } - - fun createFactory(): JetSingleIntentionActionFactory { - return object : JetSingleIntentionActionFactory() { - public override fun createAction(diagnostic: Diagnostic): IntentionAction? { - val typeExpr = getImportOrUsageFromDiagnostic(diagnostic) ?: return null - - val context = typeExpr.analyze() - val platformClass = resolveToClass(typeExpr, context) ?: return null - - val parametrizedDiagnostic = Errors.PLATFORM_CLASS_MAPPED_TO_KOTLIN.cast(diagnostic) - - return MapPlatformClassToKotlinFix(typeExpr, platformClass, parametrizedDiagnostic.a) - } + else { + (diagnostic.psiElement.getNonStrictParentOfType() ?: return null).referenceExpression } } private fun resolveToClass(referenceExpression: JetReferenceExpression, context: BindingContext): ClassDescriptor? { - val descriptor = context.get(BindingContext.REFERENCE_TARGET, referenceExpression) - val ambiguousTargets = context.get(BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression) - if (descriptor is ClassDescriptor) { - return descriptor - } else if (ambiguousTargets != null) { - for (target in ambiguousTargets) { - if (target is ClassDescriptor) { - return target - } - } - } - return null + return referenceExpression.mainReference.resolveToDescriptors(context).firstIsInstanceOrNull() } + } } diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index fc7c9d7cff2..682621cc20b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -277,7 +277,7 @@ public class QuickFixRegistrar : QuickFixContributor { SMARTCAST_IMPOSSIBLE.registerFactory(CastExpressionFix.createFactoryForSmartCastImpossible()) - PLATFORM_CLASS_MAPPED_TO_KOTLIN.registerFactory(MapPlatformClassToKotlinFix.createFactory()) + PLATFORM_CLASS_MAPPED_TO_KOTLIN.registerFactory(MapPlatformClassToKotlinFix) MANY_CLASSES_IN_SUPERTYPE_LIST.registerFactory(RemoveSupertypeFix.createFactory())