Make quickfix factories frontend-agnostic.

Remove AbstractQuickFixFactory and its subobjects, and use
a QuickFixesPsiBasedFactory instead. Add a factory() helper method that
handles the common parent-element lookup logic.

^KTIJ-25177

GitOrigin-RevId: 6e0501192e57edea85e903a028e8243ecbeb57f5
This commit is contained in:
Justin Paupore
2023-04-05 18:37:27 -07:00
committed by intellij-monorepo-bot
parent 85a1e7a26a
commit f11b39eeee
11 changed files with 62 additions and 56 deletions

View File

@@ -10,14 +10,11 @@
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="kotlinc.kotlin-stdlib" level="project" />
<orderEntry type="library" name="kotlinc.kotlin-compiler-common" level="project" />
<orderEntry type="library" name="kotlinc.kotlin-compiler-fe10" level="project" />
<orderEntry type="library" name="kotlinc.parcelize-compiler-plugin" level="project" />
<orderEntry type="module" module-name="kotlin.base.util" />
<orderEntry type="module" module-name="kotlin.base.project-structure" />
<orderEntry type="module" module-name="kotlin.base.analysis" />
<orderEntry type="module" module-name="kotlin.base.code-insight" />
<orderEntry type="module" module-name="kotlin.base.fe10.analysis" />
<orderEntry type="module" module-name="kotlin.base.fe10.code-insight" />
<orderEntry type="module" module-name="kotlin.core" />
<orderEntry type="module" module-name="kotlin.idea" />
<orderEntry type="module" module-name="intellij.java.psi.impl" />

View File

@@ -2,14 +2,14 @@
package org.jetbrains.kotlin.idea.compilerPlugin.parcelize.quickfixes
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.diagnostics.Diagnostic
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.base.codeInsight.ShortenReferencesFacility
import org.jetbrains.kotlin.idea.codeinsight.api.classic.quickfixes.KotlinPsiOnlyQuickFixAction
import org.jetbrains.kotlin.idea.codeinsight.api.classic.quickfixes.KotlinQuickFixAction
import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory
import org.jetbrains.kotlin.idea.codeinsight.api.classic.quickfixes.QuickFixActionBase
import org.jetbrains.kotlin.idea.codeinsight.api.classic.quickfixes.quickFixesPsiBasedFactory
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtPsiFactory
@@ -51,10 +51,6 @@ abstract class AbstractParcelizePsiOnlyQuickFix<T : KtElement>(element: T) : Kot
}
}
abstract class AbstractQuickFixFactory(private val f: Diagnostic.() -> IntentionAction?) : KotlinSingleIntentionActionFactory() {
companion object {
inline fun <reified T : KtElement> Diagnostic.findElement() = psiElement.getNonStrictParentOfType<T>()
}
override fun createAction(diagnostic: Diagnostic) = f(diagnostic)
inline fun <reified T : KtElement> factory(crossinline constructor: (T) -> QuickFixActionBase<*>?) = quickFixesPsiBasedFactory<PsiElement> {
listOfNotNull(it.getNonStrictParentOfType<T>()?.let(constructor))
}

View File

@@ -2,24 +2,16 @@
package org.jetbrains.kotlin.idea.compilerPlugin.parcelize.quickfixes
import org.jetbrains.kotlin.idea.util.addAnnotation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.parcelize.diagnostic.ErrorsParcelize
import org.jetbrains.kotlin.idea.compilerPlugin.parcelize.KotlinParcelizeBundle
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtPsiFactory
class AnnotateWithParcelizeQuickFix(clazz: KtClassOrObject) : AbstractParcelizePsiOnlyQuickFix<KtClassOrObject>(clazz) {
object Factory : AbstractQuickFixFactory(
{
val targetClass = ErrorsParcelize.CLASS_SHOULD_BE_PARCELIZE.cast(this).a
AnnotateWithParcelizeQuickFix(targetClass)
}
)
override fun getText() = KotlinParcelizeBundle.message("parcelize.fix.annotate.containing.class.with.parcelize")
override fun invoke(ktPsiFactory: KtPsiFactory, element: KtClassOrObject) {
element.addAnnotation(FqName("kotlinx.parcelize.Parcelize"))
element.addAnnotationEntry(ktPsiFactory.createAnnotationEntry("@kotlinx.parcelize.Parcelize")).shortenReferences()
}
// No factory - this quickfix needs targeting information from the diagnostic.
}

View File

@@ -2,20 +2,24 @@
package org.jetbrains.kotlin.idea.compilerPlugin.parcelize.quickfixes
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.codeinsight.api.classic.quickfixes.quickFixesPsiBasedFactory
import org.jetbrains.kotlin.idea.compilerPlugin.parcelize.KotlinParcelizeBundle
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPsiFactory
class ParcelRemoveCustomCreatorProperty(property: KtProperty) : AbstractParcelizePsiOnlyQuickFix<KtProperty>(property) {
object Factory : AbstractQuickFixFactory(f@ {
// KtProperty or its name identifier
psiElement as? KtProperty ?: (psiElement.parent as? KtProperty) ?: return@f null
findElement<KtProperty>()?.let(::ParcelRemoveCustomCreatorProperty)
})
override fun getText() = KotlinParcelizeBundle.message("parcelize.fix.remove.custom.creator.property")
override fun invoke(ktPsiFactory: KtPsiFactory, element: KtProperty) {
element.delete()
}
companion object {
val FACTORY = quickFixesPsiBasedFactory<PsiElement> {
// KtProperty or its name identifier
val targetElement = it as? KtProperty ?: it.parent as? KtProperty ?: return@quickFixesPsiBasedFactory emptyList()
listOf(ParcelRemoveCustomCreatorProperty(targetElement))
}
}
}

View File

@@ -7,11 +7,13 @@ import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtPsiFactory
class ParcelRemoveCustomWriteToParcel(function: KtFunction) : AbstractParcelizePsiOnlyQuickFix<KtFunction>(function) {
object Factory : AbstractQuickFixFactory({ findElement<KtFunction>()?.let(::ParcelRemoveCustomWriteToParcel) })
override fun getText() = KotlinParcelizeBundle.message("parcelize.fix.remove.custom.write.to.parcel.function")
override fun invoke(ktPsiFactory: KtPsiFactory, element: KtFunction) {
element.delete()
}
companion object {
val FACTORY = factory(::ParcelRemoveCustomWriteToParcel)
}
}

View File

@@ -2,16 +2,22 @@
package org.jetbrains.kotlin.idea.compilerPlugin.parcelize.quickfixes
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.codeinsight.api.classic.quickfixes.QuickFixesPsiBasedFactory
import org.jetbrains.kotlin.idea.compilerPlugin.parcelize.KotlinParcelizeBundle
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
class ParcelizeAddIgnoreOnParcelAnnotationQuickFix(property: KtProperty) : AbstractParcelizePsiOnlyQuickFix<KtProperty>(property) {
object Factory : AbstractQuickFixFactory({ findElement<KtProperty>()?.let(::ParcelizeAddIgnoreOnParcelAnnotationQuickFix) })
override fun getText() = KotlinParcelizeBundle.message("parcelize.fix.add.ignored.on.parcel.annotation")
override fun invoke(ktPsiFactory: KtPsiFactory, element: KtProperty) {
element.addAnnotationEntry(ktPsiFactory.createAnnotationEntry("@kotlinx.parcelize.IgnoredOnParcel")).shortenReferences()
}
companion object {
val FACTORY = factory(::ParcelizeAddIgnoreOnParcelAnnotationQuickFix)
}
}

View File

@@ -8,8 +8,6 @@ import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.createPrimaryConstructorIfAbsent
class ParcelizeAddPrimaryConstructorQuickFix(clazz: KtClass) : AbstractParcelizePsiOnlyQuickFix<KtClass>(clazz) {
object Factory : AbstractQuickFixFactory({ findElement<KtClass>()?.let(::ParcelizeAddPrimaryConstructorQuickFix) })
override fun getText() = KotlinParcelizeBundle.message("parcelize.fix.add.empty.primary.constructor")
override fun invoke(ktPsiFactory: KtPsiFactory, element: KtClass) {
@@ -23,4 +21,8 @@ class ParcelizeAddPrimaryConstructorQuickFix(clazz: KtClass) : AbstractParcelize
}
}
}
companion object {
val FACTORY = factory(::ParcelizeAddPrimaryConstructorQuickFix)
}
}

View File

@@ -21,12 +21,14 @@ import org.jetbrains.kotlin.parcelize.ParcelizeNames
import org.jetbrains.kotlin.psi.*
class ParcelizeAddSupertypeQuickFix(clazz: KtClassOrObject) : AbstractParcelizePsiOnlyQuickFix<KtClassOrObject>(clazz) {
object Factory : AbstractQuickFixFactory({ findElement<KtClassOrObject>()?.let(::ParcelizeAddSupertypeQuickFix) })
override fun getText() = KotlinParcelizeBundle.message("parcelize.fix.add.parcelable.supertype")
override fun invoke(ktPsiFactory: KtPsiFactory, element: KtClassOrObject) {
val supertypeName = ParcelizeNames.PARCELABLE_ID.asFqNameString()
element.addSuperTypeListEntry(ktPsiFactory.createSuperTypeEntry(supertypeName)).shortenReferences()
}
companion object {
val FACTORY = factory(::ParcelizeAddSupertypeQuickFix)
}
}

View File

@@ -7,11 +7,13 @@ import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtPsiFactory
class ParcelizeRemoveDuplicatingTypeParcelerAnnotationQuickFix(anno: KtAnnotationEntry) : AbstractParcelizePsiOnlyQuickFix<KtAnnotationEntry>(anno) {
object Factory : AbstractQuickFixFactory({ findElement<KtAnnotationEntry>()?.let(::ParcelizeRemoveDuplicatingTypeParcelerAnnotationQuickFix) })
override fun getText() = KotlinParcelizeBundle.message("parcelize.fix.remove.redundant.type.parceler.annotation")
override fun invoke(ktPsiFactory: KtPsiFactory, element: KtAnnotationEntry) {
element.delete()
}
companion object {
val FACTORY = factory(::ParcelizeRemoveDuplicatingTypeParcelerAnnotationQuickFix)
}
}

View File

@@ -4,6 +4,7 @@ package org.jetbrains.kotlin.idea.compilerPlugin.parcelize.quickfixes
import org.jetbrains.kotlin.idea.quickfix.QuickFixContributor
import org.jetbrains.kotlin.idea.quickfix.QuickFixes
import org.jetbrains.kotlin.idea.quickfix.RemoveModifierFix
import org.jetbrains.kotlin.idea.util.createIntentionFactory
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.parcelize.diagnostic.ErrorsParcelize
@@ -14,17 +15,21 @@ class K1ParcelizeQuickFixContributor : QuickFixContributor {
RemoveModifierFix.createRemoveModifierFromListOwnerFactory(KtTokens.INNER_KEYWORD, false)
)
quickFixes.register(ErrorsParcelize.NO_PARCELABLE_SUPERTYPE, ParcelizeAddSupertypeQuickFix.Factory)
quickFixes.register(ErrorsParcelize.PARCELABLE_SHOULD_HAVE_PRIMARY_CONSTRUCTOR, ParcelizeAddPrimaryConstructorQuickFix.Factory)
quickFixes.register(ErrorsParcelize.PROPERTY_WONT_BE_SERIALIZED, ParcelizeAddIgnoreOnParcelAnnotationQuickFix.Factory)
quickFixes.register(ErrorsParcelize.NO_PARCELABLE_SUPERTYPE, ParcelizeAddSupertypeQuickFix.FACTORY)
quickFixes.register(ErrorsParcelize.PARCELABLE_SHOULD_HAVE_PRIMARY_CONSTRUCTOR, ParcelizeAddPrimaryConstructorQuickFix.FACTORY)
quickFixes.register(ErrorsParcelize.PROPERTY_WONT_BE_SERIALIZED, ParcelizeAddIgnoreOnParcelAnnotationQuickFix.FACTORY)
quickFixes.register(ErrorsParcelize.OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED, ParcelMigrateToParcelizeQuickFix.FactoryForWrite)
quickFixes.register(ErrorsParcelize.OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED, ParcelRemoveCustomWriteToParcel.Factory)
quickFixes.register(ErrorsParcelize.OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED, ParcelMigrateToParcelizeQuickFix.FACTORY_FOR_WRITE)
quickFixes.register(ErrorsParcelize.OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED, ParcelRemoveCustomWriteToParcel.FACTORY)
quickFixes.register(ErrorsParcelize.CREATOR_DEFINITION_IS_NOT_ALLOWED, ParcelMigrateToParcelizeQuickFix.FactoryForCREATOR)
quickFixes.register(ErrorsParcelize.CREATOR_DEFINITION_IS_NOT_ALLOWED, ParcelRemoveCustomCreatorProperty.Factory)
quickFixes.register(ErrorsParcelize.CREATOR_DEFINITION_IS_NOT_ALLOWED, ParcelMigrateToParcelizeQuickFix.FACTORY_FOR_CREATOR)
quickFixes.register(ErrorsParcelize.CREATOR_DEFINITION_IS_NOT_ALLOWED, ParcelRemoveCustomCreatorProperty.FACTORY)
quickFixes.register(ErrorsParcelize.REDUNDANT_TYPE_PARCELER, ParcelizeRemoveDuplicatingTypeParcelerAnnotationQuickFix.Factory)
quickFixes.register(ErrorsParcelize.CLASS_SHOULD_BE_PARCELIZE, AnnotateWithParcelizeQuickFix.Factory)
quickFixes.register(ErrorsParcelize.REDUNDANT_TYPE_PARCELER, ParcelizeRemoveDuplicatingTypeParcelerAnnotationQuickFix.FACTORY)
quickFixes.register(
ErrorsParcelize.CLASS_SHOULD_BE_PARCELIZE,
createIntentionFactory { AnnotateWithParcelizeQuickFix(ErrorsParcelize.CLASS_SHOULD_BE_PARCELIZE.cast(it).a) }
)
}
}

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.compilerPlugin.parcelize.quickfixes
@@ -38,6 +38,11 @@ class ParcelMigrateToParcelizeQuickFix(function: KtClass) : AbstractParcelizeQui
private val PARCELER_CREATE_FUNCTION_NAME = Name.identifier("create")
private val LOG = Logger.getInstance(ParcelMigrateToParcelizeQuickFix::class.java)
val FACTORY_FOR_WRITE = factory(::ParcelMigrateToParcelizeQuickFix)
val FACTORY_FOR_CREATOR = factory<KtObjectDeclaration> {
it.getStrictParentOfType<KtClass>()?.let(::ParcelMigrateToParcelizeQuickFix)
}
private fun KtClass.findParcelerCompanionObject(): Pair<KtObjectDeclaration, ClassDescriptor>? {
for (obj in companionObjects) {
val objDescriptor = obj.resolveToDescriptorIfAny() ?: continue
@@ -154,13 +159,6 @@ class ParcelMigrateToParcelizeQuickFix(function: KtClass) : AbstractParcelizeQui
?.constructor?.declarationDescriptor?.fqNameSafe?.asString()
}
object FactoryForWrite : AbstractQuickFixFactory({ findElement<KtClass>()?.let { ParcelMigrateToParcelizeQuickFix(it) } })
object FactoryForCREATOR : AbstractQuickFixFactory({
findElement<KtObjectDeclaration>()?.getStrictParentOfType<KtClass>()
?.let { ParcelMigrateToParcelizeQuickFix(it) }
})
override fun getText() = KotlinParcelizeBundle.message("parcelize.fix.migrate.to.parceler.companion.object")
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")