[kotlin] Move AddDefaultConstructorFix to frontend independent module

^KTIJ-29474

GitOrigin-RevId: b1aba567b8a669fbc2bb10e0d298a6becc4e1008
This commit is contained in:
Andrey Cherkasov
2024-07-13 02:51:45 +04:00
committed by intellij-monorepo-bot
parent ae0a33ac3b
commit 0de534227c
4 changed files with 57 additions and 52 deletions

View File

@@ -0,0 +1,25 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.quickfix
import com.intellij.modcommand.ActionContext
import com.intellij.modcommand.ModPsiUpdater
import org.jetbrains.kotlin.idea.base.resources.KotlinBundle
import org.jetbrains.kotlin.idea.codeinsight.api.applicable.intentions.KotlinPsiUpdateModCommandAction
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.createPrimaryConstructorIfAbsent
class AddDefaultConstructorFix(
element: KtClass,
) : KotlinPsiUpdateModCommandAction.ElementBased<KtClass, Unit>(element, Unit) {
override fun getFamilyName() = KotlinBundle.message("fix.add.default.constructor")
override fun invoke(
actionContext: ActionContext,
element: KtClass,
elementContext: Unit,
updater: ModPsiUpdater,
) {
element.createPrimaryConstructorIfAbsent()
}
}

View File

@@ -3,63 +3,43 @@
package org.jetbrains.kotlin.idea.quickfix
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.modcommand.ActionContext
import com.intellij.modcommand.ModPsiUpdater
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.base.resources.KotlinBundle
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.codeinsight.api.applicable.intentions.KotlinPsiUpdateModCommandAction
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypes
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
class AddDefaultConstructorFix(
element: KtClass,
) : KotlinPsiUpdateModCommandAction.ElementBased<KtClass, Unit>(element, Unit) {
override fun getFamilyName() = KotlinBundle.message("fix.add.default.constructor")
override fun invoke(
actionContext: ActionContext,
element: KtClass,
elementContext: Unit,
updater: ModPsiUpdater,
) {
element.createPrimaryConstructorIfAbsent()
internal object AddDefaultConstructorFixFactory : KotlinSingleIntentionActionFactory() {
fun superTypeEntryToClass(typeEntry: KtSuperTypeListEntry, context: BindingContext): KtClass? {
val baseType = context[BindingContext.TYPE, typeEntry.typeReference] ?: return null
val baseClassDescriptor = baseType.constructor.declarationDescriptor as? ClassDescriptor ?: return null
if (!baseClassDescriptor.isExpect) return null
if (baseClassDescriptor.kind != ClassKind.CLASS) return null
return DescriptorToSourceUtils.descriptorToDeclaration(baseClassDescriptor) as? KtClass
}
companion object : KotlinSingleIntentionActionFactory() {
fun superTypeEntryToClass(typeEntry: KtSuperTypeListEntry, context: BindingContext): KtClass? {
val baseType = context[BindingContext.TYPE, typeEntry.typeReference] ?: return null
val baseClassDescriptor = baseType.constructor.declarationDescriptor as? ClassDescriptor ?: return null
if (!baseClassDescriptor.isExpect) return null
if (baseClassDescriptor.kind != ClassKind.CLASS) return null
return DescriptorToSourceUtils.descriptorToDeclaration(baseClassDescriptor) as? KtClass
}
private fun annotationEntryToClass(entry: KtAnnotationEntry, context: BindingContext): KtClass? {
val descriptor =
context[BindingContext.ANNOTATION, entry]?.type?.constructor?.declarationDescriptor as? ClassDescriptor ?: return null
if (!descriptor.isExpect) return null
return DescriptorToSourceUtils.descriptorToDeclaration(descriptor) as? KtClass
}
private fun annotationEntryToClass(entry: KtAnnotationEntry, context: BindingContext): KtClass? {
val descriptor =
context[BindingContext.ANNOTATION, entry]?.type?.constructor?.declarationDescriptor as? ClassDescriptor ?: return null
if (!descriptor.isExpect) return null
return DescriptorToSourceUtils.descriptorToDeclaration(descriptor) as? KtClass
}
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val element = diagnostic.psiElement
if (element is KtValueArgumentList && element.arguments.isNotEmpty()) return null
val parent = element.getParentOfTypes(true, KtClassOrObject::class.java, KtAnnotationEntry::class.java) ?: return null
val context by lazy { parent.analyze() }
val baseClass = when (parent) {
is KtClassOrObject -> parent.superTypeListEntries.asSequence().filterIsInstance<KtSuperTypeCallEntry>().firstOrNull()?.let {
superTypeEntryToClass(it, context)
}
is KtAnnotationEntry -> annotationEntryToClass(parent, context)
else -> null
} ?: return null
return AddDefaultConstructorFix(baseClass).asIntention()
}
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val element = diagnostic.psiElement
if (element is KtValueArgumentList && element.arguments.isNotEmpty()) return null
val parent = element.getParentOfTypes(true, KtClassOrObject::class.java, KtAnnotationEntry::class.java) ?: return null
val context by lazy { parent.analyze() }
val baseClass = when (parent) {
is KtClassOrObject -> parent.superTypeListEntries.asSequence().filterIsInstance<KtSuperTypeCallEntry>().firstOrNull()?.let {
superTypeEntryToClass(it, context)
}
is KtAnnotationEntry -> annotationEntryToClass(parent, context)
else -> null
} ?: return null
return AddDefaultConstructorFix(baseClass).asIntention()
}
}

View File

@@ -661,7 +661,7 @@ class QuickFixRegistrar : QuickFixContributor {
WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET.registerFactory(MoveReceiverAnnotationFix, AddAnnotationTargetFix)
NO_CONSTRUCTOR.registerFactory(RemoveNoConstructorFixFactory)
NO_CONSTRUCTOR.registerFactory(AddDefaultConstructorFix)
NO_CONSTRUCTOR.registerFactory(AddDefaultConstructorFixFactory)
NO_CONSTRUCTOR_WARNING.registerFactory(RemoveNoConstructorFixFactory)
ANNOTATION_USED_AS_ANNOTATION_ARGUMENT.registerFactory(RemoveAtFromAnnotationArgument)

View File

@@ -14,17 +14,16 @@ import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.annotations.Nls
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.base.psi.replaced
import org.jetbrains.kotlin.idea.base.resources.KotlinBundle
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.caches.resolve.resolveToParameterDescriptorIfAny
import org.jetbrains.kotlin.idea.codeinsight.api.classic.quickfixes.KotlinQuickFixAction
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.core.isVisible
import org.jetbrains.kotlin.idea.core.moveCaret
import org.jetbrains.kotlin.idea.base.psi.replaced
import org.jetbrains.kotlin.util.match
import org.jetbrains.kotlin.idea.codeinsight.api.classic.quickfixes.KotlinQuickFixAction
import org.jetbrains.kotlin.idea.resolve.languageVersionSettings
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.util.application.isUnitTestMode
@@ -32,6 +31,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
import org.jetbrains.kotlin.psi.psiUtil.parents
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.renderer.render
import org.jetbrains.kotlin.resolve.BindingContext
@@ -42,8 +42,8 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
import org.jetbrains.kotlin.types.isError
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import org.jetbrains.kotlin.util.match
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.psi.psiUtil.parents
object SuperClassNotInitialized : KotlinIntentionActionsFactory() {
private const val DISPLAY_MAX_PARAMS = 5
@@ -133,7 +133,7 @@ object SuperClassNotInitialized : KotlinIntentionActionsFactory() {
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val context = (element.getStrictParentOfType<KtClassOrObject>() ?: element).analyze()
val baseClass = AddDefaultConstructorFix.superTypeEntryToClass(element, context)
val baseClass = AddDefaultConstructorFixFactory.superTypeEntryToClass(element, context)
val newSpecifier = element.replaced(KtPsiFactory(project).createSuperTypeCallEntry(element.text + "()"))
if (baseClass != null && baseClass.hasExpectModifier() && baseClass.secondaryConstructors.isEmpty()) {