Switch to 191 platform

This commit is contained in:
Vyacheslav Gerasimov
2019-04-22 21:52:19 +03:00
parent 21232d202e
commit 8723ad4f46
128 changed files with 1025 additions and 1025 deletions
@@ -79,10 +79,14 @@ abstract class KotlinAbstractUElement(private val givenParent: UElement?) : Kotl
parent = parent.parent
}
while (parent is KtStringTemplateEntryWithExpression ||
parent is KtStringTemplateExpression && parent.entries.size == 1) {
parent = parent.parent
}
if (KotlinConverter.forceUInjectionHost) {
if (parent is KtBlockStringTemplateEntry) {
parent = parent.parent
}
} else
while (parent is KtStringTemplateEntryWithExpression || parent is KtStringTemplateExpression && parent.entries.size == 1) {
parent = parent.parent
}
if (parent is KtWhenConditionWithExpression) {
parent = parent.parent
@@ -110,7 +114,7 @@ abstract class KotlinAbstractUElement(private val givenParent: UElement?) : Kotl
val result = doConvertParent(this, parent)
if (result == this) {
throw IllegalStateException("Loop in parent structure when converting a $psi of type ${psi?.javaClass} with parent $parent of type ${parent?.javaClass} text: [${parent?.text}]")
throw IllegalStateException("Loop in parent structure when converting a $psi of type ${psi?.javaClass} with parent $parent of type ${parent?.javaClass} text: [${parent?.text}], result = $result")
}
return result
@@ -79,14 +79,10 @@ abstract class KotlinAbstractUElement(private val givenParent: UElement?) : Kotl
parent = parent.parent
}
if (KotlinConverter.forceUInjectionHost) {
if (parent is KtBlockStringTemplateEntry) {
parent = parent.parent
}
} else
while (parent is KtStringTemplateEntryWithExpression || parent is KtStringTemplateExpression && parent.entries.size == 1) {
parent = parent.parent
}
while (parent is KtStringTemplateEntryWithExpression ||
parent is KtStringTemplateExpression && parent.entries.size == 1) {
parent = parent.parent
}
if (parent is KtWhenConditionWithExpression) {
parent = parent.parent
@@ -114,7 +110,7 @@ abstract class KotlinAbstractUElement(private val givenParent: UElement?) : Kotl
val result = doConvertParent(this, parent)
if (result == this) {
throw IllegalStateException("Loop in parent structure when converting a $psi of type ${psi?.javaClass} with parent $parent of type ${parent?.javaClass} text: [${parent?.text}], result = $result")
throw IllegalStateException("Loop in parent structure when converting a $psi of type ${psi?.javaClass} with parent $parent of type ${parent?.javaClass} text: [${parent?.text}]")
}
return result
@@ -19,13 +19,16 @@ package org.jetbrains.uast.kotlin
import com.intellij.lang.Language
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.registry.Registry
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.elements.*
import org.jetbrains.kotlin.asJava.findFacadeClass
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.LanguageVersionSettings
@@ -39,6 +42,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.uast.*
import org.jetbrains.uast.expressions.UInjectionHost
import org.jetbrains.uast.kotlin.KotlinConverter.convertDeclaration
import org.jetbrains.uast.kotlin.KotlinConverter.convertDeclarationOrElement
import org.jetbrains.uast.kotlin.declarations.KotlinUIdentifier
@@ -75,15 +79,15 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
override fun convertElement(element: PsiElement, parent: UElement?, requiredType: Class<out UElement>?): UElement? {
if (!element.isJvmElement) return null
return convertDeclarationOrElement(element, parent, requiredType)
return convertDeclarationOrElement(element, parent, elementTypes(requiredType))
}
override fun convertElementWithParent(element: PsiElement, requiredType: Class<out UElement>?): UElement? {
if (!element.isJvmElement) return null
if (element is PsiFile) return convertDeclaration(element, null, requiredType)
if (element is KtLightClassForFacade) return convertDeclaration(element, null, requiredType)
if (element is PsiFile) return convertDeclaration(element, null, elementTypes(requiredType))
if (element is KtLightClassForFacade) return convertDeclaration(element, null, elementTypes(requiredType))
return convertDeclarationOrElement(element, null, requiredType)
return convertDeclarationOrElement(element, null, elementTypes(requiredType))
}
override fun getMethodCallExpression(
@@ -136,16 +140,45 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
else -> false
}
}
@Suppress("UNCHECKED_CAST")
fun <T : UElement> convertElement(element: PsiElement, parent: UElement?, expectedTypes: Array<out Class<out T>>): T? {
if (!element.isJvmElement) return null
val nonEmptyExpectedTypes = expectedTypes.nonEmptyOr(DEFAULT_TYPES_LIST)
return (convertDeclaration(element, parent, nonEmptyExpectedTypes)
?: KotlinConverter.convertPsiElement(element, parent, nonEmptyExpectedTypes)) as? T
}
override fun <T : UElement> convertElementWithParent(element: PsiElement, requiredTypes: Array<out Class<out T>>): T? {
return convertElement(element, null, requiredTypes)
}
@Suppress("UNCHECKED_CAST")
override fun <T : UElement> convertToAlternatives(element: PsiElement, requiredTypes: Array<out Class<out T>>): Sequence<T> =
if (!element.isJvmElement) emptySequence() else when {
element is KtFile -> KotlinConverter.convertKtFile(element, null, requiredTypes) as Sequence<T>
(element is KtProperty && !element.isLocal) ->
KotlinConverter.convertNonLocalProperty(element, null, requiredTypes) as Sequence<T>
element is KtParameter -> KotlinConverter.convertParameter(element, null, requiredTypes) as Sequence<T>
element is KtClassOrObject -> KotlinConverter.convertClassOrObject(element, null, requiredTypes) as Sequence<T>
else -> sequenceOf(convertElementWithParent(element, requiredTypes.nonEmptyOr(DEFAULT_TYPES_LIST)) as? T).filterNotNull()
}
}
internal inline fun <reified ActualT : UElement> Class<out UElement>?.el(f: () -> UElement?): UElement? {
internal inline fun <reified ActualT : UElement> Class<*>?.el(f: () -> UElement?): UElement? {
return if (this == null || isAssignableFrom(ActualT::class.java)) 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 inline fun <reified ActualT : UElement> Array<out Class<out UElement>>.el(f: () -> UElement?): UElement? {
return if (isAssignableFrom(ActualT::class.java)) f() else null
}
internal inline fun <reified ActualT : UElement> Array<out Class<out UElement>>.expr(f: () -> UExpression?): UExpression? {
return if (isAssignableFrom(ActualT::class.java)) f() else null
}
internal fun Array<out Class<out UElement>>.isAssignableFrom(cls: Class<*>) = any { it.isAssignableFrom(cls) }
internal object KotlinConverter {
@@ -166,12 +199,13 @@ internal object KotlinConverter {
internal fun convertPsiElement(element: PsiElement?,
givenParent: UElement?,
requiredType: Class<out UElement>?): UElement? {
expectedTypes: Array<out Class<out UElement>>
): UElement? {
fun <P : PsiElement> build(ctor: (P, UElement?) -> UElement): () -> UElement? {
return { ctor(element as P, givenParent) }
}
return with (requiredType) { when (element) {
return with (expectedTypes) { when (element) {
is KtParameterList -> el<UDeclarationsExpression> {
val declarationsExpression = KotlinUDeclarationsExpression(givenParent)
declarationsExpression.apply {
@@ -184,11 +218,7 @@ internal object KotlinConverter {
is KtCatchClause -> el<UCatchClause>(build(::KotlinUCatchClause))
is KtVariableDeclaration ->
if (element is KtProperty && !element.isLocal) {
el<UField> {
LightClassUtil.getLightClassBackingField(element)?.let {
KotlinUField(it, element, givenParent)
}
}
convertNonLocalProperty(element, givenParent, this).firstOrNull()
}
else {
el<UVariable> {
@@ -196,19 +226,19 @@ internal object KotlinConverter {
}
}
is KtExpression -> KotlinConverter.convertExpression(element, givenParent, requiredType)
is KtLambdaArgument -> element.getLambdaExpression()?.let { KotlinConverter.convertExpression(it, givenParent, requiredType) }
is KtExpression -> KotlinConverter.convertExpression(element, givenParent, expectedTypes)
is KtLambdaArgument -> element.getLambdaExpression()?.let { KotlinConverter.convertExpression(it, givenParent, expectedTypes) }
is KtLightElementBase -> {
val expression = element.kotlinOrigin
when (expression) {
is KtExpression -> KotlinConverter.convertExpression(expression, givenParent, requiredType)
is KtExpression -> KotlinConverter.convertExpression(expression, givenParent, expectedTypes)
else -> el<UExpression> { UastEmptyExpression(givenParent) }
}
}
is KtLiteralStringTemplateEntry, is KtEscapeStringTemplateEntry -> el<ULiteralExpression>(build(::KotlinStringULiteralExpression))
is KtStringTemplateEntry -> element.expression?.let { convertExpression(it, givenParent, requiredType) } ?: expr<UExpression> { UastEmptyExpression }
is KtStringTemplateEntry -> element.expression?.let { convertExpression(it, givenParent, expectedTypes) } ?: expr<UExpression> { UastEmptyExpression }
is KtWhenEntry -> el<USwitchClauseExpressionWithBody>(build(::KotlinUSwitchEntry))
is KtWhenCondition -> convertWhenCondition(element, givenParent, requiredType)
is KtWhenCondition -> convertWhenCondition(element, givenParent, expectedTypes)
is KtTypeReference -> el<UTypeReferenceExpression> { LazyKotlinUTypeReferenceExpression(element, givenParent) }
is KtConstructorDelegationCall ->
el<UCallExpression> { KotlinUFunctionCallExpression(element, givenParent) }
@@ -246,7 +276,8 @@ internal object KotlinConverter {
internal fun convertEntry(entry: KtStringTemplateEntry,
givenParent: UElement?,
requiredType: Class<out UElement>? = null): UExpression? {
requiredType: Array<out Class<out UElement>>
): UExpression? {
return with(requiredType) {
if (entry is KtStringTemplateEntryWithExpression) {
expr<UExpression> {
@@ -264,9 +295,16 @@ internal object KotlinConverter {
}
}
var forceUInjectionHost = Registry.`is`("kotlin.uast.force.uinjectionhost", false)
@TestOnly
set(value) {
field = value
}
internal fun convertExpression(expression: KtExpression,
givenParent: UElement?,
requiredType: Class<out UElement>? = null): UExpression? {
requiredType: Array<out Class<out UElement>>
): UExpression? {
fun <P : PsiElement> build(ctor: (P, UElement?) -> UExpression): () -> UExpression? {
return { ctor(expression as P, givenParent) }
}
@@ -276,13 +314,16 @@ internal object KotlinConverter {
is KtStringTemplateExpression -> {
when {
forceUInjectionHost || requiredType.contains(UInjectionHost::class.java) ->
expr<UInjectionHost> { KotlinStringTemplateUPolyadicExpression(expression, givenParent) }
expression.entries.isEmpty() -> {
expr<ULiteralExpression> { KotlinStringULiteralExpression(expression, givenParent, "") }
}
expression.entries.size == 1 -> convertEntry(expression.entries[0], givenParent, requiredType)
else -> {
expr<UExpression> { KotlinStringTemplateUPolyadicExpression(expression, givenParent) }
}
else ->
expr<KotlinStringTemplateUPolyadicExpression> { KotlinStringTemplateUPolyadicExpression(expression, givenParent) }
}
}
is KtDestructuringDeclaration -> expr<UDeclarationsExpression> {
@@ -355,7 +396,7 @@ internal object KotlinConverter {
internal fun convertWhenCondition(condition: KtWhenCondition,
givenParent: UElement?,
requiredType: Class<out UElement>? = null
requiredType: Array<out Class<out UElement>>
): UExpression? {
return with(requiredType) {
when (condition) {
@@ -405,7 +446,7 @@ internal object KotlinConverter {
internal fun convertDeclaration(
element: PsiElement,
givenParent: UElement?,
requiredType: Class<out UElement>?
expectedTypes: Array<out Class<out UElement>>
): UElement? {
fun <P : PsiElement> build(ctor: (P, UElement?) -> UElement): () -> UElement? = { ctor(element as P, givenParent) }
@@ -416,7 +457,7 @@ internal object KotlinConverter {
{ ctor(element as P, ktElement, givenParent) }
val original = element.originalElement
return with(requiredType) {
return with(expectedTypes) {
when (original) {
is KtLightMethod -> el<UMethod>(build(KotlinUMethod.Companion::create)) // .Companion is needed because of KT-13934
is KtLightClass -> when (original.kotlinOrigin) {
@@ -434,11 +475,7 @@ internal object KotlinConverter {
is KtEnumEntry -> el<UEnumConstant> {
convertEnumEntry(original, givenParent)
}
is KtClassOrObject -> el<UClass> {
original.toLightClass()?.let { lightClass ->
KotlinUClass.create(lightClass, givenParent)
}
}
is KtClassOrObject -> convertClassOrObject(original, givenParent, this).firstOrNull()
is KtFunction ->
if (original.isLocal) {
el<ULambdaExpression> {
@@ -447,49 +484,41 @@ internal object KotlinConverter {
KotlinULambdaExpression(parent, givenParent) // your parent is the ULambdaExpression
} else if (original.name.isNullOrEmpty()) {
createLocalFunctionLambdaExpression(original, givenParent)
}
else {
} else {
val uDeclarationsExpression = createLocalFunctionDeclaration(original, givenParent)
val localFunctionVar = uDeclarationsExpression.declarations.single() as KotlinLocalFunctionUVariable
localFunctionVar.uastInitializer
}
}
}
else {
} else {
el<UMethod> {
val lightMethod = LightClassUtil.getLightClassMethod(original) ?: return null
convertDeclaration(lightMethod, givenParent, requiredType)
convertDeclaration(lightMethod, givenParent, expectedTypes)
}
}
is KtPropertyAccessor -> el<UMethod> {
val lightMethod = LightClassUtil.getLightClassAccessorMethod(original) ?: return null
convertDeclaration(lightMethod, givenParent, requiredType)
convertDeclaration(lightMethod, givenParent, expectedTypes)
}
is KtProperty ->
if (original.isLocal) {
KotlinConverter.convertPsiElement(element, givenParent, requiredType)
}
else {
convertNonLocalProperty(original, givenParent, requiredType)
KotlinConverter.convertPsiElement(element, givenParent, expectedTypes)
} else {
convertNonLocalProperty(original, givenParent, expectedTypes).firstOrNull()
}
is KtParameter -> el<UParameter> {
val ownerFunction = original.ownerFunction as? KtFunction ?: return null
val lightMethod = LightClassUtil.getLightClassMethod(ownerFunction) ?: return null
val lightParameter = lightMethod.parameterList.parameters.find { it.name == original.name } ?: return null
KotlinUParameter(lightParameter, original, givenParent)
}
is KtParameter -> convertParameter(original, givenParent, this).firstOrNull()
is KtFile -> el<UFile> { KotlinUFile(original) }
is KtFile -> convertKtFile(original, givenParent, this).firstOrNull()
is FakeFileForLightClass -> el<UFile> { KotlinUFile(original.navigationElement) }
is KtAnnotationEntry -> el<UAnnotation>(build(::KotlinUAnnotation))
is KtCallExpression ->
if (requiredType != null && UAnnotation::class.java.isAssignableFrom(requiredType)) {
if (expectedTypes.isAssignableFrom(KotlinUNestedAnnotation::class.java) && !expectedTypes.isAssignableFrom(UCallExpression::class.java)) {
el<UAnnotation> { KotlinUNestedAnnotation.tryCreate(original, givenParent) }
} else null
is KtLightAnnotationForSourceEntry -> convertDeclarationOrElement(original.kotlinOrigin, givenParent, requiredType)
is KtLightAnnotationForSourceEntry -> convertDeclarationOrElement(original.kotlinOrigin, givenParent, expectedTypes)
is KtDelegatedSuperTypeEntry -> el<KotlinSupertypeDelegationUExpression> {
KotlinSupertypeDelegationUExpression(original, givenParent)
}
@@ -499,17 +528,21 @@ internal object KotlinConverter {
}
fun convertDeclarationOrElement(element: PsiElement, givenParent: UElement?, requiredType: Class<out UElement>?): UElement? {
fun convertDeclarationOrElement(
element: PsiElement,
givenParent: UElement?,
expectedTypes: Array<out Class<out UElement>>
): UElement? {
if (element is UElement) return element
if (element.isValid) {
element.getUserData(KOTLIN_CACHED_UELEMENT_KEY)?.get()?.let { cachedUElement ->
return if (requiredType == null || requiredType.isInstance(cachedUElement)) cachedUElement else null
return if (expectedTypes.isAssignableFrom(cachedUElement.javaClass)) cachedUElement else null
}
}
val uElement = convertDeclaration(element, givenParent, requiredType)
?: KotlinConverter.convertPsiElement(element, givenParent, requiredType)
val uElement = convertDeclaration(element, givenParent, expectedTypes)
?: KotlinConverter.convertPsiElement(element, givenParent, expectedTypes)
/*
if (uElement != null) {
element.putUserData(KOTLIN_CACHED_UELEMENT_KEY, WeakReference(uElement))
@@ -518,27 +551,71 @@ internal object KotlinConverter {
return uElement
}
private fun convertNonLocalProperty(
private fun convertToPropertyAlternatives(
methods: LightClassUtil.PropertyAccessorsPsiMethods?,
givenParent: UElement?
): Array<UElementAlternative<*>> = if (methods != null) arrayOf(
alternative { methods.backingField?.let { KotlinUField(it, (it as? KtLightElement<*, *>)?.kotlinOrigin, givenParent) } },
alternative { methods.getter?.let { convertDeclaration(it, givenParent, arrayOf(UMethod::class.java)) as? UMethod } },
alternative { methods.setter?.let { convertDeclaration(it, givenParent, arrayOf(UMethod::class.java)) as? UMethod } }
) else emptyArray()
fun convertNonLocalProperty(
property: KtProperty,
givenParent: UElement?,
requiredType: Class<out UElement>?
): UElement? {
val methods = LightClassUtil.getLightClassPropertyMethods(property)
return methods.backingField?.let { backingField ->
with(requiredType) {
el<UField> { KotlinUField(backingField, (backingField as? KtLightElement<*,*>)?.kotlinOrigin, givenParent) }
expectedTypes: Array<out Class<out UElement>>
): Sequence<UElement> =
expectedTypes.accommodate(*convertToPropertyAlternatives(LightClassUtil.getLightClassPropertyMethods(property), givenParent))
fun convertParameter(
element: KtParameter,
givenParent: UElement?,
expectedTypes: Array<out Class<out UElement>>
): Sequence<UElement> = expectedTypes.accommodate(
alternative uParam@{
val ownerFunction = element.ownerFunction as? KtFunction ?: return@uParam null
val lightMethod = LightClassUtil.getLightClassMethod(ownerFunction) ?: return@uParam null
val lightParameter = lightMethod.parameterList.parameters.find { it.name == element.name } ?: return@uParam null
KotlinUParameter(lightParameter, element, givenParent)
},
*convertToPropertyAlternatives(LightClassUtil.getLightClassPropertyMethods(element), givenParent)
)
fun convertClassOrObject(
element: KtClassOrObject,
givenParent: UElement?,
expectedTypes: Array<out Class<out UElement>>
): Sequence<UElement> {
val ktLightClass = element.toLightClass() ?: return emptySequence()
val uClass = KotlinUClass.create(ktLightClass, givenParent)
return expectedTypes.accommodate(
alternative { uClass },
alternative primaryConstructor@{
val primaryConstructor = element.primaryConstructor ?: return@primaryConstructor null
uClass.methods.asSequence()
.filter { it.sourcePsi == primaryConstructor }
.firstOrNull()
}
} ?: methods.getter?.let { getter ->
convertDeclaration(getter, givenParent, requiredType)
}
)
}
fun convertKtFile(
element: KtFile,
givenParent: UElement?,
requiredTypes: Array<out Class<out UElement>>
): Sequence<UElement> = requiredTypes.accommodate(
alternative { KotlinUFile(element) },
alternative { element.findFacadeClass()?.let { KotlinUClass.create(it, givenParent) } }
)
internal fun convertOrEmpty(expression: KtExpression?, parent: UElement?): UExpression {
return expression?.let { convertExpression(it, parent, null) } ?: UastEmptyExpression
return expression?.let { convertExpression(it, parent, DEFAULT_EXPRESSION_TYPES_LIST) } ?: 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, DEFAULT_EXPRESSION_TYPES_LIST) else null
}
internal fun KtPsiFactory.createAnalyzableExpression(text: String, context: PsiElement): KtExpression =
@@ -571,3 +648,22 @@ private fun convertVariablesDeclaration(
}
val kotlinUastPlugin get() = UastLanguagePlugin.getInstances().find { it.language == KotlinLanguage.INSTANCE } ?: KotlinUastLanguagePlugin()
private fun expressionTypes(requiredType: Class<out UElement>?) = requiredType?.let { arrayOf(it) } ?: DEFAULT_EXPRESSION_TYPES_LIST
private fun elementTypes(requiredType: Class<out UElement>?) = requiredType?.let { arrayOf(it) } ?: DEFAULT_TYPES_LIST
private fun <T : UElement> Array<out Class<out T>>.nonEmptyOr(default: Array<out Class<out UElement>>) = takeIf { it.isNotEmpty() }
?: default
private fun <U : UElement> Array<out Class<out UElement>>.accommodate(vararg makers: UElementAlternative<out U>): Sequence<UElement> {
val makersSeq = makers.asSequence()
return this.asSequence()
.flatMap { requiredType -> makersSeq.filter { requiredType.isAssignableFrom(it.uType) } }
.distinct()
.mapNotNull { it.make.invoke() }
}
private inline fun <reified U : UElement> alternative(noinline make: () -> U?) = UElementAlternative(U::class.java, make)
private class UElementAlternative<U : UElement>(val uType: Class<U>, val make: () -> U?)
@@ -19,16 +19,13 @@ package org.jetbrains.uast.kotlin
import com.intellij.lang.Language
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.registry.Registry
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.elements.*
import org.jetbrains.kotlin.asJava.findFacadeClass
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.LanguageVersionSettings
@@ -42,7 +39,6 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.uast.*
import org.jetbrains.uast.expressions.UInjectionHost
import org.jetbrains.uast.kotlin.KotlinConverter.convertDeclaration
import org.jetbrains.uast.kotlin.KotlinConverter.convertDeclarationOrElement
import org.jetbrains.uast.kotlin.declarations.KotlinUIdentifier
@@ -79,15 +75,15 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
override fun convertElement(element: PsiElement, parent: UElement?, requiredType: Class<out UElement>?): UElement? {
if (!element.isJvmElement) return null
return convertDeclarationOrElement(element, parent, elementTypes(requiredType))
return convertDeclarationOrElement(element, parent, requiredType)
}
override fun convertElementWithParent(element: PsiElement, requiredType: Class<out UElement>?): UElement? {
if (!element.isJvmElement) return null
if (element is PsiFile) return convertDeclaration(element, null, elementTypes(requiredType))
if (element is KtLightClassForFacade) return convertDeclaration(element, null, elementTypes(requiredType))
if (element is PsiFile) return convertDeclaration(element, null, requiredType)
if (element is KtLightClassForFacade) return convertDeclaration(element, null, requiredType)
return convertDeclarationOrElement(element, null, elementTypes(requiredType))
return convertDeclarationOrElement(element, null, requiredType)
}
override fun getMethodCallExpression(
@@ -140,45 +136,16 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
else -> false
}
}
@Suppress("UNCHECKED_CAST")
fun <T : UElement> convertElement(element: PsiElement, parent: UElement?, expectedTypes: Array<out Class<out T>>): T? {
if (!element.isJvmElement) return null
val nonEmptyExpectedTypes = expectedTypes.nonEmptyOr(DEFAULT_TYPES_LIST)
return (convertDeclaration(element, parent, nonEmptyExpectedTypes)
?: KotlinConverter.convertPsiElement(element, parent, nonEmptyExpectedTypes)) as? T
}
override fun <T : UElement> convertElementWithParent(element: PsiElement, requiredTypes: Array<out Class<out T>>): T? {
return convertElement(element, null, requiredTypes)
}
@Suppress("UNCHECKED_CAST")
override fun <T : UElement> convertToAlternatives(element: PsiElement, requiredTypes: Array<out Class<out T>>): Sequence<T> =
if (!element.isJvmElement) emptySequence() else when {
element is KtFile -> KotlinConverter.convertKtFile(element, null, requiredTypes) as Sequence<T>
(element is KtProperty && !element.isLocal) ->
KotlinConverter.convertNonLocalProperty(element, null, requiredTypes) as Sequence<T>
element is KtParameter -> KotlinConverter.convertParameter(element, null, requiredTypes) as Sequence<T>
element is KtClassOrObject -> KotlinConverter.convertClassOrObject(element, null, requiredTypes) as Sequence<T>
else -> sequenceOf(convertElementWithParent(element, requiredTypes.nonEmptyOr(DEFAULT_TYPES_LIST)) as? T).filterNotNull()
}
}
internal inline fun <reified ActualT : UElement> Class<*>?.el(f: () -> UElement?): UElement? {
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 ActualT : UElement> Array<out Class<out UElement>>.el(f: () -> UElement?): UElement? {
return if (isAssignableFrom(ActualT::class.java)) 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 inline fun <reified ActualT : UElement> Array<out Class<out UElement>>.expr(f: () -> UExpression?): UExpression? {
return if (isAssignableFrom(ActualT::class.java)) f() else null
}
internal fun Array<out Class<out UElement>>.isAssignableFrom(cls: Class<*>) = any { it.isAssignableFrom(cls) }
internal object KotlinConverter {
@@ -199,13 +166,12 @@ internal object KotlinConverter {
internal fun convertPsiElement(element: PsiElement?,
givenParent: UElement?,
expectedTypes: Array<out Class<out UElement>>
): UElement? {
requiredType: Class<out UElement>?): UElement? {
fun <P : PsiElement> build(ctor: (P, UElement?) -> UElement): () -> UElement? {
return { ctor(element as P, givenParent) }
}
return with (expectedTypes) { when (element) {
return with (requiredType) { when (element) {
is KtParameterList -> el<UDeclarationsExpression> {
val declarationsExpression = KotlinUDeclarationsExpression(givenParent)
declarationsExpression.apply {
@@ -218,7 +184,11 @@ internal object KotlinConverter {
is KtCatchClause -> el<UCatchClause>(build(::KotlinUCatchClause))
is KtVariableDeclaration ->
if (element is KtProperty && !element.isLocal) {
convertNonLocalProperty(element, givenParent, this).firstOrNull()
el<UField> {
LightClassUtil.getLightClassBackingField(element)?.let {
KotlinUField(it, element, givenParent)
}
}
}
else {
el<UVariable> {
@@ -226,19 +196,19 @@ internal object KotlinConverter {
}
}
is KtExpression -> KotlinConverter.convertExpression(element, givenParent, expectedTypes)
is KtLambdaArgument -> element.getLambdaExpression()?.let { KotlinConverter.convertExpression(it, givenParent, expectedTypes) }
is KtExpression -> KotlinConverter.convertExpression(element, givenParent, requiredType)
is KtLambdaArgument -> element.getLambdaExpression()?.let { KotlinConverter.convertExpression(it, givenParent, requiredType) }
is KtLightElementBase -> {
val expression = element.kotlinOrigin
when (expression) {
is KtExpression -> KotlinConverter.convertExpression(expression, givenParent, expectedTypes)
is KtExpression -> KotlinConverter.convertExpression(expression, givenParent, requiredType)
else -> el<UExpression> { UastEmptyExpression(givenParent) }
}
}
is KtLiteralStringTemplateEntry, is KtEscapeStringTemplateEntry -> el<ULiteralExpression>(build(::KotlinStringULiteralExpression))
is KtStringTemplateEntry -> element.expression?.let { convertExpression(it, givenParent, expectedTypes) } ?: expr<UExpression> { UastEmptyExpression }
is KtStringTemplateEntry -> element.expression?.let { convertExpression(it, givenParent, requiredType) } ?: expr<UExpression> { UastEmptyExpression }
is KtWhenEntry -> el<USwitchClauseExpressionWithBody>(build(::KotlinUSwitchEntry))
is KtWhenCondition -> convertWhenCondition(element, givenParent, expectedTypes)
is KtWhenCondition -> convertWhenCondition(element, givenParent, requiredType)
is KtTypeReference -> el<UTypeReferenceExpression> { LazyKotlinUTypeReferenceExpression(element, givenParent) }
is KtConstructorDelegationCall ->
el<UCallExpression> { KotlinUFunctionCallExpression(element, givenParent) }
@@ -276,8 +246,7 @@ internal object KotlinConverter {
internal fun convertEntry(entry: KtStringTemplateEntry,
givenParent: UElement?,
requiredType: Array<out Class<out UElement>>
): UExpression? {
requiredType: Class<out UElement>? = null): UExpression? {
return with(requiredType) {
if (entry is KtStringTemplateEntryWithExpression) {
expr<UExpression> {
@@ -295,16 +264,9 @@ internal object KotlinConverter {
}
}
var forceUInjectionHost = Registry.`is`("kotlin.uast.force.uinjectionhost", false)
@TestOnly
set(value) {
field = value
}
internal fun convertExpression(expression: KtExpression,
givenParent: UElement?,
requiredType: Array<out Class<out UElement>>
): UExpression? {
requiredType: Class<out UElement>? = null): UExpression? {
fun <P : PsiElement> build(ctor: (P, UElement?) -> UExpression): () -> UExpression? {
return { ctor(expression as P, givenParent) }
}
@@ -314,16 +276,13 @@ internal object KotlinConverter {
is KtStringTemplateExpression -> {
when {
forceUInjectionHost || requiredType.contains(UInjectionHost::class.java) ->
expr<UInjectionHost> { KotlinStringTemplateUPolyadicExpression(expression, givenParent) }
expression.entries.isEmpty() -> {
expr<ULiteralExpression> { KotlinStringULiteralExpression(expression, givenParent, "") }
}
expression.entries.size == 1 -> convertEntry(expression.entries[0], givenParent, requiredType)
else ->
expr<KotlinStringTemplateUPolyadicExpression> { KotlinStringTemplateUPolyadicExpression(expression, givenParent) }
else -> {
expr<UExpression> { KotlinStringTemplateUPolyadicExpression(expression, givenParent) }
}
}
}
is KtDestructuringDeclaration -> expr<UDeclarationsExpression> {
@@ -396,7 +355,7 @@ internal object KotlinConverter {
internal fun convertWhenCondition(condition: KtWhenCondition,
givenParent: UElement?,
requiredType: Array<out Class<out UElement>>
requiredType: Class<out UElement>? = null
): UExpression? {
return with(requiredType) {
when (condition) {
@@ -446,7 +405,7 @@ internal object KotlinConverter {
internal fun convertDeclaration(
element: PsiElement,
givenParent: UElement?,
expectedTypes: Array<out Class<out UElement>>
requiredType: Class<out UElement>?
): UElement? {
fun <P : PsiElement> build(ctor: (P, UElement?) -> UElement): () -> UElement? = { ctor(element as P, givenParent) }
@@ -457,7 +416,7 @@ internal object KotlinConverter {
{ ctor(element as P, ktElement, givenParent) }
val original = element.originalElement
return with(expectedTypes) {
return with(requiredType) {
when (original) {
is KtLightMethod -> el<UMethod>(build(KotlinUMethod.Companion::create)) // .Companion is needed because of KT-13934
is KtLightClass -> when (original.kotlinOrigin) {
@@ -475,7 +434,11 @@ internal object KotlinConverter {
is KtEnumEntry -> el<UEnumConstant> {
convertEnumEntry(original, givenParent)
}
is KtClassOrObject -> convertClassOrObject(original, givenParent, this).firstOrNull()
is KtClassOrObject -> el<UClass> {
original.toLightClass()?.let { lightClass ->
KotlinUClass.create(lightClass, givenParent)
}
}
is KtFunction ->
if (original.isLocal) {
el<ULambdaExpression> {
@@ -484,41 +447,49 @@ internal object KotlinConverter {
KotlinULambdaExpression(parent, givenParent) // your parent is the ULambdaExpression
} else if (original.name.isNullOrEmpty()) {
createLocalFunctionLambdaExpression(original, givenParent)
} else {
}
else {
val uDeclarationsExpression = createLocalFunctionDeclaration(original, givenParent)
val localFunctionVar = uDeclarationsExpression.declarations.single() as KotlinLocalFunctionUVariable
localFunctionVar.uastInitializer
}
}
} else {
}
else {
el<UMethod> {
val lightMethod = LightClassUtil.getLightClassMethod(original) ?: return null
convertDeclaration(lightMethod, givenParent, expectedTypes)
convertDeclaration(lightMethod, givenParent, requiredType)
}
}
is KtPropertyAccessor -> el<UMethod> {
val lightMethod = LightClassUtil.getLightClassAccessorMethod(original) ?: return null
convertDeclaration(lightMethod, givenParent, expectedTypes)
convertDeclaration(lightMethod, givenParent, requiredType)
}
is KtProperty ->
if (original.isLocal) {
KotlinConverter.convertPsiElement(element, givenParent, expectedTypes)
} else {
convertNonLocalProperty(original, givenParent, expectedTypes).firstOrNull()
KotlinConverter.convertPsiElement(element, givenParent, requiredType)
}
else {
convertNonLocalProperty(original, givenParent, requiredType)
}
is KtParameter -> convertParameter(original, givenParent, this).firstOrNull()
is KtParameter -> el<UParameter> {
val ownerFunction = original.ownerFunction as? KtFunction ?: return null
val lightMethod = LightClassUtil.getLightClassMethod(ownerFunction) ?: return null
val lightParameter = lightMethod.parameterList.parameters.find { it.name == original.name } ?: return null
KotlinUParameter(lightParameter, original, givenParent)
}
is KtFile -> convertKtFile(original, givenParent, this).firstOrNull()
is KtFile -> el<UFile> { KotlinUFile(original) }
is FakeFileForLightClass -> el<UFile> { KotlinUFile(original.navigationElement) }
is KtAnnotationEntry -> el<UAnnotation>(build(::KotlinUAnnotation))
is KtCallExpression ->
if (expectedTypes.isAssignableFrom(KotlinUNestedAnnotation::class.java) && !expectedTypes.isAssignableFrom(UCallExpression::class.java)) {
if (requiredType != null && UAnnotation::class.java.isAssignableFrom(requiredType)) {
el<UAnnotation> { KotlinUNestedAnnotation.tryCreate(original, givenParent) }
} else null
is KtLightAnnotationForSourceEntry -> convertDeclarationOrElement(original.kotlinOrigin, givenParent, expectedTypes)
is KtLightAnnotationForSourceEntry -> convertDeclarationOrElement(original.kotlinOrigin, givenParent, requiredType)
is KtDelegatedSuperTypeEntry -> el<KotlinSupertypeDelegationUExpression> {
KotlinSupertypeDelegationUExpression(original, givenParent)
}
@@ -528,21 +499,17 @@ internal object KotlinConverter {
}
fun convertDeclarationOrElement(
element: PsiElement,
givenParent: UElement?,
expectedTypes: Array<out Class<out UElement>>
): UElement? {
fun convertDeclarationOrElement(element: PsiElement, givenParent: UElement?, requiredType: Class<out UElement>?): UElement? {
if (element is UElement) return element
if (element.isValid) {
element.getUserData(KOTLIN_CACHED_UELEMENT_KEY)?.get()?.let { cachedUElement ->
return if (expectedTypes.isAssignableFrom(cachedUElement.javaClass)) cachedUElement else null
return if (requiredType == null || requiredType.isInstance(cachedUElement)) cachedUElement else null
}
}
val uElement = convertDeclaration(element, givenParent, expectedTypes)
?: KotlinConverter.convertPsiElement(element, givenParent, expectedTypes)
val uElement = convertDeclaration(element, givenParent, requiredType)
?: KotlinConverter.convertPsiElement(element, givenParent, requiredType)
/*
if (uElement != null) {
element.putUserData(KOTLIN_CACHED_UELEMENT_KEY, WeakReference(uElement))
@@ -551,71 +518,27 @@ internal object KotlinConverter {
return uElement
}
private fun convertToPropertyAlternatives(
methods: LightClassUtil.PropertyAccessorsPsiMethods?,
givenParent: UElement?
): Array<UElementAlternative<*>> = if (methods != null) arrayOf(
alternative { methods.backingField?.let { KotlinUField(it, (it as? KtLightElement<*, *>)?.kotlinOrigin, givenParent) } },
alternative { methods.getter?.let { convertDeclaration(it, givenParent, arrayOf(UMethod::class.java)) as? UMethod } },
alternative { methods.setter?.let { convertDeclaration(it, givenParent, arrayOf(UMethod::class.java)) as? UMethod } }
) else emptyArray()
fun convertNonLocalProperty(
private fun convertNonLocalProperty(
property: KtProperty,
givenParent: UElement?,
expectedTypes: Array<out Class<out UElement>>
): Sequence<UElement> =
expectedTypes.accommodate(*convertToPropertyAlternatives(LightClassUtil.getLightClassPropertyMethods(property), givenParent))
fun convertParameter(
element: KtParameter,
givenParent: UElement?,
expectedTypes: Array<out Class<out UElement>>
): Sequence<UElement> = expectedTypes.accommodate(
alternative uParam@{
val ownerFunction = element.ownerFunction as? KtFunction ?: return@uParam null
val lightMethod = LightClassUtil.getLightClassMethod(ownerFunction) ?: return@uParam null
val lightParameter = lightMethod.parameterList.parameters.find { it.name == element.name } ?: return@uParam null
KotlinUParameter(lightParameter, element, givenParent)
},
*convertToPropertyAlternatives(LightClassUtil.getLightClassPropertyMethods(element), givenParent)
)
fun convertClassOrObject(
element: KtClassOrObject,
givenParent: UElement?,
expectedTypes: Array<out Class<out UElement>>
): Sequence<UElement> {
val ktLightClass = element.toLightClass() ?: return emptySequence()
val uClass = KotlinUClass.create(ktLightClass, givenParent)
return expectedTypes.accommodate(
alternative { uClass },
alternative primaryConstructor@{
val primaryConstructor = element.primaryConstructor ?: return@primaryConstructor null
uClass.methods.asSequence()
.filter { it.sourcePsi == primaryConstructor }
.firstOrNull()
requiredType: Class<out UElement>?
): UElement? {
val methods = LightClassUtil.getLightClassPropertyMethods(property)
return methods.backingField?.let { backingField ->
with(requiredType) {
el<UField> { KotlinUField(backingField, (backingField as? KtLightElement<*,*>)?.kotlinOrigin, givenParent) }
}
)
} ?: methods.getter?.let { getter ->
convertDeclaration(getter, givenParent, requiredType)
}
}
fun convertKtFile(
element: KtFile,
givenParent: UElement?,
requiredTypes: Array<out Class<out UElement>>
): Sequence<UElement> = requiredTypes.accommodate(
alternative { KotlinUFile(element) },
alternative { element.findFacadeClass()?.let { KotlinUClass.create(it, givenParent) } }
)
internal fun convertOrEmpty(expression: KtExpression?, parent: UElement?): UExpression {
return expression?.let { convertExpression(it, parent, DEFAULT_EXPRESSION_TYPES_LIST) } ?: UastEmptyExpression
return expression?.let { convertExpression(it, parent, null) } ?: UastEmptyExpression
}
internal fun convertOrNull(expression: KtExpression?, parent: UElement?): UExpression? {
return if (expression != null) convertExpression(expression, parent, DEFAULT_EXPRESSION_TYPES_LIST) else null
return if (expression != null) convertExpression(expression, parent, null) else null
}
internal fun KtPsiFactory.createAnalyzableExpression(text: String, context: PsiElement): KtExpression =
@@ -648,22 +571,3 @@ private fun convertVariablesDeclaration(
}
val kotlinUastPlugin get() = UastLanguagePlugin.getInstances().find { it.language == KotlinLanguage.INSTANCE } ?: KotlinUastLanguagePlugin()
private fun expressionTypes(requiredType: Class<out UElement>?) = requiredType?.let { arrayOf(it) } ?: DEFAULT_EXPRESSION_TYPES_LIST
private fun elementTypes(requiredType: Class<out UElement>?) = requiredType?.let { arrayOf(it) } ?: DEFAULT_TYPES_LIST
private fun <T : UElement> Array<out Class<out T>>.nonEmptyOr(default: Array<out Class<out UElement>>) = takeIf { it.isNotEmpty() }
?: default
private fun <U : UElement> Array<out Class<out UElement>>.accommodate(vararg makers: UElementAlternative<out U>): Sequence<UElement> {
val makersSeq = makers.asSequence()
return this.asSequence()
.flatMap { requiredType -> makersSeq.filter { requiredType.isAssignableFrom(it.uType) } }
.distinct()
.mapNotNull { it.make.invoke() }
}
private inline fun <reified U : UElement> alternative(noinline make: () -> U?) = UElementAlternative(U::class.java, make)
private class UElementAlternative<U : UElement>(val uType: Class<U>, val make: () -> U?)
@@ -107,7 +107,7 @@ open class KotlinUMethod(
KotlinUBlockExpression.KotlinLazyUBlockExpression(this, { block ->
val implicitReturn = KotlinUImplicitReturnExpression(block)
val uBody = getLanguagePlugin().convertElement(bodyExpression, implicitReturn) as? UExpression
?: return@KotlinLazyUBlockExpression emptyList()
?: return@KotlinLazyUBlockExpression emptyList()
listOf(implicitReturn.apply { returnExpression = uBody })
})
@@ -123,6 +123,12 @@ open class KotlinUMethod(
override fun getOriginalElement(): PsiElement? = super<UAnnotationMethod>.getOriginalElement()
override val returnTypeReference: UTypeReferenceExpression? by lz {
(sourcePsi as? KtCallableDeclaration)?.typeReference?.let {
LazyKotlinUTypeReferenceExpression(it, this) { javaPsi.returnType ?: UastErrorType }
}
}
override fun equals(other: Any?) = other is KotlinUMethod && psi == other.psi
companion object {
@@ -107,7 +107,7 @@ open class KotlinUMethod(
KotlinUBlockExpression.KotlinLazyUBlockExpression(this, { block ->
val implicitReturn = KotlinUImplicitReturnExpression(block)
val uBody = getLanguagePlugin().convertElement(bodyExpression, implicitReturn) as? UExpression
?: return@KotlinLazyUBlockExpression emptyList()
?: return@KotlinLazyUBlockExpression emptyList()
listOf(implicitReturn.apply { returnExpression = uBody })
})
@@ -123,12 +123,6 @@ open class KotlinUMethod(
override fun getOriginalElement(): PsiElement? = super<UAnnotationMethod>.getOriginalElement()
override val returnTypeReference: UTypeReferenceExpression? by lz {
(sourcePsi as? KtCallableDeclaration)?.typeReference?.let {
LazyKotlinUTypeReferenceExpression(it, this) { javaPsi.returnType ?: UastErrorType }
}
}
override fun equals(other: Any?) = other is KotlinUMethod && psi == other.psi
companion object {
@@ -9,6 +9,7 @@ import org.jetbrains.uast.evaluation.UEvaluationState
import org.jetbrains.uast.kotlin.KotlinBinaryOperators
import org.jetbrains.uast.kotlin.KotlinPostfixOperators
import org.jetbrains.uast.values.*
import org.jetbrains.uast.evaluation.to
class KotlinEvaluatorExtension : AbstractEvaluatorExtension(KotlinLanguage.INSTANCE) {
@@ -9,7 +9,6 @@ import org.jetbrains.uast.evaluation.UEvaluationState
import org.jetbrains.uast.kotlin.KotlinBinaryOperators
import org.jetbrains.uast.kotlin.KotlinPostfixOperators
import org.jetbrains.uast.values.*
import org.jetbrains.uast.evaluation.to
class KotlinEvaluatorExtension : AbstractEvaluatorExtension(KotlinLanguage.INSTANCE) {
@@ -67,7 +67,7 @@ private fun createElvisExpressions(
override val sourcePsi: PsiElement? = null
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, DEFAULT_EXPRESSION_TYPES_LIST) }
override val isTernary: Boolean = false
override val annotations: List<UAnnotation> = emptyList()
override val ifIdentifier: UIdentifier = KotlinUIdentifier(null, this)
@@ -67,7 +67,7 @@ private fun createElvisExpressions(
override val sourcePsi: PsiElement? = null
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, DEFAULT_EXPRESSION_TYPES_LIST) }
override val elseExpression: UExpression? by lz { KotlinConverter.convertExpression(right, this ) }
override val isTernary: Boolean = false
override val annotations: List<UAnnotation> = emptyList()
override val ifIdentifier: UIdentifier = KotlinUIdentifier(null, this)
@@ -16,19 +16,33 @@
package org.jetbrains.uast.kotlin
import com.intellij.psi.PsiLanguageInjectionHost
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.UPolyadicExpression
import org.jetbrains.uast.UastBinaryOperator
import org.jetbrains.uast.*
import org.jetbrains.uast.expressions.UInjectionHost
class KotlinStringTemplateUPolyadicExpression(
override val psi: KtStringTemplateExpression,
givenParent: UElement?
override val psi: KtStringTemplateExpression,
givenParent: UElement?
) : KotlinAbstractUExpression(givenParent),
UPolyadicExpression,
KotlinUElementWithType,
KotlinEvaluatableUElement {
override val operands: List<UExpression> by lz { psi.entries.map { KotlinConverter.convertEntry(it, this)!! } }
UPolyadicExpression,
KotlinUElementWithType,
KotlinEvaluatableUElement,
UInjectionHost {
override val operands: List<UExpression> by lz {
psi.entries.map {
KotlinConverter.convertEntry(
it,
this,
DEFAULT_EXPRESSION_TYPES_LIST
)!!
}
}
override val operator = UastBinaryOperator.PLUS
override val psiLanguageInjectionHost: PsiLanguageInjectionHost get() = psi
override val isString: Boolean get() = true
override fun asRenderString(): String = if (operands.isEmpty()) "\"\"" else super<UPolyadicExpression>.asRenderString()
override fun asLogString(): String = if (operands.isEmpty()) "UPolyadicExpression (value = \"\")" else super.asLogString()
}
@@ -0,0 +1,34 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.UPolyadicExpression
import org.jetbrains.uast.UastBinaryOperator
class KotlinStringTemplateUPolyadicExpression(
override val psi: KtStringTemplateExpression,
givenParent: UElement?
) : KotlinAbstractUExpression(givenParent),
UPolyadicExpression,
KotlinUElementWithType,
KotlinEvaluatableUElement {
override val operands: List<UExpression> by lz { psi.entries.map { KotlinConverter.convertEntry(it, this)!! } }
override val operator = UastBinaryOperator.PLUS
}
@@ -1,48 +0,0 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.uast.kotlin
import com.intellij.psi.PsiLanguageInjectionHost
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
import org.jetbrains.uast.*
import org.jetbrains.uast.expressions.UInjectionHost
class KotlinStringTemplateUPolyadicExpression(
override val psi: KtStringTemplateExpression,
givenParent: UElement?
) : KotlinAbstractUExpression(givenParent),
UPolyadicExpression,
KotlinUElementWithType,
KotlinEvaluatableUElement,
UInjectionHost {
override val operands: List<UExpression> by lz {
psi.entries.map {
KotlinConverter.convertEntry(
it,
this,
DEFAULT_EXPRESSION_TYPES_LIST
)!!
}
}
override val operator = UastBinaryOperator.PLUS
override val psiLanguageInjectionHost: PsiLanguageInjectionHost get() = psi
override val isString: Boolean get() = true
override fun asRenderString(): String = if (operands.isEmpty()) "\"\"" else super<UPolyadicExpression>.asRenderString()
override fun asLogString(): String = if (operands.isEmpty()) "UPolyadicExpression (value = \"\")" else super.asLogString()
}
@@ -20,10 +20,7 @@ import com.intellij.psi.PsiNamedElement
import com.intellij.psi.ResolveResult
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
import org.jetbrains.kotlin.resolve.BindingContext.DOUBLE_COLON_LHS
import org.jetbrains.uast.UCallableReferenceExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.UMultiResolvable
import org.jetbrains.uast.*
import org.jetbrains.uast.kotlin.internal.getResolveResultVariants
class KotlinUCallableReferenceExpression(
@@ -34,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, DEFAULT_EXPRESSION_TYPES_LIST)
}
override val qualifierType by lz {
@@ -20,7 +20,10 @@ import com.intellij.psi.PsiNamedElement
import com.intellij.psi.ResolveResult
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
import org.jetbrains.kotlin.resolve.BindingContext.DOUBLE_COLON_LHS
import org.jetbrains.uast.*
import org.jetbrains.uast.UCallableReferenceExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.UMultiResolvable
import org.jetbrains.uast.kotlin.internal.getResolveResultVariants
class KotlinUCallableReferenceExpression(
@@ -31,7 +34,7 @@ class KotlinUCallableReferenceExpression(
get() {
if (qualifierType != null) return null
val receiverExpression = psi.receiverExpression ?: return null
return KotlinConverter.convertExpression(receiverExpression, this, DEFAULT_EXPRESSION_TYPES_LIST)
return KotlinConverter.convertExpression(receiverExpression, this)
}
override val qualifierType by lz {
@@ -18,6 +18,7 @@ package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtClassLiteralExpression
import org.jetbrains.kotlin.resolve.BindingContext.DOUBLE_COLON_LHS
import org.jetbrains.uast.DEFAULT_EXPRESSION_TYPES_LIST
import org.jetbrains.uast.UClassLiteralExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
@@ -35,6 +36,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, DEFAULT_EXPRESSION_TYPES_LIST)
}
}
@@ -18,7 +18,6 @@ package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtClassLiteralExpression
import org.jetbrains.kotlin.resolve.BindingContext.DOUBLE_COLON_LHS
import org.jetbrains.uast.DEFAULT_EXPRESSION_TYPES_LIST
import org.jetbrains.uast.UClassLiteralExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
@@ -36,6 +35,6 @@ class KotlinUClassLiteralExpression(
get() {
if (type != null) return null
val receiverExpression = psi.receiverExpression ?: return null
return KotlinConverter.convertExpression(receiverExpression, this, DEFAULT_EXPRESSION_TYPES_LIST)
return KotlinConverter.convertExpression(receiverExpression, this)
}
}
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.psi.KtObjectLiteralExpression
import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.uast.*
import org.jetbrains.uast.kotlin.declarations.KotlinUIdentifier
import org.jetbrains.uast.kotlin.internal.DelegatedMultiResolve
class KotlinUObjectLiteralExpression(
@@ -82,7 +83,10 @@ class KotlinUObjectLiteralExpression(
get() = identifier
override val identifier: String
get() = psi.name ?: "<error>"
get() = psi.name ?: referenceNameElement.sourcePsi?.text ?: "<error>"
override val referenceNameElement: UElement
get() = KotlinUIdentifier(psi.typeReference?.nameElement, this)
}
}
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.psi.KtObjectLiteralExpression
import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.uast.*
import org.jetbrains.uast.kotlin.declarations.KotlinUIdentifier
import org.jetbrains.uast.kotlin.internal.DelegatedMultiResolve
class KotlinUObjectLiteralExpression(
@@ -83,10 +82,7 @@ class KotlinUObjectLiteralExpression(
get() = identifier
override val identifier: String
get() = psi.name ?: referenceNameElement.sourcePsi?.text ?: "<error>"
override val referenceNameElement: UElement
get() = KotlinUIdentifier(psi.typeReference?.nameElement, this)
get() = psi.name ?: "<error>"
}
}
@@ -18,6 +18,7 @@ package org.jetbrains.uast.kotlin
import com.intellij.psi.PsiNamedElement
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
import org.jetbrains.uast.UCallExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UQualifiedReferenceExpression
import org.jetbrains.uast.UastQualifiedExpressionAccessType
@@ -36,4 +37,10 @@ class KotlinUQualifiedReferenceExpression(
override val resolvedName: String?
get() = (resolve() as? PsiNamedElement)?.name
override val referenceNameElement: UElement?
get() = when (val selector = selector) {
is UCallExpression -> selector.methodIdentifier
else -> super.referenceNameElement
}
}
@@ -18,7 +18,6 @@ package org.jetbrains.uast.kotlin
import com.intellij.psi.PsiNamedElement
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
import org.jetbrains.uast.UCallExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UQualifiedReferenceExpression
import org.jetbrains.uast.UastQualifiedExpressionAccessType
@@ -37,10 +36,4 @@ class KotlinUQualifiedReferenceExpression(
override val resolvedName: String?
get() = (resolve() as? PsiNamedElement)?.name
override val referenceNameElement: UElement?
get() = when (val selector = selector) {
is UCallExpression -> selector.methodIdentifier
else -> super.referenceNameElement
}
}
@@ -71,6 +71,8 @@ open class KotlinUSimpleReferenceExpression(
visitor.afterVisitSimpleNameReferenceExpression(this)
}
override val referenceNameElement: UElement? by lz { psi.getIdentifier()?.toUElement() }
private fun visitAccessorCalls(visitor: UastVisitor) {
// Visit Kotlin get-set synthetic Java property calls as function calls
val bindingContext = psi.analyze()
@@ -71,8 +71,6 @@ open class KotlinUSimpleReferenceExpression(
visitor.afterVisitSimpleNameReferenceExpression(this)
}
override val referenceNameElement: UElement? by lz { psi.getIdentifier()?.toUElement() }
private fun visitAccessorCalls(visitor: UastVisitor) {
// Visit Kotlin get-set synthetic Java property calls as function calls
val bindingContext = psi.analyze()
@@ -54,7 +54,7 @@ class KotlinUSwitchEntry(
givenParent: UElement?
) : KotlinAbstractUExpression(givenParent), USwitchClauseExpressionWithBody {
override val caseValues by lz {
psi.conditions.map { KotlinConverter.convertWhenCondition(it, this) ?: UastEmptyExpression }
psi.conditions.map { KotlinConverter.convertWhenCondition(it, this, DEFAULT_EXPRESSION_TYPES_LIST) ?: UastEmptyExpression }
}
override val body: UExpressionList by lz {
@@ -54,7 +54,7 @@ class KotlinUSwitchEntry(
givenParent: UElement?
) : KotlinAbstractUExpression(givenParent), USwitchClauseExpressionWithBody {
override val caseValues by lz {
psi.conditions.map { KotlinConverter.convertWhenCondition(it, this, DEFAULT_EXPRESSION_TYPES_LIST) ?: UastEmptyExpression }
psi.conditions.map { KotlinConverter.convertWhenCondition(it, this) ?: UastEmptyExpression }
}
override val body: UExpressionList by lz {
@@ -17,10 +17,7 @@
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtTryExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UIdentifier
import org.jetbrains.uast.UTryExpression
import org.jetbrains.uast.UVariable
import org.jetbrains.uast.*
import org.jetbrains.uast.kotlin.declarations.KotlinUIdentifier
class KotlinUTryExpression(
@@ -29,7 +26,15 @@ class KotlinUTryExpression(
) : KotlinAbstractUExpression(givenParent), 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,
DEFAULT_EXPRESSION_TYPES_LIST
)
}
}
override val resourceVariables: List<UVariable>
get() = emptyList()
@@ -17,7 +17,10 @@
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtTryExpression
import org.jetbrains.uast.*
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UIdentifier
import org.jetbrains.uast.UTryExpression
import org.jetbrains.uast.UVariable
import org.jetbrains.uast.kotlin.declarations.KotlinUIdentifier
class KotlinUTryExpression(
@@ -26,15 +29,7 @@ class KotlinUTryExpression(
) : KotlinAbstractUExpression(givenParent), 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,
DEFAULT_EXPRESSION_TYPES_LIST
)
}
}
override val finallyClause by lz { psi.finallyBlock?.finalExpression?.let { KotlinConverter.convertExpression(it, this) } }
override val resourceVariables: List<UVariable>
get() = emptyList()
@@ -1,7 +1,7 @@
Test -> UAnnotation (fqName = null)
A -> UClass (name = A)
MyAnnotation -> UClass (name = MyAnnotation)
text -> [!] UnknownKotlinExpression (VALUE_PARAMETER)
text -> UAnnotationMethod (name = text)
String -> USimpleNameReferenceExpression (identifier = String)
MyAnnotation -> UAnnotation (fqName = MyAnnotation)
B -> UClass (name = B)
@@ -1,7 +1,7 @@
Test -> UAnnotation (fqName = null)
A -> UClass (name = A)
MyAnnotation -> UClass (name = MyAnnotation)
text -> UAnnotationMethod (name = text)
text -> [!] UnknownKotlinExpression (VALUE_PARAMETER)
String -> USimpleNameReferenceExpression (identifier = String)
MyAnnotation -> UAnnotation (fqName = MyAnnotation)
B -> UClass (name = B)
@@ -1,7 +1,12 @@
package org.jetbrains.uast.test.kotlin
import com.intellij.psi.PsiElement
import org.jetbrains.uast.*
import org.jetbrains.uast.test.common.UElementToParentMap
import org.jetbrains.uast.test.common.kotlin.IdentifiersTestBase
import org.jetbrains.uast.test.env.assertEqualsToFile
import java.io.File
import kotlin.test.assertNotNull
abstract class AbstractKotlinIdentifiersTest : AbstractKotlinUastTest(), IdentifiersTestBase {
@@ -11,5 +16,21 @@ abstract class AbstractKotlinIdentifiersTest : AbstractKotlinUastTest(), Identif
override fun getIdentifiersFile(testName: String): File = getTestFile(testName, "identifiers.txt")
override fun check(testName: String, file: UFile) {
super.check(testName, file)
assertEqualsToFile("refNames", getTestFile(testName, "refNames.txt"), file.asRefNames())
}
}
}
private fun refNameRetriever(psiElement: PsiElement): UElement? =
when (val uElement = psiElement.toUElementOfExpectedTypes(UCallExpression::class.java, UReferenceExpression::class.java)) {
is UReferenceExpression -> uElement.referenceNameElement
is UCallExpression -> uElement.classReference?.referenceNameElement
else -> null
}?.also {
assertNotNull(it.sourcePsi, "referenceNameElement should have physical source, origin = $psiElement")
}
fun UFile.asRefNames() = object : UElementToParentMap(::refNameRetriever) {
override fun renderSource(element: PsiElement): String = element.javaClass.simpleName
}.visitUFileAndGetResult(this)
@@ -0,0 +1,15 @@
package org.jetbrains.uast.test.kotlin
import org.jetbrains.uast.test.common.kotlin.IdentifiersTestBase
import java.io.File
abstract class AbstractKotlinIdentifiersTest : AbstractKotlinUastTest(), IdentifiersTestBase {
private fun getTestFile(testName: String, ext: String) =
File(File(AbstractKotlinUastTest.TEST_KOTLIN_MODEL_DIR, testName).canonicalPath + '.' + ext)
override fun getIdentifiersFile(testName: String): File = getTestFile(testName, "identifiers.txt")
}
@@ -1,36 +0,0 @@
package org.jetbrains.uast.test.kotlin
import com.intellij.psi.PsiElement
import org.jetbrains.uast.*
import org.jetbrains.uast.test.common.UElementToParentMap
import org.jetbrains.uast.test.common.kotlin.IdentifiersTestBase
import org.jetbrains.uast.test.env.assertEqualsToFile
import java.io.File
import kotlin.test.assertNotNull
abstract class AbstractKotlinIdentifiersTest : AbstractKotlinUastTest(), IdentifiersTestBase {
private fun getTestFile(testName: String, ext: String) =
File(File(AbstractKotlinUastTest.TEST_KOTLIN_MODEL_DIR, testName).canonicalPath + '.' + ext)
override fun getIdentifiersFile(testName: String): File = getTestFile(testName, "identifiers.txt")
override fun check(testName: String, file: UFile) {
super.check(testName, file)
assertEqualsToFile("refNames", getTestFile(testName, "refNames.txt"), file.asRefNames())
}
}
private fun refNameRetriever(psiElement: PsiElement): UElement? =
when (val uElement = psiElement.toUElementOfExpectedTypes(UCallExpression::class.java, UReferenceExpression::class.java)) {
is UReferenceExpression -> uElement.referenceNameElement
is UCallExpression -> uElement.classReference?.referenceNameElement
else -> null
}?.also {
assertNotNull(it.sourcePsi, "referenceNameElement should have physical source, origin = $psiElement")
}
fun UFile.asRefNames() = object : UElementToParentMap(::refNameRetriever) {
override fun renderSource(element: PsiElement): String = element.javaClass.simpleName
}.visitUFileAndGetResult(this)
+22 -6
View File
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.sure
import org.jetbrains.uast.*
import org.jetbrains.uast.expressions.UInjectionHost
import org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin
import org.jetbrains.uast.test.env.kotlin.findElementByText
import org.jetbrains.uast.test.env.kotlin.findElementByTextFromPsi
@@ -216,21 +217,21 @@ class KotlinUastApiTest : AbstractKotlinUastTest() {
fun testWhenStringLiteral() {
doTest("WhenStringLiteral") { _, file ->
file.findElementByTextFromPsi<ULiteralExpression>("abc").let { literalExpression ->
file.findElementByTextFromPsi<UInjectionHost>("\"abc\"").let { literalExpression ->
val psi = literalExpression.psi!!
Assert.assertTrue(psi is KtLiteralStringTemplateEntry)
Assert.assertTrue(psi is KtStringTemplateExpression)
UsefulTestCase.assertInstanceOf(literalExpression.uastParent, USwitchClauseExpressionWithBody::class.java)
}
file.findElementByTextFromPsi<ULiteralExpression>("def").let { literalExpression ->
file.findElementByTextFromPsi<UInjectionHost>("\"def\"").let { literalExpression ->
val psi = literalExpression.psi!!
Assert.assertTrue(psi is KtLiteralStringTemplateEntry)
Assert.assertTrue(psi is KtStringTemplateExpression)
UsefulTestCase.assertInstanceOf(literalExpression.uastParent, USwitchClauseExpressionWithBody::class.java)
}
file.findElementByTextFromPsi<ULiteralExpression>("def1").let { literalExpression ->
file.findElementByTextFromPsi<UInjectionHost>("\"def1\"").let { literalExpression ->
val psi = literalExpression.psi!!
Assert.assertTrue(psi is KtLiteralStringTemplateEntry)
Assert.assertTrue(psi is KtStringTemplateExpression)
UsefulTestCase.assertInstanceOf(literalExpression.uastParent, UBlockExpression::class.java)
}
@@ -549,6 +550,21 @@ class KotlinUastApiTest : AbstractKotlinUastTest() {
}
}
@Test
fun testMethodReturnTypeReference() {
doTest("Elvis") { _, file ->
assertEquals(
"UTypeReferenceExpression (name = java.lang.String)",
file.findElementByTextFromPsi<UMethod>("fun foo(bar: String): String? = null").returnTypeReference?.asLogString()
)
assertEquals(
null,
file.findElementByTextFromPsi<UMethod>("fun bar() = 42").returnTypeReference?.asLogString()
)
}
}
@Test
fun testVariablesTypeReferences() {
doTest("TypeReferences") { _, file ->
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.sure
import org.jetbrains.uast.*
import org.jetbrains.uast.expressions.UInjectionHost
import org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin
import org.jetbrains.uast.test.env.kotlin.findElementByText
import org.jetbrains.uast.test.env.kotlin.findElementByTextFromPsi
@@ -217,21 +216,21 @@ class KotlinUastApiTest : AbstractKotlinUastTest() {
fun testWhenStringLiteral() {
doTest("WhenStringLiteral") { _, file ->
file.findElementByTextFromPsi<UInjectionHost>("\"abc\"").let { literalExpression ->
file.findElementByTextFromPsi<ULiteralExpression>("abc").let { literalExpression ->
val psi = literalExpression.psi!!
Assert.assertTrue(psi is KtStringTemplateExpression)
Assert.assertTrue(psi is KtLiteralStringTemplateEntry)
UsefulTestCase.assertInstanceOf(literalExpression.uastParent, USwitchClauseExpressionWithBody::class.java)
}
file.findElementByTextFromPsi<UInjectionHost>("\"def\"").let { literalExpression ->
file.findElementByTextFromPsi<ULiteralExpression>("def").let { literalExpression ->
val psi = literalExpression.psi!!
Assert.assertTrue(psi is KtStringTemplateExpression)
Assert.assertTrue(psi is KtLiteralStringTemplateEntry)
UsefulTestCase.assertInstanceOf(literalExpression.uastParent, USwitchClauseExpressionWithBody::class.java)
}
file.findElementByTextFromPsi<UInjectionHost>("\"def1\"").let { literalExpression ->
file.findElementByTextFromPsi<ULiteralExpression>("def1").let { literalExpression ->
val psi = literalExpression.psi!!
Assert.assertTrue(psi is KtStringTemplateExpression)
Assert.assertTrue(psi is KtLiteralStringTemplateEntry)
UsefulTestCase.assertInstanceOf(literalExpression.uastParent, UBlockExpression::class.java)
}
@@ -550,21 +549,6 @@ class KotlinUastApiTest : AbstractKotlinUastTest() {
}
}
@Test
fun testMethodReturnTypeReference() {
doTest("Elvis") { _, file ->
assertEquals(
"UTypeReferenceExpression (name = java.lang.String)",
file.findElementByTextFromPsi<UMethod>("fun foo(bar: String): String? = null").returnTypeReference?.asLogString()
)
assertEquals(
null,
file.findElementByTextFromPsi<UMethod>("fun bar() = 42").returnTypeReference?.asLogString()
)
}
}
@Test
fun testVariablesTypeReferences() {
doTest("TypeReferences") { _, file ->
@@ -9,7 +9,7 @@ import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.util.Disposer
import com.intellij.patterns.uast.literalExpression
import com.intellij.patterns.uast.injectionHostUExpression
import com.intellij.psi.*
import com.intellij.psi.impl.source.resolve.reference.PsiReferenceContributorEP
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry
@@ -35,7 +35,7 @@ class KotlinUastReferencesTest : KotlinLightCodeInsightFixtureTestCase() {
fun `test original getter is visible when reference is under renaming`() {
registerReferenceProviders(testRootDisposable) {
registerUastReferenceProvider(literalExpression(), uastLiteralReferenceProvider { _, psiLanguageInjectionHost ->
registerUastReferenceProvider(injectionHostUExpression(), uastInjectionHostReferenceProvider { _, psiLanguageInjectionHost ->
arrayOf(GetterReference("KotlinBean", psiLanguageInjectionHost))
})
}
@@ -9,7 +9,7 @@ import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.util.Disposer
import com.intellij.patterns.uast.injectionHostUExpression
import com.intellij.patterns.uast.literalExpression
import com.intellij.psi.*
import com.intellij.psi.impl.source.resolve.reference.PsiReferenceContributorEP
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry
@@ -35,7 +35,7 @@ class KotlinUastReferencesTest : KotlinLightCodeInsightFixtureTestCase() {
fun `test original getter is visible when reference is under renaming`() {
registerReferenceProviders(testRootDisposable) {
registerUastReferenceProvider(injectionHostUExpression(), uastInjectionHostReferenceProvider { _, psiLanguageInjectionHost ->
registerUastReferenceProvider(literalExpression(), uastLiteralReferenceProvider { _, psiLanguageInjectionHost ->
arrayOf(GetterReference("KotlinBean", psiLanguageInjectionHost))
})
}
@@ -1,5 +1,6 @@
package org.jetbrains.uast.test.kotlin
import org.jetbrains.uast.kotlin.KotlinConverter
import org.junit.Test
class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() {
@@ -27,6 +28,11 @@ class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() {
@Test fun testStringTemplateComplex() = doTest("StringTemplateComplex")
@Test
fun testStringTemplateComplexForUInjectionHost() = withForceUInjectionHostValue {
doTest("StringTemplateComplexForUInjectionHost")
}
@Test fun testQualifiedConstructorCall() = doTest("QualifiedConstructorCall")
@Test fun testPropertyDelegate() = doTest("PropertyDelegate")
@@ -94,3 +100,13 @@ class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() {
@Test
fun testConstructorDelegate() = doTest("ConstructorDelegate")
}
fun withForceUInjectionHostValue(call: () -> Unit) {
val prev = KotlinConverter.forceUInjectionHost
KotlinConverter.forceUInjectionHost = true
try {
call.invoke()
} finally {
KotlinConverter.forceUInjectionHost = prev
}
}
@@ -1,6 +1,5 @@
package org.jetbrains.uast.test.kotlin
import org.jetbrains.uast.kotlin.KotlinConverter
import org.junit.Test
class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() {
@@ -28,11 +27,6 @@ class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() {
@Test fun testStringTemplateComplex() = doTest("StringTemplateComplex")
@Test
fun testStringTemplateComplexForUInjectionHost() = withForceUInjectionHostValue {
doTest("StringTemplateComplexForUInjectionHost")
}
@Test fun testQualifiedConstructorCall() = doTest("QualifiedConstructorCall")
@Test fun testPropertyDelegate() = doTest("PropertyDelegate")
@@ -100,13 +94,3 @@ class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() {
@Test
fun testConstructorDelegate() = doTest("ConstructorDelegate")
}
fun withForceUInjectionHostValue(call: () -> Unit) {
val prev = KotlinConverter.forceUInjectionHost
KotlinConverter.forceUInjectionHost = true
try {
call.invoke()
} finally {
KotlinConverter.forceUInjectionHost = prev
}
}