diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinExpressionTypeProvider.kt b/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinExpressionTypeProvider.kt index 83d3eb53136..e11e0af94a3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinExpressionTypeProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinExpressionTypeProvider.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.renderer.RenderingFormat import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.callUtil.getType import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode class KotlinExpressionTypeProvider : ExpressionTypeProvider() { private val typeRenderer = DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.withOptions { @@ -38,19 +39,28 @@ class KotlinExpressionTypeProvider : ExpressionTypeProvider() { override fun getExpressionsAt(elementAt: PsiElement): List = elementAt.parentsWithSelf.filterIsInstance().filter { it.shouldShowType() }.toList() - private fun KtExpression.shouldShowType() = when(this) { + private fun KtExpression.shouldShowType() = when (this) { is KtFunctionLiteral -> false is KtFunction -> !hasBlockBody() && !hasDeclaredReturnType() is KtProperty -> typeReference == null is KtPropertyAccessor -> false is KtDestructuringDeclarationEntry -> true is KtStatementExpression, is KtDestructuringDeclaration -> false - is KtIfExpression, is KtLoopExpression, is KtWhenExpression, is KtTryExpression -> parent !is KtBlockExpression + is KtIfExpression, is KtWhenExpression, is KtTryExpression -> shouldShowStatementType() + is KtLoopExpression -> false else -> getQualifiedExpressionForSelector() == null } + private fun KtExpression.shouldShowStatementType(): Boolean { + if (parent !is KtBlockExpression) return true + if (parent.children.lastOrNull() == this) { + return analyze(BodyResolveMode.PARTIAL)[BindingContext.USED_AS_EXPRESSION, this] ?: false + } + return false + } + override fun getInformationHint(element: KtExpression): String { - val bindingContext = element.analyze() + val bindingContext = element.analyze(BodyResolveMode.PARTIAL) return "${renderExpressionType(element, bindingContext)}" } @@ -65,7 +75,7 @@ class KotlinExpressionTypeProvider : ExpressionTypeProvider() { val expressionTypeInfo = bindingContext[BindingContext.EXPRESSION_TYPE_INFO, element] ?: return "Type is unknown" val expressionType = element.getType(bindingContext) - val result = expressionType?.let { typeRenderer.renderType(it) } ?: return "Type is unknown" + val result = expressionType?.let { typeRenderer.renderType(it) } ?: return "Type is unknown" val dataFlowValue = DataFlowValueFactory.createDataFlowValue(element, expressionType, bindingContext, element.findModuleDescriptor()) val types = expressionTypeInfo.dataFlowInfo.getStableTypes(dataFlowValue) diff --git a/idea/testData/codeInsight/expressionType/IfAsExpressionInsideBlock.kt b/idea/testData/codeInsight/expressionType/IfAsExpressionInsideBlock.kt new file mode 100644 index 00000000000..1e9dfc9d08f --- /dev/null +++ b/idea/testData/codeInsight/expressionType/IfAsExpressionInsideBlock.kt @@ -0,0 +1,8 @@ +val x = if (flag) { + if (flag2) 13 else 7 +} else 42 + +// TYPE: 13 -> Int +// TYPE: if (flag2) 13 else 7 -> Int +// TYPE: if (flag) { if (flag2) 13 else 7 } else 42 -> Int +// TYPE: val x = if (flag) { if (flag2) 13 else 7 } else 42 -> Int diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/ExpressionTypeTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/ExpressionTypeTestGenerated.java index a12ba9286d8..bdc7519e630 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/ExpressionTypeTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/ExpressionTypeTestGenerated.java @@ -47,6 +47,12 @@ public class ExpressionTypeTestGenerated extends AbstractExpressionTypeTest { doTest(fileName); } + @TestMetadata("IfAsExpressionInsideBlock.kt") + public void testIfAsExpressionInsideBlock() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/expressionType/IfAsExpressionInsideBlock.kt"); + doTest(fileName); + } + @TestMetadata("Kt11601.kt") public void testKt11601() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/expressionType/Kt11601.kt");