Uast: constructors calls consistency except anonymous object literals (KT-21409)

This commit is contained in:
Nicolay Mitropolsky
2017-11-27 13:07:59 +03:00
committed by xiexed
parent 77be33d433
commit 1dbce18afc
6 changed files with 43 additions and 10 deletions
@@ -66,6 +66,10 @@ abstract class KotlinAbstractUElement(private val givenParent: UElement?) : UEle
parent = parent.parent
}
if (psi is KtSuperTypeCallEntry) {
parent = parent?.parent
}
val result = doConvertParent(this, parent)
if (result == this) {
throw IllegalStateException("Loop in parent structure when converting a $psi of type ${psi?.javaClass} with parent $parent of type ${parent?.javaClass} text: [${parent?.text}]")
@@ -309,6 +309,10 @@ internal object KotlinConverter {
is KtWhenEntry -> el<USwitchClauseExpressionWithBody>(build(::KotlinUSwitchEntry))
is KtWhenCondition -> convertWhenCondition(element, givenParent, requiredType)
is KtTypeReference -> el<UTypeReferenceExpression> { LazyKotlinUTypeReferenceExpression(element, givenParent) }
is KtConstructorDelegationCall ->
el<UCallExpression> { KotlinUFunctionCallExpression(element, givenParent) }
is KtSuperTypeCallEntry ->
el<UCallExpression> { KotlinUFunctionCallExpression(element, givenParent) }
else -> {
if (element is LeafPsiElement && element.elementType == KtTokens.IDENTIFIER) {
@@ -105,18 +105,17 @@ open class KotlinUClass private constructor(
class KotlinConstructorUMethod(
private val ktClass: KtClassOrObject?,
override val psi: KtLightMethod,
override val uastParent: UElement?
): KotlinUMethod(psi, uastParent) {
givenParent: UElement?
) : KotlinUMethod(psi, givenParent) {
val isPrimary: Boolean
get() = psi.kotlinOrigin is KtPrimaryConstructor
get() = psi.kotlinOrigin.let { it is KtPrimaryConstructor || it is KtObjectDeclaration }
override val uastBody: UExpression? by lz {
val delegationCall: KtCallElement? = psi.kotlinOrigin.let {
when (it) {
is KtPrimaryConstructor, is KtObjectDeclaration ->
ktClass?.superTypeListEntries?.firstIsInstanceOrNull<KtSuperTypeCallEntry>()
is KtSecondaryConstructor -> it.getDelegationCall()
when {
isPrimary -> ktClass?.superTypeListEntries?.firstIsInstanceOrNull<KtSuperTypeCallEntry>()
it is KtSecondaryConstructor -> it.getDelegationCall()
else -> null
}
}
@@ -16,13 +16,17 @@
package org.jetbrains.uast.kotlin.declarations
import com.intellij.psi.*
import com.intellij.psi.PsiCodeBlock
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.elements.isGetter
import org.jetbrains.kotlin.asJava.elements.isSetter
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.uast.*
import org.jetbrains.uast.java.annotations
import org.jetbrains.uast.java.internal.JavaUElementWithComments
@@ -84,6 +88,14 @@ open class KotlinUMethod(
override fun equals(other: Any?) = other is KotlinUMethod && psi == other.psi
companion object {
fun create(psi: KtLightMethod, containingElement: UElement?) = KotlinUMethod(psi, containingElement)
fun create(psi: KtLightMethod, containingElement: UElement?) =
if (psi.kotlinOrigin is KtConstructor<*>) {
KotlinConstructorUMethod(
psi.kotlinOrigin?.containingClassOrObject,
psi, containingElement
)
}
else
KotlinUMethod(psi, containingElement)
}
}
@@ -124,4 +124,18 @@ class KotlinUFunctionCallExpression(
// KtAnnotationEntry -> KtValueArgumentList -> KtValueArgument -> arrayOf call
return psi.parents.elementAtOrNull(2) is KtAnnotationEntry && CompileTimeConstantUtils.isArrayFunctionCall(resolvedCall)
}
override fun convertParent(): UElement? = super.convertParent().let { result ->
when (result) {
is UMethod -> result.uastBody ?: result
is UClass ->
result.methods
.filterIsInstance<KotlinConstructorUMethod>()
.firstOrNull { it.isPrimary }
?.uastBody
?: result
else -> result
}
}
}
@@ -55,5 +55,5 @@ class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() {
fun testWhenAndDestructing() = doTest("WhenAndDestructing") { testName, file -> check(testName, file, false) }
@Test
fun testSuperCalls() = doTest("SuperCalls") { testName, file -> check(testName, file, false) }
fun testSuperCalls() = doTest("SuperCalls")
}