Wrap with let: fix it works correctly for invoking function type

#KT-39182 Fixed
This commit is contained in:
Toshiaki Kameyama
2020-06-11 13:13:26 +09:00
committed by igoriakovlev
parent babdeacdaf
commit f6e70cfed8
6 changed files with 68 additions and 2 deletions
@@ -20,12 +20,16 @@ import com.intellij.codeInsight.intention.HighPriorityAction
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
import org.jetbrains.kotlin.idea.core.NewDeclarationNameValidator
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
import org.jetbrains.kotlin.psi.psiUtil.getLastParentOfTypeInRow
@@ -48,13 +52,25 @@ class WrapWithSafeLetCallFix(
val nullableExpression = nullableExpressionPointer.element ?: return
val qualifiedExpression = element.getQualifiedExpressionForSelector()
val receiverExpression = qualifiedExpression?.receiverExpression
val isInvokingFunctionType = if (nullableExpression.parent is KtCallExpression) {
val property = nullableExpression.mainReference?.resolve() as? KtProperty
(property?.descriptor as? PropertyDescriptor)?.type?.isFunctionType == true
} else {
false
}
val factory = KtPsiFactory(element)
val nullableText = nullableExpression.text
val nullableText = if (receiverExpression != null && isInvokingFunctionType) {
"${receiverExpression.text}${qualifiedExpression.operationSign.value}${nullableExpression.text}"
} else {
nullableExpression.text
}
val validator = NewDeclarationNameValidator(element, nullableExpression, NewDeclarationNameValidator.Target.VARIABLES)
val name = KotlinNameSuggester.suggestNameByName("it", validator)
nullableExpression.replace(factory.createExpression(name))
val underLetExpression = when {
receiverExpression != null -> factory.createExpressionByPattern("$0.$1", receiverExpression, element)
receiverExpression != null && !isInvokingFunctionType -> factory.createExpressionByPattern("$0.$1", receiverExpression, element)
else -> element
}
val wrapped = when (name) {
@@ -0,0 +1,10 @@
// "Wrap with '?.let { ... }' call" "true"
// WITH_RUNTIME
interface Foo {
val bar: ((Int) -> Unit)?
}
fun test(foo: Foo) {
foo.bar<caret>(1)
}
@@ -0,0 +1,10 @@
// "Wrap with '?.let { ... }' call" "true"
// WITH_RUNTIME
interface Foo {
val bar: ((Int) -> Unit)?
}
fun test(foo: Foo) {
foo.bar?.let { it(1) }
}
@@ -0,0 +1,10 @@
// "Wrap with '?.let { ... }' call" "true"
// WITH_RUNTIME
interface Foo {
val bar: ((Int) -> Unit)?
}
fun Foo.test() {
<caret>bar(1)
}
@@ -0,0 +1,10 @@
// "Wrap with '?.let { ... }' call" "true"
// WITH_RUNTIME
interface Foo {
val bar: ((Int) -> Unit)?
}
fun Foo.test() {
bar?.let { it(1) }
}
@@ -15474,6 +15474,16 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/wrapWithSafeLetCall/invokeFuncUnsafe.kt");
}
@TestMetadata("invokeFunctionType.kt")
public void testInvokeFunctionType() throws Exception {
runTest("idea/testData/quickfix/wrapWithSafeLetCall/invokeFunctionType.kt");
}
@TestMetadata("invokeFunctionType2.kt")
public void testInvokeFunctionType2() throws Exception {
runTest("idea/testData/quickfix/wrapWithSafeLetCall/invokeFunctionType2.kt");
}
@TestMetadata("invokeUnsafe.kt")
public void testInvokeUnsafe() throws Exception {
runTest("idea/testData/quickfix/wrapWithSafeLetCall/invokeUnsafe.kt");