Support lazy conversion of parent chain; correctly check expected class
This commit is contained in:
@@ -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
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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 })
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -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
|
||||
|
||||
+9
-1
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -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())
|
||||
}
|
||||
|
||||
+6
-3
@@ -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
|
||||
}
|
||||
+2
-1
@@ -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?
|
||||
|
||||
+2
-2
@@ -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) }
|
||||
|
||||
+1
-1
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user