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.resolve.calls.util.hasUnmappedParameters
|
||||||
import org.jetbrains.jet.lang.descriptors.Visibilities
|
import org.jetbrains.jet.lang.descriptors.Visibilities
|
||||||
import org.jetbrains.jet.lang.psi.JetBlockExpression
|
import org.jetbrains.jet.lang.psi.JetBlockExpression
|
||||||
|
import org.jetbrains.jet.plugin.util.makeNullable
|
||||||
|
import org.jetbrains.jet.plugin.util.makeNotNullable
|
||||||
|
|
||||||
enum class Tail {
|
enum class Tail {
|
||||||
COMMA
|
COMMA
|
||||||
@@ -161,7 +163,7 @@ class ExpectedInfos(val bindingContext: BindingContext, val moduleDescriptor: Mo
|
|||||||
val otherOperand = if (expressionWithType == binaryExpression.getRight()) binaryExpression.getLeft() else binaryExpression.getRight()
|
val otherOperand = if (expressionWithType == binaryExpression.getRight()) binaryExpression.getLeft() else binaryExpression.getRight()
|
||||||
if (otherOperand != null) {
|
if (otherOperand != null) {
|
||||||
val expressionType = bindingContext[BindingContext.EXPRESSION_TYPE, otherOperand] ?: return 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) {
|
if (binaryExpression != null) {
|
||||||
val operationToken = binaryExpression.getOperationToken()
|
val operationToken = binaryExpression.getOperationToken()
|
||||||
if (operationToken == JetTokens.ELVIS && expressionWithType == binaryExpression.getRight()) {
|
if (operationToken == JetTokens.ELVIS && expressionWithType == binaryExpression.getRight()) {
|
||||||
val otherOperand = binaryExpression.getLeft() ?: return null
|
val leftExpression = binaryExpression.getLeft() ?: return null
|
||||||
val otherOperandType = bindingContext[BindingContext.EXPRESSION_TYPE, otherOperand]
|
val leftType = bindingContext[BindingContext.EXPRESSION_TYPE, leftExpression]
|
||||||
|
val leftTypeNotNullable = leftType?.makeNotNullable()
|
||||||
val expectedInfos = calculate(binaryExpression)
|
val expectedInfos = calculate(binaryExpression)
|
||||||
if (expectedInfos != null) {
|
if (expectedInfos != null) {
|
||||||
return if (otherOperandType != null)
|
return if (leftTypeNotNullable != null)
|
||||||
expectedInfos.filter { it.`type`.isSubtypeOf(otherOperandType) }
|
expectedInfos.filter { leftTypeNotNullable.isSubtypeOf(it.`type`) }
|
||||||
else
|
else
|
||||||
expectedInfos
|
expectedInfos
|
||||||
}
|
}
|
||||||
else if (otherOperandType != null) {
|
else if (leftTypeNotNullable != null) {
|
||||||
return listOf(ExpectedInfo(TypeUtils.makeNotNullable(otherOperandType), 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");
|
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")
|
@TestMetadata("InaccessibleConstructor.kt")
|
||||||
public void testInaccessibleConstructor() throws Exception {
|
public void testInaccessibleConstructor() throws Exception {
|
||||||
doTest("idea/testData/completion/smart/InaccessibleConstructor.kt");
|
doTest("idea/testData/completion/smart/InaccessibleConstructor.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user