Add a quick fix for NO_CONSTRUCTOR error on 'expect' annotation entry

#KT-20718 Fixed
This commit is contained in:
Toshiaki Kameyama
2019-12-20 13:13:25 +09:00
committed by Dmitry Gridin
parent d846a22e33
commit 7be5410877
7 changed files with 77 additions and 8 deletions
@@ -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");