Evaluate parents of UAST elements lazily

Also add tests for UAST consistency in various cases
This commit is contained in:
Dmitry Jemerov
2017-09-12 17:58:27 +02:00
parent 91459bbd6a
commit 40daeb13d1
52 changed files with 281 additions and 205 deletions
@@ -17,11 +17,16 @@
package org.jetbrains.uast.kotlin package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtAnnotatedExpression import org.jetbrains.kotlin.psi.KtAnnotatedExpression
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtValueArgument
import org.jetbrains.uast.UAnnotation import org.jetbrains.uast.UAnnotation
import org.jetbrains.uast.UElement import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression import org.jetbrains.uast.UExpression
abstract class KotlinAbstractUElement : UElement { abstract class KotlinAbstractUElement(private val givenParent: UElement?) : UElement {
override val uastParent: UElement? by lz { convertParent(givenParent) }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (other !is UElement) { if (other !is UElement) {
return false return false
@@ -33,7 +38,30 @@ abstract class KotlinAbstractUElement : UElement {
override fun hashCode() = psi?.hashCode() ?: 0 override fun hashCode() = psi?.hashCode() ?: 0
} }
abstract class KotlinAbstractUExpression : KotlinAbstractUElement(), UExpression { internal fun UElement.convertParent(givenParent: UElement?): UElement? {
return if (givenParent != null)
givenParent
else {
val parent = psi?.parent
val result = KotlinConverter.unwrapElements(parent)?.let { parentUnwrapped ->
if (parent is KtValueArgument && parentUnwrapped is KtAnnotationEntry) {
val argumentName = parent.getArgumentName()?.asName?.asString() ?: ""
(KotlinUastLanguagePlugin().convertElementWithParent(parentUnwrapped, null) as? UAnnotation)
?.attributeValues?.find { it.name == argumentName }
}
else
KotlinUastLanguagePlugin().convertElementWithParent(parentUnwrapped, null)
}
if (result == this) {
throw IllegalStateException("Loop in parent structure")
}
result
}
}
abstract class KotlinAbstractUExpression(givenParent: UElement?)
: KotlinAbstractUElement(givenParent), UExpression {
override val annotations: List<UAnnotation> override val annotations: List<UAnnotation>
get() { get() {
val annotatedExpression = psi?.parent as? KtAnnotatedExpression ?: return emptyList() val annotatedExpression = psi?.parent as? KtAnnotatedExpression ?: return emptyList()
@@ -20,7 +20,6 @@ import com.intellij.lang.Language
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import com.intellij.psi.impl.source.tree.LeafPsiElement import com.intellij.psi.impl.source.tree.LeafPsiElement
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.asJava.LightClassUtil import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
@@ -60,28 +59,17 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
} }
override fun convertElement(element: PsiElement, parent: UElement?, requiredType: Class<out UElement>?): UElement? { override fun convertElement(element: PsiElement, parent: UElement?, requiredType: Class<out UElement>?): UElement? {
return convertDeclarationOrElement(element, parent.toCallback(), requiredType) return convertDeclarationOrElement(element, parent, requiredType)
} }
override fun convertElementWithParent(element: PsiElement, requiredType: Class<out UElement>?): UElement? { override fun convertElementWithParent(element: PsiElement, requiredType: Class<out UElement>?): UElement? {
if (element is PsiFile) return convertDeclaration(element, null, requiredType) if (element is PsiFile) return convertDeclaration(element, null, requiredType)
if (element is KtLightClassForFacade) return convertDeclaration(element, null, requiredType) if (element is KtLightClassForFacade) return convertDeclaration(element, null, requiredType)
val parentCallback = fun(): UElement? { return convertDeclarationOrElement(element, null, requiredType)
val parent = element.parent
val parentUnwrapped = KotlinConverter.unwrapElements(parent) ?: return null
if (parent is KtValueArgument && parentUnwrapped is KtAnnotationEntry) {
val argumentName = parent.getArgumentName()?.asName?.asString() ?: ""
return (convertElementWithParent(parentUnwrapped, null) as? UAnnotation)
?.attributeValues?.find { it.name == argumentName }
}
else
return convertElementWithParent(parentUnwrapped, null)
}
return convertDeclarationOrElement(element, parentCallback, requiredType)
} }
private fun convertDeclarationOrElement(element: PsiElement, parentCallback: (() -> UElement?)?, requiredType: Class<out UElement>?): UElement? { private fun convertDeclarationOrElement(element: PsiElement, givenParent: UElement?, requiredType: Class<out UElement>?): UElement? {
if (element is UElement) return element if (element is UElement) return element
if (element.isValid) { if (element.isValid) {
@@ -90,8 +78,8 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
} }
} }
val uElement = convertDeclaration(element, parentCallback, requiredType) val uElement = convertDeclaration(element, givenParent, requiredType)
?: KotlinConverter.convertPsiElement(element, parentCallback, requiredType) ?: KotlinConverter.convertPsiElement(element, givenParent, requiredType)
if (uElement != null) { if (uElement != null) {
element.putUserData(KOTLIN_CACHED_UELEMENT_KEY, WeakReference(uElement)) element.putUserData(KOTLIN_CACHED_UELEMENT_KEY, WeakReference(uElement))
} }
@@ -139,13 +127,10 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
} }
private fun convertDeclaration(element: PsiElement, private fun convertDeclaration(element: PsiElement,
parentCallback: (() -> UElement?)?, givenParent: UElement?,
requiredType: Class<out UElement>?): UElement? { requiredType: Class<out UElement>?): UElement? {
fun <P : PsiElement> build(ctor: (P, UElement?) -> UElement): () -> UElement? { fun <P : PsiElement> build(ctor: (P, UElement?) -> UElement): () -> UElement? {
return fun(): UElement? { return { ctor(element as P, givenParent) }
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
return ctor(element as P, parent)
}
} }
val original = element.originalElement val original = element.originalElement
@@ -161,24 +146,21 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
is KtClassOrObject -> el<UClass> { is KtClassOrObject -> el<UClass> {
original.toLightClass()?.let { lightClass -> original.toLightClass()?.let { lightClass ->
val parent = if (parentCallback == null) null else (parentCallback() ?: return null) KotlinUClass.create(lightClass, givenParent)
KotlinUClass.create(lightClass, parent)
} }
} }
is KtFunction -> el<UMethod> { is KtFunction -> el<UMethod> {
val lightMethod = LightClassUtil.getLightClassMethod(original) ?: return null val lightMethod = LightClassUtil.getLightClassMethod(original) ?: return null
convertDeclaration(lightMethod, parentCallback, requiredType) convertDeclaration(lightMethod, givenParent, requiredType)
} }
is KtPropertyAccessor -> el<UMethod> { is KtPropertyAccessor -> el<UMethod> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
javaPlugin.convertOpt<UMethod>( javaPlugin.convertOpt<UMethod>(
LightClassUtil.getLightClassAccessorMethod(original), parent) LightClassUtil.getLightClassAccessorMethod(original), givenParent)
} }
is KtProperty -> el<UField> { is KtProperty -> el<UField> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
javaPlugin.convertOpt<UField>( javaPlugin.convertOpt<UField>(
LightClassUtil.getLightClassBackingField(original), parent) LightClassUtil.getLightClassBackingField(original), givenParent)
?: convertDeclaration(element.parent, parentCallback, requiredType) ?: convertDeclaration(element.parent, givenParent, requiredType)
} }
is KtFile -> el<UFile> { KotlinUFile(original, this@KotlinUastLanguagePlugin) } is KtFile -> el<UFile> { KotlinUFile(original, this@KotlinUastLanguagePlugin) }
@@ -216,44 +198,39 @@ internal object KotlinConverter {
is KtValueArgumentList -> unwrapElements(element.parent) is KtValueArgumentList -> unwrapElements(element.parent)
is KtValueArgument -> unwrapElements(element.parent) is KtValueArgument -> unwrapElements(element.parent)
is KtDeclarationModifierList -> unwrapElements(element.parent) is KtDeclarationModifierList -> unwrapElements(element.parent)
is KtContainerNode -> unwrapElements(element.parent)
else -> element else -> element
} }
internal fun convertPsiElement(element: PsiElement?, internal fun convertPsiElement(element: PsiElement?,
parentCallback: (() -> UElement?)?, givenParent: UElement?,
requiredType: Class<out UElement>?): UElement? { requiredType: Class<out UElement>?): UElement? {
fun <P : PsiElement> build(ctor: (P, UElement?) -> UElement): () -> UElement? { fun <P : PsiElement> build(ctor: (P, UElement?) -> UElement): () -> UElement? {
return fun(): UElement? { return { ctor(element as P, givenParent) }
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
return ctor(element as P, parent)
}
} }
return with (requiredType) { when (element) { return with (requiredType) { when (element) {
is KtParameterList -> el<UDeclarationsExpression> { is KtParameterList -> el<UDeclarationsExpression> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null) val declarationsExpression = KotlinUDeclarationsExpression(givenParent)
KotlinUDeclarationsExpression(parent).apply { declarationsExpression.apply {
declarations = element.parameters.mapIndexed { i, p -> declarations = element.parameters.mapIndexed { i, p ->
KotlinUParameter(UastKotlinPsiParameter.create(p, element, parent!!, i), this) KotlinUParameter(UastKotlinPsiParameter.create(p, element, declarationsExpression, i), this)
} }
} }
} }
is KtClassBody -> el<UExpressionList>(build(KotlinUExpressionList.Companion::createClassBody)) is KtClassBody -> el<UExpressionList>(build(KotlinUExpressionList.Companion::createClassBody))
is KtCatchClause -> el<UCatchClause>(build(::KotlinUCatchClause)) is KtCatchClause -> el<UCatchClause>(build(::KotlinUCatchClause))
is KtExpression -> KotlinConverter.convertExpression(element, parentCallback, requiredType) is KtExpression -> KotlinConverter.convertExpression(element, givenParent, requiredType)
is KtLambdaArgument -> KotlinConverter.convertExpression(element.getLambdaExpression(), parentCallback, requiredType) is KtLambdaArgument -> KotlinConverter.convertExpression(element.getLambdaExpression(), givenParent, requiredType)
is KtContainerNode -> element.getExpression()?.let {
KotlinConverter.convertExpression(it, parentCallback, requiredType)
} ?: el<UExpression> { UastEmptyExpression }
is KtLightAnnotationForSourceEntry.LightExpressionValue<*> -> { is KtLightAnnotationForSourceEntry.LightExpressionValue<*> -> {
val expression = element.originalExpression val expression = element.originalExpression
when (expression) { when (expression) {
is KtExpression -> KotlinConverter.convertExpression(expression, parentCallback, requiredType) is KtExpression -> KotlinConverter.convertExpression(expression, givenParent, requiredType)
else -> el<UExpression> { UastEmptyExpression } else -> el<UExpression> { UastEmptyExpression }
} }
} }
is KtLiteralStringTemplateEntry, is KtEscapeStringTemplateEntry -> el<ULiteralExpression>(build(::KotlinStringULiteralExpression)) is KtLiteralStringTemplateEntry, is KtEscapeStringTemplateEntry -> el<ULiteralExpression>(build(::KotlinStringULiteralExpression))
is KtStringTemplateEntry -> element.expression?.let { convertExpression(it, parentCallback, requiredType) } ?: expr<UExpression> { UastEmptyExpression } is KtStringTemplateEntry -> element.expression?.let { convertExpression(it, givenParent, requiredType) } ?: expr<UExpression> { UastEmptyExpression }
else -> { else -> {
if (element is LeafPsiElement && element.elementType == KtTokens.IDENTIFIER) { if (element is LeafPsiElement && element.elementType == KtTokens.IDENTIFIER) {
@@ -267,35 +244,30 @@ internal object KotlinConverter {
internal fun convertEntry(entry: KtStringTemplateEntry, internal fun convertEntry(entry: KtStringTemplateEntry,
parentCallback: (() -> UElement?)?, givenParent: UElement?,
requiredType: Class<out UElement>? = null): UExpression? { requiredType: Class<out UElement>? = null): UExpression? {
return with(requiredType) { return with(requiredType) {
if (entry is KtStringTemplateEntryWithExpression) { if (entry is KtStringTemplateEntryWithExpression) {
expr<UExpression> { expr<UExpression> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null) KotlinConverter.convertOrEmpty(entry.expression, givenParent)
KotlinConverter.convertOrEmpty(entry.expression, parent)
} }
} }
else { else {
expr<ULiteralExpression> { expr<ULiteralExpression> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
if (entry is KtEscapeStringTemplateEntry) if (entry is KtEscapeStringTemplateEntry)
KotlinStringULiteralExpression(entry, parent, entry.unescapedValue) KotlinStringULiteralExpression(entry, givenParent, entry.unescapedValue)
else else
KotlinStringULiteralExpression(entry, parent) KotlinStringULiteralExpression(entry, givenParent)
} }
} }
} }
} }
internal fun convertExpression(expression: KtExpression, internal fun convertExpression(expression: KtExpression,
parentCallback: (() -> UElement?)?, givenParent: UElement?,
requiredType: Class<out UElement>? = null): UExpression? { requiredType: Class<out UElement>? = null): UExpression? {
fun <P : PsiElement> build(ctor: (P, UElement?) -> UExpression): () -> UExpression? { fun <P : PsiElement> build(ctor: (P, UElement?) -> UExpression): () -> UExpression? {
return fun(): UExpression? { return { ctor(expression as P, givenParent) }
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
return ctor(expression as P, parent)
}
} }
return with (requiredType) { when (expression) { return with (requiredType) { when (expression) {
@@ -304,25 +276,22 @@ internal object KotlinConverter {
is KtStringTemplateExpression -> { is KtStringTemplateExpression -> {
when { when {
expression.entries.isEmpty() -> { expression.entries.isEmpty() -> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null) expr<ULiteralExpression> { KotlinStringULiteralExpression(expression, givenParent, "") }
expr<ULiteralExpression> { KotlinStringULiteralExpression(expression, parent, "") }
} }
expression.entries.size == 1 -> convertEntry(expression.entries[0], parentCallback, requiredType) expression.entries.size == 1 -> convertEntry(expression.entries[0], givenParent, requiredType)
else -> { else -> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null) expr<UExpression> { KotlinStringTemplateUPolyadicExpression(expression, givenParent) }
expr<UExpression> { KotlinStringTemplateUPolyadicExpression(expression, parent) }
} }
} }
} }
is KtDestructuringDeclaration -> expr<UDeclarationsExpression> { is KtDestructuringDeclaration -> expr<UDeclarationsExpression> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null) KotlinUDeclarationsExpression(givenParent).apply {
KotlinUDeclarationsExpression(parent).apply { val tempAssignment = KotlinULocalVariable(UastKotlinPsiVariable.create(expression, uastParent!!), givenParent)
val tempAssignment = KotlinULocalVariable(UastKotlinPsiVariable.create(expression, parent!!), parent)
val destructuringAssignments = expression.entries.mapIndexed { i, entry -> val destructuringAssignments = expression.entries.mapIndexed { i, entry ->
val psiFactory = KtPsiFactory(expression.project) val psiFactory = KtPsiFactory(expression.project)
val initializer = psiFactory.createAnalyzableExpression("${tempAssignment.name}.component${i + 1}()", val initializer = psiFactory.createAnalyzableExpression("${tempAssignment.name}.component${i + 1}()",
expression.containingFile) expression.containingFile)
KotlinULocalVariable(UastKotlinPsiVariable.create(entry, tempAssignment.psi, parent, initializer), parent) KotlinULocalVariable(UastKotlinPsiVariable.create(entry, tempAssignment.psi, uastParent!!, initializer), givenParent)
} }
declarations = listOf(tempAssignment) + destructuringAssignments declarations = listOf(tempAssignment) + destructuringAssignments
} }
@@ -364,8 +333,7 @@ internal object KotlinConverter {
is KtBinaryExpressionWithTypeRHS -> expr<UBinaryExpressionWithType>(build(::KotlinUBinaryExpressionWithType)) is KtBinaryExpressionWithTypeRHS -> expr<UBinaryExpressionWithType>(build(::KotlinUBinaryExpressionWithType))
is KtClassOrObject -> expr<UDeclarationsExpression> { is KtClassOrObject -> expr<UDeclarationsExpression> {
expression.toLightClass()?.let { lightClass -> expression.toLightClass()?.let { lightClass ->
val parent = if (parentCallback == null) null else (parentCallback() ?: return null) KotlinUDeclarationsExpression(givenParent).apply {
KotlinUDeclarationsExpression(parent).apply {
declarations = listOf(KotlinUClass.create(lightClass, this)) declarations = listOf(KotlinUClass.create(lightClass, this))
} }
} ?: UastEmptyExpression } ?: UastEmptyExpression
@@ -382,11 +350,11 @@ internal object KotlinConverter {
} }
internal fun convertOrEmpty(expression: KtExpression?, parent: UElement?): UExpression { internal fun convertOrEmpty(expression: KtExpression?, parent: UElement?): UExpression {
return expression?.let { convertExpression(it, parent.toCallback(), null) } ?: UastEmptyExpression return expression?.let { convertExpression(it, parent, null) } ?: UastEmptyExpression
} }
internal fun convertOrNull(expression: KtExpression?, parent: UElement?): UExpression? { internal fun convertOrNull(expression: KtExpression?, parent: UElement?): UExpression? {
return if (expression != null) convertExpression(expression, parent.toCallback(), null) else null return if (expression != null) convertExpression(expression, parent, null) else null
} }
internal fun KtPsiFactory.createAnalyzableExpression(text: String, context: PsiElement): KtExpression = internal fun KtPsiFactory.createAnalyzableExpression(text: String, context: PsiElement): KtExpression =
@@ -401,19 +369,17 @@ internal object KotlinConverter {
assert(declarations.size == 1) { "${declarations.size} declarations in $text" } assert(declarations.size == 1) { "${declarations.size} declarations in $text" }
return declarations.first() as TDeclaration return declarations.first() as TDeclaration
} }
internal fun KtContainerNode.getExpression(): KtExpression? =
PsiTreeUtil.getChildOfType(this, KtExpression::class.java)
} }
private fun convertVariablesDeclaration( private fun convertVariablesDeclaration(
psi: KtVariableDeclaration, psi: KtVariableDeclaration,
parent: UElement? parent: UElement?
): UDeclarationsExpression { ): UDeclarationsExpression {
val declarationsExpression = KotlinUDeclarationsExpression(parent)
val parentPsiElement = parent?.psi val parentPsiElement = parent?.psi
val variable = KotlinUAnnotatedLocalVariable( val variable = KotlinUAnnotatedLocalVariable(
UastKotlinPsiVariable.create(psi, parentPsiElement, parent!!), parent) { annotationParent -> UastKotlinPsiVariable.create(psi, parentPsiElement, declarationsExpression), declarationsExpression) { annotationParent ->
psi.annotationEntries.map { KotlinUAnnotation(it, annotationParent) } psi.annotationEntries.map { KotlinUAnnotation(it, annotationParent) }
} }
return KotlinUDeclarationsExpression(parent).apply { declarations = listOf(variable) } return declarationsExpression.apply { declarations = listOf(variable) }
} }
@@ -13,8 +13,10 @@ import org.jetbrains.uast.*
class KotlinUAnnotation( class KotlinUAnnotation(
override val psi: KtAnnotationEntry, override val psi: KtAnnotationEntry,
override val uastParent: UElement? private val givenParent: UElement?
) : UAnnotation { ) : UAnnotation {
override val uastParent: UElement? by lz { convertParent(givenParent) }
private val resolvedAnnotation: AnnotationDescriptor? by lz { psi.analyze()[BindingContext.ANNOTATION, psi] } private val resolvedAnnotation: AnnotationDescriptor? by lz { psi.analyze()[BindingContext.ANNOTATION, psi] }
private val resolvedCall: ResolvedCall<*>? by lz { psi.getResolvedCall(psi.analyze()) } private val resolvedCall: ResolvedCall<*>? by lz { psi.getResolvedCall(psi.analyze()) }
@@ -30,11 +30,13 @@ import org.jetbrains.uast.kotlin.declarations.UastLightIdentifier
open class KotlinUClass private constructor( open class KotlinUClass private constructor(
psi: KtLightClass, psi: KtLightClass,
override val uastParent: UElement? private val givenParent: UElement?
) : AbstractJavaUClass(), PsiClass by psi { ) : AbstractJavaUClass(), PsiClass by psi {
val ktClass = psi.kotlinOrigin val ktClass = psi.kotlinOrigin
override val uastParent: UElement? by lz { convertParent(givenParent) }
override val psi = unwrap<UClass, PsiClass>(psi) override val psi = unwrap<UClass, PsiClass>(psi)
override fun getOriginalElement(): PsiElement? = super.getOriginalElement() override fun getOriginalElement(): PsiElement? = super.getOriginalElement()
@@ -110,9 +112,11 @@ open class KotlinUClass private constructor(
class KotlinUAnonymousClass( class KotlinUAnonymousClass(
psi: PsiAnonymousClass, psi: PsiAnonymousClass,
override val uastParent: UElement? private val givenParent: UElement?
) : AbstractJavaUClass(), UAnonymousClass, PsiAnonymousClass by psi { ) : AbstractJavaUClass(), UAnonymousClass, PsiAnonymousClass by psi {
override val uastParent: UElement? by lz { convertParent(givenParent) }
override val psi: PsiAnonymousClass = unwrap<UAnonymousClass, PsiAnonymousClass>(psi) override val psi: PsiAnonymousClass = unwrap<UAnonymousClass, PsiAnonymousClass>(psi)
override fun getOriginalElement(): PsiElement? = super<AbstractJavaUClass>.getOriginalElement() override fun getOriginalElement(): PsiElement? = super<AbstractJavaUClass>.getOriginalElement()
@@ -28,8 +28,10 @@ import org.jetbrains.uast.USimpleNameReferenceExpression
class KotlinUImportStatement( class KotlinUImportStatement(
override val psi: KtImportDirective, override val psi: KtImportDirective,
override val uastParent: UElement? private val givenParent: UElement?
) : UImportStatement { ) : UImportStatement {
override val uastParent: UElement? by lz { convertParent(givenParent) }
override val isOnDemand: Boolean override val isOnDemand: Boolean
get() = psi.isAllUnder get() = psi.isAllUnder
@@ -47,9 +49,9 @@ class KotlinUImportStatement(
private class ImportReference( private class ImportReference(
override val psi: KtExpression, override val psi: KtExpression,
override val identifier: String, override val identifier: String,
override val uastParent: UElement?, givenParent: UElement?,
private val importDirective: KtImportDirective private val importDirective: KtImportDirective
) : KotlinAbstractUExpression(), USimpleNameReferenceExpression { ) : KotlinAbstractUExpression(givenParent), USimpleNameReferenceExpression {
override val resolvedName: String? override val resolvedName: String?
get() = identifier get() = identifier
@@ -30,10 +30,12 @@ import org.jetbrains.uast.kotlin.*
open class KotlinUMethod( open class KotlinUMethod(
psi: KtLightMethod, psi: KtLightMethod,
override val uastParent: UElement? private val givenParent: UElement?
) : UAnnotationMethod, JavaUElementWithComments, PsiMethod by psi { ) : UAnnotationMethod, JavaUElementWithComments, PsiMethod by psi {
override val psi: KtLightMethod = unwrap<UMethod, KtLightMethod>(psi) override val psi: KtLightMethod = unwrap<UMethod, KtLightMethod>(psi)
override val uastParent: UElement? by lz { convertParent(givenParent) }
override val uastDefaultValue by lz { override val uastDefaultValue by lz {
val annotationParameter = psi.kotlinOrigin as? KtParameter ?: return@lz null val annotationParameter = psi.kotlinOrigin as? KtParameter ?: return@lz null
val defaultValue = annotationParameter.defaultValue ?: return@lz null val defaultValue = annotationParameter.defaultValue ?: return@lz null
@@ -33,7 +33,11 @@ import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable
import org.jetbrains.uast.visitor.UastVisitor import org.jetbrains.uast.visitor.UastVisitor
abstract class AbstractKotlinUVariable : PsiVariable, UVariable, KotlinUElementWithComments { abstract class AbstractKotlinUVariable(private val givenParent: UElement?)
: PsiVariable, UVariable, KotlinUElementWithComments {
override val uastParent: UElement? by lz { convertParent(givenParent) }
override val uastInitializer: UExpression? override val uastInitializer: UExpression?
get() { get() {
val psi = psi val psi = psi
@@ -85,8 +89,8 @@ abstract class AbstractKotlinUVariable : PsiVariable, UVariable, KotlinUElementW
class KotlinUVariable( class KotlinUVariable(
psi: PsiVariable, psi: PsiVariable,
override val uastParent: UElement? givenParent: UElement?
) : AbstractKotlinUVariable(), UVariable, PsiVariable by psi { ) : AbstractKotlinUVariable(givenParent), UVariable, PsiVariable by psi {
override val psi = unwrap<UVariable, PsiVariable>(psi) override val psi = unwrap<UVariable, PsiVariable>(psi)
override val annotations by lz { psi.annotations.map { JavaUAnnotation(it, this) } } override val annotations by lz { psi.annotations.map { JavaUAnnotation(it, this) } }
@@ -112,8 +116,8 @@ class KotlinUVariable(
open class KotlinUParameter( open class KotlinUParameter(
psi: PsiParameter, psi: PsiParameter,
override val uastParent: UElement? givenParent: UElement?
) : AbstractKotlinUVariable(), UParameter, PsiParameter by psi { ) : AbstractKotlinUVariable(givenParent), UParameter, PsiParameter by psi {
override val psi = unwrap<UParameter, PsiParameter>(psi) override val psi = unwrap<UParameter, PsiParameter>(psi)
@@ -136,8 +140,8 @@ open class KotlinUParameter(
open class KotlinUField( open class KotlinUField(
psi: PsiField, psi: PsiField,
override val uastParent: UElement? givenParent: UElement?
) : AbstractKotlinUVariable(), UField, PsiField by psi { ) : AbstractKotlinUVariable(givenParent), UField, PsiField by psi {
override val psi = unwrap<UField, PsiField>(psi) override val psi = unwrap<UField, PsiField>(psi)
@@ -172,8 +176,8 @@ open class KotlinUField(
open class KotlinULocalVariable( open class KotlinULocalVariable(
psi: PsiLocalVariable, psi: PsiLocalVariable,
override val uastParent: UElement? givenParent: UElement?
) : AbstractKotlinUVariable(), ULocalVariable, PsiLocalVariable by psi { ) : AbstractKotlinUVariable(givenParent), ULocalVariable, PsiLocalVariable by psi {
override val psi = unwrap<ULocalVariable, PsiLocalVariable>(psi) override val psi = unwrap<ULocalVariable, PsiLocalVariable>(psi)
@@ -213,8 +217,8 @@ open class KotlinUAnnotatedLocalVariable(
open class KotlinUEnumConstant( open class KotlinUEnumConstant(
psi: PsiEnumConstant, psi: PsiEnumConstant,
override val uastParent: UElement? givenParent: UElement?
) : AbstractKotlinUVariable(), UEnumConstant, PsiEnumConstant by psi { ) : AbstractKotlinUVariable(givenParent), UEnumConstant, PsiEnumConstant by psi {
override fun getContainingFile(): PsiFile { override fun getContainingFile(): PsiFile {
return super.getContainingFile() return super.getContainingFile()
@@ -268,8 +272,9 @@ open class KotlinUEnumConstant(
private class KotlinEnumConstantClassReference( private class KotlinEnumConstantClassReference(
override val psi: PsiEnumConstant, override val psi: PsiEnumConstant,
override val uastParent: UElement? private val givenParent: UElement?
) : JavaAbstractUExpression(), USimpleNameReferenceExpression { ) : JavaAbstractUExpression(), USimpleNameReferenceExpression {
override val uastParent: UElement? by lz { convertParent(givenParent) }
override fun resolve() = psi.containingClass override fun resolve() = psi.containingClass
override val resolvedName: String? override val resolvedName: String?
get() = psi.containingClass?.name get() = psi.containingClass?.name
@@ -58,7 +58,7 @@ private fun createElvisExpressions(
override val uastParent: UElement? = containingElement override val uastParent: UElement? = containingElement
override val condition: UExpression by lz { createNotEqWithNullExpression(tempVariable, this) } override val condition: UExpression by lz { createNotEqWithNullExpression(tempVariable, this) }
override val thenExpression: UExpression? by lz { createVariableReferenceExpression(tempVariable, this) } override val thenExpression: UExpression? by lz { createVariableReferenceExpression(tempVariable, this) }
override val elseExpression: UExpression? by lz { KotlinConverter.convertExpression(right, this.toCallback() ) } override val elseExpression: UExpression? by lz { KotlinConverter.convertExpression(right, this ) }
override val isTernary: Boolean = false override val isTernary: Boolean = false
override val annotations: List<UAnnotation> = emptyList() override val annotations: List<UAnnotation> = emptyList()
override val ifIdentifier: UIdentifier = UIdentifier(null, this) override val ifIdentifier: UIdentifier = UIdentifier(null, this)
@@ -24,11 +24,11 @@ import org.jetbrains.uast.UastBinaryOperator
class KotlinStringTemplateUPolyadicExpression( class KotlinStringTemplateUPolyadicExpression(
override val psi: KtStringTemplateExpression, override val psi: KtStringTemplateExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), ) : KotlinAbstractUExpression(givenParent),
UPolyadicExpression, UPolyadicExpression,
KotlinUElementWithType, KotlinUElementWithType,
KotlinEvaluatableUElement { KotlinEvaluatableUElement {
override val operands: List<UExpression> by lz { psi.entries.map { KotlinConverter.convertEntry(it, { this })!! } } override val operands: List<UExpression> by lz { psi.entries.map { KotlinConverter.convertEntry(it, this)!! } }
override val operator = UastBinaryOperator.PLUS override val operator = UastBinaryOperator.PLUS
} }
@@ -22,8 +22,8 @@ import org.jetbrains.uast.UElement
class KotlinUArrayAccessExpression( class KotlinUArrayAccessExpression(
override val psi: KtArrayAccessExpression, override val psi: KtArrayAccessExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UArrayAccessExpression, KotlinUElementWithType, KotlinEvaluatableUElement { ) : KotlinAbstractUExpression(givenParent), UArrayAccessExpression, KotlinUElementWithType, KotlinEvaluatableUElement {
override val receiver by lz { KotlinConverter.convertOrEmpty(psi.arrayExpression, this) } override val receiver by lz { KotlinConverter.convertOrEmpty(psi.arrayExpression, this) }
override val indices by lz { psi.indexExpressions.map { KotlinConverter.convertOrEmpty(it, this) } } override val indices by lz { psi.indexExpressions.map { KotlinConverter.convertOrEmpty(it, this) } }
} }
@@ -28,8 +28,8 @@ import org.jetbrains.uast.*
class KotlinUBinaryExpression( class KotlinUBinaryExpression(
override val psi: KtBinaryExpression, override val psi: KtBinaryExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UBinaryExpression, KotlinUElementWithType, KotlinEvaluatableUElement { ) : KotlinAbstractUExpression(givenParent), UBinaryExpression, KotlinUElementWithType, KotlinEvaluatableUElement {
private companion object { private companion object {
val BITWISE_OPERATORS = mapOf( val BITWISE_OPERATORS = mapOf(
"or" to UastBinaryOperator.BITWISE_OR, "or" to UastBinaryOperator.BITWISE_OR,
@@ -88,8 +88,8 @@ class KotlinUBinaryExpression(
class KotlinCustomUBinaryExpression( class KotlinCustomUBinaryExpression(
override val psi: PsiElement, override val psi: PsiElement,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UBinaryExpression { ) : KotlinAbstractUExpression(givenParent), UBinaryExpression {
lateinit override var leftOperand: UExpression lateinit override var leftOperand: UExpression
internal set internal set
@@ -24,8 +24,8 @@ import org.jetbrains.uast.*
class KotlinUBinaryExpressionWithType( class KotlinUBinaryExpressionWithType(
override val psi: KtBinaryExpressionWithTypeRHS, override val psi: KtBinaryExpressionWithTypeRHS,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UBinaryExpressionWithType, ) : KotlinAbstractUExpression(givenParent), UBinaryExpressionWithType,
KotlinUElementWithType, KotlinEvaluatableUElement { KotlinUElementWithType, KotlinEvaluatableUElement {
override val operand by lz { KotlinConverter.convertOrEmpty(psi.left, this) } override val operand by lz { KotlinConverter.convertOrEmpty(psi.left, this) }
@@ -44,8 +44,8 @@ class KotlinUBinaryExpressionWithType(
class KotlinCustomUBinaryExpressionWithType( class KotlinCustomUBinaryExpressionWithType(
override val psi: PsiElement, override val psi: PsiElement,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UBinaryExpressionWithType { ) : KotlinAbstractUExpression(givenParent), UBinaryExpressionWithType {
lateinit override var operand: UExpression lateinit override var operand: UExpression
internal set internal set
@@ -23,9 +23,8 @@ import org.jetbrains.uast.*
class KotlinUBlockExpression( class KotlinUBlockExpression(
override val psi: KtBlockExpression, override val psi: KtBlockExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UBlockExpression, KotlinUElementWithType { ) : KotlinAbstractUExpression(givenParent), UBlockExpression, KotlinUElementWithType {
override val expressions by lz { psi.statements.map { KotlinConverter.convertOrEmpty(it, this) } } override val expressions by lz { psi.statements.map { KotlinConverter.convertOrEmpty(it, this) } }
private class KotlinLazyUBlockExpression( private class KotlinLazyUBlockExpression(
@@ -23,8 +23,8 @@ import org.jetbrains.uast.kotlin.KotlinAbstractUExpression
class KotlinUBreakExpression( class KotlinUBreakExpression(
override val psi: KtBreakExpression, override val psi: KtBreakExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UBreakExpression { ) : KotlinAbstractUExpression(givenParent), UBreakExpression {
override val label: String? override val label: String?
get() = psi.getLabelName() get() = psi.getLabelName()
} }
@@ -25,13 +25,13 @@ import org.jetbrains.uast.UExpression
class KotlinUCallableReferenceExpression( class KotlinUCallableReferenceExpression(
override val psi: KtCallableReferenceExpression, override val psi: KtCallableReferenceExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UCallableReferenceExpression, KotlinUElementWithType { ) : KotlinAbstractUExpression(givenParent), UCallableReferenceExpression, KotlinUElementWithType {
override val qualifierExpression: UExpression? override val qualifierExpression: UExpression?
get() { get() {
if (qualifierType != null) return null if (qualifierType != null) return null
val receiverExpression = psi.receiverExpression ?: return null val receiverExpression = psi.receiverExpression ?: return null
return KotlinConverter.convertExpression(receiverExpression, { this }) return KotlinConverter.convertExpression(receiverExpression, this)
} }
override val qualifierType by lz { override val qualifierType by lz {
@@ -25,8 +25,8 @@ import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter
class KotlinUCatchClause( class KotlinUCatchClause(
override val psi: KtCatchClause, override val psi: KtCatchClause,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUElement(), UCatchClause { ) : KotlinAbstractUElement(givenParent), UCatchClause {
override val body by lz { KotlinConverter.convertOrEmpty(psi.catchBody, this) } override val body by lz { KotlinConverter.convertOrEmpty(psi.catchBody, this) }
override val parameters by lz { override val parameters by lz {
@@ -24,8 +24,8 @@ import org.jetbrains.uast.UExpression
class KotlinUClassLiteralExpression( class KotlinUClassLiteralExpression(
override val psi: KtClassLiteralExpression, override val psi: KtClassLiteralExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UClassLiteralExpression, KotlinUElementWithType { ) : KotlinAbstractUExpression(givenParent), UClassLiteralExpression, KotlinUElementWithType {
override val type by lz { override val type by lz {
val ktType = psi.analyze()[DOUBLE_COLON_LHS, psi.receiverExpression]?.type ?: return@lz null val ktType = psi.analyze()[DOUBLE_COLON_LHS, psi.receiverExpression]?.type ?: return@lz null
ktType.toPsiType(this, psi, boxed = true) ktType.toPsiType(this, psi, boxed = true)
@@ -35,6 +35,6 @@ class KotlinUClassLiteralExpression(
get() { get() {
if (type != null) return null if (type != null) return null
val receiverExpression = psi.receiverExpression ?: return null val receiverExpression = psi.receiverExpression ?: return null
return KotlinConverter.convertExpression(receiverExpression, { this }) return KotlinConverter.convertExpression(receiverExpression, this)
} }
} }
@@ -23,8 +23,8 @@ import org.jetbrains.uast.kotlin.KotlinAbstractUExpression
class KotlinUContinueExpression( class KotlinUContinueExpression(
override val psi: KtContinueExpression, override val psi: KtContinueExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UContinueExpression { ) : KotlinAbstractUExpression(givenParent), UContinueExpression {
override val label: String? override val label: String?
get() = psi.getLabelName() get() = psi.getLabelName()
} }
@@ -20,8 +20,8 @@ import org.jetbrains.uast.kotlin.KotlinAbstractUExpression
class KotlinUDeclarationsExpression( class KotlinUDeclarationsExpression(
override val psi: PsiElement?, override val psi: PsiElement?,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UDeclarationsExpression { ) : KotlinAbstractUExpression(givenParent), UDeclarationsExpression {
constructor(uastParent: UElement?) : this(null, uastParent) constructor(uastParent: UElement?) : this(null, uastParent)
@@ -23,8 +23,8 @@ import org.jetbrains.uast.UIdentifier
class KotlinUDoWhileExpression( class KotlinUDoWhileExpression(
override val psi: KtDoWhileExpression, override val psi: KtDoWhileExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UDoWhileExpression { ) : KotlinAbstractUExpression(givenParent), UDoWhileExpression {
override val condition by lz { KotlinConverter.convertOrEmpty(psi.condition, this) } override val condition by lz { KotlinConverter.convertOrEmpty(psi.condition, this) }
override val body by lz { KotlinConverter.convertOrEmpty(psi.body, this) } override val body by lz { KotlinConverter.convertOrEmpty(psi.body, this) }
@@ -29,8 +29,8 @@ import org.jetbrains.uast.kotlin.kinds.KotlinSpecialExpressionKinds
open class KotlinUExpressionList( open class KotlinUExpressionList(
override val psi: PsiElement?, override val psi: PsiElement?,
override val kind: UastSpecialExpressionKind, // original element override val kind: UastSpecialExpressionKind, // original element
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UExpressionList, KotlinUElementWithType, KotlinEvaluatableUElement { ) : KotlinAbstractUExpression(givenParent), UExpressionList, KotlinUElementWithType, KotlinEvaluatableUElement {
override lateinit var expressions: List<UExpression> override lateinit var expressions: List<UExpression>
internal set internal set
@@ -26,8 +26,8 @@ import org.jetbrains.uast.psi.UastPsiParameterNotResolved
class KotlinUForEachExpression( class KotlinUForEachExpression(
override val psi: KtForExpression, override val psi: KtForExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UForEachExpression { ) : KotlinAbstractUExpression(givenParent), UForEachExpression {
override val iteratedValue by lz { KotlinConverter.convertOrEmpty(psi.loopRange, this) } override val iteratedValue by lz { KotlinConverter.convertOrEmpty(psi.loopRange, this) }
override val body by lz { KotlinConverter.convertOrEmpty(psi.body, this) } override val body by lz { KotlinConverter.convertOrEmpty(psi.body, this) }
@@ -23,7 +23,10 @@ import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.psiUtil.parents import org.jetbrains.kotlin.psi.psiUtil.parents
import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
@@ -34,9 +37,9 @@ import org.jetbrains.uast.visitor.UastVisitor
class KotlinUFunctionCallExpression( class KotlinUFunctionCallExpression(
override val psi: KtCallExpression, override val psi: KtCallExpression,
override val uastParent: UElement?, givenParent: UElement?,
private val _resolvedCall: ResolvedCall<*>? private val _resolvedCall: ResolvedCall<*>?
) : KotlinAbstractUExpression(), UCallExpression, KotlinUElementWithType { ) : KotlinAbstractUExpression(givenParent), UCallExpression, KotlinUElementWithType {
companion object { companion object {
fun resolveSource(descriptor: DeclarationDescriptor, source: PsiElement?): PsiMethod? { fun resolveSource(descriptor: DeclarationDescriptor, source: PsiElement?): PsiMethod? {
if (descriptor is ConstructorDescriptor && descriptor.isPrimary if (descriptor is ConstructorDescriptor && descriptor.isPrimary
@@ -99,12 +102,7 @@ class KotlinUFunctionCallExpression(
} }
override val receiver: UExpression? override val receiver: UExpression?
get() { get() = (uastParent as? UQualifiedReferenceExpression)?.takeIf { it.selector == this }?.receiver
return if (uastParent is UQualifiedReferenceExpression && uastParent.selector == this)
uastParent.receiver
else
null
}
override fun resolve(): PsiMethod? { override fun resolve(): PsiMethod? {
val descriptor = resolvedCall?.resultingDescriptor ?: return null val descriptor = resolvedCall?.resultingDescriptor ?: return null
@@ -23,8 +23,8 @@ import org.jetbrains.uast.UIfExpression
class KotlinUIfExpression( class KotlinUIfExpression(
override val psi: KtIfExpression, override val psi: KtIfExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UIfExpression, KotlinUElementWithType, KotlinEvaluatableUElement { ) : KotlinAbstractUExpression(givenParent), UIfExpression, KotlinUElementWithType, KotlinEvaluatableUElement {
override val condition by lz { KotlinConverter.convertOrEmpty(psi.condition, this) } override val condition by lz { KotlinConverter.convertOrEmpty(psi.condition, this) }
override val thenExpression by lz { KotlinConverter.convertOrNull(psi.then, this) } override val thenExpression by lz { KotlinConverter.convertOrNull(psi.then, this) }
override val elseExpression by lz { KotlinConverter.convertOrNull(psi.`else`, this) } override val elseExpression by lz { KotlinConverter.convertOrNull(psi.`else`, this) }
@@ -23,8 +23,8 @@ import org.jetbrains.uast.ULabeledExpression
class KotlinULabeledExpression( class KotlinULabeledExpression(
override val psi: KtLabeledExpression, override val psi: KtLabeledExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), ULabeledExpression { ) : KotlinAbstractUExpression(givenParent), ULabeledExpression {
override val label: String override val label: String
get() = psi.getLabelName().orAnonymous("label") get() = psi.getLabelName().orAnonymous("label")
@@ -26,8 +26,8 @@ import org.jetbrains.uast.withMargin
class KotlinULambdaExpression( class KotlinULambdaExpression(
override val psi: KtLambdaExpression, override val psi: KtLambdaExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), ULambdaExpression, KotlinUElementWithType { ) : KotlinAbstractUExpression(givenParent), ULambdaExpression, KotlinUElementWithType {
val functionalInterfaceType: PsiType? val functionalInterfaceType: PsiType?
get() = getFunctionalInterfaceType() get() = getFunctionalInterfaceType()
@@ -25,8 +25,8 @@ import org.jetbrains.uast.ULiteralExpression
class KotlinULiteralExpression( class KotlinULiteralExpression(
override val psi: KtConstantExpression, override val psi: KtConstantExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), ULiteralExpression, KotlinUElementWithType, KotlinEvaluatableUElement { ) : KotlinAbstractUExpression(givenParent), ULiteralExpression, KotlinUElementWithType, KotlinEvaluatableUElement {
override val isNull: Boolean override val isNull: Boolean
get() = psi.unwrapBlockOrParenthesis().node?.elementType == KtNodeTypes.NULL get() = psi.unwrapBlockOrParenthesis().node?.elementType == KtNodeTypes.NULL
@@ -35,9 +35,9 @@ class KotlinULiteralExpression(
class KotlinStringULiteralExpression( class KotlinStringULiteralExpression(
override val psi: PsiElement, override val psi: PsiElement,
override val uastParent: UElement?, givenParent: UElement?,
val text: String val text: String
) : KotlinAbstractUExpression(), ULiteralExpression, KotlinUElementWithType{ ) : KotlinAbstractUExpression(givenParent), ULiteralExpression, KotlinUElementWithType{
constructor(psi: PsiElement, uastParent: UElement?) constructor(psi: PsiElement, uastParent: UElement?)
: this(psi, uastParent, if (psi is KtEscapeStringTemplateEntry) psi.unescapedValue else psi.text) : this(psi, uastParent, if (psi is KtEscapeStringTemplateEntry) psi.unescapedValue else psi.text)
@@ -23,7 +23,7 @@ import org.jetbrains.uast.*
class KotlinUNamedExpression private constructor( class KotlinUNamedExpression private constructor(
override val name: String?, override val name: String?,
override val uastParent: UElement?, private val givenParent: UElement?,
expressionProducer: (UElement) -> UExpression expressionProducer: (UElement) -> UExpression
) : UNamedExpression { ) : UNamedExpression {
override val expression: UExpression by lz { expressionProducer(this) } override val expression: UExpression by lz { expressionProducer(this) }
@@ -32,6 +32,8 @@ class KotlinUNamedExpression private constructor(
override val psi: PsiElement? = null override val psi: PsiElement? = null
override val uastParent: UElement? by lz { convertParent(givenParent) }
companion object { companion object {
internal fun create(name: String?, valueArgument: ValueArgument, uastParent: UElement?): UNamedExpression { internal fun create(name: String?, valueArgument: ValueArgument, uastParent: UElement?): UNamedExpression {
val expression = valueArgument.getArgumentExpression() val expression = valueArgument.getArgumentExpression()
@@ -45,7 +47,7 @@ class KotlinUNamedExpression private constructor(
valueArguments: List<ValueArgument>, valueArguments: List<ValueArgument>,
uastParent: UElement?): UNamedExpression { uastParent: UElement?): UNamedExpression {
return KotlinUNamedExpression(name, uastParent) { expressionParent -> return KotlinUNamedExpression(name, uastParent) { expressionParent ->
object : KotlinAbstractUExpression(), UCallExpression { object : KotlinAbstractUExpression(uastParent), UCallExpression {
override val uastParent: UElement? = expressionParent override val uastParent: UElement? = expressionParent
override val kind: UastCallKind = UastCallKind.NESTED_ARRAY_INITIALIZER override val kind: UastCallKind = UastCallKind.NESTED_ARRAY_INITIALIZER
@@ -29,8 +29,8 @@ import org.jetbrains.uast.*
class KotlinUObjectLiteralExpression( class KotlinUObjectLiteralExpression(
override val psi: KtObjectLiteralExpression, override val psi: KtObjectLiteralExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UObjectLiteralExpression, KotlinUElementWithType { ) : KotlinAbstractUExpression(givenParent), UObjectLiteralExpression, KotlinUElementWithType {
override val declaration: UClass by lz { override val declaration: UClass by lz {
val lightClass: KtLightClass? = psi.objectDeclaration.toLightClass() val lightClass: KtLightClass? = psi.objectDeclaration.toLightClass()
if (lightClass != null) { if (lightClass != null) {
@@ -73,8 +73,8 @@ class KotlinUObjectLiteralExpression(
private class ObjectLiteralClassReference( private class ObjectLiteralClassReference(
override val psi: KtSuperTypeCallEntry, override val psi: KtSuperTypeCallEntry,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUElement(), USimpleNameReferenceExpression { ) : KotlinAbstractUElement(givenParent), USimpleNameReferenceExpression {
override fun resolve() = (psi.resolveCallToDeclaration(this) as? PsiMethod)?.containingClass override fun resolve() = (psi.resolveCallToDeclaration(this) as? PsiMethod)?.containingClass
override val annotations: List<UAnnotation> override val annotations: List<UAnnotation>
@@ -22,7 +22,7 @@ import org.jetbrains.uast.UParenthesizedExpression
class KotlinUParenthesizedExpression( class KotlinUParenthesizedExpression(
override val psi: KtParenthesizedExpression, override val psi: KtParenthesizedExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UParenthesizedExpression, KotlinUElementWithType { ) : KotlinAbstractUExpression(givenParent), UParenthesizedExpression, KotlinUElementWithType {
override val expression by lz { KotlinConverter.convertOrEmpty(psi.expression, this) } override val expression by lz { KotlinConverter.convertOrEmpty(psi.expression, this) }
} }
@@ -23,8 +23,8 @@ import org.jetbrains.uast.*
class KotlinUPostfixExpression( class KotlinUPostfixExpression(
override val psi: KtPostfixExpression, override val psi: KtPostfixExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UPostfixExpression, KotlinUElementWithType, KotlinEvaluatableUElement, UResolvable { ) : KotlinAbstractUExpression(givenParent), UPostfixExpression, KotlinUElementWithType, KotlinEvaluatableUElement, UResolvable {
override val operand by lz { KotlinConverter.convertOrEmpty(psi.baseExpression, this) } override val operand by lz { KotlinConverter.convertOrEmpty(psi.baseExpression, this) }
override val operator = when (psi.operationToken) { override val operator = when (psi.operationToken) {
@@ -26,8 +26,8 @@ import org.jetbrains.uast.UastPrefixOperator
class KotlinUPrefixExpression( class KotlinUPrefixExpression(
override val psi: KtPrefixExpression, override val psi: KtPrefixExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UPrefixExpression, KotlinUElementWithType, KotlinEvaluatableUElement { ) : KotlinAbstractUExpression(givenParent), UPrefixExpression, KotlinUElementWithType, KotlinEvaluatableUElement {
override val operand by lz { KotlinConverter.convertOrEmpty(psi.baseExpression, this) } override val operand by lz { KotlinConverter.convertOrEmpty(psi.baseExpression, this) }
override val operatorIdentifier: UIdentifier? override val operatorIdentifier: UIdentifier?
@@ -28,8 +28,8 @@ import org.jetbrains.uast.UastQualifiedExpressionAccessType
class KotlinUQualifiedReferenceExpression( class KotlinUQualifiedReferenceExpression(
override val psi: KtDotQualifiedExpression, override val psi: KtDotQualifiedExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UQualifiedReferenceExpression, ) : KotlinAbstractUExpression(givenParent), UQualifiedReferenceExpression,
KotlinUElementWithType, KotlinEvaluatableUElement { KotlinUElementWithType, KotlinEvaluatableUElement {
override val receiver by lz { KotlinConverter.convertOrEmpty(psi.receiverExpression, this) } override val receiver by lz { KotlinConverter.convertOrEmpty(psi.receiverExpression, this) }
override val selector by lz { KotlinConverter.convertOrEmpty(psi.selectorExpression, this) } override val selector by lz { KotlinConverter.convertOrEmpty(psi.selectorExpression, this) }
@@ -43,8 +43,8 @@ class KotlinUQualifiedReferenceExpression(
class KotlinUComponentQualifiedReferenceExpression( class KotlinUComponentQualifiedReferenceExpression(
override val psi: KtDestructuringDeclarationEntry, override val psi: KtDestructuringDeclarationEntry,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UQualifiedReferenceExpression, ) : KotlinAbstractUExpression(givenParent), UQualifiedReferenceExpression,
KotlinUElementWithType, KotlinEvaluatableUElement { KotlinUElementWithType, KotlinEvaluatableUElement {
override val accessType = UastQualifiedExpressionAccessType.SIMPLE override val accessType = UastQualifiedExpressionAccessType.SIMPLE
@@ -22,7 +22,7 @@ import org.jetbrains.uast.UReturnExpression
class KotlinUReturnExpression( class KotlinUReturnExpression(
override val psi: KtReturnExpression, override val psi: KtReturnExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UReturnExpression, KotlinUElementWithType { ) : KotlinAbstractUExpression(givenParent), UReturnExpression, KotlinUElementWithType {
override val returnExpression by lz { KotlinConverter.convertOrNull(psi.returnedExpression, this) } override val returnExpression by lz { KotlinConverter.convertOrNull(psi.returnedExpression, this) }
} }
@@ -23,8 +23,8 @@ import org.jetbrains.uast.UQualifiedReferenceExpression
class KotlinUSafeQualifiedExpression( class KotlinUSafeQualifiedExpression(
override val psi: KtSafeQualifiedExpression, override val psi: KtSafeQualifiedExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UQualifiedReferenceExpression, ) : KotlinAbstractUExpression(givenParent), UQualifiedReferenceExpression,
KotlinUElementWithType, KotlinEvaluatableUElement { KotlinUElementWithType, KotlinEvaluatableUElement {
override val receiver by lz { KotlinConverter.convertOrEmpty(psi.receiverExpression, this) } override val receiver by lz { KotlinConverter.convertOrEmpty(psi.receiverExpression, this) }
override val selector by lz { KotlinConverter.convertOrEmpty(psi.selectorExpression, this) } override val selector by lz { KotlinConverter.convertOrEmpty(psi.selectorExpression, this) }
@@ -35,8 +35,8 @@ import org.jetbrains.uast.visitor.UastVisitor
open class KotlinUSimpleReferenceExpression( open class KotlinUSimpleReferenceExpression(
override val psi: KtSimpleNameExpression, override val psi: KtSimpleNameExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), USimpleNameReferenceExpression, KotlinUElementWithType, KotlinEvaluatableUElement { ) : KotlinAbstractUExpression(givenParent), USimpleNameReferenceExpression, KotlinUElementWithType, KotlinEvaluatableUElement {
private val resolvedDeclaration by lz { psi.resolveCallToDeclaration(this) } private val resolvedDeclaration by lz { psi.resolveCallToDeclaration(this) }
override val identifier get() = psi.getReferencedName() override val identifier get() = psi.getReferencedName()
@@ -185,8 +185,8 @@ open class KotlinUSimpleReferenceExpression(
class KotlinClassViaConstructorUSimpleReferenceExpression( class KotlinClassViaConstructorUSimpleReferenceExpression(
override val psi: KtCallExpression, override val psi: KtCallExpression,
override val identifier: String, override val identifier: String,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), USimpleNameReferenceExpression, KotlinUElementWithType { ) : KotlinAbstractUExpression(givenParent), USimpleNameReferenceExpression, KotlinUElementWithType {
override val resolvedName: String? override val resolvedName: String?
get() = (psi.getResolvedCall(psi.analyze())?.resultingDescriptor as? ConstructorDescriptor) get() = (psi.getResolvedCall(psi.analyze())?.resultingDescriptor as? ConstructorDescriptor)
?.containingDeclaration?.name?.asString() ?.containingDeclaration?.name?.asString()
@@ -201,8 +201,8 @@ class KotlinClassViaConstructorUSimpleReferenceExpression(
class KotlinStringUSimpleReferenceExpression( class KotlinStringUSimpleReferenceExpression(
override val identifier: String, override val identifier: String,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), USimpleNameReferenceExpression { ) : KotlinAbstractUExpression(givenParent), USimpleNameReferenceExpression {
override val psi: PsiElement? override val psi: PsiElement?
get() = null get() = null
override fun resolve() = null override fun resolve() = null
@@ -24,8 +24,8 @@ import org.jetbrains.uast.USuperExpression
class KotlinUSuperExpression( class KotlinUSuperExpression(
override val psi: KtSuperExpression, override val psi: KtSuperExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), USuperExpression, KotlinUElementWithType, KotlinEvaluatableUElement { ) : KotlinAbstractUExpression(givenParent), USuperExpression, KotlinUElementWithType, KotlinEvaluatableUElement {
override val label: String? override val label: String?
get() = psi.getLabelName() get() = psi.getLabelName()
@@ -23,8 +23,8 @@ import org.jetbrains.uast.kotlin.kinds.KotlinSpecialExpressionKinds
class KotlinUSwitchExpression( class KotlinUSwitchExpression(
override val psi: KtWhenExpression, override val psi: KtWhenExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), USwitchExpression, KotlinUElementWithType { ) : KotlinAbstractUExpression(givenParent), USwitchExpression, KotlinUElementWithType {
override val expression by lz { KotlinConverter.convertOrNull(psi.subjectExpression, this) } override val expression by lz { KotlinConverter.convertOrNull(psi.subjectExpression, this) }
override val body: UExpressionList by lz { override val body: UExpressionList by lz {
@@ -48,8 +48,8 @@ class KotlinUSwitchExpression(
class KotlinUSwitchEntry( class KotlinUSwitchEntry(
override val psi: KtWhenEntry, override val psi: KtWhenEntry,
override val uastParent: UExpression givenParent: UExpression
) : KotlinAbstractUExpression(), USwitchClauseExpressionWithBody { ) : KotlinAbstractUExpression(givenParent), USwitchClauseExpressionWithBody {
override val caseValues by lz { override val caseValues by lz {
psi.conditions.map { when (it) { psi.conditions.map { when (it) {
is KtWhenConditionInRange -> KotlinCustomUBinaryExpression(it, this).apply { is KtWhenConditionInRange -> KotlinCustomUBinaryExpression(it, this).apply {
@@ -24,8 +24,8 @@ import org.jetbrains.uast.UThisExpression
class KotlinUThisExpression( class KotlinUThisExpression(
override val psi: KtThisExpression, override val psi: KtThisExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UThisExpression, KotlinUElementWithType, KotlinEvaluatableUElement { ) : KotlinAbstractUExpression(givenParent), UThisExpression, KotlinUElementWithType, KotlinEvaluatableUElement {
override val label: String? override val label: String?
get() = psi.getLabelName() get() = psi.getLabelName()
@@ -22,7 +22,7 @@ import org.jetbrains.uast.UThrowExpression
class KotlinUThrowExpression( class KotlinUThrowExpression(
override val psi: KtThrowExpression, override val psi: KtThrowExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UThrowExpression, KotlinUElementWithType { ) : KotlinAbstractUExpression(givenParent), UThrowExpression, KotlinUElementWithType {
override val thrownExpression by lz { KotlinConverter.convertOrEmpty(psi.thrownExpression, this) } override val thrownExpression by lz { KotlinConverter.convertOrEmpty(psi.thrownExpression, this) }
} }
@@ -24,11 +24,11 @@ import org.jetbrains.uast.UVariable
class KotlinUTryExpression( class KotlinUTryExpression(
override val psi: KtTryExpression, override val psi: KtTryExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UTryExpression, KotlinUElementWithType { ) : KotlinAbstractUExpression(givenParent), UTryExpression, KotlinUElementWithType {
override val tryClause by lz { KotlinConverter.convertOrEmpty(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 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> override val resourceVariables: List<UVariable>
get() = emptyList() get() = emptyList()
@@ -23,8 +23,8 @@ import org.jetbrains.uast.UastBinaryExpressionWithTypeKind
class KotlinUTypeCheckExpression( class KotlinUTypeCheckExpression(
override val psi: KtIsExpression, override val psi: KtIsExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UBinaryExpressionWithType, KotlinUElementWithType, KotlinEvaluatableUElement { ) : KotlinAbstractUExpression(givenParent), UBinaryExpressionWithType, KotlinUElementWithType, KotlinEvaluatableUElement {
override val operand by lz { KotlinConverter.convertOrEmpty(psi.leftHandSide, this) } override val operand by lz { KotlinConverter.convertOrEmpty(psi.leftHandSide, this) }
override val type by lz { psi.typeReference.toPsiType(this) } override val type by lz { psi.typeReference.toPsiType(this) }
@@ -8,14 +8,14 @@ import org.jetbrains.uast.UTypeReferenceExpression
open class KotlinUTypeReferenceExpression( open class KotlinUTypeReferenceExpression(
override val type: PsiType, override val type: PsiType,
override val psi: PsiElement?, override val psi: PsiElement?,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UTypeReferenceExpression, KotlinUElementWithType ) : KotlinAbstractUExpression(givenParent), UTypeReferenceExpression, KotlinUElementWithType
class LazyKotlinUTypeReferenceExpression( class LazyKotlinUTypeReferenceExpression(
override val psi: PsiElement, override val psi: PsiElement,
override val uastParent: UElement?, givenParent: UElement?,
private val typeSupplier: () -> PsiType private val typeSupplier: () -> PsiType
) : KotlinAbstractUExpression(), UTypeReferenceExpression { ) : KotlinAbstractUExpression(givenParent), UTypeReferenceExpression {
override val type: PsiType by lz { typeSupplier() } override val type: PsiType by lz { typeSupplier() }
} }
@@ -23,8 +23,8 @@ import org.jetbrains.uast.UWhileExpression
class KotlinUWhileExpression( class KotlinUWhileExpression(
override val psi: KtWhileExpression, override val psi: KtWhileExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UWhileExpression { ) : KotlinAbstractUExpression(givenParent), UWhileExpression {
override val condition by lz { KotlinConverter.convertOrEmpty(psi.condition, this) } override val condition by lz { KotlinConverter.convertOrEmpty(psi.condition, this) }
override val body by lz { KotlinConverter.convertOrEmpty(psi.body, this) } override val body by lz { KotlinConverter.convertOrEmpty(psi.body, this) }
@@ -12,8 +12,10 @@ import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable
private class KotlinLocalFunctionUVariable( private class KotlinLocalFunctionUVariable(
val function: KtFunction, val function: KtFunction,
override val psi: PsiVariable, override val psi: PsiVariable,
override val uastParent: UElement? private val givenParent: UElement?
) : UVariable, PsiVariable by psi { ) : UVariable, PsiVariable by psi {
override val uastParent: UElement? by lz { convertParent(givenParent) }
override val uastInitializer: UExpression? by lz { override val uastInitializer: UExpression? by lz {
createLocalFunctionLambdaExpression(function, this) createLocalFunctionLambdaExpression(function, this)
} }
@@ -28,8 +30,8 @@ private class KotlinLocalFunctionUVariable(
private class KotlinLocalFunctionULambdaExpression( private class KotlinLocalFunctionULambdaExpression(
override val psi: KtFunction, override val psi: KtFunction,
override val uastParent: UElement? givenParent: UElement?
): KotlinAbstractUExpression(), ULambdaExpression { ): KotlinAbstractUExpression(givenParent), ULambdaExpression {
val functionalInterfaceType: PsiType? val functionalInterfaceType: PsiType?
get() = null get() = null
@@ -22,7 +22,7 @@ import org.jetbrains.uast.UExpression
class UnknownKotlinExpression( class UnknownKotlinExpression(
override val psi: KtExpression, override val psi: KtExpression,
override val uastParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(), UExpression { ) : KotlinAbstractUExpression(givenParent), UExpression {
override fun asLogString() = "[!] UnknownKotlinExpression ($psi)" override fun asLogString() = "[!] UnknownKotlinExpression ($psi)"
} }
+3
View File
@@ -0,0 +1,3 @@
fun foo() {
val x = if ("abc" != "def") 1 else 0
}
+12
View File
@@ -0,0 +1,12 @@
UFile (package = )
UClass (name = IfStatementKt)
UAnnotationMethod (name = foo)
UBlockExpression
UDeclarationsExpression
ULocalVariable (name = x)
UIfExpression
UBinaryExpression (operator = !=)
ULiteralExpression (value = "abc")
ULiteralExpression (value = "def")
ULiteralExpression (value = 1)
ULiteralExpression (value = 0)
+5
View File
@@ -0,0 +1,5 @@
public final class IfStatementKt {
public static final fun foo() : void {
var x: int = if ("abc" != "def") 1 else 0
}
}
@@ -1,15 +1,18 @@
package org.jetbrains.uast.test.kotlin package org.jetbrains.uast.test.kotlin
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiRecursiveElementVisitor
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
import org.jetbrains.uast.UDeclaration import org.jetbrains.uast.UDeclaration
import org.jetbrains.uast.UElement import org.jetbrains.uast.UElement
import org.jetbrains.uast.UFile import org.jetbrains.uast.UFile
import org.jetbrains.uast.UIdentifier import org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin
import org.jetbrains.uast.test.common.RenderLogTestBase import org.jetbrains.uast.test.common.RenderLogTestBase
import org.jetbrains.uast.visitor.UastVisitor import org.jetbrains.uast.visitor.UastVisitor
import org.junit.Assert
import java.io.File import java.io.File
import java.util.*
abstract class AbstractKotlinRenderLogTest : AbstractKotlinUastTest(), RenderLogTestBase { abstract class AbstractKotlinRenderLogTest : AbstractKotlinUastTest(), RenderLogTestBase {
override fun getTestFile(testName: String, ext: String) = override fun getTestFile(testName: String, ext: String) =
@@ -17,6 +20,34 @@ abstract class AbstractKotlinRenderLogTest : AbstractKotlinUastTest(), RenderLog
override fun check(testName: String, file: UFile) { override fun check(testName: String, file: UFile) {
super.check(testName, file) super.check(testName, file)
file.psi.accept(object : PsiRecursiveElementVisitor() {
override fun visitElement(element: PsiElement) {
KotlinUastLanguagePlugin().convertElementWithParent(element, null)
super.visitElement(element)
}
})
file.accept(object : UastVisitor {
private val parentStack = Stack<UElement>()
override fun visitElement(node: UElement): Boolean {
val parent = node.uastParent
if (parent == null) {
Assert.assertTrue("Wrong parent of $node", parentStack.empty())
}
else {
Assert.assertEquals("Wrong parent of $node", parentStack.peek(), parent)
}
parentStack.push(node)
return false
}
override fun afterVisitElement(node: UElement) {
super.afterVisitElement(node)
parentStack.pop()
}
})
file.checkContainingFileForAllElements() file.checkContainingFileForAllElements()
} }
@@ -1,11 +1,14 @@
package org.jetbrains.uast.test.kotlin package org.jetbrains.uast.test.kotlin
import com.intellij.psi.PsiModifier import com.intellij.psi.PsiModifier
import com.intellij.testFramework.UsefulTestCase
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry
import org.jetbrains.kotlin.psi.KtStringTemplateExpression import org.jetbrains.kotlin.psi.KtStringTemplateExpression
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
import org.jetbrains.uast.* import org.jetbrains.uast.*
import org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin
import org.jetbrains.uast.test.env.findElementByText import org.jetbrains.uast.test.env.findElementByText
import org.junit.Assert import org.junit.Assert
import org.junit.Test import org.junit.Test
@@ -112,4 +115,14 @@ class KotlinUastApiTest : AbstractKotlinUastTest() {
assertEquals(42, witDefaultValue.findAttributeValue(null)!!.evaluate()) assertEquals(42, witDefaultValue.findAttributeValue(null)!!.evaluate())
} }
} }
@Test fun testIfCondition() {
doTest("IfStatement") { _, file ->
val psiFile = file.psi
val element = psiFile.findElementAt(psiFile.text.indexOf("\"abc\""))!!
val binaryExpression = element.getParentOfType<KtBinaryExpression>(false)!!
val uBinaryExpression = KotlinUastLanguagePlugin().convertElementWithParent(binaryExpression, null)!!
UsefulTestCase.assertInstanceOf(uBinaryExpression.uastParent, UIfExpression::class.java)
}
}
} }
@@ -31,6 +31,8 @@ class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() {
@Test fun testPropertyWithAnnotation() = doTest("PropertyWithAnnotation") @Test fun testPropertyWithAnnotation() = doTest("PropertyWithAnnotation")
@Test fun testIfStatement() = doTest("IfStatement")
@Test fun testInnerClasses() = doTest("InnerClasses") @Test fun testInnerClasses() = doTest("InnerClasses")
@Test fun testSimpleScript() = doTest("SimpleScript") @Test fun testSimpleScript() = doTest("SimpleScript")