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 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.builtins.createFunctionType
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
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.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.UDeclaration
|
||||||
import org.jetbrains.uast.UElement
|
import org.jetbrains.uast.UElement
|
||||||
import org.jetbrains.uast.UastErrorType
|
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.orAnonymous
|
||||||
import org.jetbrains.uast.kotlin.toPsiType
|
import org.jetbrains.uast.kotlin.toPsiType
|
||||||
|
|
||||||
class UastKotlinPsiVariable(
|
class UastKotlinPsiVariable private constructor(
|
||||||
manager: PsiManager,
|
manager: PsiManager,
|
||||||
name: String,
|
name: String,
|
||||||
type: PsiType,
|
typeProducer: () -> PsiType,
|
||||||
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, 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 {
|
private val psiTypeElement: PsiTypeElement by lz {
|
||||||
LightTypeElement(manager, type)
|
LightTypeElement(manager, psiType)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val psiInitializer: PsiExpression? by lz {
|
private val psiInitializer: PsiExpression? by lz {
|
||||||
ktInitializer?.let { KotlinUastPsiExpression(it, containingElement) }
|
ktInitializer?.let { KotlinUastPsiExpression(it, containingElement) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getType(): PsiType = psiType
|
||||||
|
|
||||||
|
override fun getText(): String = ktElement.text
|
||||||
|
|
||||||
override fun getParent() = psiParent
|
override fun getParent() = psiParent
|
||||||
|
|
||||||
override fun hasInitializer() = ktInitializer != null
|
override fun hasInitializer() = ktInitializer != null
|
||||||
@@ -61,54 +73,55 @@ class UastKotlinPsiVariable(
|
|||||||
fun create(
|
fun create(
|
||||||
declaration: KtVariableDeclaration,
|
declaration: KtVariableDeclaration,
|
||||||
parent: PsiElement?,
|
parent: PsiElement?,
|
||||||
containingElement: UElement,
|
containingElement: UElement,
|
||||||
initializer: KtExpression? = null
|
initializer: KtExpression? = null
|
||||||
): PsiLocalVariable {
|
): PsiLocalVariable {
|
||||||
val psiParent = containingElement.getParentOfType<UDeclaration>()?.psi ?: parent
|
val psiParent = containingElement.getParentOfType<UDeclaration>()?.psi ?: parent
|
||||||
|
val initializerExpression = initializer ?: declaration.initializer
|
||||||
return UastKotlinPsiVariable(
|
return UastKotlinPsiVariable(
|
||||||
declaration.manager,
|
manager = declaration.manager,
|
||||||
declaration.name.orAnonymous("unnamed"),
|
name = declaration.name.orAnonymous("<unnamed>"),
|
||||||
declaration.typeReference.toPsiType(containingElement),
|
typeProducer = { declaration.getType(containingElement) ?: UastErrorType },
|
||||||
initializer ?: declaration.initializer,
|
ktInitializer = initializerExpression,
|
||||||
psiParent,
|
psiParent = psiParent,
|
||||||
containingElement,
|
containingElement = containingElement,
|
||||||
declaration)
|
ktElement = declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun create(declaration: KtDestructuringDeclaration, containingElement: UElement): PsiLocalVariable {
|
fun create(declaration: KtDestructuringDeclaration, containingElement: UElement): PsiLocalVariable {
|
||||||
val psiParent = containingElement.getParentOfType<UDeclaration>()?.psi ?: declaration.parent
|
val psiParent = containingElement.getParentOfType<UDeclaration>()?.psi ?: declaration.parent
|
||||||
return UastKotlinPsiVariable(
|
return UastKotlinPsiVariable(
|
||||||
declaration.manager,
|
manager = declaration.manager,
|
||||||
"var" + Integer.toHexString(declaration.getHashCode()),
|
name = "var" + Integer.toHexString(declaration.getHashCode()),
|
||||||
declaration.initializer?.getType(containingElement) ?: UastErrorType,
|
typeProducer = { declaration.getType(containingElement) ?: UastErrorType },
|
||||||
declaration.initializer,
|
ktInitializer = declaration.initializer,
|
||||||
psiParent,
|
psiParent = psiParent,
|
||||||
containingElement,
|
containingElement = containingElement,
|
||||||
declaration)
|
ktElement = declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun create(initializer: KtExpression, containingElement: UElement, parent: PsiElement): PsiLocalVariable {
|
fun create(initializer: KtExpression, containingElement: UElement, parent: PsiElement): PsiLocalVariable {
|
||||||
val psiParent = containingElement.getParentOfType<UDeclaration>()?.psi ?: parent
|
val psiParent = containingElement.getParentOfType<UDeclaration>()?.psi ?: parent
|
||||||
return UastKotlinPsiVariable(
|
return UastKotlinPsiVariable(
|
||||||
initializer.manager,
|
manager = initializer.manager,
|
||||||
"var" + Integer.toHexString(initializer.getHashCode()),
|
name = "var" + Integer.toHexString(initializer.getHashCode()),
|
||||||
initializer.getType(containingElement) ?: UastErrorType,
|
typeProducer = { initializer.getType(containingElement) ?: UastErrorType },
|
||||||
initializer,
|
ktInitializer = initializer,
|
||||||
psiParent,
|
psiParent = psiParent,
|
||||||
containingElement,
|
containingElement = containingElement,
|
||||||
initializer)
|
ktElement = initializer)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun create(name: String, localFunction: KtFunction, containingElement: UElement): PsiLocalVariable {
|
fun create(name: String, localFunction: KtFunction, containingElement: UElement): PsiLocalVariable {
|
||||||
val psiParent = containingElement.getParentOfType<UDeclaration>()?.psi ?: localFunction.parent
|
val psiParent = containingElement.getParentOfType<UDeclaration>()?.psi ?: localFunction.parent
|
||||||
return UastKotlinPsiVariable(
|
return UastKotlinPsiVariable(
|
||||||
localFunction.manager,
|
manager = localFunction.manager,
|
||||||
name,
|
name = name,
|
||||||
localFunction.getFunctionType(containingElement) ?: UastErrorType,
|
typeProducer = { localFunction.getFunctionType(containingElement) ?: UastErrorType },
|
||||||
localFunction,
|
ktInitializer = localFunction,
|
||||||
psiParent,
|
psiParent = psiParent,
|
||||||
containingElement,
|
containingElement = containingElement,
|
||||||
localFunction)
|
ktElement = localFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,18 +135,25 @@ private fun KtFunction.getFunctionType(parent: UElement): PsiType? {
|
|||||||
val returnType = descriptor.returnType ?: return null
|
val returnType = descriptor.returnType ?: return null
|
||||||
|
|
||||||
return createFunctionType(
|
return createFunctionType(
|
||||||
descriptor.builtIns,
|
builtIns = descriptor.builtIns,
|
||||||
descriptor.annotations,
|
annotations = descriptor.annotations,
|
||||||
descriptor.extensionReceiverParameter?.type,
|
receiverType = descriptor.extensionReceiverParameter?.type,
|
||||||
descriptor.valueParameters.map { it.type },
|
parameterTypes = descriptor.valueParameters.map { it.type },
|
||||||
descriptor.valueParameters.map { it.name },
|
parameterNames = descriptor.valueParameters.map { it.name },
|
||||||
returnType
|
returnType = returnType
|
||||||
).toPsiType(parent, this, boxed = false)
|
).toPsiType(parent, this, boxed = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtExpression.getType(parent: UElement): PsiType? =
|
private fun KtExpression.getType(parent: UElement): PsiType? =
|
||||||
analyze()[BindingContext.EXPRESSION_TYPE_INFO, this]?.type?.toPsiType(parent, this, boxed = false)
|
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 {
|
private fun PsiElement.getHashCode(): Int {
|
||||||
var result = 42
|
var result = 42
|
||||||
result = 41 * result + containingFile.name.hashCode()
|
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 {...}]
|
UClass (name = InKt) [public final class InKt {...}]
|
||||||
UAnnotationMethod (name = foo) [public static final fun foo() : boolean {...}]
|
UAnnotationMethod (name = foo) [public static final fun foo() : boolean {...}]
|
||||||
UBlockExpression [{...}] = Nothing
|
UBlockExpression [{...}] = Nothing
|
||||||
UDeclarationsExpression [var x: <ErrorType> = 1] = Undetermined
|
UDeclarationsExpression [var x: int = 1] = Undetermined
|
||||||
ULocalVariable (name = x) [var x: <ErrorType> = 1]
|
ULocalVariable (name = x) [var x: int = 1]
|
||||||
ULiteralExpression (value = 1) [1] = 1
|
ULiteralExpression (value = 1) [1] = 1
|
||||||
UDeclarationsExpression [var y: <ErrorType> = 10] = Undetermined
|
UDeclarationsExpression [var y: int = 10] = Undetermined
|
||||||
ULocalVariable (name = y) [var y: <ErrorType> = 10]
|
ULocalVariable (name = y) [var y: int = 10]
|
||||||
ULiteralExpression (value = 10) [10] = 10
|
ULiteralExpression (value = 10) [10] = 10
|
||||||
UReturnExpression [return x in 0 .. 5 && y !in 4 .. 9] = Nothing
|
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))
|
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 () {
|
var bar: <ErrorType> = fun () {
|
||||||
<init>()
|
<init>()
|
||||||
}
|
}
|
||||||
var baz: <ErrorType> = fun () {
|
var baz: kotlin.jvm.functions.Function0<? extends kotlin.Unit> = 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) {
|
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>
|
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 baz: <ErrorType> = fun () {...}]
|
UDeclarationsExpression [var baz: kotlin.jvm.functions.Function0<? extends kotlin.Unit> = fun () {...}]
|
||||||
ULocalVariable (name = baz) [var baz: <ErrorType> = fun () {...}]
|
ULocalVariable (name = baz) [var baz: kotlin.jvm.functions.Function0<? extends kotlin.Unit> = fun () {...}]
|
||||||
ULambdaExpression [fun () {...}]
|
ULambdaExpression [fun () {...}]
|
||||||
UBlockExpression [{...}] : PsiType:<ErrorType>
|
UBlockExpression [{...}] : PsiType:<ErrorType>
|
||||||
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [<init>()] : 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>()()
|
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 baz: <ErrorType> = fun () {...}] = Undetermined
|
UDeclarationsExpression [var baz: kotlin.jvm.functions.Function0<? extends kotlin.Unit> = fun () {...}] = Undetermined
|
||||||
ULocalVariable (name = baz) [var baz: <ErrorType> = fun () {...}]
|
ULocalVariable (name = baz) [var baz: kotlin.jvm.functions.Function0<? extends kotlin.Unit> = fun () {...}]
|
||||||
ULambdaExpression [fun () {...}] = Undetermined
|
ULambdaExpression [fun () {...}] = Undetermined
|
||||||
UBlockExpression [{...}] = external <init>()()
|
UBlockExpression [{...}] = external <init>()()
|
||||||
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [<init>()] = 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
|
private static final var sdCardPath$delegate: kotlin.Lazy
|
||||||
public static final fun getSdCardPath() : java.lang.String = UastEmptyExpression
|
public static final fun getSdCardPath() : java.lang.String = UastEmptyExpression
|
||||||
public static final fun localPropertyTest() : void {
|
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 testInnerClasses() = doTest("InnerClasses")
|
||||||
|
|
||||||
@Test fun testSimpleScript() = doTest("SimpleScript")
|
@Test fun testSimpleScript() = doTest("SimpleScript")
|
||||||
|
|
||||||
|
@Test fun testParameterPropertyWithAnnotation() = doTest("ParameterPropertyWithAnnotation")
|
||||||
|
|
||||||
|
@Test fun testParametersWithDefaultValues() = doTest("ParametersWithDefaultValues")
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user