From 698096f13ea7a7562677d861bae7abe30dcf666b Mon Sep 17 00:00:00 2001 From: Nicolay Mitropolsky Date: Wed, 27 Jun 2018 16:37:53 +0300 Subject: [PATCH] Uast: fix for creating an `UClass` for invalid `object`-literals (EA-122644, KT-20056) --- .../uast/kotlin/declarations/KotlinUClass.kt | 32 ++++++++++++++++++ .../kotlin/declarations/KotlinUClass.kt.173 | 33 +++++++++++++++++++ .../KotlinUObjectLiteralExpression.kt | 21 ++---------- .../KotlinUObjectLiteralExpression.kt.173 | 21 ++---------- .../testData/Anonymous.identifiers.txt | 4 +++ plugins/uast-kotlin/testData/Anonymous.kt | 4 +++ .../uast-kotlin/testData/Anonymous.log.txt | 6 ++++ .../uast-kotlin/testData/Anonymous.render.txt | 3 ++ 8 files changed, 88 insertions(+), 36 deletions(-) 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 538fccf6561..6716217b4c0 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 @@ -17,6 +17,7 @@ package org.jetbrains.uast.kotlin import com.intellij.psi.* +import com.intellij.psi.impl.light.LightPsiClassBuilder import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.classes.KtLightClassForScript import org.jetbrains.kotlin.asJava.elements.KtLightMethod @@ -284,6 +285,37 @@ class KotlinScriptUClass( } } +/** + * implementation of [UClass] for invalid code, when it is impossible to create a [KtLightClass] + */ +class KotlinInvalidUClass( + override val psi: PsiClass, + givenParent: UElement? +) : AbstractKotlinUClass(givenParent), PsiClass by psi { + + constructor(name: String, context: PsiElement, givenParent: UElement?) : this(LightPsiClassBuilder(context, name), givenParent) + + override fun getContainingFile(): PsiFile? = uastParent?.getContainingUFile()?.sourcePsi as? PsiFile + + override val sourcePsi: PsiElement? get() = null + + override val uastAnchor: UIdentifier? get() = null + + override val javaPsi: PsiClass get() = psi + + override fun getFields(): Array = emptyArray() + + override fun getInitializers(): Array = emptyArray() + + override fun getInnerClasses(): Array = emptyArray() + + override fun getMethods(): Array = emptyArray() + + override fun getSuperClass(): UClass? = null + + override fun getOriginalElement(): PsiElement? = null +} + private fun reportConvertFailure(psiMethod: PsiMethod): Nothing { val isValid = psiMethod.isValid val report = KotlinExceptionWithAttachments( diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt.173 index 9258fb3ca64..c2849708e07 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt.173 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt.173 @@ -17,6 +17,7 @@ package org.jetbrains.uast.kotlin import com.intellij.psi.* +import com.intellij.psi.impl.light.LightPsiClassBuilder import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.classes.KtLightClassForScript import org.jetbrains.kotlin.asJava.elements.KtLightMethod @@ -274,6 +275,38 @@ class KotlinScriptUClass( } } +/** + * implementation of [UClass] for invalid code, when it is impossible to create a [KtLightClass] + */ +class KotlinInvalidUClass( + override val psi: PsiClass, + givenParent: UElement? +) : AbstractKotlinUClass(givenParent), PsiClass by psi { + + constructor(name: String, context: PsiElement, givenParent: UElement?) : this(LightPsiClassBuilder(context, name), givenParent) + + override fun getContainingFile(): PsiFile? = + (uastParent?.getContainingUFile() as? JvmDeclarationUElementPlaceholder)?.sourcePsi as? PsiFile + + override val sourcePsi: PsiElement? get() = null + + override val uastAnchor: UIdentifier? get() = null + + override val javaPsi: PsiClass get() = psi + + override fun getFields(): Array = emptyArray() + + override fun getInitializers(): Array = emptyArray() + + override fun getInnerClasses(): Array = emptyArray() + + override fun getMethods(): Array = emptyArray() + + override fun getSuperClass(): UClass? = null + + override fun getOriginalElement(): PsiElement? = null +} + private fun reportConvertFailure(psiMethod: PsiMethod): Nothing { val isValid = psiMethod.isValid val report = KotlinExceptionWithAttachments( diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt index 40e3c72b6a7..8802269b954 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt @@ -16,12 +16,8 @@ package org.jetbrains.uast.kotlin -import com.intellij.openapi.diagnostic.Attachment -import com.intellij.openapi.diagnostic.Logger import com.intellij.psi.PsiMethod import com.intellij.psi.PsiType -import com.intellij.psi.impl.light.LightPsiClassBuilder -import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.psi.KtObjectLiteralExpression import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry @@ -34,17 +30,9 @@ class KotlinUObjectLiteralExpression( ) : KotlinAbstractUExpression(givenParent), UObjectLiteralExpression, UCallExpressionEx, KotlinUElementWithType { override val declaration: UClass by lz { - val lightClass: KtLightClass? = psi.objectDeclaration.toLightClass() - if (lightClass != null) { - getLanguagePlugin().convert(lightClass, this) - } else { - logger.error( - "Failed to create light class for object declaration", - Attachment(psi.containingFile.virtualFile?.path ?: "", psi.containingFile.text) - ) - - getLanguagePlugin().convert(LightPsiClassBuilder(psi, ""), this) - } + psi.objectDeclaration.toLightClass() + ?.let { getLanguagePlugin().convert(it, this) } + ?: KotlinInvalidUClass("", psi, this) } override fun getExpressionType() = psi.objectDeclaration.toPsiType() @@ -96,7 +84,4 @@ class KotlinUObjectLiteralExpression( get() = psi.name ?: "" } - companion object { - val logger by lz { Logger.getInstance(KotlinUObjectLiteralExpression::class.java) } - } } \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt.173 index 1b91c631f1f..4851083d1ac 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt.173 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt.173 @@ -16,12 +16,8 @@ package org.jetbrains.uast.kotlin -import com.intellij.openapi.diagnostic.Attachment -import com.intellij.openapi.diagnostic.Logger import com.intellij.psi.PsiMethod import com.intellij.psi.PsiType -import com.intellij.psi.impl.light.LightPsiClassBuilder -import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.psi.KtObjectLiteralExpression import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry @@ -32,17 +28,9 @@ class KotlinUObjectLiteralExpression( givenParent: UElement? ) : KotlinAbstractUExpression(givenParent), UObjectLiteralExpression, KotlinUElementWithType { override val declaration: UClass by lz { - val lightClass: KtLightClass? = psi.objectDeclaration.toLightClass() - if (lightClass != null) { - getLanguagePlugin().convert(lightClass, this) - } else { - logger.error( - "Failed to create light class for object declaration", - Attachment(psi.containingFile.virtualFile?.path ?: "", psi.containingFile.text) - ) - - getLanguagePlugin().convert(LightPsiClassBuilder(psi, ""), this) - } + psi.objectDeclaration.toLightClass() + ?.let { getLanguagePlugin().convert(it, this) } + ?: KotlinInvalidUClass("", psi, this) } override fun getExpressionType() = psi.objectDeclaration.toPsiType() @@ -91,7 +79,4 @@ class KotlinUObjectLiteralExpression( get() = psi.name ?: "" } - companion object { - val logger by lz { Logger.getInstance(KotlinUObjectLiteralExpression::class.java) } - } } \ No newline at end of file diff --git a/plugins/uast-kotlin/testData/Anonymous.identifiers.txt b/plugins/uast-kotlin/testData/Anonymous.identifiers.txt index 40cc421ef48..b79f2db7340 100644 --- a/plugins/uast-kotlin/testData/Anonymous.identifiers.txt +++ b/plugins/uast-kotlin/testData/Anonymous.identifiers.txt @@ -29,3 +29,7 @@ foo -> UAnnotationMethod (name = foo) read -> UAnnotationMethod (name = read) Int -> USimpleNameReferenceExpression (identifier = Int) run -> UAnnotationMethod (name = run) +withErr -> UAnnotationMethod (name = withErr) + runnable -> ULocalVariable (name = runnable) + object -> UastEmptyExpression + Runnable -> null diff --git a/plugins/uast-kotlin/testData/Anonymous.kt b/plugins/uast-kotlin/testData/Anonymous.kt index 5c7b53ee275..349124b5b5e 100644 --- a/plugins/uast-kotlin/testData/Anonymous.kt +++ b/plugins/uast-kotlin/testData/Anonymous.kt @@ -9,4 +9,8 @@ fun foo() { runnable2.run() val closeableRunnable = object : Runnable, Closeable { override fun close() {} override fun run() {} } val runnableIs = object : InputStream(), Runnable { override fun read(): Int = 0; override fun run() {} } +} + +fun withErr() { + val runnable = object Runnable {} // EA-122644 } \ No newline at end of file diff --git a/plugins/uast-kotlin/testData/Anonymous.log.txt b/plugins/uast-kotlin/testData/Anonymous.log.txt index e6dafc08225..6cdd3d80d57 100644 --- a/plugins/uast-kotlin/testData/Anonymous.log.txt +++ b/plugins/uast-kotlin/testData/Anonymous.log.txt @@ -51,3 +51,9 @@ UFile (package = ) UAnnotationMethod (name = run) UBlockExpression UAnnotationMethod (name = AnonymousKt$foo$runnableIs$1) + UAnnotationMethod (name = withErr) + UBlockExpression + UDeclarationsExpression + ULocalVariable (name = runnable) + UObjectLiteralExpression + UClass (name = ) diff --git a/plugins/uast-kotlin/testData/Anonymous.render.txt b/plugins/uast-kotlin/testData/Anonymous.render.txt index 20214e56d9f..bb2e36e3b69 100644 --- a/plugins/uast-kotlin/testData/Anonymous.render.txt +++ b/plugins/uast-kotlin/testData/Anonymous.render.txt @@ -12,4 +12,7 @@ public final class AnonymousKt { var closeableRunnable: = anonymous object : Runnable, Closeable { override fun close() {} override fun run() {} } var runnableIs: = anonymous object : InputStream(), Runnable { override fun read(): Int = 0; override fun run() {} } } + public static final fun withErr() : void { + var runnable: = anonymous null + } }