[kotlin] Port AddDefaultConstructorFix to K2

^KTIJ-29474

GitOrigin-RevId: ed1ba91b4127b284a0879cdda7be396de1c2004d
This commit is contained in:
Andrey Cherkasov
2024-07-17 17:22:52 +00:00
committed by intellij-monorepo-bot
parent ae16b81972
commit e6aaa8a221
13 changed files with 160 additions and 7 deletions
@@ -0,0 +1,61 @@
// 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.psi.PsiElement
import org.jetbrains.kotlin.analysis.api.KaSession
import org.jetbrains.kotlin.analysis.api.fir.diagnostics.KaFirDiagnostic
import org.jetbrains.kotlin.analysis.api.symbols.KaClassKind
import org.jetbrains.kotlin.idea.codeinsight.api.applicators.fixes.KotlinQuickFixFactory
import org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
internal object AddDefaultConstructorFixFactory {
val addDefaultConstructorFixFactory = KotlinQuickFixFactory.ModCommandBased { diagnostic: KaFirDiagnostic.UnresolvedReference ->
val baseClass = elementToBaseClass(diagnostic.psi) ?: return@ModCommandBased emptyList()
listOf(
AddDefaultConstructorFix(baseClass)
)
}
}
context(KaSession)
private fun elementToBaseClass(element: PsiElement): KtClass? {
return when {
element is KtConstructorCalleeExpression ->
element.getStrictParentOfType<KtClassOrObject>()
?.superTypeListEntries
?.asSequence()
?.filterIsInstance<KtSuperTypeCallEntry>()
?.firstOrNull()?.let {
superTypeEntryToClass(it)
}
element is KtNameReferenceExpression && element.parent is KtUserType ->
element.getStrictParentOfType<KtAnnotationEntry>()
?.let {
annotationEntryToClass(it)
}
else -> null
}
}
context(KaSession)
private fun superTypeEntryToClass(typeEntry: KtSuperTypeListEntry): KtClass? {
val baseType = typeEntry.typeReference?.type ?: return null
val baseClassSymbol = baseType.expandedSymbol ?: return null
if (!baseClassSymbol.isExpect) return null
if (baseClassSymbol.classKind != KaClassKind.CLASS) return null
return baseClassSymbol.psi as? KtClass
}
context(KaSession)
private fun annotationEntryToClass(entry: KtAnnotationEntry): KtClass? {
val symbol = entry.typeReference?.type?.expandedSymbol ?: return null
if (!symbol.isExpect) return null
return symbol.psi as? KtClass
}
@@ -124,6 +124,7 @@ class KotlinK2QuickFixRegistrar : KotlinQuickFixRegistrar() {
registerFactory(RenameModToRemFixFactory.forbiddenBinaryModFactory)
registerFactory(AddEmptyArgumentListFixFactory.addEmptyArgumentListFixFactory)
registerFactory(KaFirDiagnostic.UnresolvedLabel::class, CreateLabelFixFactory.createLabelFixFactory)
registerFactory(AddDefaultConstructorFixFactory.addDefaultConstructorFixFactory)
}
private val addAbstract = KtQuickFixesListBuilder.registerPsiQuickFix {
@@ -5685,7 +5685,59 @@ public abstract class HighLevelQuickFixTestGenerated extends AbstractHighLevelQu
}
}
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("../../../idea/tests/testData/quickfix/addDefaultConstructor")
public static class AddDefaultConstructor 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("expect.kt")
public void testExpect() throws Exception {
runTest("../../../idea/tests/testData/quickfix/addDefaultConstructor/expect.kt");
}
@TestMetadata("expectAnnotation.kt")
public void testExpectAnnotation() throws Exception {
runTest("../../../idea/tests/testData/quickfix/addDefaultConstructor/expectAnnotation.kt");
}
@TestMetadata("expectAnnotation2.kt")
public void testExpectAnnotation2() throws Exception {
runTest("../../../idea/tests/testData/quickfix/addDefaultConstructor/expectAnnotation2.kt");
}
@TestMetadata("expectAnnotation3.kt")
public void testExpectAnnotation3() throws Exception {
runTest("../../../idea/tests/testData/quickfix/addDefaultConstructor/expectAnnotation3.kt");
}
@TestMetadata("expectAnnotationWithUnresolvedParams.kt")
public void testExpectAnnotationWithUnresolvedParams() throws Exception {
runTest("../../../idea/tests/testData/quickfix/addDefaultConstructor/expectAnnotationWithUnresolvedParams.kt");
}
@TestMetadata("expectInterface.kt")
public void testExpectInterface() throws Exception {
runTest("../../../idea/tests/testData/quickfix/addDefaultConstructor/expectInterface.kt");
}
@TestMetadata("expectWithUnresolvedParams.kt")
public void testExpectWithUnresolvedParams() throws Exception {
runTest("../../../idea/tests/testData/quickfix/addDefaultConstructor/expectWithUnresolvedParams.kt");
}
@TestMetadata("interface.kt")
public void testInterface() throws Exception {
runTest("../../../idea/tests/testData/quickfix/addDefaultConstructor/interface.kt");
}
}
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("../../../idea/tests/testData/quickfix/addElseBranchToIf")
@@ -703,11 +703,21 @@ public abstract class K1QuickFixTestGenerated extends AbstractK1QuickFixTest {
runTest("testData/quickfix/addDefaultConstructor/expectAnnotation3.kt");
}
@TestMetadata("expectAnnotationWithUnresolvedParams.kt")
public void testExpectAnnotationWithUnresolvedParams() throws Exception {
runTest("testData/quickfix/addDefaultConstructor/expectAnnotationWithUnresolvedParams.kt");
}
@TestMetadata("expectInterface.kt")
public void testExpectInterface() throws Exception {
runTest("testData/quickfix/addDefaultConstructor/expectInterface.kt");
}
@TestMetadata("expectWithUnresolvedParams.kt")
public void testExpectWithUnresolvedParams() throws Exception {
runTest("testData/quickfix/addDefaultConstructor/expectWithUnresolvedParams.kt");
}
@TestMetadata("interface.kt")
public void testInterface() throws Exception {
runTest("testData/quickfix/addDefaultConstructor/interface.kt");
@@ -6,4 +6,5 @@ expect open class A
open class C : A<caret>()
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
@@ -6,4 +6,5 @@ expect open class A()
open class C : A()
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
@@ -6,4 +6,5 @@ expect annotation class Foo
@Foo<caret>
fun bar() {}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
@@ -6,4 +6,5 @@ expect annotation class Foo()
@Foo
fun bar() {}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
@@ -6,4 +6,5 @@ expect annotation class Foo
@Foo()<caret>
fun bar() {}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
@@ -6,4 +6,5 @@ expect annotation class Foo()
@Foo()
fun bar() {}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddDefaultConstructorFix
@@ -0,0 +1,12 @@
// "Add default constructor to 'expect' class" "false"
// ENABLE_MULTIPLATFORM
// ERROR: Expected annotation class 'Foo' has no actual declaration in module light_idea_test_case for JVM
// ERROR: This class does not have a constructor
// ERROR: Unresolved reference: x
// ERROR: Unresolved reference: y
// ERROR: Unresolved reference: z
expect annotation class Foo
@Foo(x, y<caret>, z)
fun bar() {}
@@ -0,0 +1,11 @@
// "Add default constructor to 'expect' class" "false"
// ENABLE_MULTIPLATFORM
// ERROR: Expected class 'A' has no actual declaration in module light_idea_test_case for JVM
// ERROR: This class does not have a constructor
// ERROR: Unresolved reference: x
// ERROR: Unresolved reference: y
// ERROR: Unresolved reference: z
expect open class A
open class C : A(x, y<caret>, z)
@@ -66,7 +66,7 @@ internal fun MutableTWorkspace.generateK2FixTests() {
model("$idea/quickfix/addConversionCall", pattern = pattern, isIgnored = true)
model("$idea/quickfix/addCrossinline", pattern = pattern)
model("$idea/quickfix/addDataModifier", pattern = pattern)
model("$idea/quickfix/addDefaultConstructor", pattern = pattern, isIgnored = true)
model("$idea/quickfix/addDefaultConstructor", pattern = pattern)
model("$idea/quickfix/addElseBranchToIf", pattern = pattern)
model("$idea/quickfix/addEmptyArgumentList", pattern = pattern)
model("$idea/quickfix/addEqEqTrue", pattern = pattern)