Replace explicit parameter with it: don't suggest if overload resolution ambiguity error occurs
#KT-20795 Fixed
This commit is contained in:
committed by
Yan Zhulanow
parent
69a2697598
commit
5b927d798c
+21
-6
@@ -27,14 +27,16 @@ import com.intellij.usageView.UsageInfo
|
||||
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.analysis.analyzeAsReplacement
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.core.copied
|
||||
import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors
|
||||
import org.jetbrains.kotlin.psi.KtFunctionLiteral
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class ReplaceExplicitFunctionLiteralParamWithItIntention : PsiElementBaseIntentionAction() {
|
||||
override fun getFamilyName() = KotlinBundle.message("replace.explicit.lambda.parameter.with.it")
|
||||
@@ -50,6 +52,19 @@ class ReplaceExplicitFunctionLiteralParamWithItIntention : PsiElementBaseIntenti
|
||||
literal.usesName(element.text) && (!literal.hasParameterSpecification() || literal.usesName("it"))
|
||||
}) return false
|
||||
|
||||
val lambda = functionLiteral.parent as? KtLambdaExpression ?: return false
|
||||
val call = lambda.getStrictParentOfType<KtCallExpression>()
|
||||
if (call != null) {
|
||||
val argumentIndex = call.valueArguments.indexOfFirst { it.getArgumentExpression() == lambda }
|
||||
val callOrQualified = call.getQualifiedExpressionForSelectorOrThis()
|
||||
val newCallOrQualified = callOrQualified.copied()
|
||||
val newCall = newCallOrQualified.safeAs<KtQualifiedExpression>()?.callExpression ?: newCallOrQualified.safeAs() ?: return false
|
||||
val newArgument = newCall.valueArguments.getOrNull(argumentIndex) ?: newCall.lambdaArguments.singleOrNull() ?: return false
|
||||
newArgument.replace(KtPsiFactory(element).createLambdaExpression("", "TODO()"))
|
||||
val newContext = newCallOrQualified.analyzeAsReplacement(callOrQualified, callOrQualified.analyze(BodyResolveMode.PARTIAL))
|
||||
if (newCallOrQualified.getResolvedCall(newContext)?.resultingDescriptor == null) return false
|
||||
}
|
||||
|
||||
text = KotlinBundle.message("replace.explicit.parameter.0.with.it", parameter.name.toString())
|
||||
return true
|
||||
}
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
fun foo() {
|
||||
val a: (Int) -> Unit = { <caret>a -> bar(a) }
|
||||
}
|
||||
|
||||
fun bar(i: Int) {}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
fun foo() {
|
||||
val a: (Int) -> Unit = { bar(it) }
|
||||
}
|
||||
|
||||
fun bar(i: Int) {}
|
||||
idea/testData/intentions/replaceExplicitFunctionLiteralParamWithIt/applicable_qualifiedExpression.kt
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
fun test() {
|
||||
C().foo { <caret>i -> i + 1 }
|
||||
}
|
||||
|
||||
class C {
|
||||
fun foo(f: (Int) -> Int) {}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
fun test() {
|
||||
C().foo { it + 1 }
|
||||
}
|
||||
|
||||
class C {
|
||||
fun foo(f: (Int) -> Int) {}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// IS_APPLICABLE: false
|
||||
fun test() {
|
||||
foo { <caret>i -> i + 1 }
|
||||
}
|
||||
|
||||
fun foo(f: (Int) -> Int) {}
|
||||
fun foo(f: (Int, Int) -> Int) {}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// IS_APPLICABLE: false
|
||||
fun test() {
|
||||
C().foo { <caret>i -> i + 1 }
|
||||
}
|
||||
|
||||
class C {
|
||||
fun foo(f: (Int) -> Int) {}
|
||||
fun foo(f: (Int, Int) -> Int) {}
|
||||
}
|
||||
@@ -14634,11 +14634,21 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
runTest("idea/testData/intentions/replaceExplicitFunctionLiteralParamWithIt/applicable_formatsProperly.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("applicable_inPropertyInitializer.kt")
|
||||
public void testApplicable_inPropertyInitializer() throws Exception {
|
||||
runTest("idea/testData/intentions/replaceExplicitFunctionLiteralParamWithIt/applicable_inPropertyInitializer.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("applicable_nestedLiteralsNoUseInside.kt")
|
||||
public void testApplicable_nestedLiteralsNoUseInside() throws Exception {
|
||||
runTest("idea/testData/intentions/replaceExplicitFunctionLiteralParamWithIt/applicable_nestedLiteralsNoUseInside.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("applicable_qualifiedExpression.kt")
|
||||
public void testApplicable_qualifiedExpression() throws Exception {
|
||||
runTest("idea/testData/intentions/replaceExplicitFunctionLiteralParamWithIt/applicable_qualifiedExpression.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("notApplicable_alreadyUsesImplicitIt.kt")
|
||||
public void testNotApplicable_alreadyUsesImplicitIt() throws Exception {
|
||||
runTest("idea/testData/intentions/replaceExplicitFunctionLiteralParamWithIt/notApplicable_alreadyUsesImplicitIt.kt");
|
||||
@@ -14674,6 +14684,16 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
runTest("idea/testData/intentions/replaceExplicitFunctionLiteralParamWithIt/notApplicable_notFunctionLiteralParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("notApplicable_overloadResolutionAmbiguity.kt")
|
||||
public void testNotApplicable_overloadResolutionAmbiguity() throws Exception {
|
||||
runTest("idea/testData/intentions/replaceExplicitFunctionLiteralParamWithIt/notApplicable_overloadResolutionAmbiguity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("notApplicable_overloadResolutionAmbiguity2.kt")
|
||||
public void testNotApplicable_overloadResolutionAmbiguity2() throws Exception {
|
||||
runTest("idea/testData/intentions/replaceExplicitFunctionLiteralParamWithIt/notApplicable_overloadResolutionAmbiguity2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("notApplicable_parameterHasExplicitType.kt")
|
||||
public void testNotApplicable_parameterHasExplicitType() throws Exception {
|
||||
runTest("idea/testData/intentions/replaceExplicitFunctionLiteralParamWithIt/notApplicable_parameterHasExplicitType.kt");
|
||||
|
||||
Reference in New Issue
Block a user