diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createVariable/CreateParameterByRefActionFactory.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createVariable/CreateParameterByRefActionFactory.kt index af04ea953c8..5a7000c1d8f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createVariable/CreateParameterByRefActionFactory.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createVariable/CreateParameterByRefActionFactory.kt @@ -71,38 +71,47 @@ object CreateParameterByRefActionFactory : CreateParameterFromUsageFactory() as? JetClass } // todo: skip lambdas for now because Change Signature doesn't apply to them yet - val container = element.parents - .filter { - it is JetNamedFunction || it is JetPropertyAccessor || it is JetClassBody || it is JetClassInitializer || - it is JetDelegationSpecifier + fun chooseContainerPreferringClass(): PsiElement? { + return element.parents + .filter { + it is JetNamedFunction || it is JetSecondaryConstructor || it is JetPropertyAccessor || + it is JetClassBody || it is JetClassInitializer || it is JetDelegationSpecifier + } + .firstOrNull() + ?.let { + when { + (it is JetNamedFunction || it is JetSecondaryConstructor) && varExpected, + it is JetPropertyAccessor -> chooseContainingClass(it) + it is JetClassInitializer -> it.parent?.parent as? JetClass + it is JetDelegationSpecifier -> { + val klass = it.getStrictParentOfType() + if (klass is JetClass && !klass.isInterface() && klass !is JetEnumEntry) klass else null + } + it is JetClassBody -> { + val klass = it.parent as? JetClass + when { + klass is JetEnumEntry -> chooseContainingClass(klass) + klass != null && klass.isInterface() -> null + else -> klass } - .firstOrNull() - ?.let { - when { - it is JetNamedFunction && varExpected, - it is JetPropertyAccessor -> chooseContainingClass(it) - it is JetClassInitializer -> it.parent?.parent as? JetClass - it is JetDelegationSpecifier -> { - val klass = it.getStrictParentOfType() - if (klass != null && !klass.isInterface() && klass !is JetEnumEntry) klass else null - } - it is JetClassBody -> { - val klass = it.parent as? JetClass - when { - klass is JetEnumEntry -> chooseContainingClass(klass) - klass != null && klass.isInterface() -> null - else -> klass - } - } - else -> it - } - } ?: return null + } + else -> it + } + } + } + + val container = chooseContainerPreferringClass() ?: chooseFunction() val functionDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, container]?.let { if (it is ClassDescriptor) it.unsubstitutedPrimaryConstructor else it diff --git a/idea/testData/quickfix/createFromUsage/createVariable/parameter/inAnonymousObject.kt b/idea/testData/quickfix/createFromUsage/createVariable/parameter/inAnonymousObject.kt new file mode 100644 index 00000000000..0f5a1c8f386 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createVariable/parameter/inAnonymousObject.kt @@ -0,0 +1,8 @@ +// "Create parameter 'name'" "true" +fun f() { + object : A(name) { + + } +} + +open class A(s: String) \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createVariable/parameter/inAnonymousObject.kt.after b/idea/testData/quickfix/createFromUsage/createVariable/parameter/inAnonymousObject.kt.after new file mode 100644 index 00000000000..52ed850447e --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createVariable/parameter/inAnonymousObject.kt.after @@ -0,0 +1,8 @@ +// "Create parameter 'name'" "true" +fun f(name: String) { + object : A(name) { + + } +} + +open class A(s: String) \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createVariable/parameter/inAnonymousObjectInSecondaryConstructor.kt b/idea/testData/quickfix/createFromUsage/createVariable/parameter/inAnonymousObjectInSecondaryConstructor.kt new file mode 100644 index 00000000000..36be4719078 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createVariable/parameter/inAnonymousObjectInSecondaryConstructor.kt @@ -0,0 +1,10 @@ +// "Create parameter 'name'" "true" +class B { + constructor() { + object : A(name) { + + } + } +} + +open class A(s: String) \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createVariable/parameter/inAnonymousObjectInSecondaryConstructor.kt.after b/idea/testData/quickfix/createFromUsage/createVariable/parameter/inAnonymousObjectInSecondaryConstructor.kt.after new file mode 100644 index 00000000000..d9a21148381 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createVariable/parameter/inAnonymousObjectInSecondaryConstructor.kt.after @@ -0,0 +1,10 @@ +// "Create parameter 'name'" "true" +class B { + constructor(name: String) { + object : A(name) { + + } + } +} + +open class A(s: String) \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createVariable/parameter/inSecondaryConstructor.kt b/idea/testData/quickfix/createFromUsage/createVariable/parameter/inSecondaryConstructor.kt new file mode 100644 index 00000000000..7a57e8a1a53 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createVariable/parameter/inSecondaryConstructor.kt @@ -0,0 +1,7 @@ +// "Create parameter 'foo'" "true" + +class A { + constructor(n: Int) { + val t: Int = foo + } +} diff --git a/idea/testData/quickfix/createFromUsage/createVariable/parameter/inSecondaryConstructor.kt.after b/idea/testData/quickfix/createFromUsage/createVariable/parameter/inSecondaryConstructor.kt.after new file mode 100644 index 00000000000..8529ca40d4d --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createVariable/parameter/inSecondaryConstructor.kt.after @@ -0,0 +1,7 @@ +// "Create parameter 'foo'" "true" + +class A { + constructor(n: Int, foo: Int) { + val t: Int = foo + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index b6b95302ad7..83a9bae19ea 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -2564,6 +2564,18 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest(fileName); } + @TestMetadata("inAnonymousObject.kt") + public void testInAnonymousObject() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/parameter/inAnonymousObject.kt"); + doTest(fileName); + } + + @TestMetadata("inAnonymousObjectInSecondaryConstructor.kt") + public void testInAnonymousObjectInSecondaryConstructor() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/parameter/inAnonymousObjectInSecondaryConstructor.kt"); + doTest(fileName); + } + @TestMetadata("inClassInitializer.kt") public void testInClassInitializer() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/parameter/inClassInitializer.kt"); @@ -2708,6 +2720,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest(fileName); } + @TestMetadata("inSecondaryConstructor.kt") + public void testInSecondaryConstructor() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/parameter/inSecondaryConstructor.kt"); + doTest(fileName); + } + @TestMetadata("namedArgInConstructorCall.kt") public void testNamedArgInConstructorCall() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/parameter/namedArgInConstructorCall.kt");