Implement getTypeElement for UastKotlinPsiVariable

#KT-16849 Fixed
This commit is contained in:
Vyacheslav Gerasimov
2017-04-03 20:45:03 +03:00
parent 1d134ffc72
commit 107879a78a
9 changed files with 91 additions and 40 deletions
@@ -1,17 +1,20 @@
package org.jetbrains.uast.kotlin.psi
import com.intellij.lang.Language
import com.intellij.psi.*
import com.intellij.psi.impl.light.LightTypeElement
import org.jetbrains.kotlin.asJava.elements.LightVariableBuilder
import org.jetbrains.kotlin.builtins.createFunctionType
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.uast.UDeclaration
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UastErrorType
import org.jetbrains.uast.getParentOfType
import org.jetbrains.uast.kotlin.analyze
import org.jetbrains.uast.kotlin.lz
import org.jetbrains.uast.kotlin.orAnonymous
import org.jetbrains.uast.kotlin.toPsiType
@@ -19,28 +22,38 @@ class UastKotlinPsiVariable(
manager: PsiManager,
name: String,
type: PsiType,
language: Language,
val ktInitializer: KtExpression?,
val psiParent: PsiElement?,
val containingElement: UElement,
val ktElement: KtElement
) : LightVariableBuilder(manager, name, type, language), PsiLocalVariable {
) : LightVariableBuilder(manager, name, type, KotlinLanguage.INSTANCE), PsiLocalVariable {
private val psiTypeElement: PsiTypeElement by lz {
LightTypeElement(manager, type)
}
private val psiInitializer: PsiExpression? by lz {
ktInitializer?.let { KotlinUastPsiExpression(it, containingElement) }
}
override fun getParent() = psiParent
override fun hasInitializer() = ktInitializer != null
override fun getInitializer(): PsiExpression? = ktInitializer?.let { KotlinUastPsiExpression(it, containingElement) }
override fun getInitializer(): PsiExpression? = psiInitializer
override fun getTypeElement() = psiTypeElement
override fun setInitializer(initializer: PsiExpression?) = throw NotImplementedError()
override fun getContainingFile(): PsiFile? = ktElement.containingFile
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || other::class.java != this::class.java) return false
return ktElement == (other as? UastKotlinPsiVariable)?.ktElement
}
override fun getTypeElement() = throw NotImplementedError()
override fun setInitializer(initializer: PsiExpression?) = throw NotImplementedError()
override fun getContainingFile(): PsiFile? = ktElement.containingFile
override fun hashCode() = ktElement.hashCode()
companion object {
@@ -55,7 +68,6 @@ class UastKotlinPsiVariable(
declaration.manager,
declaration.name.orAnonymous("unnamed"),
declaration.typeReference.toPsiType(containingElement),
KotlinLanguage.INSTANCE,
initializer ?: declaration.initializer,
psiParent,
containingElement,
@@ -67,8 +79,7 @@ class UastKotlinPsiVariable(
return UastKotlinPsiVariable(
declaration.manager,
"var" + Integer.toHexString(declaration.getHashCode()),
UastErrorType, //TODO,
KotlinLanguage.INSTANCE,
declaration.initializer?.getType(containingElement) ?: UastErrorType,
declaration.initializer,
psiParent,
containingElement,
@@ -80,8 +91,7 @@ class UastKotlinPsiVariable(
return UastKotlinPsiVariable(
initializer.manager,
"var" + Integer.toHexString(initializer.getHashCode()),
UastErrorType, //TODO,
KotlinLanguage.INSTANCE,
initializer.getType(containingElement) ?: UastErrorType,
initializer,
psiParent,
containingElement,
@@ -93,8 +103,7 @@ class UastKotlinPsiVariable(
return UastKotlinPsiVariable(
localFunction.manager,
name,
UastErrorType, // TODO,
KotlinLanguage.INSTANCE,
localFunction.getFunctionType(containingElement) ?: UastErrorType,
localFunction,
psiParent,
containingElement,
@@ -104,12 +113,26 @@ class UastKotlinPsiVariable(
}
private class KotlinUastPsiExpression(val ktExpression: KtExpression, val parent: UElement) : PsiElement by ktExpression, PsiExpression {
override fun getType(): PsiType? {
val ktType = ktExpression.analyze()[BindingContext.EXPRESSION_TYPE_INFO, ktExpression]?.type ?: return null
return ktType.toPsiType(parent, ktExpression, boxed = false)
}
override fun getType(): PsiType? = ktExpression.getType(parent)
}
private fun KtFunction.getFunctionType(parent: UElement): PsiType? {
val descriptor = analyze()[BindingContext.FUNCTION, this] ?: return null
val returnType = descriptor.returnType ?: return null
return createFunctionType(
descriptor.builtIns,
descriptor.annotations,
descriptor.extensionReceiverParameter?.type,
descriptor.valueParameters.map { it.type },
descriptor.valueParameters.map { it.name },
returnType
).toPsiType(parent, this, boxed = false)
}
private fun KtExpression.getType(parent: UElement): PsiType? =
analyze()[BindingContext.EXPRESSION_TYPE_INFO, this]?.type?.toPsiType(parent, this, boxed = false)
private fun PsiElement.getHashCode(): Int {
var result = 42
result = 41 * result + containingFile.name.hashCode()
+5 -3
View File
@@ -1,6 +1,8 @@
fun foo(bar: String): Any? = null
fun foo(bar: String): String? = null
fun baz(): Any? {
return foo("Lorem ipsum") ?: foo("dolor sit amet") ?: foo("consectetuer adipiscing elit")
fun bar() = 42
fun baz(): String? {
return foo("Lorem ipsum") ?: foo("dolor sit amet") ?: bar().toString()
}
+15 -10
View File
@@ -4,34 +4,39 @@ UFile (package = )
UParameter (name = bar)
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
ULiteralExpression (value = null)
UAnnotationMethod (name = bar)
ULiteralExpression (value = 42)
UAnnotationMethod (name = baz)
UBlockExpression
UReturnExpression
UExpressionList (elvis)
UDeclarationsExpression
ULocalVariable (name = var243c4e1a)
ULocalVariable (name = var243c51a0)
UExpressionList (elvis)
UDeclarationsExpression
ULocalVariable (name = varc4aef1e3)
ULocalVariable (name = varc4aef569)
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
UIdentifier (Identifier (foo))
USimpleNameReferenceExpression (identifier = foo)
ULiteralExpression (value = "Lorem ipsum")
UIfExpression
UBinaryExpression (operator = !=)
USimpleNameReferenceExpression (identifier = varc4aef1e3)
USimpleNameReferenceExpression (identifier = varc4aef569)
ULiteralExpression (value = null)
USimpleNameReferenceExpression (identifier = varc4aef1e3)
USimpleNameReferenceExpression (identifier = varc4aef569)
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
UIdentifier (Identifier (foo))
USimpleNameReferenceExpression (identifier = foo)
ULiteralExpression (value = "dolor sit amet")
UIfExpression
UBinaryExpression (operator = !=)
USimpleNameReferenceExpression (identifier = var243c4e1a)
USimpleNameReferenceExpression (identifier = var243c51a0)
ULiteralExpression (value = null)
USimpleNameReferenceExpression (identifier = var243c4e1a)
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
UIdentifier (Identifier (foo))
USimpleNameReferenceExpression (identifier = foo)
ULiteralExpression (value = "consectetuer adipiscing elit")
USimpleNameReferenceExpression (identifier = var243c51a0)
UQualifiedReferenceExpression
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
UIdentifier (Identifier (bar))
USimpleNameReferenceExpression (identifier = bar)
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
UIdentifier (Identifier (toString))
USimpleNameReferenceExpression (identifier = toString)
+7 -6
View File
@@ -1,12 +1,13 @@
public final class ElvisKt {
public static final fun foo(bar: java.lang.String) : java.lang.Object = null
public static final fun baz() : java.lang.Object {
public static final fun foo(bar: java.lang.String) : java.lang.String = null
public static final fun bar() : int = 42
public static final fun baz() : java.lang.String {
return elvis {
var var243c4e1a: <ErrorType> = elvis {
var varc4aef1e3: <ErrorType> = foo("Lorem ipsum")
if (varc4aef1e3 != null) varc4aef1e3 else foo("dolor sit amet")
var var243c51a0: java.lang.String = elvis {
var varc4aef569: java.lang.String = foo("Lorem ipsum")
if (varc4aef569 != null) varc4aef569 else foo("dolor sit amet")
}
if (var243c4e1a != null) var243c4e1a else foo("consectetuer adipiscing elit")
if (var243c51a0 != null) var243c51a0 else bar().toString()
}
}
}
+2
View File
@@ -6,5 +6,7 @@ fun foo(): Boolean {
Local()
}
fun Int.someLocalFun(text: String) = 42
return bar() == Local()
}
@@ -18,6 +18,11 @@ UFile (package = )
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0))
UIdentifier (Identifier (Local))
USimpleNameReferenceExpression (identifier = <init>)
UDeclarationsExpression
UVariable (name = someLocalFun)
ULambdaExpression
UParameter (name = text)
ULiteralExpression (value = 42)
UReturnExpression
UBinaryExpression (operator = ==)
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
@@ -9,6 +9,9 @@ public final class LocalDeclarationsKt {
var baz: <ErrorType> = fun () {
<init>()
}
var someLocalFun: kotlin.jvm.functions.Function2<? super java.lang.Integer,? super java.lang.String,? extends java.lang.Integer> = fun (var text: java.lang.String) {
42
}
return bar() == <init>()
}
}
@@ -18,6 +18,11 @@ UFile (package = ) [public final class LocalDeclarationsKt {...]
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [<init>()] : PsiType:<ErrorType>
UIdentifier (Identifier (Local)) [UIdentifier (Identifier (Local))]
USimpleNameReferenceExpression (identifier = <init>) [<init>] : PsiType:<ErrorType>
UDeclarationsExpression [var someLocalFun: kotlin.jvm.functions.Function2<? super java.lang.Integer,? super java.lang.String,? extends java.lang.Integer> = fun (var text: java.lang.String) {...}]
UVariable (name = someLocalFun) [var someLocalFun: kotlin.jvm.functions.Function2<? super java.lang.Integer,? super java.lang.String,? extends java.lang.Integer> = fun (var text: java.lang.String) {...}]
ULambdaExpression [fun (var text: java.lang.String) {...}]
UParameter (name = text) [var text: java.lang.String]
ULiteralExpression (value = 42) [42] : PsiType:int
UReturnExpression [return bar() == <init>()] : PsiType:Void
UBinaryExpression (operator = ==) [bar() == <init>()] : PsiType:boolean
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) [bar()] : PsiType:<ErrorType>
@@ -18,6 +18,11 @@ UFile (package = ) [public final class LocalDeclarationsKt {...]
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [<init>()] = external <init>()()
UIdentifier (Identifier (Local)) [UIdentifier (Identifier (Local))]
USimpleNameReferenceExpression (identifier = <init>) [<init>] = external <init>()
UDeclarationsExpression [var someLocalFun: kotlin.jvm.functions.Function2<? super java.lang.Integer,? super java.lang.String,? extends java.lang.Integer> = fun (var text: java.lang.String) {...}] = Undetermined
UVariable (name = someLocalFun) [var someLocalFun: kotlin.jvm.functions.Function2<? super java.lang.Integer,? super java.lang.String,? extends java.lang.Integer> = fun (var text: java.lang.String) {...}]
ULambdaExpression [fun (var text: java.lang.String) {...}] = Undetermined
UParameter (name = text) [var text: java.lang.String]
ULiteralExpression (value = 42) [42] = 42
UReturnExpression [return bar() == <init>()] = Nothing
UBinaryExpression (operator = ==) [bar() == <init>()] = Undetermined
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) [bar()] = external bar()()