Add missing required type checks; correctly skip elements which have no UAST equivalents when converting an element together with parent; correctly convert string template entries (they aren't expressions)
This commit is contained in:
@@ -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<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 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<UClass> { original.toLightClass()?.let { lightClass -> KotlinUClass.create(lightClass, parent) } }
|
||||
is KtFunction -> el<UMethod> {
|
||||
val lightMethod = LightClassUtil.getLightClassMethod(original) ?: return null
|
||||
convertDeclaration(lightMethod, parent, requiredType)
|
||||
}
|
||||
is KtPropertyAccessor -> el<UMethod> {
|
||||
javaPlugin.convertOpt<UMethod>(
|
||||
LightClassUtil.getLightClassAccessorMethod(original), parent)
|
||||
}
|
||||
is KtProperty -> el<UField> {
|
||||
javaPlugin.convertOpt<UField>(
|
||||
LightClassUtil.getLightClassBackingField(original), parent)
|
||||
?: convertDeclaration(element.parent, parent, requiredType)
|
||||
}
|
||||
|
||||
is KtFile -> el<UFile> { KotlinUFile(original, this@KotlinUastLanguagePlugin) }
|
||||
is FakeFileForLightClass -> el<UFile> { KotlinUFile(original.navigationElement, this@KotlinUastLanguagePlugin) }
|
||||
|
||||
else -> null
|
||||
}
|
||||
is KtPropertyAccessor -> javaPlugin.convertOpt<UMethod>(
|
||||
LightClassUtil.getLightClassAccessorMethod(original), parent)
|
||||
is KtProperty -> javaPlugin.convertOpt<UField>(
|
||||
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 <reified T : UElement> Class<out UElement>?.el(f: () -> UEle
|
||||
return if (this == null || T::class.java == this) f() else null
|
||||
}
|
||||
|
||||
internal inline fun <reified T : UElement> Class<out UElement>?.expr(f: () -> UExpression): UExpression {
|
||||
return if (this == null || T::class.java == this) f() else UastEmptyExpression
|
||||
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 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<out UElement>?): UElement? {
|
||||
return with (requiredType) { when (element) {
|
||||
is KtParameterList -> el<UDeclarationsExpression> {
|
||||
@@ -178,22 +190,28 @@ internal object KotlinConverter {
|
||||
}
|
||||
}
|
||||
}
|
||||
is KtClassBody -> KotlinUExpressionList(element, KotlinSpecialExpressionKinds.CLASS_BODY, parent).apply {
|
||||
expressions = emptyList()
|
||||
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 KtContainerNode -> element.getExpression()?.let {
|
||||
KotlinConverter.convertExpression(it, parent, requiredType)
|
||||
} ?: UastEmptyExpression
|
||||
} ?: el<UExpression> { UastEmptyExpression }
|
||||
is KtLightAnnotation.LightExpressionValue<*> -> {
|
||||
val expression = element.originalExpression
|
||||
when (expression) {
|
||||
is KtExpression -> KotlinConverter.convertExpression(expression, parent, requiredType)
|
||||
else -> UastEmptyExpression
|
||||
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 }
|
||||
|
||||
else -> {
|
||||
if (element is LeafPsiElement && element.elementType == KtTokens.IDENTIFIER) {
|
||||
el<UIdentifier> { UIdentifier(element, parent) }
|
||||
@@ -221,7 +239,7 @@ internal object KotlinConverter {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun convertExpression(expression: KtExpression, parent: UElement?, requiredType: Class<out UElement>? = null): UExpression {
|
||||
internal fun convertExpression(expression: KtExpression, parent: UElement?, requiredType: Class<out UElement>? = null): UExpression? {
|
||||
return with (requiredType) { when (expression) {
|
||||
is KtVariableDeclaration -> expr<UDeclarationsExpression> { convertVariablesDeclaration(expression, parent) }
|
||||
|
||||
@@ -249,7 +267,6 @@ internal object KotlinConverter {
|
||||
is KtLabeledExpression -> expr<ULabeledExpression> { KotlinULabeledExpression(expression, parent) }
|
||||
is KtClassLiteralExpression -> expr<UClassLiteralExpression> { KotlinUClassLiteralExpression(expression, parent) }
|
||||
is KtObjectLiteralExpression -> expr<UObjectLiteralExpression> { KotlinUObjectLiteralExpression(expression, parent) }
|
||||
is KtStringTemplateEntry -> expression.expression?.let { convertExpression(it, parent, requiredType) } ?: UastEmptyExpression
|
||||
is KtDotQualifiedExpression -> expr<UQualifiedReferenceExpression> { KotlinUQualifiedReferenceExpression(expression, parent) }
|
||||
is KtSafeQualifiedExpression -> expr<UQualifiedReferenceExpression> { KotlinUSafeQualifiedExpression(expression, parent) }
|
||||
is KtSimpleNameExpression -> expr<USimpleNameReferenceExpression> {
|
||||
@@ -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? {
|
||||
|
||||
+1
-1
@@ -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) } }
|
||||
}
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-2
@@ -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) } }
|
||||
|
||||
|
||||
+1
-1
@@ -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) }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user