Implement getTypeElement for UastKotlinPsiVariable
#KT-16849 Fixed
This commit is contained in:
@@ -1,17 +1,20 @@
|
|||||||
package org.jetbrains.uast.kotlin.psi
|
package org.jetbrains.uast.kotlin.psi
|
||||||
|
|
||||||
import com.intellij.lang.Language
|
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
|
import com.intellij.psi.impl.light.LightTypeElement
|
||||||
import org.jetbrains.kotlin.asJava.elements.LightVariableBuilder
|
import org.jetbrains.kotlin.asJava.elements.LightVariableBuilder
|
||||||
|
import org.jetbrains.kotlin.builtins.createFunctionType
|
||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.uast.UDeclaration
|
import org.jetbrains.uast.UDeclaration
|
||||||
import org.jetbrains.uast.UElement
|
import org.jetbrains.uast.UElement
|
||||||
import org.jetbrains.uast.UastErrorType
|
import org.jetbrains.uast.UastErrorType
|
||||||
import org.jetbrains.uast.getParentOfType
|
import org.jetbrains.uast.getParentOfType
|
||||||
import org.jetbrains.uast.kotlin.analyze
|
import org.jetbrains.uast.kotlin.analyze
|
||||||
|
import org.jetbrains.uast.kotlin.lz
|
||||||
import org.jetbrains.uast.kotlin.orAnonymous
|
import org.jetbrains.uast.kotlin.orAnonymous
|
||||||
import org.jetbrains.uast.kotlin.toPsiType
|
import org.jetbrains.uast.kotlin.toPsiType
|
||||||
|
|
||||||
@@ -19,16 +22,31 @@ class UastKotlinPsiVariable(
|
|||||||
manager: PsiManager,
|
manager: PsiManager,
|
||||||
name: String,
|
name: String,
|
||||||
type: PsiType,
|
type: PsiType,
|
||||||
language: Language,
|
|
||||||
val ktInitializer: KtExpression?,
|
val ktInitializer: KtExpression?,
|
||||||
val psiParent: PsiElement?,
|
val psiParent: PsiElement?,
|
||||||
val containingElement: UElement,
|
val containingElement: UElement,
|
||||||
val ktElement: KtElement
|
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 getParent() = psiParent
|
||||||
|
|
||||||
override fun hasInitializer() = ktInitializer != null
|
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 {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
@@ -36,11 +54,6 @@ class UastKotlinPsiVariable(
|
|||||||
return ktElement == (other as? UastKotlinPsiVariable)?.ktElement
|
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()
|
override fun hashCode() = ktElement.hashCode()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -55,7 +68,6 @@ class UastKotlinPsiVariable(
|
|||||||
declaration.manager,
|
declaration.manager,
|
||||||
declaration.name.orAnonymous("unnamed"),
|
declaration.name.orAnonymous("unnamed"),
|
||||||
declaration.typeReference.toPsiType(containingElement),
|
declaration.typeReference.toPsiType(containingElement),
|
||||||
KotlinLanguage.INSTANCE,
|
|
||||||
initializer ?: declaration.initializer,
|
initializer ?: declaration.initializer,
|
||||||
psiParent,
|
psiParent,
|
||||||
containingElement,
|
containingElement,
|
||||||
@@ -67,8 +79,7 @@ class UastKotlinPsiVariable(
|
|||||||
return UastKotlinPsiVariable(
|
return UastKotlinPsiVariable(
|
||||||
declaration.manager,
|
declaration.manager,
|
||||||
"var" + Integer.toHexString(declaration.getHashCode()),
|
"var" + Integer.toHexString(declaration.getHashCode()),
|
||||||
UastErrorType, //TODO,
|
declaration.initializer?.getType(containingElement) ?: UastErrorType,
|
||||||
KotlinLanguage.INSTANCE,
|
|
||||||
declaration.initializer,
|
declaration.initializer,
|
||||||
psiParent,
|
psiParent,
|
||||||
containingElement,
|
containingElement,
|
||||||
@@ -80,8 +91,7 @@ class UastKotlinPsiVariable(
|
|||||||
return UastKotlinPsiVariable(
|
return UastKotlinPsiVariable(
|
||||||
initializer.manager,
|
initializer.manager,
|
||||||
"var" + Integer.toHexString(initializer.getHashCode()),
|
"var" + Integer.toHexString(initializer.getHashCode()),
|
||||||
UastErrorType, //TODO,
|
initializer.getType(containingElement) ?: UastErrorType,
|
||||||
KotlinLanguage.INSTANCE,
|
|
||||||
initializer,
|
initializer,
|
||||||
psiParent,
|
psiParent,
|
||||||
containingElement,
|
containingElement,
|
||||||
@@ -93,8 +103,7 @@ class UastKotlinPsiVariable(
|
|||||||
return UastKotlinPsiVariable(
|
return UastKotlinPsiVariable(
|
||||||
localFunction.manager,
|
localFunction.manager,
|
||||||
name,
|
name,
|
||||||
UastErrorType, // TODO,
|
localFunction.getFunctionType(containingElement) ?: UastErrorType,
|
||||||
KotlinLanguage.INSTANCE,
|
|
||||||
localFunction,
|
localFunction,
|
||||||
psiParent,
|
psiParent,
|
||||||
containingElement,
|
containingElement,
|
||||||
@@ -104,12 +113,26 @@ class UastKotlinPsiVariable(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class KotlinUastPsiExpression(val ktExpression: KtExpression, val parent: UElement) : PsiElement by ktExpression, PsiExpression {
|
private class KotlinUastPsiExpression(val ktExpression: KtExpression, val parent: UElement) : PsiElement by ktExpression, PsiExpression {
|
||||||
override fun getType(): PsiType? {
|
override fun getType(): PsiType? = ktExpression.getType(parent)
|
||||||
val ktType = ktExpression.analyze()[BindingContext.EXPRESSION_TYPE_INFO, ktExpression]?.type ?: return null
|
|
||||||
return ktType.toPsiType(parent, ktExpression, boxed = false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
private fun PsiElement.getHashCode(): Int {
|
||||||
var result = 42
|
var result = 42
|
||||||
result = 41 * result + containingFile.name.hashCode()
|
result = 41 * result + containingFile.name.hashCode()
|
||||||
|
|||||||
+5
-3
@@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
fun foo(bar: String): Any? = null
|
fun foo(bar: String): String? = null
|
||||||
|
|
||||||
fun baz(): Any? {
|
fun bar() = 42
|
||||||
return foo("Lorem ipsum") ?: foo("dolor sit amet") ?: foo("consectetuer adipiscing elit")
|
|
||||||
|
fun baz(): String? {
|
||||||
|
return foo("Lorem ipsum") ?: foo("dolor sit amet") ?: bar().toString()
|
||||||
}
|
}
|
||||||
+15
-10
@@ -4,34 +4,39 @@ UFile (package = )
|
|||||||
UParameter (name = bar)
|
UParameter (name = bar)
|
||||||
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||||
ULiteralExpression (value = null)
|
ULiteralExpression (value = null)
|
||||||
|
UAnnotationMethod (name = bar)
|
||||||
|
ULiteralExpression (value = 42)
|
||||||
UAnnotationMethod (name = baz)
|
UAnnotationMethod (name = baz)
|
||||||
UBlockExpression
|
UBlockExpression
|
||||||
UReturnExpression
|
UReturnExpression
|
||||||
UExpressionList (elvis)
|
UExpressionList (elvis)
|
||||||
UDeclarationsExpression
|
UDeclarationsExpression
|
||||||
ULocalVariable (name = var243c4e1a)
|
ULocalVariable (name = var243c51a0)
|
||||||
UExpressionList (elvis)
|
UExpressionList (elvis)
|
||||||
UDeclarationsExpression
|
UDeclarationsExpression
|
||||||
ULocalVariable (name = varc4aef1e3)
|
ULocalVariable (name = varc4aef569)
|
||||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
|
||||||
UIdentifier (Identifier (foo))
|
UIdentifier (Identifier (foo))
|
||||||
USimpleNameReferenceExpression (identifier = foo)
|
USimpleNameReferenceExpression (identifier = foo)
|
||||||
ULiteralExpression (value = "Lorem ipsum")
|
ULiteralExpression (value = "Lorem ipsum")
|
||||||
UIfExpression
|
UIfExpression
|
||||||
UBinaryExpression (operator = !=)
|
UBinaryExpression (operator = !=)
|
||||||
USimpleNameReferenceExpression (identifier = varc4aef1e3)
|
USimpleNameReferenceExpression (identifier = varc4aef569)
|
||||||
ULiteralExpression (value = null)
|
ULiteralExpression (value = null)
|
||||||
USimpleNameReferenceExpression (identifier = varc4aef1e3)
|
USimpleNameReferenceExpression (identifier = varc4aef569)
|
||||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
|
||||||
UIdentifier (Identifier (foo))
|
UIdentifier (Identifier (foo))
|
||||||
USimpleNameReferenceExpression (identifier = foo)
|
USimpleNameReferenceExpression (identifier = foo)
|
||||||
ULiteralExpression (value = "dolor sit amet")
|
ULiteralExpression (value = "dolor sit amet")
|
||||||
UIfExpression
|
UIfExpression
|
||||||
UBinaryExpression (operator = !=)
|
UBinaryExpression (operator = !=)
|
||||||
USimpleNameReferenceExpression (identifier = var243c4e1a)
|
USimpleNameReferenceExpression (identifier = var243c51a0)
|
||||||
ULiteralExpression (value = null)
|
ULiteralExpression (value = null)
|
||||||
USimpleNameReferenceExpression (identifier = var243c4e1a)
|
USimpleNameReferenceExpression (identifier = var243c51a0)
|
||||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
|
UQualifiedReferenceExpression
|
||||||
UIdentifier (Identifier (foo))
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||||
USimpleNameReferenceExpression (identifier = foo)
|
UIdentifier (Identifier (bar))
|
||||||
ULiteralExpression (value = "consectetuer adipiscing elit")
|
USimpleNameReferenceExpression (identifier = bar)
|
||||||
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||||
|
UIdentifier (Identifier (toString))
|
||||||
|
USimpleNameReferenceExpression (identifier = toString)
|
||||||
|
|||||||
+7
-6
@@ -1,12 +1,13 @@
|
|||||||
public final class ElvisKt {
|
public final class ElvisKt {
|
||||||
public static final fun foo(bar: java.lang.String) : java.lang.Object = null
|
public static final fun foo(bar: java.lang.String) : java.lang.String = null
|
||||||
public static final fun baz() : java.lang.Object {
|
public static final fun bar() : int = 42
|
||||||
|
public static final fun baz() : java.lang.String {
|
||||||
return elvis {
|
return elvis {
|
||||||
var var243c4e1a: <ErrorType> = elvis {
|
var var243c51a0: java.lang.String = elvis {
|
||||||
var varc4aef1e3: <ErrorType> = foo("Lorem ipsum")
|
var varc4aef569: java.lang.String = foo("Lorem ipsum")
|
||||||
if (varc4aef1e3 != null) varc4aef1e3 else foo("dolor sit amet")
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,5 +6,7 @@ fun foo(): Boolean {
|
|||||||
Local()
|
Local()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Int.someLocalFun(text: String) = 42
|
||||||
|
|
||||||
return bar() == Local()
|
return bar() == Local()
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,11 @@ UFile (package = )
|
|||||||
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0))
|
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0))
|
||||||
UIdentifier (Identifier (Local))
|
UIdentifier (Identifier (Local))
|
||||||
USimpleNameReferenceExpression (identifier = <init>)
|
USimpleNameReferenceExpression (identifier = <init>)
|
||||||
|
UDeclarationsExpression
|
||||||
|
UVariable (name = someLocalFun)
|
||||||
|
ULambdaExpression
|
||||||
|
UParameter (name = text)
|
||||||
|
ULiteralExpression (value = 42)
|
||||||
UReturnExpression
|
UReturnExpression
|
||||||
UBinaryExpression (operator = ==)
|
UBinaryExpression (operator = ==)
|
||||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ public final class LocalDeclarationsKt {
|
|||||||
var baz: <ErrorType> = fun () {
|
var baz: <ErrorType> = fun () {
|
||||||
<init>()
|
<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>()
|
return bar() == <init>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ UFile (package = ) [public final class LocalDeclarationsKt {...]
|
|||||||
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [<init>()] : PsiType:<ErrorType>
|
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [<init>()] : PsiType:<ErrorType>
|
||||||
UIdentifier (Identifier (Local)) [UIdentifier (Identifier (Local))]
|
UIdentifier (Identifier (Local)) [UIdentifier (Identifier (Local))]
|
||||||
USimpleNameReferenceExpression (identifier = <init>) [<init>] : PsiType:<ErrorType>
|
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
|
UReturnExpression [return bar() == <init>()] : PsiType:Void
|
||||||
UBinaryExpression (operator = ==) [bar() == <init>()] : PsiType:boolean
|
UBinaryExpression (operator = ==) [bar() == <init>()] : PsiType:boolean
|
||||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) [bar()] : PsiType:<ErrorType>
|
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>()()
|
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [<init>()] = external <init>()()
|
||||||
UIdentifier (Identifier (Local)) [UIdentifier (Identifier (Local))]
|
UIdentifier (Identifier (Local)) [UIdentifier (Identifier (Local))]
|
||||||
USimpleNameReferenceExpression (identifier = <init>) [<init>] = external <init>()
|
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
|
UReturnExpression [return bar() == <init>()] = Nothing
|
||||||
UBinaryExpression (operator = ==) [bar() == <init>()] = Undetermined
|
UBinaryExpression (operator = ==) [bar() == <init>()] = Undetermined
|
||||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) [bar()] = external bar()()
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) [bar()] = external bar()()
|
||||||
|
|||||||
Reference in New Issue
Block a user