Fixes: use isExactFunctionOrExtensionFunctionType() to detect when lambda can be passed

This commit is contained in:
Valentin Kipyatkov
2015-07-06 21:17:31 +03:00
parent 6b78a53c3d
commit 88dd86d603
8 changed files with 29 additions and 5 deletions
@@ -188,7 +188,7 @@ class ExpectedInfos(
if (parameter.hasDefaultValue()) return false // parameter is optional if (parameter.hasDefaultValue()) return false // parameter is optional
if (parameter.getVarargElementType() != null) return false // vararg arguments list can be empty if (parameter.getVarargElementType() != null) return false // vararg arguments list can be empty
// last parameter of functional type can be placed outside parenthesis: // last parameter of functional type can be placed outside parenthesis:
if (parameter == parameters.last() && KotlinBuiltIns.isFunctionOrExtensionFunctionType(parameter.getType())) return false if (parameter == parameters.last() && KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(parameter.getType())) return false
return true return true
} }
@@ -303,7 +303,7 @@ public class LookupElementFactory(
1 -> { 1 -> {
val parameterType = parameters.single().getType() val parameterType = parameters.single().getType()
if (KotlinBuiltIns.isFunctionOrExtensionFunctionType(parameterType)) { if (KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(parameterType)) {
val parameterCount = KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(parameterType).size() val parameterCount = KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(parameterType).size()
if (parameterCount <= 1) { if (parameterCount <= 1) {
// otherwise additional item with lambda template is to be added // otherwise additional item with lambda template is to be added
@@ -106,7 +106,7 @@ class LookupElementsCollector(
val parameters = descriptor.getValueParameters() val parameters = descriptor.getValueParameters()
if (parameters.size() == 1) { if (parameters.size() == 1) {
val parameterType = parameters.get(0).getType() val parameterType = parameters.get(0).getType()
if (KotlinBuiltIns.isFunctionOrExtensionFunctionType(parameterType)) { if (KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(parameterType)) {
val parameterCount = KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(parameterType).size() val parameterCount = KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(parameterType).size()
if (parameterCount > 1) { if (parameterCount > 1) {
var lookupElement = lookupElementFactory.createLookupElement(descriptor, true) var lookupElement = lookupElementFactory.createLookupElement(descriptor, true)
@@ -0,0 +1,9 @@
interface I : () -> Unit
fun foo(i: I){}
fun bar() {
<caret>
}
// ELEMENT: foo
@@ -0,0 +1,9 @@
interface I : () -> Unit
fun foo(i: I){}
fun bar() {
foo(<caret>)
}
// ELEMENT: foo
@@ -220,6 +220,12 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion
doTest(fileName); doTest(fileName);
} }
@TestMetadata("ParameterTypeIsDerivedFromFunction.kt")
public void testParameterTypeIsDerivedFromFunction() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/highOrderFunctions/ParameterTypeIsDerivedFromFunction.kt");
doTest(fileName);
}
@TestMetadata("ReplaceByLambdaTemplateNoClosingParenth.kt") @TestMetadata("ReplaceByLambdaTemplateNoClosingParenth.kt")
public void testReplaceByLambdaTemplateNoClosingParenth() throws Exception { public void testReplaceByLambdaTemplateNoClosingParenth() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/highOrderFunctions/ReplaceByLambdaTemplateNoClosingParenth.kt"); String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/highOrderFunctions/ReplaceByLambdaTemplateNoClosingParenth.kt");
@@ -45,7 +45,7 @@ public class MoveLambdaOutsideParenthesesIntention : JetSelfTargetingIntention<J
// if there are functions among candidates but none of them have last function parameter then not show the intention // if there are functions among candidates but none of them have last function parameter then not show the intention
if (candidates.isNotEmpty() && candidates.none { if (candidates.isNotEmpty() && candidates.none {
val lastParameter = it.getValueParameters().lastOrNull() val lastParameter = it.getValueParameters().lastOrNull()
lastParameter != null && KotlinBuiltIns.isFunctionOrExtensionFunctionType(lastParameter.getType()) lastParameter != null && KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(lastParameter.getType())
}) { }) {
return false return false
} }
@@ -107,7 +107,7 @@ private class LambdaToFunctionExpression(
init { init {
val bindingContext = functionLiteralExpression.analyze() val bindingContext = functionLiteralExpression.analyze()
val functionLiteralType = bindingContext.getType(functionLiteralExpression) val functionLiteralType = bindingContext.getType(functionLiteralExpression)
assert(functionLiteralType != null && KotlinBuiltIns.isFunctionOrExtensionFunctionType(functionLiteralType)) { assert(functionLiteralType != null && KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(functionLiteralType)) {
"Broken function type for expression: ${functionLiteralExpression.getText()}, at: ${DiagnosticUtils.atLocation(functionLiteralExpression)}" "Broken function type for expression: ${functionLiteralExpression.getText()}, at: ${DiagnosticUtils.atLocation(functionLiteralExpression)}"
} }
receiverType = KotlinBuiltIns.getReceiverType(functionLiteralType)?.let { IdeDescriptorRenderers.SOURCE_CODE.renderType(it) } receiverType = KotlinBuiltIns.getReceiverType(functionLiteralType)?.let { IdeDescriptorRenderers.SOURCE_CODE.renderType(it) }