diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ConvertToAnonymousObjectFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ConvertToAnonymousObjectFix.kt index 70b4a57ccab..64bc8f61de4 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ConvertToAnonymousObjectFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ConvertToAnonymousObjectFix.kt @@ -7,6 +7,7 @@ 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.ClassifierDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.diagnostics.Diagnostic @@ -20,7 +21,7 @@ import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtNameReferenceExpression import org.jetbrains.kotlin.psi.KtReferenceExpression import org.jetbrains.kotlin.resolve.calls.tower.WrongResolutionToClassifier -import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor +import org.jetbrains.kotlin.resolve.sam.getAbstractMembers import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult class ConvertToAnonymousObjectFix(element: KtNameReferenceExpression) : KotlinQuickFixAction(element) { @@ -52,6 +53,10 @@ class ConvertToAnonymousObjectFix(element: KtNameReferenceExpression) : KotlinQu private fun getFunctionDescriptor( d: DiagnosticWithParameters3 - ) = (d.a as? LazyClassDescriptor)?.declaredCallableMembers?.singleOrNull() as? SimpleFunctionDescriptor + ): SimpleFunctionDescriptor? { + val classDescriptor = d.a as? ClassDescriptor ?: return null + val singleAbstractFunction = getAbstractMembers(classDescriptor).singleOrNull() as? SimpleFunctionDescriptor ?: return null + return if (singleAbstractFunction.typeParameters.isEmpty()) singleAbstractFunction else null + } } } \ No newline at end of file diff --git a/idea/testData/quickfix/convertToAnonymousObject/hasConcreateMember.kt b/idea/testData/quickfix/convertToAnonymousObject/hasConcreateMember.kt new file mode 100644 index 00000000000..931dd42628a --- /dev/null +++ b/idea/testData/quickfix/convertToAnonymousObject/hasConcreateMember.kt @@ -0,0 +1,11 @@ +// "Convert to anonymous object" "true" +interface I { + fun a() + fun b() {} +} + +fun foo(i: I) {} + +fun test() { + foo(I {}) +} \ No newline at end of file diff --git a/idea/testData/quickfix/convertToAnonymousObject/hasConcreateMember.kt.after b/idea/testData/quickfix/convertToAnonymousObject/hasConcreateMember.kt.after new file mode 100644 index 00000000000..059ee127fb4 --- /dev/null +++ b/idea/testData/quickfix/convertToAnonymousObject/hasConcreateMember.kt.after @@ -0,0 +1,15 @@ +// "Convert to anonymous object" "true" +interface I { + fun a() + fun b() {} +} + +fun foo(i: I) {} + +fun test() { + foo(object : I { + override fun a() { + + } + }) +} \ No newline at end of file diff --git a/idea/testData/quickfix/convertToAnonymousObject/hasConcreateMember2.kt b/idea/testData/quickfix/convertToAnonymousObject/hasConcreateMember2.kt new file mode 100644 index 00000000000..ddce372a4dc --- /dev/null +++ b/idea/testData/quickfix/convertToAnonymousObject/hasConcreateMember2.kt @@ -0,0 +1,12 @@ +// "Convert to anonymous object" "true" +interface I { + fun a() + val b: Int + get() = 1 +} + +fun foo(i: I) {} + +fun test() { + foo(I {}) +} \ No newline at end of file diff --git a/idea/testData/quickfix/convertToAnonymousObject/hasConcreateMember2.kt.after b/idea/testData/quickfix/convertToAnonymousObject/hasConcreateMember2.kt.after new file mode 100644 index 00000000000..356c8dc5fee --- /dev/null +++ b/idea/testData/quickfix/convertToAnonymousObject/hasConcreateMember2.kt.after @@ -0,0 +1,16 @@ +// "Convert to anonymous object" "true" +interface I { + fun a() + val b: Int + get() = 1 +} + +fun foo(i: I) {} + +fun test() { + foo(object : I { + override fun a() { + + } + }) +} \ No newline at end of file diff --git a/idea/testData/quickfix/convertToAnonymousObject/hasTypeParameter.kt b/idea/testData/quickfix/convertToAnonymousObject/hasTypeParameter.kt new file mode 100644 index 00000000000..9fdf6631607 --- /dev/null +++ b/idea/testData/quickfix/convertToAnonymousObject/hasTypeParameter.kt @@ -0,0 +1,11 @@ +// "Convert to anonymous object" "false" +// ERROR: Interface I does not have constructors +// ACTION: Introduce import alias +// ACTION: Split property declaration +interface I { + fun foo(): String +} + +fun test() { + val i = I { "" } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 12ff3b7e264..6c83cb0e7d1 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -2911,6 +2911,21 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/quickfix/convertToAnonymousObject"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true); } + @TestMetadata("hasConcreateMember.kt") + public void testHasConcreateMember() throws Exception { + runTest("idea/testData/quickfix/convertToAnonymousObject/hasConcreateMember.kt"); + } + + @TestMetadata("hasConcreateMember2.kt") + public void testHasConcreateMember2() throws Exception { + runTest("idea/testData/quickfix/convertToAnonymousObject/hasConcreateMember2.kt"); + } + + @TestMetadata("hasTypeParameter.kt") + public void testHasTypeParameter() throws Exception { + runTest("idea/testData/quickfix/convertToAnonymousObject/hasTypeParameter.kt"); + } + @TestMetadata("labeledReturn.kt") public void testLabeledReturn() throws Exception { runTest("idea/testData/quickfix/convertToAnonymousObject/labeledReturn.kt");