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.uast.*
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.psi.*
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.uast.*
import org.jetbrains.uast.kotlin.declarations.KotlinUMethod
import org.jetbrains.uast.kotlin.internal.multiResolveResults
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.load.java.JvmAbi
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.uast.*
import org.jetbrains.uast.internal.acceptList
import org.jetbrains.uast.kotlin.declarations.KotlinUMethod
import org.jetbrains.uast.visitor.UastVisitor
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(
psi: PsiAnonymousClass,
givenParent: UElement?
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.uast.kotlin.declarations
package org.jetbrains.uast.kotlin
import com.intellij.psi.*
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.getParentOfType
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.uast.*
import org.jetbrains.uast.java.internal.JavaUElementWithComments
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(
psi: KtLightMethod,
givenParent: UElement?