diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/ElvisExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/ElvisExpression.kt index b6a39c01b19..ad66385d37a 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/ElvisExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/ElvisExpression.kt @@ -2,8 +2,11 @@ package org.jetbrains.uast.kotlin.expressions import com.intellij.psi.PsiElement import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiType import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.types.CommonSupertypes import org.jetbrains.uast.* import org.jetbrains.uast.kotlin.* import org.jetbrains.uast.kotlin.kinds.KotlinSpecialExpressionKinds @@ -69,7 +72,7 @@ fun createElvisExpression(elvisExpression: KtBinaryExpression, containingElement val left = elvisExpression.left ?: return UastEmptyExpression val right = elvisExpression.right ?: return UastEmptyExpression - return object : UExpressionList, KotlinEvaluatableUElement, KotlinUElementWithType { + return object : UExpressionList, KotlinEvaluatableUElement { override val psi: PsiElement? = elvisExpression override val kind = KotlinSpecialExpressionKinds.ELVIS override val uastParent: UElement? = containingElement @@ -77,9 +80,19 @@ fun createElvisExpression(elvisExpression: KtBinaryExpression, containingElement override val expressions: List by lz { createElvisExpressions(left, right, this, elvisExpression.parent) } - override fun asRenderString(): String = kind.name + " " + - expressions.joinToString(separator = "\n", prefix = "{\n", postfix = "\n}") { - it.asRenderString().withMargin - } + override fun asRenderString(): String { + return kind.name + " " + + expressions.joinToString(separator = "\n", prefix = "{\n", postfix = "\n}") { + it.asRenderString().withMargin + } + } + override fun getExpressionType(): PsiType? { + val leftType = left.analyze()[BindingContext.EXPRESSION_TYPE_INFO, left]?.type ?: return null + val rightType = right.analyze()[BindingContext.EXPRESSION_TYPE_INFO, right]?.type ?: return null + + return CommonSupertypes + .commonSupertype(listOf(leftType, rightType)) + .toPsiType(this, elvisExpression, boxed = false) + } } } \ No newline at end of file diff --git a/plugins/uast-kotlin/testData/ElvisType.kt b/plugins/uast-kotlin/testData/ElvisType.kt new file mode 100644 index 00000000000..eb4a6ffc15e --- /dev/null +++ b/plugins/uast-kotlin/testData/ElvisType.kt @@ -0,0 +1,6 @@ + +fun foo(text: String?) = bar(text ?: return) + +fun bar(o: Any) { + +} diff --git a/plugins/uast-kotlin/tests/KotlinUastApiTest.kt b/plugins/uast-kotlin/tests/KotlinUastApiTest.kt index 0dae12ad762..65feb55de6b 100644 --- a/plugins/uast-kotlin/tests/KotlinUastApiTest.kt +++ b/plugins/uast-kotlin/tests/KotlinUastApiTest.kt @@ -7,7 +7,6 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase import org.jetbrains.uast.* import org.jetbrains.uast.test.env.findElementByText -import org.jetbrains.uast.visitor.UastVisitor import org.junit.Assert import org.junit.Test @@ -98,4 +97,11 @@ class KotlinUastApiTest : AbstractKotlinUastTest() { test2.fields.find { it.name == "bar" }!!.annotations.single { it.qualifiedName == "MyAnnotation" } } } + + @Test fun testElvisType() { + doTest("ElvisType") { _, file -> + val elvisExpression = file.findElementByText("text ?: return") + assertEquals("String", elvisExpression.getExpressionType()!!.presentableText) + } + } }