Create from Usage: Fix generation of extensions with nullable receiver
#KT-23796 Fixed
This commit is contained in:
+8
-3
@@ -77,6 +77,7 @@ import org.jetbrains.kotlin.types.Variance
|
|||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
import java.lang.AssertionError
|
import java.lang.AssertionError
|
||||||
import java.lang.IllegalArgumentException
|
import java.lang.IllegalArgumentException
|
||||||
import java.lang.IllegalStateException
|
import java.lang.IllegalStateException
|
||||||
@@ -243,6 +244,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
|||||||
// gather relevant information
|
// gather relevant information
|
||||||
|
|
||||||
val placement = placement
|
val placement = placement
|
||||||
|
var nullableReceiver = false
|
||||||
when (placement) {
|
when (placement) {
|
||||||
is CallablePlacement.NoReceiver -> {
|
is CallablePlacement.NoReceiver -> {
|
||||||
containingElement = placement.containingElement
|
containingElement = placement.containingElement
|
||||||
@@ -255,14 +257,17 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is CallablePlacement.WithReceiver -> {
|
is CallablePlacement.WithReceiver -> {
|
||||||
receiverClassDescriptor =
|
val theType = placement.receiverTypeCandidate.theType
|
||||||
placement.receiverTypeCandidate.theType.constructor.declarationDescriptor
|
nullableReceiver = theType.isMarkedNullable
|
||||||
|
receiverClassDescriptor = theType.constructor.declarationDescriptor
|
||||||
val classDeclaration = receiverClassDescriptor?.let { DescriptorToSourceUtils.getSourceFromDescriptor(it) }
|
val classDeclaration = receiverClassDescriptor?.let { DescriptorToSourceUtils.getSourceFromDescriptor(it) }
|
||||||
containingElement = if (!config.isExtension && classDeclaration != null) classDeclaration else config.currentFile
|
containingElement = if (!config.isExtension && classDeclaration != null) classDeclaration else config.currentFile
|
||||||
}
|
}
|
||||||
else -> throw IllegalArgumentException("Placement wan't initialized")
|
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
|
val project = config.currentFile.project
|
||||||
|
|
||||||
|
|||||||
+8
-3
@@ -77,6 +77,7 @@ import org.jetbrains.kotlin.types.Variance
|
|||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
import java.lang.AssertionError
|
import java.lang.AssertionError
|
||||||
import java.lang.IllegalArgumentException
|
import java.lang.IllegalArgumentException
|
||||||
import java.lang.IllegalStateException
|
import java.lang.IllegalStateException
|
||||||
@@ -243,6 +244,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
|||||||
// gather relevant information
|
// gather relevant information
|
||||||
|
|
||||||
val placement = placement
|
val placement = placement
|
||||||
|
var nullableReceiver = false
|
||||||
when (placement) {
|
when (placement) {
|
||||||
is CallablePlacement.NoReceiver -> {
|
is CallablePlacement.NoReceiver -> {
|
||||||
containingElement = placement.containingElement
|
containingElement = placement.containingElement
|
||||||
@@ -255,14 +257,17 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is CallablePlacement.WithReceiver -> {
|
is CallablePlacement.WithReceiver -> {
|
||||||
receiverClassDescriptor =
|
val theType = placement.receiverTypeCandidate.theType
|
||||||
placement.receiverTypeCandidate.theType.constructor.declarationDescriptor
|
nullableReceiver = theType.isMarkedNullable
|
||||||
|
receiverClassDescriptor = theType.constructor.declarationDescriptor
|
||||||
val classDeclaration = receiverClassDescriptor?.let { DescriptorToSourceUtils.getSourceFromDescriptor(it) }
|
val classDeclaration = receiverClassDescriptor?.let { DescriptorToSourceUtils.getSourceFromDescriptor(it) }
|
||||||
containingElement = if (!config.isExtension && classDeclaration != null) classDeclaration else config.currentFile
|
containingElement = if (!config.isExtension && classDeclaration != null) classDeclaration else config.currentFile
|
||||||
}
|
}
|
||||||
else -> throw IllegalArgumentException("Placement wan't initialized")
|
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
|
val project = config.currentFile.project
|
||||||
|
|
||||||
|
|||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
// "Create extension function 'String?.notExistingFun'" "true"
|
||||||
|
fun context(p: String?) {
|
||||||
|
p.<caret>notExistingFun()
|
||||||
|
}
|
||||||
+8
@@ -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.
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
// "Create extension property 'String?.notExistingVal'" "true"
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
fun context(p: String?) {
|
||||||
|
foo(p.<caret>notExistingVal)
|
||||||
|
}
|
||||||
+11
@@ -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");
|
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")
|
@TestMetadata("objectMemberFunNoReceiver.kt")
|
||||||
public void testObjectMemberFunNoReceiver() throws Exception {
|
public void testObjectMemberFunNoReceiver() throws Exception {
|
||||||
runTest("idea/testData/quickfix/createFromUsage/createFunction/call/objectMemberFunNoReceiver.kt");
|
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");
|
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")
|
@TestMetadata("objectMemberValNoReceiver.kt")
|
||||||
public void testObjectMemberValNoReceiver() throws Exception {
|
public void testObjectMemberValNoReceiver() throws Exception {
|
||||||
runTest("idea/testData/quickfix/createFromUsage/createVariable/property/objectMemberValNoReceiver.kt");
|
runTest("idea/testData/quickfix/createFromUsage/createVariable/property/objectMemberValNoReceiver.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user