Add a quick fix for NO_CONSTRUCTOR error on 'expect' annotation entry
#KT-20718 Fixed
This commit is contained in:
committed by
Dmitry Gridin
parent
d846a22e33
commit
7be5410877
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypes
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
|
||||
@@ -36,14 +36,25 @@ class AddDefaultConstructorFix(expectClass: KtClass) : KotlinQuickFixAction<KtCl
|
||||
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
|
||||
}
|
||||
|
||||
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.asSequence().filterIsInstance<KtSuperTypeCallEntry>().firstOrNull()
|
||||
?: return null
|
||||
val baseClass = superTypeEntryToClass(baseTypeCallEntry, context) ?: return null
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Add default constructor to expect class" "true"
|
||||
// ENABLE_MULTIPLATFORM
|
||||
// ERROR: Expected annotation class 'Foo' has no actual declaration in module light_idea_test_case for JVM
|
||||
|
||||
expect annotation class Foo
|
||||
|
||||
@Foo<caret>
|
||||
fun bar() {}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Add default constructor to expect class" "true"
|
||||
// ENABLE_MULTIPLATFORM
|
||||
// ERROR: Expected annotation class 'Foo' has no actual declaration in module light_idea_test_case for JVM
|
||||
|
||||
expect annotation class Foo()
|
||||
|
||||
@Foo
|
||||
fun bar() {}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Add default constructor to expect class" "true"
|
||||
// ENABLE_MULTIPLATFORM
|
||||
// ERROR: Expected annotation class 'Foo' has no actual declaration in module light_idea_test_case for JVM
|
||||
|
||||
expect annotation class Foo
|
||||
|
||||
@Foo()<caret>
|
||||
fun bar() {}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Add default constructor to expect class" "true"
|
||||
// ENABLE_MULTIPLATFORM
|
||||
// ERROR: Expected annotation class 'Foo' has no actual declaration in module light_idea_test_case for JVM
|
||||
|
||||
expect annotation class Foo()
|
||||
|
||||
@Foo()
|
||||
fun bar() {}
|
||||
@@ -0,0 +1,11 @@
|
||||
// "Add default constructor to expect class" "false"
|
||||
// ENABLE_MULTIPLATFORM
|
||||
// ACTION: Make internal
|
||||
// ACTION: Make private
|
||||
// ACTION: Remove constructor call
|
||||
// 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
|
||||
expect annotation class Foo
|
||||
|
||||
@Foo("")<caret>
|
||||
fun bar() {}
|
||||
@@ -550,6 +550,21 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
runTest("idea/testData/quickfix/addDefaultConstructor/expect.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("expectAnnotation.kt")
|
||||
public void testExpectAnnotation() throws Exception {
|
||||
runTest("idea/testData/quickfix/addDefaultConstructor/expectAnnotation.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("expectAnnotation2.kt")
|
||||
public void testExpectAnnotation2() throws Exception {
|
||||
runTest("idea/testData/quickfix/addDefaultConstructor/expectAnnotation2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("expectAnnotation3.kt")
|
||||
public void testExpectAnnotation3() throws Exception {
|
||||
runTest("idea/testData/quickfix/addDefaultConstructor/expectAnnotation3.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("expectInterface.kt")
|
||||
public void testExpectInterface() throws Exception {
|
||||
runTest("idea/testData/quickfix/addDefaultConstructor/expectInterface.kt");
|
||||
|
||||
Reference in New Issue
Block a user