show detailed smart cast info in "Show expression type" (KT-8803)

This commit is contained in:
Dmitry Jemerov
2016-08-26 16:34:25 +02:00
parent 2141cd268c
commit 256fd04e95
5 changed files with 51 additions and 5 deletions
@@ -20,12 +20,14 @@ import com.intellij.lang.ExpressionTypeProvider
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.renderer.DescriptorRenderer
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
class KotlinExpressionTypeProvider : ExpressionTypeProvider<KtExpression>() {
private val typeRenderer = DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.withOptions {
@@ -59,11 +61,22 @@ class KotlinExpressionTypeProvider : ExpressionTypeProvider<KtExpression>() {
}
}
val expressionType = element.getType(bindingContext) ?: return "Type is unknown"
val result = typeRenderer.renderType(expressionType)
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 dataFlowValue = DataFlowValueFactory.createDataFlowValue(element, expressionType, bindingContext, element.findModuleDescriptor())
val types = expressionTypeInfo.dataFlowInfo.getStableTypes(dataFlowValue)
if (!types.isEmpty()) {
return types.joinToString(separator = " & ") { typeRenderer.renderType(it) } + " (smart cast from " + result + ")"
}
val smartCast = bindingContext[BindingContext.SMARTCAST, element]
if (smartCast != null) {
return result + " (smart cast)"
if (smartCast != null && element is KtReferenceExpression) {
val declaredType = (bindingContext[BindingContext.REFERENCE_TARGET, element] as? CallableDescriptor)?.returnType
if (declaredType != null) {
return result + " (smart cast from " + typeRenderer.renderType(declaredType) + ")"
}
}
return result
}