Make "Specify explicit lambda signature" available on whole lambda
So #KT-22492 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
059a797e10
commit
5499078fcc
+10
-19
@@ -25,23 +25,15 @@ import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.types.isError
|
||||
|
||||
class SpecifyExplicitLambdaSignatureIntention : SelfTargetingIntention<KtLambdaExpression>(KtLambdaExpression::class.java, "Specify explicit lambda signature"), LowPriorityAction {
|
||||
class SpecifyExplicitLambdaSignatureIntention :
|
||||
SelfTargetingIntention<KtLambdaExpression>(KtLambdaExpression::class.java, "Specify explicit lambda signature"), LowPriorityAction {
|
||||
|
||||
override fun isApplicableTo(element: KtLambdaExpression, caretOffset: Int): Boolean {
|
||||
val arrow = element.functionLiteral.arrow
|
||||
if (arrow != null) {
|
||||
if (caretOffset > arrow.endOffset) return false
|
||||
if (element.valueParameters.all { it.typeReference != null }) return false
|
||||
}
|
||||
else {
|
||||
if (!element.leftCurlyBrace.textRange.containsOffset(caretOffset)) return false
|
||||
}
|
||||
|
||||
if (element.functionLiteral.arrow != null && element.valueParameters.all { it.typeReference != null }) return false
|
||||
val functionDescriptor = element.analyze(BodyResolveMode.PARTIAL)[BindingContext.FUNCTION, element.functionLiteral] ?: return false
|
||||
return functionDescriptor.valueParameters.none { it.type.isError }
|
||||
}
|
||||
@@ -55,12 +47,12 @@ class SpecifyExplicitLambdaSignatureIntention : SelfTargetingIntention<KtLambdaE
|
||||
val functionDescriptor = element.analyze(BodyResolveMode.PARTIAL)[BindingContext.FUNCTION, functionLiteral]!!
|
||||
|
||||
val parameterString = functionDescriptor.valueParameters
|
||||
.mapIndexed { index, parameterDescriptor ->
|
||||
parameterDescriptor.render(psiName = functionLiteral.valueParameters.getOrNull(index)?.let {
|
||||
it.name ?: it.destructuringDeclaration?.text
|
||||
} )
|
||||
}
|
||||
.joinToString()
|
||||
.mapIndexed { index, parameterDescriptor ->
|
||||
parameterDescriptor.render(psiName = functionLiteral.valueParameters.getOrNull(index)?.let {
|
||||
it.name ?: it.destructuringDeclaration?.text
|
||||
})
|
||||
}
|
||||
.joinToString()
|
||||
applyWithParameters(element, parameterString)
|
||||
}
|
||||
|
||||
@@ -72,8 +64,7 @@ class SpecifyExplicitLambdaSignatureIntention : SelfTargetingIntention<KtLambdaE
|
||||
val oldParameterList = functionLiteral.valueParameterList
|
||||
if (oldParameterList != null && newParameterList != null) {
|
||||
oldParameterList.replace(newParameterList)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val openBraceElement = functionLiteral.lBrace
|
||||
val nextSibling = openBraceElement.nextSibling
|
||||
val addNewline = nextSibling is PsiWhiteSpace && nextSibling.text?.contains("\n") ?: false
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
fun foo(f: (String) -> Int) {}
|
||||
fun test() {
|
||||
foo { it.length <caret>}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
fun foo(f: (String) -> Int) {}
|
||||
fun test() {
|
||||
foo { it: String -> it.length <caret>}
|
||||
}
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
// IS_APPLICABLE: false
|
||||
fun main() {
|
||||
val sum : (Int, Int) -> Int = { x, y -> <caret>x + y }
|
||||
}
|
||||
+1
@@ -4,6 +4,7 @@
|
||||
// ACTION: Introduce local variable
|
||||
// ACTION: Move lambda argument into parentheses
|
||||
// ACTION: Replace with safe (this?.) call
|
||||
// ACTION: Specify explicit lambda signature
|
||||
// ERROR: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
|
||||
|
||||
fun String?.foo(a: String?) {
|
||||
|
||||
+6
-6
@@ -14682,6 +14682,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("cursorOnRightBrace.kt")
|
||||
public void testCursorOnRightBrace() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/specifyExplicitLambdaSignature/cursorOnRightBrace.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("delegate.kt")
|
||||
public void testDelegate() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/specifyExplicitLambdaSignature/delegate.kt");
|
||||
@@ -14718,12 +14724,6 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("invalidCursorPosition.kt")
|
||||
public void testInvalidCursorPosition() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/specifyExplicitLambdaSignature/invalidCursorPosition.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaWithLambdaAsParam.kt")
|
||||
public void testLambdaWithLambdaAsParam() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/specifyExplicitLambdaSignature/lambdaWithLambdaAsParam.kt");
|
||||
|
||||
Reference in New Issue
Block a user