From 4db5ca66e31d08ace4451f96c876493b621114c6 Mon Sep 17 00:00:00 2001 From: Nicolay Mitropolsky Date: Mon, 27 Nov 2017 13:11:20 +0300 Subject: [PATCH] Uast: constructors calls consistency for `KtObjectLiteralExpression` (KT-21409) --- .../uast/kotlin/KotlinUastLanguagePlugin.kt | 7 ++++- .../uast/kotlin/declarations/KotlinUClass.kt | 18 ++++++++++--- plugins/uast-kotlin/testData/SuperCalls.kt | 12 +++++++-- .../uast-kotlin/testData/SuperCalls.log.txt | 27 +++++++++++++++++++ .../testData/SuperCalls.render.txt | 10 ++++++- 5 files changed, 66 insertions(+), 8 deletions(-) diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt index f1076e703bb..7a1bcd15177 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.uast.* @@ -312,7 +313,11 @@ internal object KotlinConverter { is KtConstructorDelegationCall -> el { KotlinUFunctionCallExpression(element, givenParent) } is KtSuperTypeCallEntry -> - el { KotlinUFunctionCallExpression(element, givenParent) } + el { + (element.getParentOfType(true)?.parent as? KtObjectLiteralExpression) + ?.toUElementOfType() + ?: KotlinUFunctionCallExpression(element, givenParent) + } else -> { if (element is LeafPsiElement && element.elementType == KtTokens.IDENTIFIER) { 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 94b1c8d52a4..3df256ff1b9 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 @@ -18,6 +18,7 @@ package org.jetbrains.uast.kotlin import com.intellij.psi.* import org.jetbrains.kotlin.asJava.classes.KtLightClass +import org.jetbrains.kotlin.asJava.classes.KtLightClassForLocalDeclaration import org.jetbrains.kotlin.asJava.classes.KtLightClassForScript import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.load.java.JvmAbi @@ -31,9 +32,17 @@ import org.jetbrains.uast.kotlin.declarations.KotlinUMethod import org.jetbrains.uast.kotlin.declarations.UastLightIdentifier abstract class AbstractKotlinUClass(private val givenParent: UElement?) : AbstractJavaUClass() { - override val uastParent: UElement? by lz { - givenParent ?: KotlinUastLanguagePlugin().convertElementWithParent(psi.parent ?: psi.containingFile, null) - } + override val uastParent: UElement? by lz { givenParent ?: convertParent() } + + //TODO: should be merged with KotlinAbstractUElement.convertParent() after detaching from AbstractJavaUClass + open fun convertParent(): UElement? = + (this.psi as? KtLightClassForLocalDeclaration)?.kotlinOrigin?.parent?.let { + when (it) { + is KtClassBody -> it.parent.toUElement() // TODO: it seems that `class_body`-s are never created in kotlin uast in top-down walk, probably they should be completely skipped and always unwrapped + else -> it.toUElement() + } + } ?: (psi.parent ?: psi.containingFile).toUElement() + } open class KotlinUClass private constructor( @@ -109,7 +118,7 @@ class KotlinConstructorUMethod( ) : KotlinUMethod(psi, givenParent) { val isPrimary: Boolean - get() = psi.kotlinOrigin.let { it is KtPrimaryConstructor || it is KtObjectDeclaration } + get() = psi.kotlinOrigin.let { it is KtPrimaryConstructor || it is KtClassOrObject } override val uastBody: UExpression? by lz { val delegationCall: KtCallElement? = psi.kotlinOrigin.let { @@ -157,6 +166,7 @@ class KotlinUAnonymousClass( val ktClassOrObject = (psi.originalElement as? KtLightClass)?.kotlinOrigin as? KtObjectDeclaration ?: return null return UIdentifier(ktClassOrObject.getObjectKeyword(), this) } + } class KotlinScriptUClass( diff --git a/plugins/uast-kotlin/testData/SuperCalls.kt b/plugins/uast-kotlin/testData/SuperCalls.kt index 04b19044396..c1da1b30fab 100644 --- a/plugins/uast-kotlin/testData/SuperCalls.kt +++ b/plugins/uast-kotlin/testData/SuperCalls.kt @@ -21,5 +21,13 @@ class C : A { object O : A("text") val anon = object : A("textForAnon") { - fun bar() {} -} \ No newline at end of file + fun bar() { + cons(object : A("inner literal")) + } + + object innerObject : A("inner object") + + inner class InnerClass : A("inner class") +} + +fun cons(a: A) {} \ No newline at end of file diff --git a/plugins/uast-kotlin/testData/SuperCalls.log.txt b/plugins/uast-kotlin/testData/SuperCalls.log.txt index cca4e2911e5..897e43fe962 100644 --- a/plugins/uast-kotlin/testData/SuperCalls.log.txt +++ b/plugins/uast-kotlin/testData/SuperCalls.log.txt @@ -7,8 +7,35 @@ UFile (package = ) UClass (name = null) UAnnotationMethod (name = bar) UBlockExpression + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) + UIdentifier (Identifier (cons)) + USimpleNameReferenceExpression (identifier = cons) + UObjectLiteralExpression + ULiteralExpression (value = "inner literal") + UClass (name = null) + UAnnotationMethod (name = SuperCallsKt$anon$1$bar$1) UAnnotationMethod (name = SuperCallsKt$anon$1) + UClass (name = innerObject) + UField (name = INSTANCE) + UAnnotation (fqName = null) + UAnnotationMethod (name = innerObject) + UBlockExpression + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) + UIdentifier (Identifier (A)) + USimpleNameReferenceExpression (identifier = ) + ULiteralExpression (value = "inner object") + UClass (name = InnerClass) + UAnnotationMethod (name = InnerClass) + UBlockExpression + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) + UIdentifier (Identifier (A)) + USimpleNameReferenceExpression (identifier = ) + ULiteralExpression (value = "inner class") UAnnotationMethod (name = getAnon) + UAnnotationMethod (name = cons) + UParameter (name = a) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression UClass (name = A) UField (name = str) UAnnotation (fqName = org.jetbrains.annotations.NotNull) diff --git a/plugins/uast-kotlin/testData/SuperCalls.render.txt b/plugins/uast-kotlin/testData/SuperCalls.render.txt index 9b291b2ea8a..12545427485 100644 --- a/plugins/uast-kotlin/testData/SuperCalls.render.txt +++ b/plugins/uast-kotlin/testData/SuperCalls.render.txt @@ -1,8 +1,16 @@ public final class SuperCallsKt { private static final var anon: A = anonymous object : A("textForAnon") { - fun bar() {} + fun bar() { + cons(object : A("inner literal")) + } + + object innerObject : A("inner object") + + inner class InnerClass : A("inner class") } public static final fun getAnon() : A = UastEmptyExpression + public static final fun cons(a: A) : void { + } } public class A {