Uast: secondary constructors delegation support (KT-21409)

This commit is contained in:
Nicolay Mitropolsky
2017-11-24 16:54:43 +03:00
committed by xiexed
parent 3bfa5c4706
commit 1ce21583ad
3 changed files with 50 additions and 23 deletions
@@ -20,7 +20,6 @@ import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClassForScript 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.asJava.toLightMethods
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.SmartList
@@ -73,12 +72,10 @@ 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 primaryConstructor = ktClass?.primaryConstructor?.toLightMethods()?.firstOrNull()
fun createUMethod(psiMethod: PsiMethod): UMethod { fun createUMethod(psiMethod: PsiMethod): UMethod {
return if (psiMethod is KtLightMethod && return if (psiMethod is KtLightMethod &&
psiMethod.isConstructor && psiMethod.isConstructor) {
(primaryConstructor == null || psiMethod == primaryConstructor)) {
KotlinPrimaryConstructorUMethod(ktClass, psiMethod, this) KotlinPrimaryConstructorUMethod(ktClass, psiMethod, this)
} else { } else {
getLanguagePlugin().convert(psiMethod, this) getLanguagePlugin().convert(psiMethod, this)
@@ -111,22 +108,27 @@ class KotlinPrimaryConstructorUMethod(
override val uastParent: UElement? override val uastParent: UElement?
): KotlinUMethod(psi, uastParent) { ): KotlinUMethod(psi, uastParent) {
override val uastBody: UExpression? by lz { override val uastBody: UExpression? by lz {
val superTypeCallEntry = ktClass?.superTypeListEntries?.firstIsInstanceOrNull<KtSuperTypeCallEntry>() val delegationCall: KtCallElement? = psi.kotlinOrigin.let {
val initializers = ktClass?.getAnonymousInitializers()?.takeIf { it.isNotEmpty() } when (it) {
if (superTypeCallEntry != null || initializers != null) is KtPrimaryConstructor, is KtObjectDeclaration ->
KotlinUBlockExpression.KotlinLazyUBlockExpression(this) { uastParent -> ktClass?.superTypeListEntries?.firstIsInstanceOrNull<KtSuperTypeCallEntry>()
SmartList<UExpression>().apply { is KtSecondaryConstructor -> it.getDelegationCall()
superTypeCallEntry?.let { else -> null
add(KotlinUFunctionCallExpression(it, uastParent)) }
} }
val languagePlugin = uastParent.getLanguagePlugin() val initializers = ktClass?.getAnonymousInitializers().orEmpty()
initializers?.forEach { if (delegationCall == null && initializers.isEmpty()) return@lz null
addIfNotNull(languagePlugin.convertOpt(it.body, uastParent)) KotlinUBlockExpression.KotlinLazyUBlockExpression(this) { uastParent ->
} SmartList<UExpression>().apply {
delegationCall?.let {
add(KotlinUFunctionCallExpression(it, uastParent))
}
val languagePlugin = uastParent.getLanguagePlugin()
initializers.forEach {
addIfNotNull(languagePlugin.convertOpt(it.body, uastParent))
} }
} }
else }
null
} }
} }
+19
View File
@@ -23,6 +23,15 @@ UFile (package = )
UAnnotationMethod (name = A) UAnnotationMethod (name = A)
UParameter (name = i) UParameter (name = i)
UAnnotation (fqName = null) UAnnotation (fqName = null)
UBlockExpression
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1))
UIdentifier (Identifier (this))
USimpleNameReferenceExpression (identifier = <init>)
UQualifiedReferenceExpression
USimpleNameReferenceExpression (identifier = i)
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
UIdentifier (Identifier (toString))
USimpleNameReferenceExpression (identifier = toString)
UClass (name = B) UClass (name = B)
UAnnotationMethod (name = B) UAnnotationMethod (name = B)
UParameter (name = param) UParameter (name = param)
@@ -46,9 +55,19 @@ UFile (package = )
UAnnotationMethod (name = C) UAnnotationMethod (name = C)
UParameter (name = p) UParameter (name = p)
UAnnotation (fqName = org.jetbrains.annotations.NotNull) UAnnotation (fqName = org.jetbrains.annotations.NotNull)
UBlockExpression
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1))
UIdentifier (Identifier (super))
USimpleNameReferenceExpression (identifier = <init>)
USimpleNameReferenceExpression (identifier = p)
UAnnotationMethod (name = C) UAnnotationMethod (name = C)
UParameter (name = i) UParameter (name = i)
UAnnotation (fqName = null) UAnnotation (fqName = null)
UBlockExpression
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1))
UIdentifier (Identifier (super))
USimpleNameReferenceExpression (identifier = <init>)
USimpleNameReferenceExpression (identifier = i)
UClass (name = O) UClass (name = O)
UField (name = INSTANCE) UField (name = INSTANCE)
UAnnotation (fqName = null) UAnnotation (fqName = null)
+11 -5
View File
@@ -1,6 +1,6 @@
public final class SuperCallsKt { public final class SuperCallsKt {
private static final var anon: A = anonymous object : A ("textForAnon"){ private static final var anon: A = anonymous object : A("textForAnon") {
fun bar(){} fun bar() {}
} }
public static final fun getAnon() : A = UastEmptyExpression public static final fun getAnon() : A = UastEmptyExpression
} }
@@ -11,7 +11,9 @@ public class A {
} }
public final fun getStr() : java.lang.String = UastEmptyExpression public final fun getStr() : java.lang.String = UastEmptyExpression
public fun A(str: java.lang.String) = UastEmptyExpression public fun A(str: java.lang.String) = UastEmptyExpression
public fun A(i: int) = UastEmptyExpression public fun A(i: int) {
<init>(i.toString())
}
} }
public final class B : A { public final class B : A {
@@ -24,8 +26,12 @@ public final class C : A {
public fun foo(a: long) : void { public fun foo(a: long) : void {
super.foo(a) super.foo(a)
} }
public fun C(p: java.lang.String) = UastEmptyExpression public fun C(p: java.lang.String) {
public fun C(i: int) = UastEmptyExpression <init>(p)
}
public fun C(i: int) {
<init>(i)
}
} }
public final class O : A { public final class O : A {