diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt index 028c0fb21b0..fe546308a93 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt @@ -39,6 +39,8 @@ 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.kotlin.KotlinConverter.convertDeclaration +import org.jetbrains.uast.kotlin.KotlinConverter.convertDeclarationOrElement import org.jetbrains.uast.kotlin.declarations.KotlinUIdentifier import org.jetbrains.uast.kotlin.declarations.KotlinUMethod import org.jetbrains.uast.kotlin.expressions.* @@ -84,25 +86,6 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin { return convertDeclarationOrElement(element, null, requiredType) } - private fun convertDeclarationOrElement(element: PsiElement, givenParent: UElement?, requiredType: Class?): 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 - } - } - - val uElement = convertDeclaration(element, givenParent, requiredType) - ?: KotlinConverter.convertPsiElement(element, givenParent, requiredType) - /* - if (uElement != null) { - element.putUserData(KOTLIN_CACHED_UELEMENT_KEY, WeakReference(uElement)) - } - */ - return uElement - } - override fun getMethodCallExpression( element: PsiElement, containingClassFqName: String?, @@ -143,108 +126,6 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin { return UastLanguagePlugin.ResolvedConstructor(uExpression, method, containingClass) } - internal fun convertDeclaration(element: PsiElement, - givenParent: UElement?, - requiredType: Class?): UElement? { - fun

build(ctor: (P, UElement?) -> UElement): () -> UElement? = { ctor(element as P, givenParent) } - - fun

buildKt(ktElement: K, ctor: (P, K, UElement?) -> UElement): () -> UElement? = - { ctor(element as P, ktElement, givenParent) } - - fun

buildKtOpt(ktElement: K?, ctor: (P, K?, UElement?) -> UElement): () -> UElement? = - { ctor(element as P, ktElement, givenParent) } - - val original = element.originalElement - return with(requiredType) { - when (original) { - is KtLightMethod -> el(build(KotlinUMethod.Companion::create)) // .Companion is needed because of KT-13934 - is KtLightClass -> when (original.kotlinOrigin) { - is KtEnumEntry -> el { - convertEnumEntry(original.kotlinOrigin as KtEnumEntry, givenParent) - } - else -> el { KotlinUClass.create(original, givenParent) } - } - is KtLightFieldImpl.KtLightEnumConstant -> el(buildKtOpt(original.kotlinOrigin, ::KotlinUEnumConstant)) - is KtLightField -> el(buildKtOpt(original.kotlinOrigin, ::KotlinUField)) - is KtLightParameter -> el(buildKtOpt(original.kotlinOrigin, ::KotlinUParameter)) - is UastKotlinPsiParameter -> el(buildKt(original.ktParameter, ::KotlinUParameter)) - is UastKotlinPsiVariable -> el(buildKt(original.ktElement, ::KotlinUVariable)) - - is KtEnumEntry -> el { - convertEnumEntry(original, givenParent) - } - is KtClassOrObject -> el { - original.toLightClass()?.let { lightClass -> - KotlinUClass.create(lightClass, givenParent) - } - } - is KtFunction -> - if (original.isLocal) { - el { - val parent = original.parent - if (parent is KtLambdaExpression) { - KotlinULambdaExpression(parent, givenParent) // your parent is the ULambdaExpression - } else if (original.name.isNullOrEmpty()) { - createLocalFunctionLambdaExpression(original, givenParent) - } - else { - val uDeclarationsExpression = createLocalFunctionDeclaration(original, givenParent) - val localFunctionVar = uDeclarationsExpression.declarations.single() as KotlinLocalFunctionUVariable - localFunctionVar.uastInitializer - } - } - } - else { - el { - val lightMethod = LightClassUtil.getLightClassMethod(original) ?: return null - convertDeclaration(lightMethod, givenParent, requiredType) - } - } - - is KtPropertyAccessor -> el { - val lightMethod = LightClassUtil.getLightClassAccessorMethod(original) ?: return null - convertDeclaration(lightMethod, givenParent, requiredType) - } - - is KtProperty -> - if (original.isLocal) { - KotlinConverter.convertPsiElement(element, givenParent, requiredType) - } - else { - convertNonLocalProperty(original, givenParent, requiredType) - } - - is KtParameter -> el { - 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 -> el { KotlinUFile(original, this@KotlinUastLanguagePlugin) } - is FakeFileForLightClass -> el { KotlinUFile(original.navigationElement, this@KotlinUastLanguagePlugin) } - is KtAnnotationEntry -> el(build(::KotlinUAnnotation)) - is KtCallExpression -> - if (requiredType != null && UAnnotation::class.java.isAssignableFrom(requiredType)) { - el { KotlinUNestedAnnotation.tryCreate(original, givenParent) } - } else null - is KtLightAnnotationForSourceEntry -> convertElement(original.kotlinOrigin, givenParent, requiredType) - else -> null - } - } - } - - private fun convertEnumEntry(original: KtEnumEntry, givenParent: UElement?): UElement? { - return LightClassUtil.getLightClassBackingField(original)?.let { psiField -> - if (psiField is KtLightFieldImpl.KtLightEnumConstant) { - KotlinUEnumConstant(psiField, psiField.kotlinOrigin, givenParent) - } - else { - null - } - } - } - override fun isExpressionValueUsed(element: UExpression): Boolean { return when (element) { is KotlinUSimpleReferenceExpression.KotlinAccessorCallExpression -> element.setterValue != null @@ -265,18 +146,7 @@ internal inline fun Class?.expr(f: () return if (this == null || isAssignableFrom(ActualT::class.java)) f() else null } -private fun convertNonLocalProperty(property: KtProperty, - givenParent: UElement?, - requiredType: Class?): UElement? { - val methods = LightClassUtil.getLightClassPropertyMethods(property) - return methods.backingField?.let { backingField -> - with(requiredType) { - el { KotlinUField(backingField, (backingField as? KtLightElement<*,*>)?.kotlinOrigin, givenParent) } - } - } ?: methods.getter?.let { getter -> - KotlinUastLanguagePlugin().convertDeclaration(getter, givenParent, requiredType) - } -} + internal object KotlinConverter { internal tailrec fun unwrapElements(element: PsiElement?): PsiElement? = when (element) { @@ -484,7 +354,8 @@ internal object KotlinConverter { internal fun convertWhenCondition(condition: KtWhenCondition, givenParent: UElement?, - requiredType: Class? = null): UExpression? { + requiredType: Class? = null + ): UExpression? { return with(requiredType) { when (condition) { is KtWhenConditionInRange -> expr { @@ -519,6 +390,145 @@ internal object KotlinConverter { } } + private fun convertEnumEntry(original: KtEnumEntry, givenParent: UElement?): UElement? { + return LightClassUtil.getLightClassBackingField(original)?.let { psiField -> + if (psiField is KtLightFieldImpl.KtLightEnumConstant) { + KotlinUEnumConstant(psiField, psiField.kotlinOrigin, givenParent) + } else { + null + } + } + } + + + internal fun convertDeclaration( + element: PsiElement, + givenParent: UElement?, + requiredType: Class? + ): UElement? { + fun

build(ctor: (P, UElement?) -> UElement): () -> UElement? = { ctor(element as P, givenParent) } + + fun

buildKt(ktElement: K, ctor: (P, K, UElement?) -> UElement): () -> UElement? = + { ctor(element as P, ktElement, givenParent) } + + fun

buildKtOpt(ktElement: K?, ctor: (P, K?, UElement?) -> UElement): () -> UElement? = + { ctor(element as P, ktElement, givenParent) } + + val original = element.originalElement + return with(requiredType) { + when (original) { + is KtLightMethod -> el(build(KotlinUMethod.Companion::create)) // .Companion is needed because of KT-13934 + is KtLightClass -> when (original.kotlinOrigin) { + is KtEnumEntry -> el { + convertEnumEntry(original.kotlinOrigin as KtEnumEntry, givenParent) + } + else -> el { KotlinUClass.create(original, givenParent) } + } + is KtLightFieldImpl.KtLightEnumConstant -> el(buildKtOpt(original.kotlinOrigin, ::KotlinUEnumConstant)) + is KtLightField -> el(buildKtOpt(original.kotlinOrigin, ::KotlinUField)) + is KtLightParameter -> el(buildKtOpt(original.kotlinOrigin, ::KotlinUParameter)) + is UastKotlinPsiParameter -> el(buildKt(original.ktParameter, ::KotlinUParameter)) + is UastKotlinPsiVariable -> el(buildKt(original.ktElement, ::KotlinUVariable)) + + is KtEnumEntry -> el { + convertEnumEntry(original, givenParent) + } + is KtClassOrObject -> el { + original.toLightClass()?.let { lightClass -> + KotlinUClass.create(lightClass, givenParent) + } + } + is KtFunction -> + if (original.isLocal) { + el { + val parent = original.parent + if (parent is KtLambdaExpression) { + KotlinULambdaExpression(parent, givenParent) // your parent is the ULambdaExpression + } else if (original.name.isNullOrEmpty()) { + createLocalFunctionLambdaExpression(original, givenParent) + } + else { + val uDeclarationsExpression = createLocalFunctionDeclaration(original, givenParent) + val localFunctionVar = uDeclarationsExpression.declarations.single() as KotlinLocalFunctionUVariable + localFunctionVar.uastInitializer + } + } + } + else { + el { + val lightMethod = LightClassUtil.getLightClassMethod(original) ?: return null + convertDeclaration(lightMethod, givenParent, requiredType) + } + } + + is KtPropertyAccessor -> el { + val lightMethod = LightClassUtil.getLightClassAccessorMethod(original) ?: return null + convertDeclaration(lightMethod, givenParent, requiredType) + } + + is KtProperty -> + if (original.isLocal) { + KotlinConverter.convertPsiElement(element, givenParent, requiredType) + } + else { + convertNonLocalProperty(original, givenParent, requiredType) + } + + is KtParameter -> el { + 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 -> el { KotlinUFile(original) } + is FakeFileForLightClass -> el { KotlinUFile(original.navigationElement) } + is KtAnnotationEntry -> el(build(::KotlinUAnnotation)) + is KtCallExpression -> + if (requiredType != null && UAnnotation::class.java.isAssignableFrom(requiredType)) { + el { KotlinUNestedAnnotation.tryCreate(original, givenParent) } + } else null + is KtLightAnnotationForSourceEntry -> convertDeclarationOrElement(original.kotlinOrigin, givenParent, requiredType) + else -> null + } + } + } + + + fun convertDeclarationOrElement(element: PsiElement, givenParent: UElement?, requiredType: Class?): 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 + } + } + + val uElement = convertDeclaration(element, givenParent, requiredType) + ?: KotlinConverter.convertPsiElement(element, givenParent, requiredType) + /* + if (uElement != null) { + element.putUserData(KOTLIN_CACHED_UELEMENT_KEY, WeakReference(uElement)) + } + */ + return uElement + } + + private fun convertNonLocalProperty( + property: KtProperty, + givenParent: UElement?, + requiredType: Class? + ): UElement? { + val methods = LightClassUtil.getLightClassPropertyMethods(property) + return methods.backingField?.let { backingField -> + with(requiredType) { + el { KotlinUField(backingField, (backingField as? KtLightElement<*,*>)?.kotlinOrigin, givenParent) } + } + } ?: methods.getter?.let { getter -> + convertDeclaration(getter, givenParent, requiredType) + } + } + internal fun convertOrEmpty(expression: KtExpression?, parent: UElement?): UExpression { return expression?.let { convertExpression(it, parent, null) } ?: UastEmptyExpression } diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.182 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.182 index 29a39ead0ec..fb0b25600da 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.182 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.182 @@ -38,6 +38,8 @@ 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.kotlin.KotlinConverter.convertDeclaration +import org.jetbrains.uast.kotlin.KotlinConverter.convertDeclarationOrElement import org.jetbrains.uast.kotlin.declarations.KotlinUIdentifier import org.jetbrains.uast.kotlin.declarations.KotlinUMethod import org.jetbrains.uast.kotlin.expressions.* @@ -82,25 +84,6 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin { return convertDeclarationOrElement(element, null, requiredType) } - private fun convertDeclarationOrElement(element: PsiElement, givenParent: UElement?, requiredType: Class?): 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 - } - } - - val uElement = convertDeclaration(element, givenParent, requiredType) - ?: KotlinConverter.convertPsiElement(element, givenParent, requiredType) - /* - if (uElement != null) { - element.putUserData(KOTLIN_CACHED_UELEMENT_KEY, WeakReference(uElement)) - } - */ - return uElement - } - override fun getMethodCallExpression( element: PsiElement, containingClassFqName: String?, @@ -141,108 +124,6 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin { return UastLanguagePlugin.ResolvedConstructor(uExpression, method, containingClass) } - internal fun convertDeclaration(element: PsiElement, - givenParent: UElement?, - requiredType: Class?): UElement? { - fun

build(ctor: (P, UElement?) -> UElement): () -> UElement? = { ctor(element as P, givenParent) } - - fun

buildKt(ktElement: K, ctor: (P, K, UElement?) -> UElement): () -> UElement? = - { ctor(element as P, ktElement, givenParent) } - - fun

buildKtOpt(ktElement: K?, ctor: (P, K?, UElement?) -> UElement): () -> UElement? = - { ctor(element as P, ktElement, givenParent) } - - val original = element.originalElement - return with(requiredType) { - when (original) { - is KtLightMethod -> el(build(KotlinUMethod.Companion::create)) // .Companion is needed because of KT-13934 - is KtLightClass -> when (original.kotlinOrigin) { - is KtEnumEntry -> el { - convertEnumEntry(original.kotlinOrigin as KtEnumEntry, givenParent) - } - else -> el { KotlinUClass.create(original, givenParent) } - } - is KtLightFieldImpl.KtLightEnumConstant -> el(buildKtOpt(original.kotlinOrigin, ::KotlinUEnumConstant)) - is KtLightField -> el(buildKtOpt(original.kotlinOrigin, ::KotlinUField)) - is KtLightParameter -> el(buildKtOpt(original.kotlinOrigin, ::KotlinUParameter)) - is UastKotlinPsiParameter -> el(buildKt(original.ktParameter, ::KotlinUParameter)) - is UastKotlinPsiVariable -> el(buildKt(original.ktElement, ::KotlinUVariable)) - - is KtEnumEntry -> el { - convertEnumEntry(original, givenParent) - } - is KtClassOrObject -> el { - original.toLightClass()?.let { lightClass -> - KotlinUClass.create(lightClass, givenParent) - } - } - is KtFunction -> - if (original.isLocal) { - el { - val parent = original.parent - if (parent is KtLambdaExpression) { - KotlinULambdaExpression(parent, givenParent) // your parent is the ULambdaExpression - } else if (original.name.isNullOrEmpty()) { - createLocalFunctionLambdaExpression(original, givenParent) - } - else { - val uDeclarationsExpression = createLocalFunctionDeclaration(original, givenParent) - val localFunctionVar = uDeclarationsExpression.declarations.single() as KotlinLocalFunctionUVariable - localFunctionVar.uastInitializer - } - } - } - else { - el { - val lightMethod = LightClassUtil.getLightClassMethod(original) ?: return null - convertDeclaration(lightMethod, givenParent, requiredType) - } - } - - is KtPropertyAccessor -> el { - val lightMethod = LightClassUtil.getLightClassAccessorMethod(original) ?: return null - convertDeclaration(lightMethod, givenParent, requiredType) - } - - is KtProperty -> - if (original.isLocal) { - KotlinConverter.convertPsiElement(element, givenParent, requiredType) - } - else { - convertNonLocalProperty(original, givenParent, requiredType) - } - - is KtParameter -> el { - 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 -> el { KotlinUFile(original, this@KotlinUastLanguagePlugin) } - is FakeFileForLightClass -> el { KotlinUFile(original.navigationElement, this@KotlinUastLanguagePlugin) } - is KtAnnotationEntry -> el(build(::KotlinUAnnotation)) - is KtCallExpression -> - if (requiredType != null && UAnnotation::class.java.isAssignableFrom(requiredType)) { - el { KotlinUNestedAnnotation.tryCreate(original, givenParent) } - } else null - is KtLightAnnotationForSourceEntry -> convertElement(original.kotlinOrigin, givenParent, requiredType) - else -> null - } - } - } - - private fun convertEnumEntry(original: KtEnumEntry, givenParent: UElement?): UElement? { - return LightClassUtil.getLightClassBackingField(original)?.let { psiField -> - if (psiField is KtLightFieldImpl.KtLightEnumConstant) { - KotlinUEnumConstant(psiField, psiField.kotlinOrigin, givenParent) - } - else { - null - } - } - } - override fun isExpressionValueUsed(element: UExpression): Boolean { return when (element) { is KotlinUSimpleReferenceExpression.KotlinAccessorCallExpression -> element.setterValue != null @@ -263,18 +144,7 @@ internal inline fun Class?.expr(f: () return if (this == null || isAssignableFrom(ActualT::class.java)) f() else null } -private fun convertNonLocalProperty(property: KtProperty, - givenParent: UElement?, - requiredType: Class?): UElement? { - val methods = LightClassUtil.getLightClassPropertyMethods(property) - return methods.backingField?.let { backingField -> - with(requiredType) { - el { KotlinUField(backingField, (backingField as? KtLightElement<*,*>)?.kotlinOrigin, givenParent) } - } - } ?: methods.getter?.let { getter -> - KotlinUastLanguagePlugin().convertDeclaration(getter, givenParent, requiredType) - } -} + internal object KotlinConverter { internal tailrec fun unwrapElements(element: PsiElement?): PsiElement? = when (element) { @@ -482,7 +352,8 @@ internal object KotlinConverter { internal fun convertWhenCondition(condition: KtWhenCondition, givenParent: UElement?, - requiredType: Class? = null): UExpression? { + requiredType: Class? = null + ): UExpression? { return with(requiredType) { when (condition) { is KtWhenConditionInRange -> expr { @@ -517,6 +388,145 @@ internal object KotlinConverter { } } + private fun convertEnumEntry(original: KtEnumEntry, givenParent: UElement?): UElement? { + return LightClassUtil.getLightClassBackingField(original)?.let { psiField -> + if (psiField is KtLightFieldImpl.KtLightEnumConstant) { + KotlinUEnumConstant(psiField, psiField.kotlinOrigin, givenParent) + } else { + null + } + } + } + + + internal fun convertDeclaration( + element: PsiElement, + givenParent: UElement?, + requiredType: Class? + ): UElement? { + fun

build(ctor: (P, UElement?) -> UElement): () -> UElement? = { ctor(element as P, givenParent) } + + fun

buildKt(ktElement: K, ctor: (P, K, UElement?) -> UElement): () -> UElement? = + { ctor(element as P, ktElement, givenParent) } + + fun

buildKtOpt(ktElement: K?, ctor: (P, K?, UElement?) -> UElement): () -> UElement? = + { ctor(element as P, ktElement, givenParent) } + + val original = element.originalElement + return with(requiredType) { + when (original) { + is KtLightMethod -> el(build(KotlinUMethod.Companion::create)) // .Companion is needed because of KT-13934 + is KtLightClass -> when (original.kotlinOrigin) { + is KtEnumEntry -> el { + convertEnumEntry(original.kotlinOrigin as KtEnumEntry, givenParent) + } + else -> el { KotlinUClass.create(original, givenParent) } + } + is KtLightFieldImpl.KtLightEnumConstant -> el(buildKtOpt(original.kotlinOrigin, ::KotlinUEnumConstant)) + is KtLightField -> el(buildKtOpt(original.kotlinOrigin, ::KotlinUField)) + is KtLightParameter -> el(buildKtOpt(original.kotlinOrigin, ::KotlinUParameter)) + is UastKotlinPsiParameter -> el(buildKt(original.ktParameter, ::KotlinUParameter)) + is UastKotlinPsiVariable -> el(buildKt(original.ktElement, ::KotlinUVariable)) + + is KtEnumEntry -> el { + convertEnumEntry(original, givenParent) + } + is KtClassOrObject -> el { + original.toLightClass()?.let { lightClass -> + KotlinUClass.create(lightClass, givenParent) + } + } + is KtFunction -> + if (original.isLocal) { + el { + val parent = original.parent + if (parent is KtLambdaExpression) { + KotlinULambdaExpression(parent, givenParent) // your parent is the ULambdaExpression + } else if (original.name.isNullOrEmpty()) { + createLocalFunctionLambdaExpression(original, givenParent) + } + else { + val uDeclarationsExpression = createLocalFunctionDeclaration(original, givenParent) + val localFunctionVar = uDeclarationsExpression.declarations.single() as KotlinLocalFunctionUVariable + localFunctionVar.uastInitializer + } + } + } + else { + el { + val lightMethod = LightClassUtil.getLightClassMethod(original) ?: return null + convertDeclaration(lightMethod, givenParent, requiredType) + } + } + + is KtPropertyAccessor -> el { + val lightMethod = LightClassUtil.getLightClassAccessorMethod(original) ?: return null + convertDeclaration(lightMethod, givenParent, requiredType) + } + + is KtProperty -> + if (original.isLocal) { + KotlinConverter.convertPsiElement(element, givenParent, requiredType) + } + else { + convertNonLocalProperty(original, givenParent, requiredType) + } + + is KtParameter -> el { + 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 -> el { KotlinUFile(original) } + is FakeFileForLightClass -> el { KotlinUFile(original.navigationElement) } + is KtAnnotationEntry -> el(build(::KotlinUAnnotation)) + is KtCallExpression -> + if (requiredType != null && UAnnotation::class.java.isAssignableFrom(requiredType)) { + el { KotlinUNestedAnnotation.tryCreate(original, givenParent) } + } else null + is KtLightAnnotationForSourceEntry -> convertDeclarationOrElement(original.kotlinOrigin, givenParent, requiredType) + else -> null + } + } + } + + + fun convertDeclarationOrElement(element: PsiElement, givenParent: UElement?, requiredType: Class?): 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 + } + } + + val uElement = convertDeclaration(element, givenParent, requiredType) + ?: KotlinConverter.convertPsiElement(element, givenParent, requiredType) + /* + if (uElement != null) { + element.putUserData(KOTLIN_CACHED_UELEMENT_KEY, WeakReference(uElement)) + } + */ + return uElement + } + + private fun convertNonLocalProperty( + property: KtProperty, + givenParent: UElement?, + requiredType: Class? + ): UElement? { + val methods = LightClassUtil.getLightClassPropertyMethods(property) + return methods.backingField?.let { backingField -> + with(requiredType) { + el { KotlinUField(backingField, (backingField as? KtLightElement<*,*>)?.kotlinOrigin, givenParent) } + } + } ?: methods.getter?.let { getter -> + convertDeclaration(getter, givenParent, requiredType) + } + } + internal fun convertOrEmpty(expression: KtExpression?, parent: UElement?): UExpression { return expression?.let { convertExpression(it, parent, null) } ?: UastEmptyExpression } diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUFile.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUFile.kt index 3f686593ffb..84e33f39e78 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUFile.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUFile.kt @@ -22,12 +22,17 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiRecursiveElementWalkingVisitor import org.jetbrains.kotlin.asJava.findFacadeClass import org.jetbrains.kotlin.asJava.toLightClass +import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.uast.* import java.util.* -class KotlinUFile(override val psi: KtFile, override val languagePlugin: UastLanguagePlugin) : UFile, JvmDeclarationUElementPlaceholder { +class KotlinUFile( + override val psi: KtFile, + override val languagePlugin: UastLanguagePlugin = + UastLanguagePlugin.getInstances().find { it.language == KotlinLanguage.INSTANCE } ?: KotlinUastLanguagePlugin() +) : UFile, JvmDeclarationUElementPlaceholder { override val packageName: String get() = psi.packageFqName.asString() diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUFile.kt.191 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUFile.kt.191 deleted file mode 100644 index 7fccefef117..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUFile.kt.191 +++ /dev/null @@ -1,66 +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.PsiClass -import com.intellij.psi.PsiComment -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiRecursiveElementWalkingVisitor -import org.jetbrains.kotlin.asJava.findFacadeClass -import org.jetbrains.kotlin.asJava.toLightClass -import org.jetbrains.kotlin.idea.KotlinLanguage -import org.jetbrains.kotlin.psi.KtClassOrObject -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.uast.* -import java.util.* - -class KotlinUFile( - override val psi: KtFile, - override val languagePlugin: UastLanguagePlugin = - UastLanguagePlugin.byLanguage(KotlinLanguage.INSTANCE) ?: KotlinUastLanguagePlugin() -) : UFile, JvmDeclarationUElementPlaceholder { - override val packageName: String - get() = psi.packageFqName.asString() - - override val annotations: List - get() = psi.annotationEntries.map { KotlinUAnnotation(it, this) } - - override val javaPsi: PsiElement? = null - - override val sourcePsi: PsiElement? = psi - - override val allCommentsInFile by lz { - val comments = ArrayList(0) - psi.accept(object : PsiRecursiveElementWalkingVisitor() { - override fun visitComment(comment: PsiComment) { - comments += UComment(comment, this@KotlinUFile) - } - }) - comments - } - - override val imports by lz { psi.importDirectives.map { KotlinUImportStatement(it, this) } } - - override val classes by lz { - val facadeOrScriptClass = if (psi.isScript()) psi.script?.toLightClass() else psi.findFacadeClass() - val classes = psi.declarations.mapNotNull { (it as? KtClassOrObject)?.toLightClass()?.toUClass() } - - (facadeOrScriptClass?.toUClass()?.let { listOf(it) } ?: emptyList()) + classes - } - - private fun PsiClass.toUClass() = languagePlugin.convertOpt(this, this@KotlinUFile) -} \ No newline at end of file