172: Revert "Uast: uastParent made final in KotlinAbstractUElement"
This reverts commit 9b006787581cca8167714d07ad36aea195ff9c02.
This commit is contained in:
@@ -0,0 +1,211 @@
|
|||||||
|
/*
|
||||||
|
* 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.PsiElement
|
||||||
|
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KtLightClassForLocalDeclaration
|
||||||
|
import org.jetbrains.kotlin.asJava.toLightGetter
|
||||||
|
import org.jetbrains.kotlin.asJava.toLightSetter
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.isPropertyParameter
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||||
|
import org.jetbrains.uast.*
|
||||||
|
import org.jetbrains.uast.kotlin.expressions.KotlinUElvisExpression
|
||||||
|
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable
|
||||||
|
|
||||||
|
abstract class KotlinAbstractUElement(private val givenParent: UElement?) : UElement, JvmDeclarationUElement {
|
||||||
|
|
||||||
|
override val uastParent: UElement? by lz {
|
||||||
|
givenParent ?: convertParent()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun convertParent(): UElement? {
|
||||||
|
val psi = psi
|
||||||
|
var parent = psi?.parent ?: psi?.containingFile
|
||||||
|
|
||||||
|
if (psi is KtLightClassForLocalDeclaration) {
|
||||||
|
val originParent = psi.kotlinOrigin.parent
|
||||||
|
parent = when (originParent) {
|
||||||
|
is KtClassBody -> originParent.parent
|
||||||
|
else -> originParent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (psi is KtAnnotationEntry) {
|
||||||
|
val parentUnwrapped = KotlinConverter.unwrapElements(parent) ?: return null
|
||||||
|
val target = psi.useSiteTarget?.getAnnotationUseSiteTarget()
|
||||||
|
when (target) {
|
||||||
|
AnnotationUseSiteTarget.PROPERTY_GETTER ->
|
||||||
|
parent = (parentUnwrapped as? KtProperty)?.getter
|
||||||
|
?: (parentUnwrapped as? KtParameter)?.toLightGetter()
|
||||||
|
?: parent
|
||||||
|
|
||||||
|
AnnotationUseSiteTarget.PROPERTY_SETTER ->
|
||||||
|
parent = (parentUnwrapped as? KtProperty)?.setter
|
||||||
|
?: (parentUnwrapped as? KtParameter)?.toLightSetter()
|
||||||
|
?: parent
|
||||||
|
AnnotationUseSiteTarget.FIELD ->
|
||||||
|
parent = (parentUnwrapped as? KtProperty)
|
||||||
|
?: (parentUnwrapped as? KtParameter)
|
||||||
|
?.takeIf { it.isPropertyParameter() }
|
||||||
|
?.let(LightClassUtil::getLightClassBackingField)
|
||||||
|
?: parent
|
||||||
|
AnnotationUseSiteTarget.SETTER_PARAMETER ->
|
||||||
|
parent = (parentUnwrapped as? KtParameter)
|
||||||
|
?.toLightSetter()?.parameterList?.parameters?.firstOrNull() ?: parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (psi is UastKotlinPsiVariable && parent != null) {
|
||||||
|
parent = parent.parent
|
||||||
|
}
|
||||||
|
|
||||||
|
while (parent is KtStringTemplateEntryWithExpression ||
|
||||||
|
parent is KtStringTemplateExpression && parent.entries.size == 1) {
|
||||||
|
parent = parent.parent
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent is KtWhenConditionWithExpression) {
|
||||||
|
parent = parent.parent
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent is KtImportList) {
|
||||||
|
parent = parent.parent
|
||||||
|
}
|
||||||
|
|
||||||
|
if (psi is KtFunctionLiteral && parent is KtLambdaExpression) {
|
||||||
|
parent = parent.parent
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent is KtLambdaArgument) {
|
||||||
|
parent = parent.parent
|
||||||
|
}
|
||||||
|
|
||||||
|
if (psi is KtSuperTypeCallEntry) {
|
||||||
|
parent = parent?.parent
|
||||||
|
}
|
||||||
|
|
||||||
|
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}]")
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (other !is UElement) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.psi == other.psi
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode() = psi?.hashCode() ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun doConvertParent(element: UElement, parent: PsiElement?): UElement? {
|
||||||
|
val parentUnwrapped = KotlinConverter.unwrapElements(parent) ?: return null
|
||||||
|
if (parent is KtValueArgument && parentUnwrapped is KtAnnotationEntry) {
|
||||||
|
return (KotlinUastLanguagePlugin().convertElementWithParent(parentUnwrapped, null) as? KotlinUAnnotation)
|
||||||
|
?.findAttributeValueExpression(parent)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent is KtParameter) {
|
||||||
|
val annotationClass = findAnnotationClassFromConstructorParameter(parent)
|
||||||
|
if (annotationClass != null) {
|
||||||
|
return annotationClass.methods.find { it.name == parent.name }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent is KtClassInitializer) {
|
||||||
|
val containingClass = parent.containingClassOrObject
|
||||||
|
if (containingClass != null) {
|
||||||
|
val containingUClass = KotlinUastLanguagePlugin().convertElementWithParent(containingClass, null) as? KotlinUClass
|
||||||
|
containingUClass?.methods?.filterIsInstance<KotlinConstructorUMethod>()?.firstOrNull { it.isPrimary }?.let {
|
||||||
|
return it.uastBody
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = KotlinUastLanguagePlugin().convertElementWithParent(parentUnwrapped, null)
|
||||||
|
|
||||||
|
if (result is UEnumConstant && element is UDeclaration) {
|
||||||
|
return result.initializingClass
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result is USwitchClauseExpressionWithBody && !isInConditionBranch(element, result)) {
|
||||||
|
return result.body
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result is KotlinUDestructuringDeclarationExpression &&
|
||||||
|
element.psi == (parent as KtDestructuringDeclaration).initializer) {
|
||||||
|
return result.tempVarAssignment
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result is KotlinUElvisExpression && parent is KtBinaryExpression) {
|
||||||
|
when (element.psi) {
|
||||||
|
parent.left -> return result.lhsDeclaration
|
||||||
|
parent.right -> return result.rhsIfExpression
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result is UMethod
|
||||||
|
&& result !is KotlinConstructorUMethod // no sense to wrap super calls with `return`
|
||||||
|
&& element is UExpression
|
||||||
|
&& element !is UBlockExpression
|
||||||
|
&& element !is UTypeReferenceExpression // when element is a type in extension methods
|
||||||
|
) {
|
||||||
|
return KotlinUBlockExpression.KotlinLazyUBlockExpression(result, { block ->
|
||||||
|
listOf(KotlinUImplicitReturnExpression(block).apply { returnExpression = element })
|
||||||
|
}).expressions.single()
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isInConditionBranch(element: UElement, result: USwitchClauseExpressionWithBody) =
|
||||||
|
element.psi?.parentsWithSelf?.takeWhile { it !== result.psi }?.any { it is KtWhenCondition } ?: false
|
||||||
|
|
||||||
|
|
||||||
|
private fun findAnnotationClassFromConstructorParameter(parameter: KtParameter): UClass? {
|
||||||
|
val primaryConstructor = parameter.getStrictParentOfType<KtPrimaryConstructor>() ?: return null
|
||||||
|
val containingClass = primaryConstructor.getContainingClassOrObject()
|
||||||
|
if (containingClass.isAnnotation()) {
|
||||||
|
return KotlinUastLanguagePlugin().convertElementWithParent(containingClass, null) as? UClass
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class KotlinAbstractUExpression(givenParent: UElement?)
|
||||||
|
: KotlinAbstractUElement(givenParent), UExpression, JvmDeclarationUElement {
|
||||||
|
|
||||||
|
override val javaPsi: PsiElement? = null
|
||||||
|
|
||||||
|
override val sourcePsi
|
||||||
|
get() = psi
|
||||||
|
|
||||||
|
override val annotations: List<UAnnotation>
|
||||||
|
get() {
|
||||||
|
val annotatedExpression = psi?.parent as? KtAnnotatedExpression ?: return emptyList()
|
||||||
|
return annotatedExpression.annotationEntries.map { KotlinUAnnotation(it, this) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,292 @@
|
|||||||
|
/*
|
||||||
|
* 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.*
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KtLightClassForScript
|
||||||
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||||
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
|
||||||
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
|
import org.jetbrains.uast.*
|
||||||
|
import org.jetbrains.uast.kotlin.declarations.KotlinUMethod
|
||||||
|
import org.jetbrains.uast.kotlin.declarations.UastLightIdentifier
|
||||||
|
|
||||||
|
abstract class AbstractKotlinUClass(givenParent: UElement?) : KotlinAbstractUElement(givenParent), UClass, JvmDeclarationUElement {
|
||||||
|
|
||||||
|
override val uastDeclarations by lz {
|
||||||
|
mutableListOf<UDeclaration>().apply {
|
||||||
|
addAll(fields)
|
||||||
|
addAll(initializers)
|
||||||
|
addAll(methods)
|
||||||
|
addAll(innerClasses)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val uastSuperTypes: List<UTypeReferenceExpression>
|
||||||
|
get() {
|
||||||
|
val ktClass = (psi as? KtLightClass)?.kotlinOrigin ?: return emptyList()
|
||||||
|
return ktClass.superTypeListEntries.mapNotNull { it.typeReference }.map {
|
||||||
|
LazyKotlinUTypeReferenceExpression(it, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val uastAnchor: UElement?
|
||||||
|
get() = UIdentifier(psi.nameIdentifier, this)
|
||||||
|
|
||||||
|
override val annotations: List<UAnnotation> by lz {
|
||||||
|
(sourcePsi as? KtModifierListOwner)?.annotationEntries.orEmpty().map { KotlinUAnnotation(it, this) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?) = other is AbstractKotlinUClass && psi == other.psi
|
||||||
|
override fun hashCode() = psi.hashCode()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
open class KotlinUClass private constructor(
|
||||||
|
psi: KtLightClass,
|
||||||
|
givenParent: UElement?
|
||||||
|
) : AbstractKotlinUClass(givenParent), PsiClass by psi {
|
||||||
|
|
||||||
|
val ktClass = psi.kotlinOrigin
|
||||||
|
|
||||||
|
override val javaPsi: KtLightClass = psi
|
||||||
|
|
||||||
|
override val sourcePsi: KtClassOrObject? = ktClass
|
||||||
|
|
||||||
|
override val psi = unwrap<UClass, PsiClass>(psi)
|
||||||
|
|
||||||
|
override fun getSourceElement() = sourcePsi ?: this
|
||||||
|
|
||||||
|
override fun getOriginalElement(): PsiElement? = super.getOriginalElement()
|
||||||
|
|
||||||
|
override fun getNameIdentifier(): PsiIdentifier? = UastLightIdentifier(psi, ktClass)
|
||||||
|
|
||||||
|
override fun getContainingFile(): PsiFile? = unwrapFakeFileForLightClass(psi.containingFile)
|
||||||
|
|
||||||
|
override val uastAnchor: UElement
|
||||||
|
get() = UIdentifier(nameIdentifier, this)
|
||||||
|
|
||||||
|
override fun getInnerClasses(): Array<UClass> {
|
||||||
|
// filter DefaultImpls to avoid processing same methods from original interface multiple times
|
||||||
|
// filter Enum entry classes to avoid duplication with PsiEnumConstant initializer class
|
||||||
|
return psi.innerClasses.filter {
|
||||||
|
it.name != JvmAbi.DEFAULT_IMPLS_CLASS_NAME && !it.isEnumEntryLightClass()
|
||||||
|
}.mapNotNull {
|
||||||
|
getLanguagePlugin().convertOpt<UClass>(it, this)
|
||||||
|
}.toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSuperClass(): UClass? = super.getSuperClass()
|
||||||
|
override fun getFields(): Array<UField> = super.getFields()
|
||||||
|
override fun getInitializers(): Array<UClassInitializer> = super.getInitializers()
|
||||||
|
|
||||||
|
override fun getMethods(): Array<UMethod> {
|
||||||
|
val hasPrimaryConstructor = ktClass?.hasPrimaryConstructor() ?: false
|
||||||
|
var secondaryConstructorsCount = 0
|
||||||
|
|
||||||
|
fun createUMethod(psiMethod: PsiMethod): UMethod {
|
||||||
|
return if (psiMethod is KtLightMethod &&
|
||||||
|
psiMethod.isConstructor) {
|
||||||
|
if (!hasPrimaryConstructor && secondaryConstructorsCount++ == 0)
|
||||||
|
KotlinSecondaryConstructorWithInitializersUMethod(ktClass, psiMethod, this)
|
||||||
|
else
|
||||||
|
KotlinConstructorUMethod(ktClass, psiMethod, this)
|
||||||
|
} else {
|
||||||
|
getLanguagePlugin().convertOpt(psiMethod, this) ?: reportConvertFailure(psiMethod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isDelegatedMethod(psiMethod: PsiMethod) = psiMethod is KtLightMethod && psiMethod.isDelegated
|
||||||
|
|
||||||
|
return psi.methods.asSequence()
|
||||||
|
.filterNot(::isDelegatedMethod)
|
||||||
|
.map(::createUMethod)
|
||||||
|
.toList()
|
||||||
|
.toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PsiClass.isEnumEntryLightClass() = (this as? KtLightClass)?.kotlinOrigin is KtEnumEntry
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun create(psi: KtLightClass, containingElement: UElement?): UClass = when (psi) {
|
||||||
|
is PsiAnonymousClass -> KotlinUAnonymousClass(psi, containingElement)
|
||||||
|
is KtLightClassForScript -> KotlinScriptUClass(psi, containingElement)
|
||||||
|
else -> KotlinUClass(psi, containingElement)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
open class KotlinConstructorUMethod(
|
||||||
|
private val ktClass: KtClassOrObject?,
|
||||||
|
override val psi: KtLightMethod,
|
||||||
|
givenParent: UElement?
|
||||||
|
) : KotlinUMethod(psi, givenParent) {
|
||||||
|
|
||||||
|
val isPrimary: Boolean
|
||||||
|
get() = psi.kotlinOrigin.let { it is KtPrimaryConstructor || it is KtClassOrObject }
|
||||||
|
|
||||||
|
override val uastBody: UExpression? by lz {
|
||||||
|
val delegationCall: KtCallElement? = psi.kotlinOrigin.let {
|
||||||
|
when {
|
||||||
|
isPrimary -> ktClass?.superTypeListEntries?.firstIsInstanceOrNull<KtSuperTypeCallEntry>()
|
||||||
|
it is KtSecondaryConstructor -> it.getDelegationCall()
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val bodyExpressions = getBodyExpressions()
|
||||||
|
if (delegationCall == null && bodyExpressions.isEmpty()) return@lz null
|
||||||
|
KotlinUBlockExpression.KotlinLazyUBlockExpression(this) { uastParent ->
|
||||||
|
SmartList<UExpression>().apply {
|
||||||
|
delegationCall?.let {
|
||||||
|
add(KotlinUFunctionCallExpression(it, uastParent))
|
||||||
|
}
|
||||||
|
bodyExpressions.forEach {
|
||||||
|
add(KotlinConverter.convertOrEmpty(it, uastParent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val javaPsi = psi
|
||||||
|
|
||||||
|
override val sourcePsi = psi.kotlinOrigin
|
||||||
|
|
||||||
|
open protected fun getBodyExpressions(): List<KtExpression> {
|
||||||
|
if (isPrimary) return getInitializers()
|
||||||
|
val bodyExpression = (psi.kotlinOrigin as? KtFunction)?.bodyExpression ?: return emptyList()
|
||||||
|
if (bodyExpression is KtBlockExpression) return bodyExpression.statements
|
||||||
|
return listOf(bodyExpression)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun getInitializers() = ktClass?.getAnonymousInitializers()?.mapNotNull { it.body } ?: emptyList()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// This class was created as a workaround for KT-21617 to be the only constructor which includes `init` block
|
||||||
|
// when there is no primary constructors in the class.
|
||||||
|
// It is expected to have only one constructor of this type in a UClass.
|
||||||
|
class KotlinSecondaryConstructorWithInitializersUMethod(
|
||||||
|
ktClass: KtClassOrObject?,
|
||||||
|
psi: KtLightMethod,
|
||||||
|
givenParent: UElement?
|
||||||
|
) : KotlinConstructorUMethod(ktClass, psi, givenParent) {
|
||||||
|
override fun getBodyExpressions(): List<KtExpression> = getInitializers() + super.getBodyExpressions()
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinUAnonymousClass(
|
||||||
|
psi: PsiAnonymousClass,
|
||||||
|
givenParent: UElement?
|
||||||
|
) : AbstractKotlinUClass(givenParent), UAnonymousClass, PsiAnonymousClass by psi {
|
||||||
|
|
||||||
|
override val psi: PsiAnonymousClass = unwrap<UAnonymousClass, PsiAnonymousClass>(psi)
|
||||||
|
|
||||||
|
override val javaPsi: PsiAnonymousClass = psi
|
||||||
|
|
||||||
|
override val sourcePsi: KtClassOrObject? = (psi as? KtLightClass)?.kotlinOrigin
|
||||||
|
|
||||||
|
override fun getOriginalElement(): PsiElement? = super<AbstractKotlinUClass>.getOriginalElement()
|
||||||
|
|
||||||
|
override fun getSuperClass(): UClass? = super<AbstractKotlinUClass>.getSuperClass()
|
||||||
|
override fun getFields(): Array<UField> = super<AbstractKotlinUClass>.getFields()
|
||||||
|
override fun getMethods(): Array<UMethod> = super<AbstractKotlinUClass>.getMethods()
|
||||||
|
override fun getInitializers(): Array<UClassInitializer> = super<AbstractKotlinUClass>.getInitializers()
|
||||||
|
override fun getInnerClasses(): Array<UClass> = super<AbstractKotlinUClass>.getInnerClasses()
|
||||||
|
|
||||||
|
override fun getContainingFile(): PsiFile = unwrapFakeFileForLightClass(psi.containingFile)
|
||||||
|
|
||||||
|
override val uastAnchor: UElement?
|
||||||
|
get() {
|
||||||
|
val ktClassOrObject = (psi.originalElement as? KtLightClass)?.kotlinOrigin as? KtObjectDeclaration ?: return null
|
||||||
|
return UIdentifier(ktClassOrObject.getObjectKeyword(), this)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinScriptUClass(
|
||||||
|
psi: KtLightClassForScript,
|
||||||
|
givenParent: UElement?
|
||||||
|
) : AbstractKotlinUClass(givenParent), PsiClass by psi {
|
||||||
|
override fun getContainingFile(): PsiFile = unwrapFakeFileForLightClass(psi.containingFile)
|
||||||
|
|
||||||
|
override fun getNameIdentifier(): PsiIdentifier? = UastLightIdentifier(psi, psi.kotlinOrigin)
|
||||||
|
|
||||||
|
override val uastAnchor: UElement
|
||||||
|
get() = UIdentifier(nameIdentifier, this)
|
||||||
|
|
||||||
|
override val javaPsi: PsiClass = psi
|
||||||
|
|
||||||
|
override val sourcePsi: KtClassOrObject? = psi.kotlinOrigin
|
||||||
|
|
||||||
|
override val psi = unwrap<UClass, KtLightClassForScript>(psi)
|
||||||
|
|
||||||
|
override fun getSuperClass(): UClass? = super.getSuperClass()
|
||||||
|
|
||||||
|
override fun getFields(): Array<UField> = super.getFields()
|
||||||
|
|
||||||
|
override fun getInitializers(): Array<UClassInitializer> = super.getInitializers()
|
||||||
|
|
||||||
|
override fun getInnerClasses(): Array<UClass> =
|
||||||
|
psi.innerClasses.mapNotNull { getLanguagePlugin().convertOpt<UClass>(it, this) }.toTypedArray()
|
||||||
|
|
||||||
|
override fun getMethods(): Array<UMethod> = psi.methods.map(this::createUMethod).toTypedArray()
|
||||||
|
|
||||||
|
private fun createUMethod(method: PsiMethod): UMethod {
|
||||||
|
return if (method.isConstructor) {
|
||||||
|
KotlinScriptConstructorUMethod(psi.script, method as KtLightMethod, this)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
getLanguagePlugin().convertOpt(method, this) ?: reportConvertFailure(method)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getOriginalElement(): PsiElement? = psi.originalElement
|
||||||
|
|
||||||
|
class KotlinScriptConstructorUMethod(
|
||||||
|
script: KtScript,
|
||||||
|
override val psi: KtLightMethod,
|
||||||
|
override val uastParent: UElement?
|
||||||
|
) : KotlinUMethod(psi, uastParent) {
|
||||||
|
override val uastBody: UExpression? by lz {
|
||||||
|
val initializers = script.declarations.filterIsInstance<KtScriptInitializer>()
|
||||||
|
KotlinUBlockExpression.create(initializers, this)
|
||||||
|
}
|
||||||
|
override val javaPsi = psi
|
||||||
|
override val sourcePsi = psi.kotlinOrigin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun reportConvertFailure(psiMethod: PsiMethod): Nothing {
|
||||||
|
val isValid = psiMethod.isValid
|
||||||
|
val report = KotlinExceptionWithAttachments(
|
||||||
|
"cant convert $psiMethod of ${psiMethod.javaClass} to UMethod"
|
||||||
|
+ if (!isValid) " (method is not valid)" else ""
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isValid) {
|
||||||
|
report.withAttachment("method", psiMethod.text)
|
||||||
|
psiMethod.containingFile?.let {
|
||||||
|
report.withAttachment("file", it.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw report
|
||||||
|
}
|
||||||
+6
-6
@@ -338,7 +338,7 @@ open class KotlinUAnnotatedLocalVariable(
|
|||||||
override val annotations: List<UAnnotation> by lz { computeAnnotations(this) }
|
override val annotations: List<UAnnotation> by lz { computeAnnotations(this) }
|
||||||
}
|
}
|
||||||
|
|
||||||
class KotlinUEnumConstant(
|
open class KotlinUEnumConstant(
|
||||||
psi: PsiEnumConstant,
|
psi: PsiEnumConstant,
|
||||||
override val sourcePsi: KtElement?,
|
override val sourcePsi: KtElement?,
|
||||||
givenParent: UElement?
|
givenParent: UElement?
|
||||||
@@ -350,10 +350,6 @@ class KotlinUEnumConstant(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getInitializer(): PsiExpression? = super<AbstractKotlinUVariable>.getInitializer()
|
|
||||||
|
|
||||||
override fun getOriginalElement(): PsiElement? = super<AbstractKotlinUVariable>.getOriginalElement()
|
|
||||||
|
|
||||||
override val javaPsi = unwrap<UEnumConstant, PsiEnumConstant>(psi)
|
override val javaPsi = unwrap<UEnumConstant, PsiEnumConstant>(psi)
|
||||||
|
|
||||||
override val psi = javaPsi
|
override val psi = javaPsi
|
||||||
@@ -409,11 +405,15 @@ class KotlinUEnumConstant(
|
|||||||
private class KotlinEnumConstantClassReference(
|
private class KotlinEnumConstantClassReference(
|
||||||
override val psi: PsiEnumConstant,
|
override val psi: PsiEnumConstant,
|
||||||
override val sourcePsi: KtElement?,
|
override val sourcePsi: KtElement?,
|
||||||
givenParent: UElement?
|
private val givenParent: UElement?
|
||||||
) : KotlinAbstractUExpression(givenParent), USimpleNameReferenceExpression {
|
) : KotlinAbstractUExpression(givenParent), USimpleNameReferenceExpression {
|
||||||
override val javaPsi: PsiElement?
|
override val javaPsi: PsiElement?
|
||||||
get() = psi
|
get() = psi
|
||||||
|
|
||||||
|
override val uastParent: UElement? by lz {
|
||||||
|
givenParent ?: KotlinUastLanguagePlugin().convertElementWithParent(psi.parent ?: psi.containingFile, null)
|
||||||
|
}
|
||||||
|
|
||||||
override fun resolve() = psi.containingClass
|
override fun resolve() = psi.containingClass
|
||||||
override val resolvedName: String?
|
override val resolvedName: String?
|
||||||
get() = psi.containingClass?.name
|
get() = psi.containingClass?.name
|
||||||
|
|||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.uast.kotlin.KotlinAbstractUExpression
|
||||||
|
import org.jetbrains.uast.kotlin.doConvertParent
|
||||||
|
|
||||||
|
open class KotlinUDeclarationsExpression(
|
||||||
|
override val psi: PsiElement?,
|
||||||
|
givenParent: UElement?,
|
||||||
|
val psiAnchor: PsiElement? = null
|
||||||
|
) : KotlinAbstractUExpression(givenParent), UDeclarationsExpression {
|
||||||
|
|
||||||
|
override val sourcePsi: PsiElement?
|
||||||
|
get() = psiAnchor
|
||||||
|
|
||||||
|
override val uastParent: UElement?
|
||||||
|
get() = if (psiAnchor != null) doConvertParent(this, psiAnchor.parent) else super.uastParent
|
||||||
|
|
||||||
|
constructor(uastParent: UElement?) : this(null, uastParent)
|
||||||
|
|
||||||
|
override lateinit var declarations: List<UDeclaration>
|
||||||
|
internal set
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinUDestructuringDeclarationExpression(
|
||||||
|
givenParent: UElement?,
|
||||||
|
psiAnchor: PsiElement
|
||||||
|
) : KotlinUDeclarationsExpression(null, givenParent, psiAnchor) {
|
||||||
|
|
||||||
|
val tempVarAssignment get() = declarations.first()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user