Uast: KotlinSecondaryConstructorWithInitializersUMethod introduced as workaround for KT-21617
to be the only constructor which includes `init` block when there is no primary constructors in the class
This commit is contained in:
committed by
xiexed
parent
b8069b48c5
commit
209ba89a49
@@ -81,11 +81,16 @@ open class KotlinUClass private constructor(
|
|||||||
override fun getInitializers(): Array<UClassInitializer> = super.getInitializers()
|
override fun getInitializers(): Array<UClassInitializer> = super.getInitializers()
|
||||||
|
|
||||||
override fun getMethods(): Array<UMethod> {
|
override fun getMethods(): Array<UMethod> {
|
||||||
|
val hasPrimaryConstructor = ktClass?.hasPrimaryConstructor() ?: false
|
||||||
|
var secondaryConstructorsCount = 0
|
||||||
|
|
||||||
fun createUMethod(psiMethod: PsiMethod): UMethod {
|
fun createUMethod(psiMethod: PsiMethod): UMethod {
|
||||||
return if (psiMethod is KtLightMethod &&
|
return if (psiMethod is KtLightMethod &&
|
||||||
psiMethod.isConstructor) {
|
psiMethod.isConstructor) {
|
||||||
KotlinConstructorUMethod(ktClass, psiMethod, this)
|
if (!hasPrimaryConstructor && secondaryConstructorsCount++ == 0)
|
||||||
|
KotlinSecondaryConstructorWithInitializersUMethod(ktClass, psiMethod, this)
|
||||||
|
else
|
||||||
|
KotlinConstructorUMethod(ktClass, psiMethod, this)
|
||||||
} else {
|
} else {
|
||||||
getLanguagePlugin().convert(psiMethod, this)
|
getLanguagePlugin().convert(psiMethod, this)
|
||||||
}
|
}
|
||||||
@@ -111,7 +116,7 @@ open class KotlinUClass private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class KotlinConstructorUMethod(
|
open class KotlinConstructorUMethod(
|
||||||
private val ktClass: KtClassOrObject?,
|
private val ktClass: KtClassOrObject?,
|
||||||
override val psi: KtLightMethod,
|
override val psi: KtLightMethod,
|
||||||
givenParent: UElement?
|
givenParent: UElement?
|
||||||
@@ -143,17 +148,28 @@ class KotlinConstructorUMethod(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getBodyExpressions(): List<KtExpression> {
|
open protected fun getBodyExpressions(): List<KtExpression> {
|
||||||
if (isPrimary) return getInitializers()
|
if (isPrimary) return getInitializers()
|
||||||
val bodyExpression = (psi.kotlinOrigin as? KtFunction)?.bodyExpression ?: return emptyList()
|
val bodyExpression = (psi.kotlinOrigin as? KtFunction)?.bodyExpression ?: return emptyList()
|
||||||
if (bodyExpression is KtBlockExpression) return bodyExpression.statements
|
if (bodyExpression is KtBlockExpression) return bodyExpression.statements
|
||||||
return listOf(bodyExpression)
|
return listOf(bodyExpression)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getInitializers() = ktClass?.getAnonymousInitializers()?.mapNotNull { it.body } ?: emptyList()
|
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?
|
||||||
|
|||||||
+12
@@ -44,4 +44,16 @@ class KotlinUBlockExpression(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun convertParent(): UElement? {
|
||||||
|
val directParent = super.convertParent()
|
||||||
|
if (directParent is UnknownKotlinExpression && directParent.psi is KtAnonymousInitializer) {
|
||||||
|
val containingUClass = directParent.getContainingUClass() ?: return directParent
|
||||||
|
containingUClass.methods
|
||||||
|
.find { it is KotlinConstructorUMethod && it.isPrimary || it is KotlinSecondaryConstructorWithInitializersUMethod }?.let {
|
||||||
|
return it.uastBody
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return directParent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -58,8 +58,6 @@ class AWithSecondaryInit {
|
|||||||
lateinit var a: String
|
lateinit var a: String
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// This body will not be picked by UAST because no lightMethod contains it.
|
|
||||||
// Of course it is not a desired behaviour, so fix it if you know how
|
|
||||||
println()
|
println()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -130,6 +130,10 @@ UFile (package = )
|
|||||||
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0))
|
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0))
|
||||||
UIdentifier (Identifier ())
|
UIdentifier (Identifier ())
|
||||||
USimpleNameReferenceExpression (identifier = <init>)
|
USimpleNameReferenceExpression (identifier = <init>)
|
||||||
|
UBlockExpression
|
||||||
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||||
|
UIdentifier (Identifier (println))
|
||||||
|
USimpleNameReferenceExpression (identifier = println)
|
||||||
UBinaryExpression (operator = =)
|
UBinaryExpression (operator = =)
|
||||||
USimpleNameReferenceExpression (identifier = a)
|
USimpleNameReferenceExpression (identifier = a)
|
||||||
UQualifiedReferenceExpression
|
UQualifiedReferenceExpression
|
||||||
|
|||||||
@@ -67,6 +67,9 @@ public final class AWithSecondaryInit {
|
|||||||
public final fun setA(p: java.lang.String) : void = UastEmptyExpression
|
public final fun setA(p: java.lang.String) : void = UastEmptyExpression
|
||||||
public fun AWithSecondaryInit(i: int) {
|
public fun AWithSecondaryInit(i: int) {
|
||||||
<init>()
|
<init>()
|
||||||
|
{
|
||||||
|
println()
|
||||||
|
}
|
||||||
a = i.toString()
|
a = i.toString()
|
||||||
}
|
}
|
||||||
public fun AWithSecondaryInit(s: java.lang.String) {
|
public fun AWithSecondaryInit(s: java.lang.String) {
|
||||||
|
|||||||
Reference in New Issue
Block a user