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:
Nicolay Mitropolsky
2017-12-05 12:22:36 +03:00
committed by xiexed
parent b8069b48c5
commit 209ba89a49
5 changed files with 39 additions and 6 deletions
@@ -81,11 +81,16 @@ open class KotlinUClass private constructor(
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) {
KotlinConstructorUMethod(ktClass, psiMethod, this)
if (!hasPrimaryConstructor && secondaryConstructorsCount++ == 0)
KotlinSecondaryConstructorWithInitializersUMethod(ktClass, psiMethod, this)
else
KotlinConstructorUMethod(ktClass, psiMethod, this)
} else {
getLanguagePlugin().convert(psiMethod, this)
}
@@ -111,7 +116,7 @@ open class KotlinUClass private constructor(
}
}
class KotlinConstructorUMethod(
open class KotlinConstructorUMethod(
private val ktClass: KtClassOrObject?,
override val psi: KtLightMethod,
givenParent: UElement?
@@ -143,17 +148,28 @@ class KotlinConstructorUMethod(
}
}
private fun getBodyExpressions(): List<KtExpression> {
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)
}
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(
psi: PsiAnonymousClass,
givenParent: UElement?
@@ -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
}
}
-2
View File
@@ -58,8 +58,6 @@ class AWithSecondaryInit {
lateinit var a: String
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()
}
+4
View File
@@ -130,6 +130,10 @@ UFile (package = )
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0))
UIdentifier (Identifier ())
USimpleNameReferenceExpression (identifier = <init>)
UBlockExpression
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
UIdentifier (Identifier (println))
USimpleNameReferenceExpression (identifier = println)
UBinaryExpression (operator = =)
USimpleNameReferenceExpression (identifier = a)
UQualifiedReferenceExpression
+3
View File
@@ -67,6 +67,9 @@ public final class AWithSecondaryInit {
public final fun setA(p: java.lang.String) : void = UastEmptyExpression
public fun AWithSecondaryInit(i: int) {
<init>()
{
println()
}
a = i.toString()
}
public fun AWithSecondaryInit(s: java.lang.String) {