FIR/UAST: commonize constructor declarations
This commit is contained in:
committed by
Ilya Kirillov
parent
cbaa645dbe
commit
5ec5b7f041
+70
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.uast.kotlin
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiMethod
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
|
import org.jetbrains.uast.UElement
|
||||||
|
import org.jetbrains.uast.UExpression
|
||||||
|
import org.jetbrains.uast.UIdentifier
|
||||||
|
|
||||||
|
abstract class BaseKotlinConstructorUMethod(
|
||||||
|
private val ktClass: KtClassOrObject?,
|
||||||
|
override val psi: PsiMethod,
|
||||||
|
kotlinOrigin: KtDeclaration?,
|
||||||
|
givenParent: UElement?
|
||||||
|
) : BaseKotlinUMethod(psi, kotlinOrigin, givenParent) {
|
||||||
|
|
||||||
|
override val javaPsi = psi
|
||||||
|
|
||||||
|
val isPrimary: Boolean
|
||||||
|
get() = sourcePsi is KtPrimaryConstructor || sourcePsi 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(buildDelegationCall(it, uastParent))
|
||||||
|
}
|
||||||
|
bodyExpressions.forEach {
|
||||||
|
add(baseResolveProviderService.baseKotlinConverter.convertOrEmpty(it, uastParent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun buildDelegationCall(delegationCall: KtCallElement, uastParent: UElement): UExpression
|
||||||
|
|
||||||
|
override val uastAnchor: UIdentifier? by lz {
|
||||||
|
KotlinUIdentifier(
|
||||||
|
javaPsi.nameIdentifier,
|
||||||
|
if (isPrimary) ktClass?.nameIdentifier else (sourcePsi as? KtSecondaryConstructor)?.getConstructorKeyword(),
|
||||||
|
this
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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(): List<KtExpression> {
|
||||||
|
return ktClass?.getAnonymousInitializers()?.mapNotNull { it.body } ?: emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.uast.kotlin
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
import org.jetbrains.uast.UElement
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
abstract class BaseKotlinSecondaryConstructorWithInitializersUMethod(
|
||||||
|
ktClass: KtClassOrObject?,
|
||||||
|
psi: KtLightMethod,
|
||||||
|
givenParent: UElement?
|
||||||
|
) : BaseKotlinConstructorUMethod(ktClass, psi, psi.kotlinOrigin, givenParent) {
|
||||||
|
|
||||||
|
override fun getBodyExpressions(): List<KtExpression> {
|
||||||
|
return getInitializers() + super.getBodyExpressions()
|
||||||
|
}
|
||||||
|
}
|
||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.uast.kotlin
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiMethod
|
||||||
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||||
|
import org.jetbrains.kotlin.psi.KtCallElement
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
|
import org.jetbrains.uast.UElement
|
||||||
|
import org.jetbrains.uast.UExpression
|
||||||
|
import org.jetbrains.uast.UParameter
|
||||||
|
import org.jetbrains.uast.UastEmptyExpression
|
||||||
|
|
||||||
|
class FirKotlinConstructorUMethod(
|
||||||
|
ktClass: KtClassOrObject?,
|
||||||
|
psi: PsiMethod,
|
||||||
|
kotlinOrigin: KtDeclaration?,
|
||||||
|
givenParent: UElement?
|
||||||
|
) : BaseKotlinConstructorUMethod(ktClass, psi, kotlinOrigin, givenParent), FirKotlinUMethodParametersProducer {
|
||||||
|
constructor(
|
||||||
|
ktClass: KtClassOrObject?,
|
||||||
|
psi: KtLightMethod,
|
||||||
|
givenParent: UElement?
|
||||||
|
) : this(ktClass, psi, psi.kotlinOrigin, givenParent)
|
||||||
|
|
||||||
|
override val uastParameters: List<UParameter> by lz { produceUastParameters(this, receiverTypeReference) }
|
||||||
|
|
||||||
|
override fun buildDelegationCall(delegationCall: KtCallElement, uastParent: UElement): UExpression {
|
||||||
|
return UastEmptyExpression(uastParent)
|
||||||
|
}
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.uast.kotlin
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||||
|
import org.jetbrains.kotlin.psi.KtCallElement
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.uast.UElement
|
||||||
|
import org.jetbrains.uast.UExpression
|
||||||
|
import org.jetbrains.uast.UParameter
|
||||||
|
import org.jetbrains.uast.UastEmptyExpression
|
||||||
|
|
||||||
|
class FirKotlinSecondaryConstructorWithInitializersUMethod(
|
||||||
|
ktClass: KtClassOrObject?,
|
||||||
|
psi: KtLightMethod,
|
||||||
|
givenParent: UElement?
|
||||||
|
) : BaseKotlinSecondaryConstructorWithInitializersUMethod(ktClass, psi, givenParent), FirKotlinUMethodParametersProducer {
|
||||||
|
override val uastParameters: List<UParameter> by lz { produceUastParameters(this, receiverTypeReference) }
|
||||||
|
|
||||||
|
override fun buildDelegationCall(delegationCall: KtCallElement, uastParent: UElement): UExpression {
|
||||||
|
return UastEmptyExpression(uastParent)
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-88
@@ -10,35 +10,25 @@ import org.jetbrains.kotlin.asJava.LightClassUtil
|
|||||||
import org.jetbrains.kotlin.asJava.elements.*
|
import org.jetbrains.kotlin.asJava.elements.*
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
import org.jetbrains.kotlin.utils.SmartList
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
|
||||||
import org.jetbrains.uast.*
|
import org.jetbrains.uast.*
|
||||||
|
|
||||||
open class FirKotlinUMethod(
|
class FirKotlinUMethod(
|
||||||
psi: PsiMethod,
|
psi: PsiMethod,
|
||||||
sourcePsi: KtDeclaration?,
|
sourcePsi: KtDeclaration?,
|
||||||
givenParent: UElement?
|
givenParent: UElement?
|
||||||
) : BaseKotlinUMethod(psi, sourcePsi, givenParent) {
|
) : BaseKotlinUMethod(psi, sourcePsi, givenParent), FirKotlinUMethodParametersProducer {
|
||||||
constructor(
|
constructor(
|
||||||
psi: KtLightMethod,
|
psi: KtLightMethod,
|
||||||
givenParent: UElement?
|
givenParent: UElement?
|
||||||
) : this(psi, getKotlinMemberOrigin(psi), givenParent)
|
) : this(psi, getKotlinMemberOrigin(psi), givenParent)
|
||||||
|
|
||||||
override val uastParameters: List<UParameter> by lz {
|
override val uastParameters: List<UParameter> by lz { produceUastParameters(this, receiverTypeReference) }
|
||||||
val lightParams = psi.parameterList.parameters
|
|
||||||
val receiverTypeReference =
|
|
||||||
receiverTypeReference ?: return@lz lightParams.map { FirKotlinUParameter(it, getKotlinMemberOrigin(it), this) }
|
|
||||||
val lightReceiver = lightParams.firstOrNull() ?: return@lz emptyList<UParameter>()
|
|
||||||
val uParameters = SmartList<UParameter>(FirKotlinReceiverUParameter(lightReceiver, receiverTypeReference, this))
|
|
||||||
lightParams.drop(1).mapTo(uParameters) { FirKotlinUParameter(it, getKotlinMemberOrigin(it), this) }
|
|
||||||
uParameters
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun create(
|
fun create(
|
||||||
psi: KtLightMethod,
|
psi: KtLightMethod,
|
||||||
givenParent: UElement?
|
givenParent: UElement?
|
||||||
): FirKotlinUMethod {
|
): UMethod {
|
||||||
return when (psi) {
|
return when (psi) {
|
||||||
is KtConstructor<*> ->
|
is KtConstructor<*> ->
|
||||||
FirKotlinConstructorUMethod(psi.containingClassOrObject, psi, givenParent)
|
FirKotlinConstructorUMethod(psi.containingClassOrObject, psi, givenParent)
|
||||||
@@ -51,7 +41,7 @@ open class FirKotlinUMethod(
|
|||||||
fun create(
|
fun create(
|
||||||
sourcePsi: KtDeclaration?,
|
sourcePsi: KtDeclaration?,
|
||||||
givenParent: UElement?
|
givenParent: UElement?
|
||||||
): FirKotlinUMethod? {
|
): UMethod? {
|
||||||
val javaPsi = when (sourcePsi) {
|
val javaPsi = when (sourcePsi) {
|
||||||
is KtPropertyAccessor ->
|
is KtPropertyAccessor ->
|
||||||
LightClassUtil.getLightClassAccessorMethod(sourcePsi)
|
LightClassUtil.getLightClassAccessorMethod(sourcePsi)
|
||||||
@@ -69,76 +59,3 @@ open class FirKotlinUMethod(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: can be commonized if *KotlinUMethod is commonized
|
|
||||||
open class FirKotlinConstructorUMethod(
|
|
||||||
private val ktClass: KtClassOrObject?,
|
|
||||||
override val psi: PsiMethod,
|
|
||||||
kotlinOrigin: KtDeclaration?,
|
|
||||||
givenParent: UElement?
|
|
||||||
) : FirKotlinUMethod(psi, kotlinOrigin, givenParent) {
|
|
||||||
constructor(
|
|
||||||
ktClass: KtClassOrObject?,
|
|
||||||
psi: KtLightMethod,
|
|
||||||
givenParent: UElement?
|
|
||||||
) : this(ktClass, psi, psi.kotlinOrigin, givenParent)
|
|
||||||
|
|
||||||
override val javaPsi = psi
|
|
||||||
|
|
||||||
val isPrimary: Boolean
|
|
||||||
get() = sourcePsi is KtPrimaryConstructor || sourcePsi 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 {
|
|
||||||
// TODO: function call for delegationCall
|
|
||||||
add(UastEmptyExpression(uastParent))
|
|
||||||
}
|
|
||||||
bodyExpressions.forEach {
|
|
||||||
add(baseResolveProviderService.baseKotlinConverter.convertOrEmpty(it, uastParent))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override val uastAnchor: UIdentifier? by lz {
|
|
||||||
KotlinUIdentifier(
|
|
||||||
javaPsi.nameIdentifier,
|
|
||||||
if (isPrimary) ktClass?.nameIdentifier else (sourcePsi as? KtSecondaryConstructor)?.getConstructorKeyword(),
|
|
||||||
this
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
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(): List<KtExpression> {
|
|
||||||
return ktClass?.getAnonymousInitializers()?.mapNotNull { it.body } ?: emptyList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: can be commonized if *KotlinUMethod is commonized
|
|
||||||
// also reuse the comments there (about KT-21617)
|
|
||||||
class FirKotlinSecondaryConstructorWithInitializersUMethod(
|
|
||||||
ktClass: KtClassOrObject?,
|
|
||||||
psi: KtLightMethod,
|
|
||||||
givenParent: UElement?
|
|
||||||
) : FirKotlinConstructorUMethod(ktClass, psi, givenParent) {
|
|
||||||
override fun getBodyExpressions(): List<KtExpression> {
|
|
||||||
return getInitializers() + super.getBodyExpressions()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.uast.kotlin
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||||
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
|
import org.jetbrains.uast.UParameter
|
||||||
|
|
||||||
|
internal interface FirKotlinUMethodParametersProducer {
|
||||||
|
fun produceUastParameters(uMethod: BaseKotlinUMethod, receiverTypeReference: KtTypeReference?): List<UParameter> {
|
||||||
|
val lightParams = uMethod.psi.parameterList.parameters
|
||||||
|
val receiver = receiverTypeReference ?: return lightParams.map { FirKotlinUParameter(it, getKotlinMemberOrigin(it), uMethod) }
|
||||||
|
val lightReceiver = lightParams.firstOrNull() ?: return emptyList()
|
||||||
|
val uParameters = SmartList<UParameter>(FirKotlinReceiverUParameter(lightReceiver, receiver, uMethod))
|
||||||
|
lightParams.drop(1).mapTo(uParameters) { FirKotlinUParameter(it, getKotlinMemberOrigin(it), uMethod) }
|
||||||
|
return uParameters
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.uast.kotlin
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiMethod
|
||||||
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||||
|
import org.jetbrains.kotlin.psi.KtCallElement
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
|
import org.jetbrains.uast.UElement
|
||||||
|
import org.jetbrains.uast.UExpression
|
||||||
|
|
||||||
|
class KotlinConstructorUMethod(
|
||||||
|
ktClass: KtClassOrObject?,
|
||||||
|
psi: PsiMethod,
|
||||||
|
kotlinOrigin: KtDeclaration?,
|
||||||
|
givenParent: UElement?
|
||||||
|
) : BaseKotlinConstructorUMethod(ktClass, psi, kotlinOrigin, givenParent), KotlinUMethodParametersProducer {
|
||||||
|
constructor(
|
||||||
|
ktClass: KtClassOrObject?,
|
||||||
|
psi: KtLightMethod,
|
||||||
|
givenParent: UElement?
|
||||||
|
) : this(ktClass, psi, psi.kotlinOrigin, givenParent)
|
||||||
|
|
||||||
|
override val uastParameters by lz { produceUastParameters(this, receiverTypeReference) }
|
||||||
|
|
||||||
|
override fun buildDelegationCall(delegationCall: KtCallElement, uastParent: UElement): UExpression {
|
||||||
|
return KotlinUFunctionCallExpression(delegationCall, uastParent)
|
||||||
|
}
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.uast.kotlin
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||||
|
import org.jetbrains.kotlin.psi.KtCallElement
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.uast.UElement
|
||||||
|
import org.jetbrains.uast.UExpression
|
||||||
|
|
||||||
|
class KotlinSecondaryConstructorWithInitializersUMethod(
|
||||||
|
ktClass: KtClassOrObject?,
|
||||||
|
psi: KtLightMethod,
|
||||||
|
givenParent: UElement?
|
||||||
|
) : BaseKotlinSecondaryConstructorWithInitializersUMethod(ktClass, psi, givenParent), KotlinUMethodParametersProducer {
|
||||||
|
|
||||||
|
override val uastParameters by lz { produceUastParameters(this, receiverTypeReference) }
|
||||||
|
|
||||||
|
override fun buildDelegationCall(delegationCall: KtCallElement, uastParent: UElement): UExpression {
|
||||||
|
return KotlinUFunctionCallExpression(delegationCall, uastParent)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,41 +21,24 @@ import org.jetbrains.kotlin.asJava.elements.*
|
|||||||
import org.jetbrains.kotlin.psi.*
|
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.addToStdlib.firstIsInstanceOrNull
|
|
||||||
import org.jetbrains.uast.*
|
import org.jetbrains.uast.*
|
||||||
import org.jetbrains.uast.kotlin.*
|
import org.jetbrains.uast.kotlin.*
|
||||||
import org.jetbrains.uast.kotlin.psi.UastFakeLightMethod
|
import org.jetbrains.uast.kotlin.psi.UastFakeLightMethod
|
||||||
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter
|
|
||||||
|
|
||||||
open class KotlinUMethod(
|
open class KotlinUMethod(
|
||||||
psi: PsiMethod,
|
psi: PsiMethod,
|
||||||
sourcePsi: KtDeclaration?,
|
sourcePsi: KtDeclaration?,
|
||||||
givenParent: UElement?
|
givenParent: UElement?
|
||||||
) : BaseKotlinUMethod(psi, sourcePsi, givenParent) {
|
) : BaseKotlinUMethod(psi, sourcePsi, givenParent), KotlinUMethodParametersProducer {
|
||||||
constructor(
|
constructor(
|
||||||
psi: KtLightMethod,
|
psi: KtLightMethod,
|
||||||
givenParent: UElement?
|
givenParent: UElement?
|
||||||
) : this(psi, getKotlinMemberOrigin(psi), givenParent)
|
) : this(psi, getKotlinMemberOrigin(psi), givenParent)
|
||||||
|
|
||||||
override val uastParameters by lz {
|
override val uastParameters by lz { produceUastParameters(this, receiverTypeReference) }
|
||||||
|
|
||||||
fun parameterOrigin(psiParameter: PsiParameter?): KtElement? = when (psiParameter) {
|
|
||||||
is KtLightElement<*, *> -> psiParameter.kotlinOrigin
|
|
||||||
is UastKotlinPsiParameter -> psiParameter.ktParameter
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
|
|
||||||
val lightParams = psi.parameterList.parameters
|
|
||||||
val receiver = receiverTypeReference ?: return@lz lightParams.map { KotlinUParameter(it, parameterOrigin(it), this) }
|
|
||||||
val receiverLight = lightParams.firstOrNull() ?: return@lz emptyList<UParameter>()
|
|
||||||
val uParameters = SmartList<UParameter>(KotlinReceiverUParameter(receiverLight, receiver, this))
|
|
||||||
lightParams.drop(1).mapTo(uParameters) { KotlinUParameter(it, parameterOrigin(it), this) }
|
|
||||||
uParameters
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun create(psi: KtLightMethod, containingElement: UElement?): KotlinUMethod {
|
fun create(psi: KtLightMethod, containingElement: UElement?): UMethod {
|
||||||
val kotlinOrigin = psi.kotlinOrigin
|
val kotlinOrigin = psi.kotlinOrigin
|
||||||
return if (kotlinOrigin is KtConstructor<*>) {
|
return if (kotlinOrigin is KtConstructor<*>) {
|
||||||
KotlinConstructorUMethod(
|
KotlinConstructorUMethod(
|
||||||
@@ -71,76 +54,6 @@ 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?
|
||||||
|
|||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.uast.kotlin
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiParameter
|
||||||
|
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
||||||
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
|
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||||
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
|
import org.jetbrains.uast.UParameter
|
||||||
|
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter
|
||||||
|
|
||||||
|
internal interface KotlinUMethodParametersProducer {
|
||||||
|
fun produceUastParameters(uMethod: BaseKotlinUMethod, receiverTypeReference: KtTypeReference?): List<UParameter> {
|
||||||
|
|
||||||
|
fun parameterOrigin(psiParameter: PsiParameter?): KtElement? = when (psiParameter) {
|
||||||
|
is KtLightElement<*, *> -> psiParameter.kotlinOrigin
|
||||||
|
is UastKotlinPsiParameter -> psiParameter.ktParameter
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
val lightParams = uMethod.psi.parameterList.parameters
|
||||||
|
val receiver = receiverTypeReference ?: return lightParams.map { KotlinUParameter(it, parameterOrigin(it), uMethod) }
|
||||||
|
val receiverLight = lightParams.firstOrNull() ?: return emptyList()
|
||||||
|
val uParameters = SmartList<UParameter>(KotlinReceiverUParameter(receiverLight, receiver, uMethod))
|
||||||
|
lightParams.drop(1).mapTo(uParameters) { KotlinUParameter(it, parameterOrigin(it), uMethod) }
|
||||||
|
return uParameters
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user