diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt index 3912b9ec744..d97ea53a6ef 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt @@ -70,7 +70,7 @@ class KotlinUastLanguagePlugin(override val project: Project) : UastLanguagePlug if (element is PsiFile) return convertDeclaration(element, null, requiredType) if (element is KtLightClassForFacade) return convertDeclaration(element, null, requiredType) - val parent = element.parent ?: return null + val parent = KotlinConverter.unwrapElements(element.parent) ?: return null val parentUElement = convertElementWithParent(parent, null) ?: return null return convertElement(element, parentUElement, requiredType) } @@ -106,7 +106,7 @@ class KotlinUastLanguagePlugin(override val project: Project) : UastLanguagePlug return null } - val parent = element.parent ?: return null + val parent = KotlinConverter.unwrapElements(element.parent) ?: return null val parentUElement = convertElementWithParent(parent, null) ?: return null val uExpression = KotlinUFunctionCallExpression(element, parentUElement, resolvedCall) @@ -123,28 +123,34 @@ class KotlinUastLanguagePlugin(override val project: Project) : UastLanguagePlug } val original = element.originalElement - return when (original) { - is KtLightMethod -> KotlinUMethod.create(original, parent) - is KtLightClass -> KotlinUClass.create(original, parent) - is KtLightField, is KtLightParameter, is UastKotlinPsiParameter, is UastKotlinPsiVariable -> { - KotlinUVariable.create(original as PsiVariable, parent) - } + return with(requiredType) { + when (original) { + is KtLightMethod -> el { KotlinUMethod.create(original, parent) } + is KtLightClass -> el { KotlinUClass.create(original, parent) } + is KtLightField, is KtLightParameter, is UastKotlinPsiParameter, is UastKotlinPsiVariable -> el { + KotlinUVariable.create(original as PsiVariable, parent) + } - is KtClassOrObject -> original.toLightClass()?.let { lightClass -> KotlinUClass.create(lightClass, parent) } - is KtFunction -> { - val lightMethod = LightClassUtil.getLightClassMethod(original) ?: return null - convertDeclaration(lightMethod, parent, requiredType) + is KtClassOrObject -> el { original.toLightClass()?.let { lightClass -> KotlinUClass.create(lightClass, parent) } } + is KtFunction -> el { + val lightMethod = LightClassUtil.getLightClassMethod(original) ?: return null + convertDeclaration(lightMethod, parent, requiredType) + } + is KtPropertyAccessor -> el { + javaPlugin.convertOpt( + LightClassUtil.getLightClassAccessorMethod(original), parent) + } + is KtProperty -> el { + javaPlugin.convertOpt( + LightClassUtil.getLightClassBackingField(original), parent) + ?: convertDeclaration(element.parent, parent, requiredType) + } + + is KtFile -> el { KotlinUFile(original, this@KotlinUastLanguagePlugin) } + is FakeFileForLightClass -> el { KotlinUFile(original.navigationElement, this@KotlinUastLanguagePlugin) } + + else -> null } - is KtPropertyAccessor -> javaPlugin.convertOpt( - LightClassUtil.getLightClassAccessorMethod(original), parent) - is KtProperty -> javaPlugin.convertOpt( - LightClassUtil.getLightClassBackingField(original), parent) - ?: convertDeclaration(element.parent, parent, requiredType) - - is KtFile -> KotlinUFile(original, this) - is FakeFileForLightClass -> KotlinUFile(original.navigationElement, this) - - else -> null } } @@ -164,11 +170,17 @@ internal inline fun Class?.el(f: () -> UEle return if (this == null || T::class.java == this) f() else null } -internal inline fun Class?.expr(f: () -> UExpression): UExpression { - return if (this == null || T::class.java == this) f() else UastEmptyExpression +internal inline fun Class?.expr(f: () -> UExpression): UExpression? { + return if (this == null || UExpression::class.java == this || T::class.java == this) f() else null } internal object KotlinConverter { + internal tailrec fun unwrapElements(element: PsiElement?): PsiElement? = when (element) { + is KtValueArgumentList -> unwrapElements(element.parent) + is KtValueArgument -> unwrapElements(element.parent) + else -> element + } + internal fun convertPsiElement(element: PsiElement?, parent: UElement?, requiredType: Class?): UElement? { return with (requiredType) { when (element) { is KtParameterList -> el { @@ -178,22 +190,28 @@ internal object KotlinConverter { } } } - is KtClassBody -> KotlinUExpressionList(element, KotlinSpecialExpressionKinds.CLASS_BODY, parent).apply { - expressions = emptyList() + is KtClassBody -> el { + KotlinUExpressionList(element, KotlinSpecialExpressionKinds.CLASS_BODY, parent).apply { + expressions = emptyList() + } } is KtCatchClause -> el { KotlinUCatchClause(element, parent) } is KtExpression -> KotlinConverter.convertExpression(element, parent, requiredType) is KtLambdaArgument -> KotlinConverter.convertExpression(element.getLambdaExpression(), parent, requiredType) is KtContainerNode -> element.getExpression()?.let { KotlinConverter.convertExpression(it, parent, requiredType) - } ?: UastEmptyExpression + } ?: el { UastEmptyExpression } is KtLightAnnotation.LightExpressionValue<*> -> { val expression = element.originalExpression when (expression) { is KtExpression -> KotlinConverter.convertExpression(expression, parent, requiredType) - else -> UastEmptyExpression + else -> el { UastEmptyExpression } } } + is KtLiteralStringTemplateEntry -> expr { KotlinStringULiteralExpression(element, parent, element.getText()) } + is KtEscapeStringTemplateEntry -> expr { KotlinStringULiteralExpression(element, parent, element.unescapedValue) } + is KtStringTemplateEntry -> element.expression?.let { convertExpression(it, parent, requiredType) } ?: expr { UastEmptyExpression } + else -> { if (element is LeafPsiElement && element.elementType == KtTokens.IDENTIFIER) { el { UIdentifier(element, parent) } @@ -221,7 +239,7 @@ internal object KotlinConverter { } } - internal fun convertExpression(expression: KtExpression, parent: UElement?, requiredType: Class? = null): UExpression { + internal fun convertExpression(expression: KtExpression, parent: UElement?, requiredType: Class? = null): UExpression? { return with (requiredType) { when (expression) { is KtVariableDeclaration -> expr { convertVariablesDeclaration(expression, parent) } @@ -249,7 +267,6 @@ internal object KotlinConverter { is KtLabeledExpression -> expr { KotlinULabeledExpression(expression, parent) } is KtClassLiteralExpression -> expr { KotlinUClassLiteralExpression(expression, parent) } is KtObjectLiteralExpression -> expr { KotlinUObjectLiteralExpression(expression, parent) } - is KtStringTemplateEntry -> expression.expression?.let { convertExpression(it, parent, requiredType) } ?: UastEmptyExpression is KtDotQualifiedExpression -> expr { KotlinUQualifiedReferenceExpression(expression, parent) } is KtSafeQualifiedExpression -> expr { KotlinUSafeQualifiedExpression(expression, parent) } is KtSimpleNameExpression -> expr { @@ -304,7 +321,7 @@ internal object KotlinConverter { } internal fun convertOrEmpty(expression: KtExpression?, parent: UElement?): UExpression { - return if (expression != null) convertExpression(expression, parent, null) else UastEmptyExpression + return expression?.let { convertExpression(it, parent, null) } ?: UastEmptyExpression } internal fun convertOrNull(expression: KtExpression?, parent: UElement?): UExpression? { diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUArrayAccessExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUArrayAccessExpression.kt index ec7e34785b9..d6ee9d0213e 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUArrayAccessExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUArrayAccessExpression.kt @@ -26,5 +26,5 @@ class KotlinUArrayAccessExpression( override val containingElement: UElement? ) : KotlinAbstractUExpression(), UArrayAccessExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement { override val receiver by lz { KotlinConverter.convertOrEmpty(psi.arrayExpression, this) } - override val indices by lz { psi.indexExpressions.map { KotlinConverter.convertExpression(it, this) } } + override val indices by lz { psi.indexExpressions.map { KotlinConverter.convertOrEmpty(it, this) } } } \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBinaryExpressionWithType.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBinaryExpressionWithType.kt index 71ad801cf41..8a094205bb5 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBinaryExpressionWithType.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBinaryExpressionWithType.kt @@ -29,7 +29,7 @@ class KotlinUBinaryExpressionWithType( ) : KotlinAbstractUExpression(), UBinaryExpressionWithType, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement { - override val operand by lz { KotlinConverter.convertExpression(psi.left, this) } + override val operand by lz { KotlinConverter.convertOrEmpty(psi.left, this) } override val type by lz { psi.right.toPsiType(this) } override val typeReference by lz { diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSwitchExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSwitchExpression.kt index 9a4a5f08a89..e1f0ce0fa56 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSwitchExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSwitchExpression.kt @@ -86,7 +86,7 @@ class KotlinUSwitchEntry( }.apply { val exprPsi = this@KotlinUSwitchEntry.psi.expression val userExpressions = when (exprPsi) { - is KtBlockExpression -> exprPsi.statements.map { KotlinConverter.convertExpression(it, this) } + is KtBlockExpression -> exprPsi.statements.map { KotlinConverter.convertOrEmpty(it, this) } else -> listOf(KotlinConverter.convertOrEmpty(exprPsi, this)) } containingElement diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTryExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTryExpression.kt index e03f2686975..ebda2ca7639 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTryExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTryExpression.kt @@ -16,7 +16,6 @@ package org.jetbrains.uast.kotlin -import com.intellij.psi.PsiResourceListElement import org.jetbrains.kotlin.psi.KtTryExpression import org.jetbrains.uast.UElement import org.jetbrains.uast.UIdentifier @@ -28,7 +27,7 @@ class KotlinUTryExpression( override val psi: KtTryExpression, override val containingElement: UElement? ) : KotlinAbstractUExpression(), UTryExpression, PsiElementBacked, KotlinUElementWithType { - override val tryClause by lz { KotlinConverter.convertExpression(psi.tryBlock, this) } + 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) } } diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeCheckExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeCheckExpression.kt index b6d7394b9cd..db550c74c79 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeCheckExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeCheckExpression.kt @@ -26,7 +26,7 @@ class KotlinUTypeCheckExpression( override val psi: KtIsExpression, override val containingElement: UElement? ) : KotlinAbstractUExpression(), UBinaryExpressionWithType, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement { - override val operand by lz { KotlinConverter.convertExpression(psi.leftHandSide, this) } + override val operand by lz { KotlinConverter.convertOrEmpty(psi.leftHandSide, this) } override val type by lz { psi.typeReference.toPsiType(this) }