Support lazy conversion of parent chain; correctly check expected class

This commit is contained in:
Dmitry Jemerov
2017-03-09 13:22:17 +01:00
parent 8c3936a0ee
commit 01a9d9a284
11 changed files with 157 additions and 103 deletions
@@ -19,7 +19,6 @@ package org.jetbrains.uast.kotlin
import com.intellij.lang.Language
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiVariable
import com.intellij.psi.impl.source.tree.LeafPsiElement
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.asJava.LightClassUtil
@@ -39,7 +38,6 @@ import org.jetbrains.uast.*
import org.jetbrains.uast.java.JavaUastLanguagePlugin
import org.jetbrains.uast.kotlin.declarations.KotlinUMethod
import org.jetbrains.uast.kotlin.expressions.*
import org.jetbrains.uast.kotlin.kinds.KotlinSpecialExpressionKinds
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable
@@ -62,7 +60,8 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
override fun convertElement(element: PsiElement, parent: UElement?, requiredType: Class<out UElement>?): UElement? {
if (element !is PsiElement) return null
return convertDeclaration(element, parent, requiredType) ?: KotlinConverter.convertPsiElement(element, parent, requiredType)
return convertDeclaration(element, parent.toCallback(), requiredType)
?: KotlinConverter.convertPsiElement(element, parent.toCallback(), requiredType)
}
override fun convertElementWithParent(element: PsiElement, requiredType: Class<out UElement>?): UElement? {
@@ -70,9 +69,12 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
if (element is PsiFile) return convertDeclaration(element, null, requiredType)
if (element is KtLightClassForFacade) return convertDeclaration(element, null, requiredType)
val parent = KotlinConverter.unwrapElements(element.parent) ?: return null
val parentUElement = convertElementWithParent(parent, null) ?: return null
return convertElement(element, parentUElement, requiredType)
val parentCallback = fun(): UElement? {
val parent = KotlinConverter.unwrapElements(element.parent) ?: return null
return convertElementWithParent(parent, null)
}
return convertDeclaration(element, parentCallback, requiredType)
?: KotlinConverter.convertPsiElement(element, parentCallback, requiredType)
}
override fun getMethodCallExpression(
@@ -115,35 +117,53 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
return UastLanguagePlugin.ResolvedConstructor(uExpression, method, containingClass)
}
private fun convertDeclaration(element: PsiElement, parent: UElement?, requiredType: Class<out UElement>?): UElement? {
private fun convertDeclaration(element: PsiElement,
parentCallback: (() -> UElement?)?,
requiredType: Class<out UElement>?): UElement? {
if (element is UElement) return element
if (element.isValid) element.getUserData(KOTLIN_CACHED_UELEMENT_KEY)?.let { ref ->
ref.get()?.let { return it }
}
fun <P : PsiElement> build(ctor: (P, UElement?) -> UElement): () -> UElement? {
return fun(): UElement? {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
return ctor(element as P, parent)
}
}
val original = element.originalElement
return with(requiredType) {
when (original) {
is KtLightMethod -> el<UMethod> { KotlinUMethod.create(original, parent) }
is KtLightClass -> el<UClass> { KotlinUClass.create(original, parent) }
is KtLightField, is KtLightParameter, is UastKotlinPsiParameter, is UastKotlinPsiVariable -> el<UVariable> {
KotlinUVariable.create(original as PsiVariable, parent)
}
is KtLightMethod -> el<UMethod>(build(KotlinUMethod.Companion::create)) // .Companion is needed because of KT-13934
is KtLightClass -> el<UClass>(build(KotlinUClass.Companion::create))
is KtClassOrObject -> el<UClass> { original.toLightClass()?.let { lightClass -> KotlinUClass.create(lightClass, parent) } }
is KtLightFieldImpl.KtLightEnumConstant -> el<UEnumConstant>(build(::KotlinUEnumConstant))
is KtLightField -> el<UField>(build(::KotlinUField))
is KtLightParameter, is UastKotlinPsiParameter -> el<UParameter>(build(::KotlinUParameter))
is UastKotlinPsiVariable -> el<UVariable>(build(::KotlinUVariable))
is KtClassOrObject -> el<UClass> {
original.toLightClass()?.let { lightClass ->
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
KotlinUClass.create(lightClass, parent)
}
}
is KtFunction -> el<UMethod> {
val lightMethod = LightClassUtil.getLightClassMethod(original) ?: return null
convertDeclaration(lightMethod, parent, requiredType)
convertDeclaration(lightMethod, parentCallback, requiredType)
}
is KtPropertyAccessor -> el<UMethod> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
javaPlugin.convertOpt<UMethod>(
LightClassUtil.getLightClassAccessorMethod(original), parent)
}
is KtProperty -> el<UField> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
javaPlugin.convertOpt<UField>(
LightClassUtil.getLightClassBackingField(original), parent)
?: convertDeclaration(element.parent, parent, requiredType)
?: convertDeclaration(element.parent, parentCallback, requiredType)
}
is KtFile -> el<UFile> { KotlinUFile(original, this@KotlinUastLanguagePlugin) }
@@ -166,14 +186,16 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
}
}
internal inline fun <reified T : UElement> Class<out UElement>?.el(f: () -> UElement?): UElement? {
return if (this == null || T::class.java == this) f() else null
internal inline fun <reified ActualT : UElement> Class<out UElement>?.el(f: () -> UElement?): UElement? {
return if (this == null || isAssignableFrom(ActualT::class.java)) f() else null
}
internal inline fun <reified T : UElement> Class<out UElement>?.expr(f: () -> UExpression): UExpression? {
return if (this == null || UExpression::class.java == this || T::class.java == this) f() else null
internal inline fun <reified ActualT : UElement> Class<out UElement>?.expr(f: () -> UExpression?): UExpression? {
return if (this == null || isAssignableFrom(ActualT::class.java)) f() else null
}
internal fun UElement?.toCallback() = if (this != null) fun(): UElement? { return this } else null
internal object KotlinConverter {
internal tailrec fun unwrapElements(element: PsiElement?): PsiElement? = when (element) {
is KtValueArgumentList -> unwrapElements(element.parent)
@@ -181,69 +203,77 @@ internal object KotlinConverter {
else -> element
}
internal fun convertPsiElement(element: PsiElement?, parent: UElement?, requiredType: Class<out UElement>?): UElement? {
internal fun convertPsiElement(element: PsiElement?,
parentCallback: (() -> UElement?)?,
requiredType: Class<out UElement>?): UElement? {
fun <P : PsiElement> build(ctor: (P, UElement?) -> UElement): () -> UElement? {
return fun(): UElement? {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
return ctor(element as P, parent)
}
}
return with (requiredType) { when (element) {
is KtParameterList -> el<UDeclarationsExpression> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
KotlinUDeclarationsExpression(parent).apply {
declarations = element.parameters.mapIndexed { i, p ->
KotlinUVariable.create(UastKotlinPsiParameter.create(p, element, parent!!, i), this)
}
}
}
is KtClassBody -> el<UExpressionList> {
KotlinUExpressionList(element, KotlinSpecialExpressionKinds.CLASS_BODY, parent).apply {
expressions = emptyList()
}
}
is KtCatchClause -> el<UCatchClause> { KotlinUCatchClause(element, parent) }
is KtExpression -> KotlinConverter.convertExpression(element, parent, requiredType)
is KtLambdaArgument -> KotlinConverter.convertExpression(element.getLambdaExpression(), parent, requiredType)
is KtClassBody -> el<UExpressionList>(build(KotlinUExpressionList.Companion::createClassBody))
is KtCatchClause -> el<UCatchClause>(build(::KotlinUCatchClause))
is KtExpression -> KotlinConverter.convertExpression(element, parentCallback, requiredType)
is KtLambdaArgument -> KotlinConverter.convertExpression(element.getLambdaExpression(), parentCallback, requiredType)
is KtContainerNode -> element.getExpression()?.let {
KotlinConverter.convertExpression(it, parent, requiredType)
KotlinConverter.convertExpression(it, parentCallback, requiredType)
} ?: el<UExpression> { UastEmptyExpression }
is KtLightAnnotation.LightExpressionValue<*> -> {
val expression = element.originalExpression
when (expression) {
is KtExpression -> KotlinConverter.convertExpression(expression, parent, requiredType)
is KtExpression -> KotlinConverter.convertExpression(expression, parentCallback, requiredType)
else -> el<UExpression> { UastEmptyExpression }
}
}
is KtLiteralStringTemplateEntry -> expr<ULiteralExpression> { KotlinStringULiteralExpression(element, parent, element.getText()) }
is KtEscapeStringTemplateEntry -> expr<ULiteralExpression> { KotlinStringULiteralExpression(element, parent, element.unescapedValue) }
is KtStringTemplateEntry -> element.expression?.let { convertExpression(it, parent, requiredType) } ?: expr<UExpression> { UastEmptyExpression }
is KtLiteralStringTemplateEntry, is KtEscapeStringTemplateEntry -> el<ULiteralExpression>(build(::KotlinStringULiteralExpression))
is KtStringTemplateEntry -> element.expression?.let { convertExpression(it, parentCallback, requiredType) } ?: expr<UExpression> { UastEmptyExpression }
else -> {
if (element is LeafPsiElement && element.elementType == KtTokens.IDENTIFIER) {
el<UIdentifier> { UIdentifier(element, parent) }
el<UIdentifier>(build(::UIdentifier))
} else {
null
}
}
}}
}
private fun convertVariablesDeclaration(
psi: KtVariableDeclaration,
parent: UElement?
): UDeclarationsExpression {
val parentPsiElement = parent?.psi
val variable = KotlinUVariable.create(UastKotlinPsiVariable.create(psi, parentPsiElement, parent!!), parent)
return KotlinUDeclarationsExpression(parent).apply { declarations = listOf(variable) }
}
internal fun convert(entry: KtStringTemplateEntry, parent: UElement?): UExpression = when (entry) {
is KtStringTemplateEntryWithExpression -> convertOrEmpty(entry.expression, parent)
is KtStringTemplateEntryWithExpression -> KotlinConverter.convertOrEmpty(entry.expression, parent)
is KtEscapeStringTemplateEntry -> KotlinStringULiteralExpression(entry, parent, entry.unescapedValue)
else -> {
KotlinStringULiteralExpression(entry, parent)
}
}
internal fun convertExpression(expression: KtExpression, parent: UElement?, requiredType: Class<out UElement>? = null): UExpression? {
internal fun convertExpression(expression: KtExpression,
parentCallback: (() -> UElement?)?,
requiredType: Class<out UElement>? = null): UExpression? {
fun <P : PsiElement> build(ctor: (P, UElement?) -> UExpression): () -> UExpression? {
return fun(): UExpression? {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
return ctor(expression as P, parent)
}
}
return with (requiredType) { when (expression) {
is KtVariableDeclaration -> expr<UDeclarationsExpression> { convertVariablesDeclaration(expression, parent) }
is KtVariableDeclaration -> expr<UDeclarationsExpression>(build(::convertVariablesDeclaration))
is KtStringTemplateExpression -> expr<ULiteralExpression> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
if (expression.entries.isEmpty())
KotlinStringULiteralExpression(expression, parent, "")
else if (expression.entries.size == 1)
@@ -252,6 +282,7 @@ internal object KotlinConverter {
KotlinStringTemplateUPolyadicExpression(expression, parent)
}
is KtDestructuringDeclaration -> expr<UDeclarationsExpression> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
KotlinUDeclarationsExpression(parent).apply {
val tempAssignment = KotlinUVariable.create(UastKotlinPsiVariable.create(expression, parent!!), parent)
val destructuringAssignments = expression.entries.mapIndexed { i, entry ->
@@ -264,68 +295,67 @@ internal object KotlinConverter {
declarations = listOf(tempAssignment) + destructuringAssignments
}
}
is KtLabeledExpression -> expr<ULabeledExpression> { KotlinULabeledExpression(expression, parent) }
is KtClassLiteralExpression -> expr<UClassLiteralExpression> { KotlinUClassLiteralExpression(expression, parent) }
is KtObjectLiteralExpression -> expr<UObjectLiteralExpression> { KotlinUObjectLiteralExpression(expression, parent) }
is KtDotQualifiedExpression -> expr<UQualifiedReferenceExpression> { KotlinUQualifiedReferenceExpression(expression, parent) }
is KtSafeQualifiedExpression -> expr<UQualifiedReferenceExpression> { KotlinUSafeQualifiedExpression(expression, parent) }
is KtSimpleNameExpression -> expr<USimpleNameReferenceExpression> {
KotlinUSimpleReferenceExpression(expression, expression.getReferencedName(), parent)
}
is KtCallExpression -> expr<UCallExpression> { KotlinUFunctionCallExpression(expression, parent) }
is KtLabeledExpression -> expr<ULabeledExpression>(build(::KotlinULabeledExpression))
is KtClassLiteralExpression -> expr<UClassLiteralExpression>(build(::KotlinUClassLiteralExpression))
is KtObjectLiteralExpression -> expr<UObjectLiteralExpression>(build(::KotlinUObjectLiteralExpression))
is KtDotQualifiedExpression -> expr<UQualifiedReferenceExpression>(build(::KotlinUQualifiedReferenceExpression))
is KtSafeQualifiedExpression -> expr<UQualifiedReferenceExpression>(build(::KotlinUSafeQualifiedExpression))
is KtSimpleNameExpression -> expr<USimpleNameReferenceExpression>(build(::KotlinUSimpleReferenceExpression))
is KtCallExpression -> expr<UCallExpression>(build(::KotlinUFunctionCallExpression))
is KtBinaryExpression -> {
if (expression.operationToken == KtTokens.ELVIS) {
expr<UExpressionList> { createElvisExpression(expression, parent) ?: UastEmptyExpression }
expr<UExpressionList>(build(::createElvisExpression))
}
else expr<UBinaryExpression> { KotlinUBinaryExpression(expression, parent) }
else expr<UBinaryExpression>(build(::KotlinUBinaryExpression))
}
is KtParenthesizedExpression -> expr<UParenthesizedExpression> { KotlinUParenthesizedExpression(expression, parent) }
is KtPrefixExpression -> expr<UPrefixExpression> { KotlinUPrefixExpression(expression, parent) }
is KtPostfixExpression -> expr<UPostfixExpression> { KotlinUPostfixExpression(expression, parent) }
is KtThisExpression -> expr<UThisExpression> { KotlinUThisExpression(expression, parent) }
is KtSuperExpression -> expr<USuperExpression> { KotlinUSuperExpression(expression, parent) }
is KtCallableReferenceExpression -> expr<UCallableReferenceExpression> { KotlinUCallableReferenceExpression(expression, parent) }
is KtIsExpression -> expr<UBinaryExpressionWithType> { KotlinUTypeCheckExpression(expression, parent) }
is KtIfExpression -> expr<UIfExpression> { KotlinUIfExpression(expression, parent) }
is KtWhileExpression -> expr<UWhileExpression> { KotlinUWhileExpression(expression, parent) }
is KtDoWhileExpression -> expr<UDoWhileExpression> { KotlinUDoWhileExpression(expression, parent) }
is KtForExpression -> expr<UForEachExpression> { KotlinUForEachExpression(expression, parent) }
is KtWhenExpression -> expr<USwitchExpression> { KotlinUSwitchExpression(expression, parent) }
is KtBreakExpression -> expr<UBreakExpression> { KotlinUBreakExpression(expression, parent) }
is KtContinueExpression -> expr<UContinueExpression> { KotlinUContinueExpression(expression, parent) }
is KtReturnExpression -> expr<UReturnExpression> { KotlinUReturnExpression(expression, parent) }
is KtThrowExpression -> expr<UThrowExpression> { KotlinUThrowExpression(expression, parent) }
is KtBlockExpression -> expr<UBlockExpression> { KotlinUBlockExpression(expression, parent) }
is KtConstantExpression -> expr<ULiteralExpression> { KotlinULiteralExpression(expression, parent) }
is KtTryExpression -> expr<UTryExpression> { KotlinUTryExpression(expression, parent) }
is KtArrayAccessExpression -> expr<UArrayAccessExpression> { KotlinUArrayAccessExpression(expression, parent) }
is KtLambdaExpression -> expr<ULambdaExpression> { KotlinULambdaExpression(expression, parent) }
is KtBinaryExpressionWithTypeRHS -> expr<UBinaryExpressionWithType> { KotlinUBinaryExpressionWithType(expression, parent) }
is KtParenthesizedExpression -> expr<UParenthesizedExpression>(build(::KotlinUParenthesizedExpression))
is KtPrefixExpression -> expr<UPrefixExpression>(build(::KotlinUPrefixExpression))
is KtPostfixExpression -> expr<UPostfixExpression>(build(::KotlinUPostfixExpression))
is KtThisExpression -> expr<UThisExpression>(build(::KotlinUThisExpression))
is KtSuperExpression -> expr<USuperExpression>(build(::KotlinUSuperExpression))
is KtCallableReferenceExpression -> expr<UCallableReferenceExpression>(build(::KotlinUCallableReferenceExpression))
is KtIsExpression -> expr<UBinaryExpressionWithType>(build(::KotlinUTypeCheckExpression))
is KtIfExpression -> expr<UIfExpression>(build(::KotlinUIfExpression))
is KtWhileExpression -> expr<UWhileExpression>(build(::KotlinUWhileExpression))
is KtDoWhileExpression -> expr<UDoWhileExpression>(build(::KotlinUDoWhileExpression))
is KtForExpression -> expr<UForEachExpression>(build(::KotlinUForEachExpression))
is KtWhenExpression -> expr<USwitchExpression>(build(::KotlinUSwitchExpression))
is KtBreakExpression -> expr<UBreakExpression>(build(::KotlinUBreakExpression))
is KtContinueExpression -> expr<UContinueExpression>(build(::KotlinUContinueExpression))
is KtReturnExpression -> expr<UReturnExpression>(build(::KotlinUReturnExpression))
is KtThrowExpression -> expr<UThrowExpression>(build(::KotlinUThrowExpression))
is KtBlockExpression -> expr<UBlockExpression>(build(::KotlinUBlockExpression))
is KtConstantExpression -> expr<ULiteralExpression>(build(::KotlinULiteralExpression))
is KtTryExpression -> expr<UTryExpression>(build(::KotlinUTryExpression))
is KtArrayAccessExpression -> expr<UArrayAccessExpression>(build(::KotlinUArrayAccessExpression))
is KtLambdaExpression -> expr<ULambdaExpression>(build(::KotlinULambdaExpression))
is KtBinaryExpressionWithTypeRHS -> expr<UBinaryExpressionWithType>(build(::KotlinUBinaryExpressionWithType))
is KtClassOrObject -> expr<UDeclarationsExpression> {
expression.toLightClass()?.let { lightClass ->
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
KotlinUDeclarationsExpression(parent).apply {
declarations = listOf(KotlinUClass.create(lightClass, this))
}
} ?: UastEmptyExpression
}
is KtFunction -> if (expression.name.isNullOrEmpty()) {
expr<ULambdaExpression> { createLocalFunctionLambdaExpression(expression, parent) }
expr<ULambdaExpression>(build(::createLocalFunctionLambdaExpression))
}
else {
expr<UDeclarationsExpression> { createLocalFunctionDeclaration(expression, parent) }
expr<UDeclarationsExpression>(build(::createLocalFunctionDeclaration))
}
else -> UnknownKotlinExpression(expression, parent)
else -> expr<UExpression>(build(::UnknownKotlinExpression))
}}
}
internal fun convertOrEmpty(expression: KtExpression?, parent: UElement?): UExpression {
return expression?.let { convertExpression(it, parent, null) } ?: UastEmptyExpression
return expression?.let { convertExpression(it, parent.toCallback(), null) } ?: UastEmptyExpression
}
internal fun convertOrNull(expression: KtExpression?, parent: UElement?): UExpression? {
return if (expression != null) convertExpression(expression, parent, null) else null
return if (expression != null) convertExpression(expression, parent.toCallback(), null) else null
}
internal fun KtPsiFactory.createAnalyzableExpression(text: String, context: PsiElement): KtExpression =
@@ -345,4 +375,13 @@ internal object KotlinConverter {
internal fun KtContainerNode.getExpression(): KtExpression? =
PsiTreeUtil.getChildOfType(this, KtExpression::class.java)
}
}
private fun convertVariablesDeclaration(
psi: KtVariableDeclaration,
parent: UElement?
): UDeclarationsExpression {
val parentPsiElement = parent?.psi
val variable = KotlinUVariable.create(UastKotlinPsiVariable.create(psi, parentPsiElement, parent!!), parent)
return KotlinUDeclarationsExpression(parent).apply { declarations = listOf(variable) }
}
@@ -56,7 +56,7 @@ private fun createElvisExpressions(
override val uastParent: UElement? = containingElement
override val condition: UExpression by lz { createNotEqWithNullExpression(tempVariable, this) }
override val thenExpression: UExpression? by lz { createVariableReferenceExpression(tempVariable, this) }
override val elseExpression: UExpression? by lz { KotlinConverter.convertExpression(right, this) }
override val elseExpression: UExpression? by lz { KotlinConverter.convertExpression(right, this.toCallback() ) }
override val isTernary: Boolean = false
override val annotations: List<UAnnotation> = emptyList()
override val ifIdentifier: UIdentifier = UIdentifier(null, this)
@@ -66,9 +66,9 @@ private fun createElvisExpressions(
return listOf(declaration, ifExpression)
}
fun createElvisExpression(elvisExpression: KtBinaryExpression, containingElement: UElement?): UExpressionList? {
val left = elvisExpression.left ?: return null
val right = elvisExpression.right ?: return null
fun createElvisExpression(elvisExpression: KtBinaryExpression, containingElement: UElement?): UExpression {
val left = elvisExpression.left ?: return UastEmptyExpression
val right = elvisExpression.right ?: return UastEmptyExpression
return object : UExpressionList, KotlinEvaluatableUElement, KotlinUElementWithType {
override val psi: PsiElement? = elvisExpression
@@ -31,7 +31,7 @@ class KotlinUCallableReferenceExpression(
get() {
if (qualifierType != null) return null
val receiverExpression = psi.receiverExpression ?: return null
return KotlinConverter.convertExpression(receiverExpression, this)
return KotlinConverter.convertExpression(receiverExpression, { this })
}
override val qualifierType by lz {
@@ -35,6 +35,6 @@ class KotlinUClassLiteralExpression(
get() {
if (type != null) return null
val receiverExpression = psi.receiverExpression ?: return null
return KotlinConverter.convertExpression(receiverExpression, this)
return KotlinConverter.convertExpression(receiverExpression, { this })
}
}
@@ -19,10 +19,11 @@ import com.intellij.psi.PsiElement
import org.jetbrains.uast.kotlin.KotlinAbstractUExpression
class KotlinUDeclarationsExpression(
override val psi: PsiElement?,
override val uastParent: UElement?
) : KotlinAbstractUExpression(), UDeclarationsExpression {
override val psi: PsiElement?
get() = null
constructor(uastParent: UElement?) : this(null, uastParent)
override lateinit var declarations: List<UDeclaration>
internal set
@@ -24,6 +24,7 @@ import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.UExpressionList
import org.jetbrains.uast.UastSpecialExpressionKind
import org.jetbrains.uast.kotlin.kinds.KotlinSpecialExpressionKinds
open class KotlinUExpressionList(
override val psi: PsiElement?,
@@ -38,4 +39,11 @@ open class KotlinUExpressionList(
val compileTimeConst = ktElement.analyze()[BindingContext.COMPILE_TIME_VALUE, ktElement]
return compileTimeConst?.getValue(TypeUtils.NO_EXPECTED_TYPE)
}
}
companion object {
fun createClassBody(psi: PsiElement?, uastParent: UElement?): KotlinUExpressionList =
KotlinUExpressionList(psi, KotlinSpecialExpressionKinds.CLASS_BODY, uastParent).apply {
expressions = emptyList()
}
}
}
@@ -35,7 +35,7 @@ import org.jetbrains.uast.visitor.UastVisitor
class KotlinUFunctionCallExpression(
override val psi: KtCallExpression,
override val uastParent: UElement?,
private val _resolvedCall: ResolvedCall<*>? = null
private val _resolvedCall: ResolvedCall<*>?
) : KotlinAbstractUExpression(), UCallExpression, KotlinUElementWithType {
companion object {
fun resolveSource(descriptor: DeclarationDescriptor, source: PsiElement?): PsiMethod? {
@@ -53,6 +53,8 @@ class KotlinUFunctionCallExpression(
}
}
constructor(psi: KtCallExpression, uastParent: UElement?): this(psi, uastParent, null)
private val resolvedCall by lz {
_resolvedCall ?: psi.getResolvedCall(psi.analyze())
}
@@ -16,10 +16,10 @@
package org.jetbrains.uast.kotlin
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.psi.KtConstantExpression
import org.jetbrains.kotlin.psi.KtEscapeStringTemplateEntry
import org.jetbrains.uast.UElement
import org.jetbrains.uast.ULiteralExpression
@@ -36,10 +36,13 @@ class KotlinULiteralExpression(
class KotlinStringULiteralExpression(
override val psi: PsiElement,
override val uastParent: UElement?,
val text: String? = null
val text: String
) : KotlinAbstractUExpression(), ULiteralExpression, KotlinUElementWithType{
constructor(psi: PsiElement, uastParent: UElement?)
: this(psi, uastParent, if (psi is KtEscapeStringTemplateEntry) psi.unescapedValue else psi.text)
override val value: String
get() = text ?: StringUtil.unescapeStringCharacters(psi.text)
get() = text
override fun evaluate() = value
}
@@ -35,11 +35,12 @@ import org.jetbrains.uast.visitor.UastVisitor
open class KotlinUSimpleReferenceExpression(
override val psi: KtSimpleNameExpression,
override val identifier: String,
override val uastParent: UElement?
) : KotlinAbstractUExpression(), USimpleNameReferenceExpression, KotlinUElementWithType, KotlinEvaluatableUElement {
private val resolvedDeclaration by lz { psi.resolveCallToDeclaration(this) }
override val identifier get() = psi.getReferencedName()
override fun resolve() = resolvedDeclaration
override val resolvedName: String?
@@ -28,7 +28,7 @@ class KotlinUSwitchExpression(
override val expression by lz { KotlinConverter.convertOrNull(psi.subjectExpression, this) }
override val body: UExpressionList by lz {
object : KotlinUExpressionList(psi, KotlinSpecialExpressionKinds.WHEN, this) {
object : KotlinUExpressionList(psi, KotlinSpecialExpressionKinds.WHEN, this@KotlinUSwitchExpression) {
override fun asRenderString() = expressions.joinToString("\n") { it.asRenderString().withMargin }
}.apply {
expressions = this@KotlinUSwitchExpression.psi.entries.map { KotlinUSwitchEntry(it, this) }
@@ -77,7 +77,7 @@ class KotlinUSwitchEntry(
}
override val body: UExpressionList by lz {
object : KotlinUExpressionList(psi, KotlinSpecialExpressionKinds.WHEN_ENTRY, this) {
object : KotlinUExpressionList(psi, KotlinSpecialExpressionKinds.WHEN_ENTRY, this@KotlinUSwitchEntry) {
override fun asRenderString() = buildString {
appendln("{")
expressions.forEach { appendln(it.asRenderString().withMargin) }
@@ -28,7 +28,7 @@ class KotlinUTryExpression(
) : KotlinAbstractUExpression(), UTryExpression, KotlinUElementWithType {
override val tryClause by lz { KotlinConverter.convertOrEmpty(psi.tryBlock, this) }
override val catchClauses by lz { psi.catchClauses.map { KotlinUCatchClause(it, this) } }
override val finallyClause by lz { psi.finallyBlock?.finalExpression?.let { KotlinConverter.convertExpression(it, this) } }
override val finallyClause by lz { psi.finallyBlock?.finalExpression?.let { KotlinConverter.convertExpression(it, { this }) } }
override val resourceVariables: List<UVariable>
get() = emptyList()