Create parameter: Look for containing function if no class is found. Support secondary constructors
#KT-9322 Fixed
This commit is contained in:
+34
-25
@@ -71,38 +71,47 @@ object CreateParameterByRefActionFactory : CreateParameterFromUsageFactory<JetSi
|
||||
|
||||
var valOrVar: JetValVar = JetValVar.None
|
||||
|
||||
fun chooseFunction(): PsiElement? {
|
||||
if (varExpected) return null
|
||||
return element.parents.filter { it is JetNamedFunction || it is JetSecondaryConstructor }.firstOrNull()
|
||||
}
|
||||
|
||||
fun chooseContainingClass(it: PsiElement): JetClass? {
|
||||
valOrVar = if (varExpected) JetValVar.Var else JetValVar.Val
|
||||
return it.parents.firstIsInstanceOrNull<JetClassOrObject>() 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<JetClassOrObject>()
|
||||
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<JetClass>()
|
||||
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
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Create parameter 'name'" "true"
|
||||
fun f() {
|
||||
object : A(<caret>name) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
open class A(s: String)
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Create parameter 'name'" "true"
|
||||
fun f(name: String) {
|
||||
object : A(name) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
open class A(s: String)
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// "Create parameter 'name'" "true"
|
||||
class B {
|
||||
constructor() {
|
||||
object : A(<caret>name) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class A(s: String)
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// "Create parameter 'name'" "true"
|
||||
class B {
|
||||
constructor(name: String) {
|
||||
object : A(name) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class A(s: String)
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Create parameter 'foo'" "true"
|
||||
|
||||
class A {
|
||||
constructor(n: Int) {
|
||||
val t: Int = <caret>foo
|
||||
}
|
||||
}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
// "Create parameter 'foo'" "true"
|
||||
|
||||
class A {
|
||||
constructor(n: Int, foo: Int) {
|
||||
val t: Int = foo
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user