From 3bfa5c4706d6b0623aa036aab50748f7417f4832 Mon Sep 17 00:00:00 2001 From: Nicolay Mitropolsky Date: Fri, 24 Nov 2017 13:02:01 +0300 Subject: [PATCH] Uast: parsing primary constructors superCalls (KT-21409) --- .../uast/kotlin/declarations/KotlinUClass.kt | 22 ++++++- .../expressions/KotlinUBlockExpression.kt | 4 +- .../KotlinUFunctionCallExpression.kt | 6 +- .../KotlinUSimpleReferenceExpression.kt | 2 +- plugins/uast-kotlin/testData/SuperCalls.kt | 25 ++++++++ .../uast-kotlin/testData/SuperCalls.log.txt | 60 +++++++++++++++++++ .../testData/SuperCalls.render.txt | 36 +++++++++++ .../tests/SimpleKotlinRenderLogTest.kt | 7 +-- 8 files changed, 149 insertions(+), 13 deletions(-) create mode 100644 plugins/uast-kotlin/testData/SuperCalls.kt create mode 100644 plugins/uast-kotlin/testData/SuperCalls.log.txt create mode 100644 plugins/uast-kotlin/testData/SuperCalls.render.txt diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt index 770cf815116..42d529e25bd 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt @@ -23,6 +23,9 @@ import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.toLightMethods import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.utils.SmartList +import org.jetbrains.kotlin.utils.addIfNotNull +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.uast.* import org.jetbrains.uast.java.AbstractJavaUClass import org.jetbrains.uast.kotlin.declarations.KotlinUMethod @@ -108,9 +111,22 @@ class KotlinPrimaryConstructorUMethod( override val uastParent: UElement? ): KotlinUMethod(psi, uastParent) { override val uastBody: UExpression? by lz { - ktClass?.getAnonymousInitializers() - ?.takeIf { it.isNotEmpty() } - ?.let { KotlinUBlockExpression.create(it, this) } + val superTypeCallEntry = ktClass?.superTypeListEntries?.firstIsInstanceOrNull() + val initializers = ktClass?.getAnonymousInitializers()?.takeIf { it.isNotEmpty() } + if (superTypeCallEntry != null || initializers != null) + KotlinUBlockExpression.KotlinLazyUBlockExpression(this) { uastParent -> + SmartList().apply { + superTypeCallEntry?.let { + add(KotlinUFunctionCallExpression(it, uastParent)) + } + val languagePlugin = uastParent.getLanguagePlugin() + initializers?.forEach { + addIfNotNull(languagePlugin.convertOpt(it.body, uastParent)) + } + } + } + else + null } } diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBlockExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBlockExpression.kt index aff3515ff67..480f0d73ae9 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBlockExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBlockExpression.kt @@ -27,9 +27,9 @@ class KotlinUBlockExpression( ) : KotlinAbstractUExpression(givenParent), UBlockExpression, KotlinUElementWithType { override val expressions by lz { psi.statements.map { KotlinConverter.convertOrEmpty(it, this) } } - private class KotlinLazyUBlockExpression( + class KotlinLazyUBlockExpression( override val uastParent: UElement?, - expressionProducer: (expressionParent: UElement?) -> List + expressionProducer: (expressionParent: UElement) -> List ) : UBlockExpression { override val psi: PsiElement? = null override val annotations: List = emptyList() diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt index 53c725d6c24..e482d5f99a2 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.psi.KtAnnotationEntry -import org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.psi.KtCallElement import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.psiUtil.parents @@ -36,7 +36,7 @@ import org.jetbrains.uast.internal.acceptList import org.jetbrains.uast.visitor.UastVisitor class KotlinUFunctionCallExpression( - override val psi: KtCallExpression, + override val psi: KtCallElement, givenParent: UElement?, private val _resolvedCall: ResolvedCall<*>? ) : KotlinAbstractUExpression(givenParent), UCallExpression, KotlinUElementWithType { @@ -56,7 +56,7 @@ class KotlinUFunctionCallExpression( } } - constructor(psi: KtCallExpression, uastParent: UElement?): this(psi, uastParent, null) + constructor(psi: KtCallElement, uastParent: UElement?) : this(psi, uastParent, null) private val resolvedCall by lz { _resolvedCall ?: psi.getResolvedCall(psi.analyze()) diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSimpleReferenceExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSimpleReferenceExpression.kt index fc856f28bab..5756815f8b2 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSimpleReferenceExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSimpleReferenceExpression.kt @@ -189,7 +189,7 @@ open class KotlinUSimpleReferenceExpression( } class KotlinClassViaConstructorUSimpleReferenceExpression( - override val psi: KtCallExpression, + override val psi: KtCallElement, override val identifier: String, givenParent: UElement? ) : KotlinAbstractUExpression(givenParent), USimpleNameReferenceExpression, KotlinUElementWithType { diff --git a/plugins/uast-kotlin/testData/SuperCalls.kt b/plugins/uast-kotlin/testData/SuperCalls.kt new file mode 100644 index 00000000000..04b19044396 --- /dev/null +++ b/plugins/uast-kotlin/testData/SuperCalls.kt @@ -0,0 +1,25 @@ +open class A(val str: String) { + + constructor(i: Int) : this(i.toString()) + + open fun foo(a: Long) {} + +} + +class B(param: String) : A(param) + +class C : A { + constructor(p: String) : super(p) + + constructor(i: Int) : super(i) + + override fun foo(a: Long) { + super.foo(a) + } +} + +object O : A("text") + +val anon = object : A("textForAnon") { + fun bar() {} +} \ No newline at end of file diff --git a/plugins/uast-kotlin/testData/SuperCalls.log.txt b/plugins/uast-kotlin/testData/SuperCalls.log.txt new file mode 100644 index 00000000000..341e9a94b30 --- /dev/null +++ b/plugins/uast-kotlin/testData/SuperCalls.log.txt @@ -0,0 +1,60 @@ +UFile (package = ) + UClass (name = SuperCallsKt) + UField (name = anon) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UObjectLiteralExpression + ULiteralExpression (value = "textForAnon") + UClass (name = null) + UAnnotationMethod (name = bar) + UBlockExpression + UAnnotationMethod (name = SuperCallsKt$anon$1) + UAnnotationMethod (name = getAnon) + UClass (name = A) + UField (name = str) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UAnnotationMethod (name = foo) + UParameter (name = a) + UAnnotation (fqName = null) + UBlockExpression + UAnnotationMethod (name = getStr) + UAnnotationMethod (name = A) + UParameter (name = str) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UAnnotationMethod (name = A) + UParameter (name = i) + UAnnotation (fqName = null) + UClass (name = B) + UAnnotationMethod (name = B) + UParameter (name = param) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) + UIdentifier (Identifier (A)) + USimpleNameReferenceExpression (identifier = ) + USimpleNameReferenceExpression (identifier = param) + UClass (name = C) + UAnnotationMethod (name = foo) + UParameter (name = a) + UAnnotation (fqName = null) + UBlockExpression + UQualifiedReferenceExpression + USuperExpression (label = null) + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) + UIdentifier (Identifier (foo)) + USimpleNameReferenceExpression (identifier = foo) + USimpleNameReferenceExpression (identifier = a) + UAnnotationMethod (name = C) + UParameter (name = p) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UAnnotationMethod (name = C) + UParameter (name = i) + UAnnotation (fqName = null) + UClass (name = O) + UField (name = INSTANCE) + UAnnotation (fqName = null) + UAnnotationMethod (name = O) + UBlockExpression + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) + UIdentifier (Identifier (A)) + USimpleNameReferenceExpression (identifier = ) + ULiteralExpression (value = "text") diff --git a/plugins/uast-kotlin/testData/SuperCalls.render.txt b/plugins/uast-kotlin/testData/SuperCalls.render.txt new file mode 100644 index 00000000000..8fb878a4f49 --- /dev/null +++ b/plugins/uast-kotlin/testData/SuperCalls.render.txt @@ -0,0 +1,36 @@ +public final class SuperCallsKt { + private static final var anon: A = anonymous object : A ("textForAnon"){ + fun bar(){} + } + public static final fun getAnon() : A = UastEmptyExpression +} + +public class A { + private final var str: java.lang.String + public fun foo(a: long) : void { + } + public final fun getStr() : java.lang.String = UastEmptyExpression + public fun A(str: java.lang.String) = UastEmptyExpression + public fun A(i: int) = UastEmptyExpression +} + +public final class B : A { + public fun B(param: java.lang.String) { + (param) + } +} + +public final class C : A { + public fun foo(a: long) : void { + super.foo(a) + } + public fun C(p: java.lang.String) = UastEmptyExpression + public fun C(i: int) = UastEmptyExpression +} + +public final class O : A { + public static final var INSTANCE: O + private fun O() { + ("text") + } +} diff --git a/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt b/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt index bae9099820e..c6df33c038e 100644 --- a/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt +++ b/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt @@ -1,9 +1,5 @@ package org.jetbrains.uast.test.kotlin -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiElementVisitor -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.psi.KtVisitor import org.junit.Test class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() { @@ -57,4 +53,7 @@ class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() { @Test fun testWhenAndDestructing() = doTest("WhenAndDestructing") { testName, file -> check(testName, file, false) } + + @Test + fun testSuperCalls() = doTest("SuperCalls") { testName, file -> check(testName, file, false) } }