Introduce "add default constructor for expect class" fix
Related to KT-24597
This commit is contained in:
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.quickfix
|
||||||
|
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
|
|
||||||
|
class AddDefaultConstructorFix(expectClass: KtClass) : KotlinQuickFixAction<KtClass>(expectClass) {
|
||||||
|
|
||||||
|
override fun getText() = "Add default constructor to expect class"
|
||||||
|
|
||||||
|
override fun getFamilyName() = text
|
||||||
|
|
||||||
|
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
||||||
|
element?.createPrimaryConstructorIfAbsent()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object : KotlinSingleIntentionActionFactory() {
|
||||||
|
override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction<KtClass>? {
|
||||||
|
val argumentList = diagnostic.psiElement as? KtValueArgumentList ?: return null
|
||||||
|
if (argumentList.arguments.isNotEmpty()) return null
|
||||||
|
val derivedClass = argumentList.getStrictParentOfType<KtClassOrObject>() ?: return null
|
||||||
|
val context = derivedClass.analyze()
|
||||||
|
val baseTypeCallEntry = derivedClass.superTypeListEntries.filterIsInstance<KtSuperTypeCallEntry>().firstOrNull() ?: return null
|
||||||
|
val baseType = context[BindingContext.TYPE, baseTypeCallEntry.typeReference] ?: return null
|
||||||
|
val baseClassDescriptor = baseType.constructor.declarationDescriptor as? ClassDescriptor ?: return null
|
||||||
|
if (!baseClassDescriptor.isExpect) return null
|
||||||
|
if (baseClassDescriptor.kind != ClassKind.CLASS) return null
|
||||||
|
val baseClass = DescriptorToSourceUtils.descriptorToDeclaration(baseClassDescriptor) as? KtClass ?: return null
|
||||||
|
return AddDefaultConstructorFix(baseClass)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -541,6 +541,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
|||||||
WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET.registerFactory(MoveReceiverAnnotationFix, AddAnnotationTargetFix)
|
WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET.registerFactory(MoveReceiverAnnotationFix, AddAnnotationTargetFix)
|
||||||
|
|
||||||
NO_CONSTRUCTOR.registerFactory(RemoveNoConstructorFix)
|
NO_CONSTRUCTOR.registerFactory(RemoveNoConstructorFix)
|
||||||
|
NO_CONSTRUCTOR.registerFactory(AddDefaultConstructorFix)
|
||||||
|
|
||||||
ANNOTATION_USED_AS_ANNOTATION_ARGUMENT.registerFactory(RemoveAtFromAnnotationArgument)
|
ANNOTATION_USED_AS_ANNOTATION_ARGUMENT.registerFactory(RemoveAtFromAnnotationArgument)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// "Add default constructor to expect class" "true"
|
||||||
|
// ENABLE_MULTIPLATFORM
|
||||||
|
// ERROR: Expected class 'A' has no actual declaration in module light_idea_test_case for JVM
|
||||||
|
|
||||||
|
expect open class A
|
||||||
|
|
||||||
|
open class C : A<caret>()
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// "Add default constructor to expect class" "true"
|
||||||
|
// ENABLE_MULTIPLATFORM
|
||||||
|
// ERROR: Expected class 'A' has no actual declaration in module light_idea_test_case for JVM
|
||||||
|
|
||||||
|
expect open class A()
|
||||||
|
|
||||||
|
open class C : A()
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// "Add default constructor to expect class" "false"
|
||||||
|
// ENABLE_MULTIPLATFORM
|
||||||
|
// ACTION: Create subclass
|
||||||
|
// ACTION: Remove constructor call
|
||||||
|
// ERROR: This class does not have a constructor
|
||||||
|
|
||||||
|
expect interface A
|
||||||
|
|
||||||
|
open class C : A<caret>()
|
||||||
|
|
||||||
|
actual interface A
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// "Add default constructor to expect class" "false"
|
||||||
|
// ACTION: Create subclass
|
||||||
|
// ACTION: Remove constructor call
|
||||||
|
// ERROR: This class does not have a constructor
|
||||||
|
|
||||||
|
interface A
|
||||||
|
|
||||||
|
open class C : A<caret>()
|
||||||
+13
@@ -86,6 +86,19 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/testData/quickfix/addDefaultConstructor")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class AddDefaultConstructor extends AbstractQuickFixMultiFileTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTestWithExtraFile, TargetBackend.ANY, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInAddDefaultConstructor() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/addDefaultConstructor"), Pattern.compile("^(\\w+)\\.((before\\.Main\\.\\w+)|(test))$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/testData/quickfix/addExclExclCall")
|
@TestMetadata("idea/testData/quickfix/addExclExclCall")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
@@ -461,6 +461,34 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/testData/quickfix/addDefaultConstructor")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class AddDefaultConstructor extends AbstractQuickFixTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInAddDefaultConstructor() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/addDefaultConstructor"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expect.kt")
|
||||||
|
public void testExpect() throws Exception {
|
||||||
|
runTest("idea/testData/quickfix/addDefaultConstructor/expect.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expectInterface.kt")
|
||||||
|
public void testExpectInterface() throws Exception {
|
||||||
|
runTest("idea/testData/quickfix/addDefaultConstructor/expectInterface.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("interface.kt")
|
||||||
|
public void testInterface() throws Exception {
|
||||||
|
runTest("idea/testData/quickfix/addDefaultConstructor/interface.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/testData/quickfix/addExclExclCall")
|
@TestMetadata("idea/testData/quickfix/addExclExclCall")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user