Create parameter: Look for containing function if no class is found. Support secondary constructors

#KT-9322 Fixed
This commit is contained in:
Alexey Sedunov
2015-09-28 15:41:09 +03:00
parent 78f7e6b459
commit 2b354cd4db
8 changed files with 102 additions and 25 deletions
@@ -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
@@ -0,0 +1,8 @@
// "Create parameter 'name'" "true"
fun f() {
object : A(<caret>name) {
}
}
open class A(s: String)
@@ -0,0 +1,8 @@
// "Create parameter 'name'" "true"
fun f(name: String) {
object : A(name) {
}
}
open class A(s: String)
@@ -0,0 +1,10 @@
// "Create parameter 'name'" "true"
class B {
constructor() {
object : A(<caret>name) {
}
}
}
open class A(s: String)
@@ -0,0 +1,10 @@
// "Create parameter 'name'" "true"
class B {
constructor(name: String) {
object : A(name) {
}
}
}
open class A(s: String)
@@ -0,0 +1,7 @@
// "Create parameter 'foo'" "true"
class A {
constructor(n: Int) {
val t: Int = <caret>foo
}
}
@@ -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");