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
|
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? {
|
fun chooseContainingClass(it: PsiElement): JetClass? {
|
||||||
valOrVar = if (varExpected) JetValVar.Var else JetValVar.Val
|
valOrVar = if (varExpected) JetValVar.Var else JetValVar.Val
|
||||||
return it.parents.firstIsInstanceOrNull<JetClassOrObject>() as? JetClass
|
return it.parents.firstIsInstanceOrNull<JetClassOrObject>() as? JetClass
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: skip lambdas for now because Change Signature doesn't apply to them yet
|
// todo: skip lambdas for now because Change Signature doesn't apply to them yet
|
||||||
val container = element.parents
|
fun chooseContainerPreferringClass(): PsiElement? {
|
||||||
.filter {
|
return element.parents
|
||||||
it is JetNamedFunction || it is JetPropertyAccessor || it is JetClassBody || it is JetClassInitializer ||
|
.filter {
|
||||||
it is JetDelegationSpecifier
|
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 {
|
else -> it
|
||||||
when {
|
}
|
||||||
it is JetNamedFunction && varExpected,
|
}
|
||||||
it is JetPropertyAccessor -> chooseContainingClass(it)
|
}
|
||||||
it is JetClassInitializer -> it.parent?.parent as? JetClass
|
|
||||||
it is JetDelegationSpecifier -> {
|
val container = chooseContainerPreferringClass() ?: chooseFunction()
|
||||||
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
|
|
||||||
|
|
||||||
val functionDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, container]?.let {
|
val functionDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, container]?.let {
|
||||||
if (it is ClassDescriptor) it.unsubstitutedPrimaryConstructor else it
|
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);
|
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")
|
@TestMetadata("inClassInitializer.kt")
|
||||||
public void testInClassInitializer() throws Exception {
|
public void testInClassInitializer() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/parameter/inClassInitializer.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/parameter/inClassInitializer.kt");
|
||||||
@@ -2708,6 +2720,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("namedArgInConstructorCall.kt")
|
||||||
public void testNamedArgInConstructorCall() throws Exception {
|
public void testNamedArgInConstructorCall() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/parameter/namedArgInConstructorCall.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/parameter/namedArgInConstructorCall.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user