Create from Usage: Fix generation of extensions with nullable receiver

#KT-23796 Fixed
This commit is contained in:
Alexey Sedunov
2018-04-17 15:42:09 +03:00
parent 4e3c1e9f56
commit a4a10c7ba4
7 changed files with 57 additions and 6 deletions
@@ -77,6 +77,7 @@ import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import java.lang.AssertionError
import java.lang.IllegalArgumentException
import java.lang.IllegalStateException
@@ -243,6 +244,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
// gather relevant information
val placement = placement
var nullableReceiver = false
when (placement) {
is CallablePlacement.NoReceiver -> {
containingElement = placement.containingElement
@@ -255,14 +257,17 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
}
}
is CallablePlacement.WithReceiver -> {
receiverClassDescriptor =
placement.receiverTypeCandidate.theType.constructor.declarationDescriptor
val theType = placement.receiverTypeCandidate.theType
nullableReceiver = theType.isMarkedNullable
receiverClassDescriptor = theType.constructor.declarationDescriptor
val classDeclaration = receiverClassDescriptor?.let { DescriptorToSourceUtils.getSourceFromDescriptor(it) }
containingElement = if (!config.isExtension && classDeclaration != null) classDeclaration else config.currentFile
}
else -> throw IllegalArgumentException("Placement wan't initialized")
}
val receiverType = receiverClassDescriptor?.defaultType
val receiverType = receiverClassDescriptor?.defaultType?.let {
if (nullableReceiver) it.makeNullable() else it
}
val project = config.currentFile.project
@@ -77,6 +77,7 @@ import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import java.lang.AssertionError
import java.lang.IllegalArgumentException
import java.lang.IllegalStateException
@@ -243,6 +244,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
// gather relevant information
val placement = placement
var nullableReceiver = false
when (placement) {
is CallablePlacement.NoReceiver -> {
containingElement = placement.containingElement
@@ -255,14 +257,17 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
}
}
is CallablePlacement.WithReceiver -> {
receiverClassDescriptor =
placement.receiverTypeCandidate.theType.constructor.declarationDescriptor
val theType = placement.receiverTypeCandidate.theType
nullableReceiver = theType.isMarkedNullable
receiverClassDescriptor = theType.constructor.declarationDescriptor
val classDeclaration = receiverClassDescriptor?.let { DescriptorToSourceUtils.getSourceFromDescriptor(it) }
containingElement = if (!config.isExtension && classDeclaration != null) classDeclaration else config.currentFile
}
else -> throw IllegalArgumentException("Placement wan't initialized")
}
val receiverType = receiverClassDescriptor?.defaultType
val receiverType = receiverClassDescriptor?.defaultType?.let {
if (nullableReceiver) it.makeNullable() else it
}
val project = config.currentFile.project
@@ -0,0 +1,4 @@
// "Create extension function 'String?.notExistingFun'" "true"
fun context(p: String?) {
p.<caret>notExistingFun()
}
@@ -0,0 +1,8 @@
// "Create extension function 'String?.notExistingFun'" "true"
fun context(p: String?) {
p.notExistingFun()
}
private fun String?.notExistingFun() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -0,0 +1,6 @@
// "Create extension property 'String?.notExistingVal'" "true"
fun foo(n: Int) {}
fun context(p: String?) {
foo(p.<caret>notExistingVal)
}
@@ -0,0 +1,11 @@
// "Create extension property 'String?.notExistingVal'" "true"
fun foo(n: Int) {}
fun context(p: String?) {
foo(p.notExistingVal)
}
private val String?.notExistingVal: Int
get() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -3084,6 +3084,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/createFromUsage/createFunction/call/notExactArgument.kt");
}
@TestMetadata("nullableReceiver.kt")
public void testNullableReceiver() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/nullableReceiver.kt");
doTest(fileName);
}
@TestMetadata("objectMemberFunNoReceiver.kt")
public void testObjectMemberFunNoReceiver() throws Exception {
runTest("idea/testData/quickfix/createFromUsage/createFunction/call/objectMemberFunNoReceiver.kt");
@@ -4599,6 +4605,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/createFromUsage/createVariable/property/nonAbstractInInterface.kt");
}
@TestMetadata("nullableReceiver.kt")
public void testNullableReceiver() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/property/nullableReceiver.kt");
doTest(fileName);
}
@TestMetadata("objectMemberValNoReceiver.kt")
public void testObjectMemberValNoReceiver() throws Exception {
runTest("idea/testData/quickfix/createFromUsage/createVariable/property/objectMemberValNoReceiver.kt");