UAST: place method declarations together

This commit is contained in:
Jinseong Jeon
2021-06-17 15:47:03 -07:00
committed by Ilya Kirillov
parent beddf03f74
commit 0c011f4e73
4 changed files with 72 additions and 77 deletions
@@ -22,8 +22,6 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.uast.* import org.jetbrains.uast.*
import org.jetbrains.uast.expressions.UInjectionHost import org.jetbrains.uast.expressions.UInjectionHost
import org.jetbrains.uast.kotlin.declarations.KotlinUMethod
import org.jetbrains.uast.kotlin.declarations.KotlinUMethodWithFakeLightDelegate
import org.jetbrains.uast.kotlin.expressions.* import org.jetbrains.uast.kotlin.expressions.*
import org.jetbrains.uast.kotlin.psi.* import org.jetbrains.uast.kotlin.psi.*
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.uast.* import org.jetbrains.uast.*
import org.jetbrains.uast.kotlin.declarations.KotlinUMethod
import org.jetbrains.uast.kotlin.internal.multiResolveResults import org.jetbrains.uast.kotlin.internal.multiResolveResults
abstract class KotlinUAnnotationBase<T : KtCallElement>( abstract class KotlinUAnnotationBase<T : KtCallElement>(
@@ -24,12 +24,9 @@ import org.jetbrains.kotlin.asJava.classes.KtLightClassForScript
import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.uast.* import org.jetbrains.uast.*
import org.jetbrains.uast.internal.acceptList import org.jetbrains.uast.internal.acceptList
import org.jetbrains.uast.kotlin.declarations.KotlinUMethod
import org.jetbrains.uast.visitor.UastVisitor import org.jetbrains.uast.visitor.UastVisitor
abstract class AbstractKotlinUClass(givenParent: UElement?) : KotlinAbstractUElement(givenParent), UClassTypeSpecific, UAnchorOwner { abstract class AbstractKotlinUClass(givenParent: UElement?) : KotlinAbstractUElement(givenParent), UClassTypeSpecific, UAnchorOwner {
@@ -175,76 +172,6 @@ open class KotlinUClass private constructor(
} }
open class KotlinConstructorUMethod(
private val ktClass: KtClassOrObject?,
override val psi: PsiMethod,
kotlinOrigin: KtDeclaration?,
givenParent: UElement?
) : KotlinUMethod(psi, kotlinOrigin, givenParent) {
constructor(
ktClass: KtClassOrObject?,
psi: KtLightMethod,
givenParent: UElement?
):this(ktClass, psi, psi.kotlinOrigin, givenParent)
val isPrimary: Boolean
get() = sourcePsi.let { it is KtPrimaryConstructor || it is KtClassOrObject }
override val uastBody: UExpression? by lz {
val delegationCall: KtCallElement? = sourcePsi.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
KotlinLazyUBlockExpression(this) { uastParent ->
SmartList<UExpression>().apply {
delegationCall?.let {
add(KotlinUFunctionCallExpression(it, uastParent))
}
bodyExpressions.forEach {
add(KotlinConverter.convertOrEmpty(it, uastParent))
}
}
}
}
override val uastAnchor: KotlinUIdentifier by lazy {
KotlinUIdentifier(
psi.nameIdentifier,
if (isPrimary) ktClass?.nameIdentifier else (sourcePsi as? KtSecondaryConstructor)?.getConstructorKeyword(),
this
)
}
override val javaPsi = psi
open protected fun getBodyExpressions(): List<KtExpression> {
if (isPrimary) return getInitializers()
val bodyExpression = (sourcePsi 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( class KotlinUAnonymousClass(
psi: PsiAnonymousClass, psi: PsiAnonymousClass,
givenParent: UElement? givenParent: UElement?
@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.uast.kotlin.declarations package org.jetbrains.uast.kotlin
import com.intellij.psi.* import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.elements.* import org.jetbrains.kotlin.asJava.elements.*
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.uast.* import org.jetbrains.uast.*
import org.jetbrains.uast.java.internal.JavaUElementWithComments import org.jetbrains.uast.java.internal.JavaUElementWithComments
import org.jetbrains.uast.kotlin.* import org.jetbrains.uast.kotlin.*
@@ -140,6 +141,76 @@ open class KotlinUMethod(
} }
} }
open class KotlinConstructorUMethod(
private val ktClass: KtClassOrObject?,
override val psi: PsiMethod,
kotlinOrigin: KtDeclaration?,
givenParent: UElement?
) : KotlinUMethod(psi, kotlinOrigin, givenParent) {
constructor(
ktClass: KtClassOrObject?,
psi: KtLightMethod,
givenParent: UElement?
) : this(ktClass, psi, psi.kotlinOrigin, givenParent)
val isPrimary: Boolean
get() = sourcePsi.let { it is KtPrimaryConstructor || it is KtClassOrObject }
override val uastBody: UExpression? by lz {
val delegationCall: KtCallElement? = sourcePsi.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
KotlinLazyUBlockExpression(this) { uastParent ->
SmartList<UExpression>().apply {
delegationCall?.let {
add(KotlinUFunctionCallExpression(it, uastParent))
}
bodyExpressions.forEach {
add(KotlinConverter.convertOrEmpty(it, uastParent))
}
}
}
}
override val uastAnchor: KotlinUIdentifier by lz {
KotlinUIdentifier(
psi.nameIdentifier,
if (isPrimary) ktClass?.nameIdentifier else (sourcePsi as? KtSecondaryConstructor)?.getConstructorKeyword(),
this
)
}
override val javaPsi = psi
protected open fun getBodyExpressions(): List<KtExpression> {
if (isPrimary) return getInitializers()
val bodyExpression = (sourcePsi 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()
}
open class KotlinUAnnotationMethod( open class KotlinUAnnotationMethod(
psi: KtLightMethod, psi: KtLightMethod,
givenParent: UElement? givenParent: UElement?