test for handling smart casts in "show expression type"
#KT-10588 Fixed
This commit is contained in:
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
|||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
|
|
||||||
class KotlinExpressionTypeProvider : ExpressionTypeProvider<KtExpression>() {
|
class KotlinExpressionTypeProvider : ExpressionTypeProvider<KtExpression>() {
|
||||||
override fun getExpressionsAt(elementAt: PsiElement): List<KtExpression> =
|
override fun getExpressionsAt(elementAt: PsiElement): List<KtExpression> =
|
||||||
@@ -39,27 +38,27 @@ class KotlinExpressionTypeProvider : ExpressionTypeProvider<KtExpression>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getInformationHint(element: KtExpression): String {
|
override fun getInformationHint(element: KtExpression): String {
|
||||||
val type = typeByExpression(element) ?: return "Type is unknown"
|
val bindingContext = element.analyze()
|
||||||
return renderTypeHint(type)
|
|
||||||
|
return "<html>${renderExpressionType(element, bindingContext)}</html>"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderExpressionType(element: KtExpression, bindingContext: BindingContext): String {
|
||||||
|
if (element is KtCallableDeclaration) {
|
||||||
|
val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, element] as? CallableDescriptor
|
||||||
|
if (descriptor != null) {
|
||||||
|
return descriptor.returnType?.let { DescriptorRenderer.HTML.renderType(it) } ?: "Type is unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val expressionType = element.getType(bindingContext) ?: return "Type is unknown"
|
||||||
|
val result = DescriptorRenderer.HTML.renderType(expressionType)
|
||||||
|
val smartCast = bindingContext[BindingContext.SMARTCAST, element]
|
||||||
|
if (smartCast != null) {
|
||||||
|
return result + " (smart cast)"
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getErrorHint(): String = "No expression found"
|
override fun getErrorHint(): String = "No expression found"
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun renderTypeHint(type: KotlinType) = "<html>" + DescriptorRenderer.HTML.renderType(type) + "</html>"
|
|
||||||
|
|
||||||
fun typeByExpression(expression: KtExpression): KotlinType? {
|
|
||||||
val bindingContext = expression.analyze()
|
|
||||||
|
|
||||||
if (expression is KtCallableDeclaration) {
|
|
||||||
val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, expression] as? CallableDescriptor
|
|
||||||
if (descriptor != null) {
|
|
||||||
return descriptor.returnType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return expression.getType(bindingContext)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fun foo(x: Any) {
|
||||||
|
if (x is String) {
|
||||||
|
<caret>x.length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TYPE: if (x is String) { x.length } -> <html>kotlin.Unit</html>
|
||||||
|
// TYPE: x -> <html>kotlin.String (smart cast)</html>
|
||||||
|
// TYPE: x.length -> <html>kotlin.Int</html>
|
||||||
@@ -29,7 +29,8 @@ abstract class AbstractExpressionTypeTest : KotlinLightCodeInsightFixtureTestCas
|
|||||||
protected fun doTest(path: String) {
|
protected fun doTest(path: String) {
|
||||||
myFixture.configureByFile(path)
|
myFixture.configureByFile(path)
|
||||||
val expressionTypeProvider = KotlinExpressionTypeProvider()
|
val expressionTypeProvider = KotlinExpressionTypeProvider()
|
||||||
val expressions = expressionTypeProvider.getExpressionsAt(myFixture.elementAtCaret)
|
val elementAtCaret = myFixture.file.findElementAt(myFixture.editor.caretModel.offset)!!
|
||||||
|
val expressions = expressionTypeProvider.getExpressionsAt(elementAtCaret)
|
||||||
val types = expressions.map { "${it.text.replace('\n', ' ')} -> ${expressionTypeProvider.getInformationHint(it)}" }
|
val types = expressions.map { "${it.text.replace('\n', ' ')} -> ${expressionTypeProvider.getInformationHint(it)}" }
|
||||||
val expectedTypes = InTextDirectivesUtils.findLinesWithPrefixesRemoved(myFixture.file.text, "// TYPE: ")
|
val expectedTypes = InTextDirectivesUtils.findLinesWithPrefixesRemoved(myFixture.file.text, "// TYPE: ")
|
||||||
UsefulTestCase.assertOrderedEquals(types, expectedTypes)
|
UsefulTestCase.assertOrderedEquals(types, expectedTypes)
|
||||||
|
|||||||
Reference in New Issue
Block a user