Smart completion: fixed logic in elvis operator

This commit is contained in:
Valentin Kipyatkov
2014-05-07 17:52:51 +04:00
parent ab563bd891
commit 7bb84c139d
6 changed files with 110 additions and 7 deletions
@@ -51,6 +51,8 @@ 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.psi.JetBlockExpression
import org.jetbrains.jet.plugin.util.makeNullable
import org.jetbrains.jet.plugin.util.makeNotNullable
enum class Tail {
COMMA
@@ -161,7 +163,7 @@ class ExpectedInfos(val bindingContext: BindingContext, val moduleDescriptor: Mo
val otherOperand = if (expressionWithType == binaryExpression.getRight()) binaryExpression.getLeft() else binaryExpression.getRight()
if (otherOperand != null) {
val expressionType = bindingContext[BindingContext.EXPRESSION_TYPE, otherOperand] ?: return null
return listOf(ExpectedInfo(TypeUtils.makeNullable(expressionType), null))
return listOf(ExpectedInfo(expressionType.makeNullable(), null))
}
}
}
@@ -193,17 +195,18 @@ class ExpectedInfos(val bindingContext: BindingContext, val moduleDescriptor: Mo
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 leftExpression = binaryExpression.getLeft() ?: return null
val leftType = bindingContext[BindingContext.EXPRESSION_TYPE, leftExpression]
val leftTypeNotNullable = leftType?.makeNotNullable()
val expectedInfos = calculate(binaryExpression)
if (expectedInfos != null) {
return if (otherOperandType != null)
expectedInfos.filter { it.`type`.isSubtypeOf(otherOperandType) }
return if (leftTypeNotNullable != null)
expectedInfos.filter { leftTypeNotNullable.isSubtypeOf(it.`type`) }
else
expectedInfos
}
else if (otherOperandType != null) {
return listOf(ExpectedInfo(TypeUtils.makeNotNullable(otherOperandType), null))
else if (leftTypeNotNullable != null) {
return listOf(ExpectedInfo(leftTypeNotNullable, null))
}
}
}
@@ -0,0 +1,20 @@
trait A
trait B : A
trait C
fun foo(a: A){}
fun foo(c: C){}
fun A.bar(a: A, b: B, c: C, a1: A?, b1: B?, c1: C?) {
foo(this ?: <caret>
}
// EXIST: { itemText:"a" }
// EXIST: { itemText:"b" }
// ABSENT: { itemText:"c" }
// ABSENT: { itemText:"a1" }
// ABSENT: { itemText:"b1" }
// ABSENT: { itemText:"c1" }
// EXIST: { itemText:"!! a1" }
// EXIST: { itemText:"!! b1" }
// ABSENT: { itemText:"!! c1" }
@@ -0,0 +1,20 @@
trait A
trait B : A
trait C
fun foo(a: A?){}
fun foo(c: C?){}
fun A.bar(a: A, b: B, c: C, a1: A?, b1: B?, c1: C?) {
foo(this ?: <caret>
}
// EXIST: { itemText:"a" }
// EXIST: { itemText:"b" }
// ABSENT: { itemText:"c" }
// EXIST: { itemText:"a1" }
// EXIST: { itemText:"b1" }
// ABSENT: { itemText:"c1" }
// ABSENT: { itemText:"!! a1" }
// ABSENT: { itemText:"!! b1" }
// ABSENT: { itemText:"!! c1" }
@@ -0,0 +1,20 @@
trait A
trait B : A
trait C
fun foo(a: A){}
fun foo(c: C){}
fun B.bar(a: A, b: B, c: C, a1: A?, b1: B?, c1: C?) {
foo(this ?: <caret>
}
// EXIST: { itemText:"a" }
// EXIST: { itemText:"b" }
// ABSENT: { itemText:"c" }
// ABSENT: { itemText:"a1" }
// ABSENT: { itemText:"b1" }
// ABSENT: { itemText:"c1" }
// EXIST: { itemText:"!! a1" }
// EXIST: { itemText:"!! b1" }
// ABSENT: { itemText:"!! c1" }
@@ -0,0 +1,20 @@
trait A
trait B : A
trait C
fun foo(a: A){}
fun foo(c: C){}
fun B?.bar(a: A, b: B, c: C, a1: A?, b1: B?, c1: C?) {
foo(this ?: <caret>
}
// EXIST: { itemText:"a" }
// EXIST: { itemText:"b" }
// ABSENT: { itemText:"c" }
// ABSENT: { itemText:"a1" }
// ABSENT: { itemText:"b1" }
// ABSENT: { itemText:"c1" }
// EXIST: { itemText:"!! a1" }
// EXIST: { itemText:"!! b1" }
// ABSENT: { itemText:"!! c1" }
@@ -236,6 +236,26 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
doTest("idea/testData/completion/smart/InElvisOperator2.kt");
}
@TestMetadata("InElvisOperator3.kt")
public void testInElvisOperator3() throws Exception {
doTest("idea/testData/completion/smart/InElvisOperator3.kt");
}
@TestMetadata("InElvisOperator4.kt")
public void testInElvisOperator4() throws Exception {
doTest("idea/testData/completion/smart/InElvisOperator4.kt");
}
@TestMetadata("InElvisOperator5.kt")
public void testInElvisOperator5() throws Exception {
doTest("idea/testData/completion/smart/InElvisOperator5.kt");
}
@TestMetadata("InElvisOperator6.kt")
public void testInElvisOperator6() throws Exception {
doTest("idea/testData/completion/smart/InElvisOperator6.kt");
}
@TestMetadata("InaccessibleConstructor.kt")
public void testInaccessibleConstructor() throws Exception {
doTest("idea/testData/completion/smart/InaccessibleConstructor.kt");