Smart completion after ?: works incorrectly

#KT-4926 Fixed
This commit is contained in:
Valentin Kipyatkov
2014-04-30 20:26:50 +04:00
parent 5e34791e68
commit 45f518a907
7 changed files with 73 additions and 1 deletions
@@ -50,7 +50,6 @@ import org.jetbrains.jet.lang.resolve.calls.util.DelegatingCall
import org.jetbrains.jet.lang.resolve.calls.util.noErrorsInValueArguments
import org.jetbrains.jet.lang.resolve.calls.util.hasUnmappedParameters
import org.jetbrains.jet.lang.descriptors.Visibilities
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorWithVisibility
enum class Tail {
COMMA
@@ -66,6 +65,7 @@ class ExpectedInfos(val bindingContext: BindingContext, val moduleDescriptor: Mo
?: calculateForFunctionLiteralArgument(expressionWithType)
?: calculateForEq(expressionWithType)
?: calculateForIf(expressionWithType)
?: calculateForElvis(expressionWithType)
?: getFromBindingContext(expressionWithType)
}
@@ -186,6 +186,28 @@ class ExpectedInfos(val bindingContext: BindingContext, val moduleDescriptor: Mo
}
}
private fun calculateForElvis(expressionWithType: JetExpression): Collection<ExpectedInfo>? {
val binaryExpression = expressionWithType.getParent() as? JetBinaryExpression
if (binaryExpression != null) {
val operationToken = binaryExpression.getOperationToken()
if (operationToken == JetTokens.ELVIS && expressionWithType == binaryExpression.getRight()) {
val otherOperand = binaryExpression.getLeft() ?: return null
val otherOperandType = bindingContext[BindingContext.EXPRESSION_TYPE, otherOperand]
val expectedInfos = calculate(binaryExpression)
if (expectedInfos != null) {
return if (otherOperandType != null)
expectedInfos.filter { it.`type`.isSubtypeOf(otherOperandType) }
else
expectedInfos
}
else if (otherOperandType != null) {
return listOf(ExpectedInfo(TypeUtils.makeNotNullable(otherOperandType), null))
}
}
}
return null
}
private fun getFromBindingContext(expressionWithType: JetExpression): Collection<ExpectedInfo>? {
val expectedType = bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, expressionWithType] ?: return null
return listOf(ExpectedInfo(expectedType, null))
@@ -0,0 +1,7 @@
fun foo(s: String, c: Char){}
fun bar(p1: String?, p2: String) {
foo(p1 ?: <caret>
}
// ELEMENT: p2
@@ -0,0 +1,7 @@
fun foo(s: String, c: Char){}
fun bar(p1: String?, p2: String) {
foo(p1 ?: p2, <caret>
}
// ELEMENT: p2
@@ -0,0 +1,9 @@
fun foo(p: String?){}
fun foo(p: Char){}
fun bar(p1: String?, p2: String?, p3: Char) {
foo(p1 ?: <caret>
}
// EXIST: { itemText:"p2" }
// ABSENT: p3
@@ -0,0 +1,12 @@
fun foo1(): String? = null
fun foo2(): String? = null
fun foo3(): String = ""
fun bar() {
foo1() ?: <caret>
}
// EXIST: { itemText:"foo3()" }
// ABSENT: { itemText:"foo2()" }
// EXIST: { itemText:"!! foo2()" }
// EXIST: { itemText:"?: foo2()" }
@@ -216,6 +216,16 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
doTest("idea/testData/completion/smart/IfValue3.kt");
}
@TestMetadata("InElvisOperator1.kt")
public void testInElvisOperator1() throws Exception {
doTest("idea/testData/completion/smart/InElvisOperator1.kt");
}
@TestMetadata("InElvisOperator2.kt")
public void testInElvisOperator2() throws Exception {
doTest("idea/testData/completion/smart/InElvisOperator2.kt");
}
@TestMetadata("InaccessibleConstructor.kt")
public void testInaccessibleConstructor() throws Exception {
doTest("idea/testData/completion/smart/InaccessibleConstructor.kt");
@@ -226,6 +226,11 @@ public class SmartCompletionHandlerTestGenerated extends AbstractSmartCompletion
doTest("idea/testData/completion/handlers/smart/IfValue3.kt");
}
@TestMetadata("InElvisOperator.kt")
public void testInElvisOperator() throws Exception {
doTest("idea/testData/completion/handlers/smart/InElvisOperator.kt");
}
@TestMetadata("JavaEnumMemberInsertsImport.kt")
public void testJavaEnumMemberInsertsImport() throws Exception {
doTest("idea/testData/completion/handlers/smart/JavaEnumMemberInsertsImport.kt");