Smart completion: fixed logic in elvis operator
This commit is contained in:
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user