UAST: Fix getType and getText for UastKotlinPsiVariable
This commit is contained in:
@@ -4,12 +4,13 @@ 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.descriptors.CallableDescriptor
|
||||
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.kotlin.utils.ifEmpty
|
||||
import org.jetbrains.kotlin.types.isError
|
||||
import org.jetbrains.uast.UDeclaration
|
||||
import org.jetbrains.uast.UElement
|
||||
import org.jetbrains.uast.UastErrorType
|
||||
@@ -19,24 +20,35 @@ import org.jetbrains.uast.kotlin.lz
|
||||
import org.jetbrains.uast.kotlin.orAnonymous
|
||||
import org.jetbrains.uast.kotlin.toPsiType
|
||||
|
||||
class UastKotlinPsiVariable(
|
||||
class UastKotlinPsiVariable private constructor(
|
||||
manager: PsiManager,
|
||||
name: String,
|
||||
type: PsiType,
|
||||
typeProducer: () -> PsiType,
|
||||
val ktInitializer: KtExpression?,
|
||||
val psiParent: PsiElement?,
|
||||
val containingElement: UElement,
|
||||
val ktElement: KtElement
|
||||
) : LightVariableBuilder(manager, name, type, KotlinLanguage.INSTANCE), PsiLocalVariable {
|
||||
) : LightVariableBuilder(
|
||||
manager,
|
||||
name,
|
||||
UastErrorType, // Type is calculated lazily
|
||||
KotlinLanguage.INSTANCE
|
||||
), PsiLocalVariable {
|
||||
|
||||
private val psiType: PsiType by lz(typeProducer)
|
||||
|
||||
private val psiTypeElement: PsiTypeElement by lz {
|
||||
LightTypeElement(manager, type)
|
||||
LightTypeElement(manager, psiType)
|
||||
}
|
||||
|
||||
private val psiInitializer: PsiExpression? by lz {
|
||||
ktInitializer?.let { KotlinUastPsiExpression(it, containingElement) }
|
||||
}
|
||||
|
||||
override fun getType(): PsiType = psiType
|
||||
|
||||
override fun getText(): String = ktElement.text
|
||||
|
||||
override fun getParent() = psiParent
|
||||
|
||||
override fun hasInitializer() = ktInitializer != null
|
||||
@@ -61,54 +73,55 @@ class UastKotlinPsiVariable(
|
||||
fun create(
|
||||
declaration: KtVariableDeclaration,
|
||||
parent: PsiElement?,
|
||||
containingElement: UElement,
|
||||
containingElement: UElement,
|
||||
initializer: KtExpression? = null
|
||||
): PsiLocalVariable {
|
||||
val psiParent = containingElement.getParentOfType<UDeclaration>()?.psi ?: parent
|
||||
val initializerExpression = initializer ?: declaration.initializer
|
||||
return UastKotlinPsiVariable(
|
||||
declaration.manager,
|
||||
declaration.name.orAnonymous("unnamed"),
|
||||
declaration.typeReference.toPsiType(containingElement),
|
||||
initializer ?: declaration.initializer,
|
||||
psiParent,
|
||||
containingElement,
|
||||
declaration)
|
||||
manager = declaration.manager,
|
||||
name = declaration.name.orAnonymous("<unnamed>"),
|
||||
typeProducer = { declaration.getType(containingElement) ?: UastErrorType },
|
||||
ktInitializer = initializerExpression,
|
||||
psiParent = psiParent,
|
||||
containingElement = containingElement,
|
||||
ktElement = declaration)
|
||||
}
|
||||
|
||||
fun create(declaration: KtDestructuringDeclaration, containingElement: UElement): PsiLocalVariable {
|
||||
val psiParent = containingElement.getParentOfType<UDeclaration>()?.psi ?: declaration.parent
|
||||
return UastKotlinPsiVariable(
|
||||
declaration.manager,
|
||||
"var" + Integer.toHexString(declaration.getHashCode()),
|
||||
declaration.initializer?.getType(containingElement) ?: UastErrorType,
|
||||
declaration.initializer,
|
||||
psiParent,
|
||||
containingElement,
|
||||
declaration)
|
||||
manager = declaration.manager,
|
||||
name = "var" + Integer.toHexString(declaration.getHashCode()),
|
||||
typeProducer = { declaration.getType(containingElement) ?: UastErrorType },
|
||||
ktInitializer = declaration.initializer,
|
||||
psiParent = psiParent,
|
||||
containingElement = containingElement,
|
||||
ktElement = declaration)
|
||||
}
|
||||
|
||||
fun create(initializer: KtExpression, containingElement: UElement, parent: PsiElement): PsiLocalVariable {
|
||||
val psiParent = containingElement.getParentOfType<UDeclaration>()?.psi ?: parent
|
||||
return UastKotlinPsiVariable(
|
||||
initializer.manager,
|
||||
"var" + Integer.toHexString(initializer.getHashCode()),
|
||||
initializer.getType(containingElement) ?: UastErrorType,
|
||||
initializer,
|
||||
psiParent,
|
||||
containingElement,
|
||||
initializer)
|
||||
manager = initializer.manager,
|
||||
name = "var" + Integer.toHexString(initializer.getHashCode()),
|
||||
typeProducer = { initializer.getType(containingElement) ?: UastErrorType },
|
||||
ktInitializer = initializer,
|
||||
psiParent = psiParent,
|
||||
containingElement = containingElement,
|
||||
ktElement = initializer)
|
||||
}
|
||||
|
||||
fun create(name: String, localFunction: KtFunction, containingElement: UElement): PsiLocalVariable {
|
||||
val psiParent = containingElement.getParentOfType<UDeclaration>()?.psi ?: localFunction.parent
|
||||
return UastKotlinPsiVariable(
|
||||
localFunction.manager,
|
||||
name,
|
||||
localFunction.getFunctionType(containingElement) ?: UastErrorType,
|
||||
localFunction,
|
||||
psiParent,
|
||||
containingElement,
|
||||
localFunction)
|
||||
manager = localFunction.manager,
|
||||
name = name,
|
||||
typeProducer = { localFunction.getFunctionType(containingElement) ?: UastErrorType },
|
||||
ktInitializer = localFunction,
|
||||
psiParent = psiParent,
|
||||
containingElement = containingElement,
|
||||
ktElement = localFunction)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,18 +135,25 @@ private fun KtFunction.getFunctionType(parent: UElement): PsiType? {
|
||||
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
|
||||
builtIns = descriptor.builtIns,
|
||||
annotations = descriptor.annotations,
|
||||
receiverType = descriptor.extensionReceiverParameter?.type,
|
||||
parameterTypes = descriptor.valueParameters.map { it.type },
|
||||
parameterNames = descriptor.valueParameters.map { it.name },
|
||||
returnType = 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 KtDeclaration.getType(parent: UElement): PsiType? {
|
||||
return (analyze()[BindingContext.DECLARATION_TO_DESCRIPTOR, this] as? CallableDescriptor)
|
||||
?.returnType
|
||||
?.takeIf { !it.isError }
|
||||
?.toPsiType(parent, this, false)
|
||||
}
|
||||
|
||||
private fun PsiElement.getHashCode(): Int {
|
||||
var result = 42
|
||||
result = 41 * result + containingFile.name.hashCode()
|
||||
|
||||
+4
-4
@@ -2,11 +2,11 @@ UFile (package = ) [public final class InKt {...]
|
||||
UClass (name = InKt) [public final class InKt {...}]
|
||||
UAnnotationMethod (name = foo) [public static final fun foo() : boolean {...}]
|
||||
UBlockExpression [{...}] = Nothing
|
||||
UDeclarationsExpression [var x: <ErrorType> = 1] = Undetermined
|
||||
ULocalVariable (name = x) [var x: <ErrorType> = 1]
|
||||
UDeclarationsExpression [var x: int = 1] = Undetermined
|
||||
ULocalVariable (name = x) [var x: int = 1]
|
||||
ULiteralExpression (value = 1) [1] = 1
|
||||
UDeclarationsExpression [var y: <ErrorType> = 10] = Undetermined
|
||||
ULocalVariable (name = y) [var y: <ErrorType> = 10]
|
||||
UDeclarationsExpression [var y: int = 10] = Undetermined
|
||||
ULocalVariable (name = y) [var y: int = 10]
|
||||
ULiteralExpression (value = 10) [10] = 10
|
||||
UReturnExpression [return x in 0 .. 5 && y !in 4 .. 9] = Nothing
|
||||
UBinaryExpression (operator = &&) [x in 0 .. 5 && y !in 4 .. 9] = true (depending on: (var x = 1), (var y = 10))
|
||||
|
||||
@@ -6,7 +6,7 @@ public final class LocalDeclarationsKt {
|
||||
var bar: <ErrorType> = fun () {
|
||||
<init>()
|
||||
}
|
||||
var baz: <ErrorType> = fun () {
|
||||
var baz: kotlin.jvm.functions.Function0<? extends kotlin.Unit> = 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) {
|
||||
|
||||
@@ -11,8 +11,8 @@ 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 baz: <ErrorType> = fun () {...}]
|
||||
ULocalVariable (name = baz) [var baz: <ErrorType> = fun () {...}]
|
||||
UDeclarationsExpression [var baz: kotlin.jvm.functions.Function0<? extends kotlin.Unit> = fun () {...}]
|
||||
ULocalVariable (name = baz) [var baz: kotlin.jvm.functions.Function0<? extends kotlin.Unit> = fun () {...}]
|
||||
ULambdaExpression [fun () {...}]
|
||||
UBlockExpression [{...}] : PsiType:<ErrorType>
|
||||
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [<init>()] : PsiType:<ErrorType>
|
||||
|
||||
@@ -11,8 +11,8 @@ 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 baz: <ErrorType> = fun () {...}] = Undetermined
|
||||
ULocalVariable (name = baz) [var baz: <ErrorType> = fun () {...}]
|
||||
UDeclarationsExpression [var baz: kotlin.jvm.functions.Function0<? extends kotlin.Unit> = fun () {...}] = Undetermined
|
||||
ULocalVariable (name = baz) [var baz: kotlin.jvm.functions.Function0<? extends kotlin.Unit> = fun () {...}]
|
||||
ULambdaExpression [fun () {...}] = Undetermined
|
||||
UBlockExpression [{...}] = external <init>()()
|
||||
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [<init>()] = external <init>()()
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
UFile (package = )
|
||||
UClass (name = MyAnnotation)
|
||||
UClass (name = Test1)
|
||||
UField (name = bar)
|
||||
UAnnotation (fqName = null)
|
||||
UAnnotationMethod (name = getBar)
|
||||
UAnnotationMethod (name = setBar)
|
||||
UParameter (name = p)
|
||||
UAnnotation (fqName = null)
|
||||
UAnnotationMethod (name = Test1)
|
||||
UParameter (name = bar)
|
||||
UAnnotation (fqName = MyAnnotation)
|
||||
UAnnotation (fqName = null)
|
||||
UClass (name = Test2)
|
||||
UField (name = bar)
|
||||
UAnnotation (fqName = MyAnnotation)
|
||||
UAnnotation (fqName = null)
|
||||
UAnnotationMethod (name = getBar)
|
||||
UAnnotation (fqName = MyAnnotation)
|
||||
UAnnotationMethod (name = setBar)
|
||||
UAnnotation (fqName = MyAnnotation)
|
||||
UParameter (name = p)
|
||||
UAnnotation (fqName = MyAnnotation)
|
||||
UAnnotation (fqName = null)
|
||||
UAnnotationMethod (name = Test2)
|
||||
UParameter (name = bar)
|
||||
UAnnotation (fqName = null)
|
||||
@@ -0,0 +1,18 @@
|
||||
public abstract annotation MyAnnotation {
|
||||
}
|
||||
|
||||
public final class Test1 {
|
||||
private var bar: int
|
||||
public final fun getBar() : int = UastEmptyExpression
|
||||
public final fun setBar(p: int) : void = UastEmptyExpression
|
||||
public fun Test1(bar: int) = UastEmptyExpression
|
||||
}
|
||||
|
||||
public final class Test2 {
|
||||
private var bar: int
|
||||
@MyAnnotation
|
||||
public final fun getBar() : int = UastEmptyExpression
|
||||
@MyAnnotation
|
||||
public final fun setBar(p: int) : void = UastEmptyExpression
|
||||
public fun Test2(bar: int) = UastEmptyExpression
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
fun foo(a: Int, b: String, c: Int = 0, flag: Boolean = false) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
UFile (package = )
|
||||
UClass (name = ParametersWithDefaultValuesKt)
|
||||
UAnnotationMethod (name = foo)
|
||||
UParameter (name = a)
|
||||
UAnnotation (fqName = null)
|
||||
UParameter (name = b)
|
||||
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||
UParameter (name = c)
|
||||
UAnnotation (fqName = null)
|
||||
ULiteralExpression (value = 0)
|
||||
UParameter (name = flag)
|
||||
UAnnotation (fqName = null)
|
||||
ULiteralExpression (value = false)
|
||||
UBlockExpression
|
||||
@@ -0,0 +1,4 @@
|
||||
public final class ParametersWithDefaultValuesKt {
|
||||
public static final fun foo(a: int, b: java.lang.String, c: int, flag: boolean) : void {
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,6 @@ public final class PropertyDelegateKt {
|
||||
private static final var sdCardPath$delegate: kotlin.Lazy
|
||||
public static final fun getSdCardPath() : java.lang.String = UastEmptyExpression
|
||||
public static final fun localPropertyTest() : void {
|
||||
var sdCardPathLocal: <ErrorType>
|
||||
var sdCardPathLocal: java.lang.String
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,4 +34,8 @@ class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() {
|
||||
@Test fun testInnerClasses() = doTest("InnerClasses")
|
||||
|
||||
@Test fun testSimpleScript() = doTest("SimpleScript")
|
||||
|
||||
@Test fun testParameterPropertyWithAnnotation() = doTest("ParameterPropertyWithAnnotation")
|
||||
|
||||
@Test fun testParametersWithDefaultValues() = doTest("ParametersWithDefaultValues")
|
||||
}
|
||||
Reference in New Issue
Block a user