[kotlin] Port RemovePartsFromPropertyFix to K2

^KTIJ-29526

GitOrigin-RevId: 4d612dcec8ea3d2833b22ae4aa25e25c0bd6f4b9
This commit is contained in:
Andrey Cherkasov
2024-05-28 01:08:49 +00:00
committed by intellij-monorepo-bot
parent 552381c09f
commit b1108a4e29
29 changed files with 234 additions and 39 deletions
@@ -371,6 +371,14 @@ class KotlinK2QuickFixRegistrar : KotlinQuickFixRegistrar() {
registerFactory(ActualAnnotationsNotMatchExpectFixFactory.factory)
}
private val removePartsFromProperty = KtQuickFixesListBuilder.registerPsiQuickFix {
registerFactory(RemovePartsFromPropertyFixFactory.abstractPropertyWithGetter)
registerFactory(RemovePartsFromPropertyFixFactory.abstractPropertyWithInitializer)
registerFactory(RemovePartsFromPropertyFixFactory.abstractPropertyWithSetter)
registerFactory(RemovePartsFromPropertyFixFactory.inapplicableLateinitModifier)
registerFactory(RemovePartsFromPropertyFixFactory.propertyInitializerInInterface)
}
private val surroundWithNullCheck = KtQuickFixesListBuilder.registerPsiQuickFix {
registerFactory(SurroundWithNullCheckFixFactory.argumentTypeMismatchFactory)
registerFactory(SurroundWithNullCheckFixFactory.assignmentTypeMismatchFactory)
@@ -398,6 +406,7 @@ class KotlinK2QuickFixRegistrar : KotlinQuickFixRegistrar() {
whenStatements,
typeMismatch,
needExplicitType,
removePartsFromProperty,
superKeyword,
surroundWithNullCheck,
vararg,
@@ -0,0 +1,132 @@
// 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.k2.codeinsight.fixes
import com.intellij.modcommand.ActionContext
import com.intellij.modcommand.ModPsiUpdater
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.api.KaSession
import org.jetbrains.kotlin.analysis.api.fir.diagnostics.KaFirDiagnostic
import org.jetbrains.kotlin.idea.codeinsight.api.applicable.intentions.KotlinPsiUpdateModCommandAction
import org.jetbrains.kotlin.idea.codeinsight.api.applicators.fixes.KotlinQuickFixFactory
import org.jetbrains.kotlin.idea.codeinsight.utils.RemovePartsFromPropertyUtils
import org.jetbrains.kotlin.idea.codeinsights.impl.base.CallableReturnTypeUpdaterUtils
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
internal object RemovePartsFromPropertyFixFactory {
val abstractPropertyWithGetter = KotlinQuickFixFactory.ModCommandBased { diagnostic: KaFirDiagnostic.AbstractPropertyWithGetter ->
createQuickFix(diagnostic.psi)
}
val abstractPropertyWithInitializer = KotlinQuickFixFactory.ModCommandBased { diagnostic: KaFirDiagnostic.AbstractPropertyWithInitializer ->
createQuickFix(diagnostic.psi)
}
val abstractPropertyWithSetter = KotlinQuickFixFactory.ModCommandBased { diagnostic: KaFirDiagnostic.AbstractPropertyWithSetter ->
createQuickFix(diagnostic.psi)
}
val inapplicableLateinitModifier = KotlinQuickFixFactory.ModCommandBased { diagnostic: KaFirDiagnostic.InapplicableLateinitModifier ->
createQuickFix(diagnostic.psi)
}
val propertyInitializerInInterface = KotlinQuickFixFactory.ModCommandBased { diagnostic: KaFirDiagnostic.PropertyInitializerInInterface ->
createQuickFix(diagnostic.psi)
}
context(KaSession)
private fun createQuickFix(
element: KtElement,
): List<RemovePartsFromPropertyFix> {
val property = element.getParentOfType<KtProperty>(strict = false) ?: return emptyList()
val removeInitializer = property.hasInitializer()
val removeGetter = property.getter?.bodyExpression != null
val removeSetter = property.setter?.bodyExpression != null
if (!removeInitializer && !removeGetter && !removeSetter) return emptyList()
val elementContext = ElementContext(
removeInitializer,
removeGetter,
removeSetter,
getTypeInfo(property),
)
return listOf(
RemovePartsFromPropertyFix(property, elementContext)
)
}
context(KaSession)
private fun getTypeInfo(property: KtProperty): CallableReturnTypeUpdaterUtils.TypeInfo? {
if (property.hasInitializer() && property.initializer != null && property.typeReference == null) {
return CallableReturnTypeUpdaterUtils.getTypeInfo(property)
}
return null
}
private data class ElementContext(
val removeInitializer: Boolean,
val removeGetter: Boolean,
val removeSetter: Boolean,
val typeInfo: CallableReturnTypeUpdaterUtils.TypeInfo?,
)
private class RemovePartsFromPropertyFix(
element: KtProperty,
elementContext: ElementContext,
) : KotlinPsiUpdateModCommandAction.ElementBased<KtProperty, ElementContext>(element, elementContext) {
override fun getFamilyName(): String = RemovePartsFromPropertyUtils.getFamilyName()
override fun getActionName(
actionContext: ActionContext,
element: KtProperty,
elementContext: ElementContext,
): String {
val (removeInitializer, removeGetter, removeSetter, _) = elementContext
return RemovePartsFromPropertyUtils.getActionName(removeInitializer, removeGetter, removeSetter)
}
override fun invoke(
actionContext: ActionContext,
element: KtProperty,
elementContext: ElementContext,
updater: ModPsiUpdater,
) {
if (elementContext.removeInitializer) {
removeInitializer(actionContext.project, element, elementContext, updater)
}
if (elementContext.removeGetter) {
element.getter?.delete()
}
if (elementContext.removeSetter) {
element.setter?.delete()
}
}
private fun removeInitializer(
project: Project,
element: KtProperty,
elementContext: ElementContext,
updater: ModPsiUpdater,
) {
val initializer = element.initializer ?: return
element.deleteChildRange(element.equalsToken ?: initializer, initializer)
if (elementContext.typeInfo == null) return
CallableReturnTypeUpdaterUtils.updateType(
declaration = element,
typeInfo = elementContext.typeInfo,
project = project,
editor = null,
updater = updater,
)
}
}
}
@@ -6542,7 +6542,44 @@ public abstract class HighLevelQuickFixTestGenerated extends AbstractHighLevelQu
}
}
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("../../../idea/tests/testData/quickfix/typeImports")
public static class TypeImports extends AbstractHighLevelQuickFixTest {
@java.lang.Override
@org.jetbrains.annotations.NotNull
public final KotlinPluginMode getPluginMode() {
return KotlinPluginMode.K2;
}
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
@TestMetadata("hasThisImport.kt")
public void testHasThisImport() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeImports/hasThisImport.kt");
}
@TestMetadata("noImportFromTheSameFile.kt")
public void testNoImportFromTheSameFile() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeImports/noImportFromTheSameFile.kt");
}
@TestMetadata("noImportJavaLang.kt")
public void testNoImportJavaLang() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeImports/noImportJavaLang.kt");
}
@TestMetadata("noImportJetStandard.kt")
public void testNoImportJetStandard() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeImports/noImportJetStandard.kt");
}
@TestMetadata("toImport1.kt")
public void testToImport1() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeImports/toImport1.kt");
}
}
@@ -3,5 +3,5 @@ abstract class A {
abstract var i = 0<caret>
}
/* IGNORE_K2 */
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -3,5 +3,5 @@ abstract class A {
abstract var i: Int
}
/* IGNORE_K2 */
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -3,5 +3,5 @@ abstract class A {
abstract var i: Int = 0<caret>
}
/* IGNORE_K2 */
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -3,5 +3,5 @@ abstract class A {
abstract var i: Int<caret>
}
/* IGNORE_K2 */
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -3,5 +3,5 @@ abstract class B {
abstract val i = <caret>0
get() = field
}
/* IGNORE_K2 */
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -2,5 +2,5 @@
abstract class B {
abstract val i: Int<caret>
}
/* IGNORE_K2 */
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -4,5 +4,5 @@ class A {
<caret>lateinit var str: String
get() = ""
}
/* IGNORE_K2 */
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -3,5 +3,5 @@
class A {
<caret>lateinit var str: String
}
/* IGNORE_K2 */
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -5,5 +5,5 @@ class A {
get() = ""
set(value) {}
}
/* IGNORE_K2 */
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -3,5 +3,5 @@
class A {
<caret>lateinit var str: String
}
/* IGNORE_K2 */
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -0,0 +1,7 @@
// "Remove initializer from property" "true"
class A {
lateinit var str: String<caret>
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -3,5 +3,5 @@
class A {
<caret>lateinit var str = ""
}
/* IGNORE_K2 */
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -3,5 +3,5 @@
class A {
<caret>lateinit var str: String
}
/* IGNORE_K2 */
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -4,5 +4,5 @@ class A {
<caret>lateinit var str: String
set(value) {}
}
/* IGNORE_K2 */
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -3,5 +3,5 @@
class A {
<caret>lateinit var str: String
}
/* IGNORE_K2 */
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -8,4 +8,5 @@ class M {
val l = <caret>emptyList<Int>()
}
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -8,4 +8,5 @@ class M {
val l: List<Int><caret>
}
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -5,4 +5,5 @@ class A() {}
class B() {
public val <caret>a = A()
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyIntention
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyIntention
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.intentions.SpecifyTypeExplicitlyIntention
@@ -5,4 +5,5 @@ class A() {}
class B() {
public val a: A<caret> = A()
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyIntention
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyIntention
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.intentions.SpecifyTypeExplicitlyIntention
@@ -6,4 +6,5 @@ class M {
abstract val e = <caret>Thread()
}
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -6,4 +6,5 @@ class M {
abstract val e: Thread<caret>
}
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -6,4 +6,5 @@ class M {
abstract val i = <caret>10
}
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -6,4 +6,5 @@ class M {
abstract val i: Int<caret>
}
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -8,4 +8,5 @@ class M {
abstract val l = <caret>emptyList<Int>()
}
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -8,4 +8,5 @@ class M {
abstract val l: List<Int><caret>
}
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.RemovePartsFromPropertyFixFactory$RemovePartsFromPropertyFix
@@ -191,7 +191,7 @@ internal fun MutableTWorkspace.generateK2FixTests() {
model("$idea/quickfix/surroundWithNullCheck", pattern = pattern)
model("$idea/quickfix/suspiciousCollectionReassignment", pattern = pattern, isIgnored = true)
model("$idea/quickfix/tooLongCharLiteralToString", pattern = pattern)
model("$idea/quickfix/typeImports", pattern = pattern, isIgnored = true)
model("$idea/quickfix/typeImports", pattern = pattern)
model("$idea/quickfix/typeInferenceExpectedTypeMismatch", pattern = pattern, isIgnored = true)
model("$idea/quickfix/typeOfAnnotationMember", pattern = pattern)
model("$idea/quickfix/typeParameters", pattern = pattern, isIgnored = true)