Uast: fix for creating an UClass for invalid object-literals (EA-122644, KT-20056)

This commit is contained in:
Nicolay Mitropolsky
2018-06-27 16:37:53 +03:00
parent 25e6b76238
commit 698096f13e
8 changed files with 88 additions and 36 deletions
@@ -17,6 +17,7 @@
package org.jetbrains.uast.kotlin package org.jetbrains.uast.kotlin
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.impl.light.LightPsiClassBuilder
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
@@ -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<UField> = emptyArray()
override fun getInitializers(): Array<UClassInitializer> = emptyArray()
override fun getInnerClasses(): Array<UClass> = emptyArray()
override fun getMethods(): Array<UMethod> = emptyArray()
override fun getSuperClass(): UClass? = null
override fun getOriginalElement(): PsiElement? = null
}
private fun reportConvertFailure(psiMethod: PsiMethod): Nothing { private fun reportConvertFailure(psiMethod: PsiMethod): Nothing {
val isValid = psiMethod.isValid val isValid = psiMethod.isValid
val report = KotlinExceptionWithAttachments( val report = KotlinExceptionWithAttachments(
@@ -17,6 +17,7 @@
package org.jetbrains.uast.kotlin package org.jetbrains.uast.kotlin
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.impl.light.LightPsiClassBuilder
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
@@ -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<UField> = emptyArray()
override fun getInitializers(): Array<UClassInitializer> = emptyArray()
override fun getInnerClasses(): Array<UClass> = emptyArray()
override fun getMethods(): Array<UMethod> = emptyArray()
override fun getSuperClass(): UClass? = null
override fun getOriginalElement(): PsiElement? = null
}
private fun reportConvertFailure(psiMethod: PsiMethod): Nothing { private fun reportConvertFailure(psiMethod: PsiMethod): Nothing {
val isValid = psiMethod.isValid val isValid = psiMethod.isValid
val report = KotlinExceptionWithAttachments( val report = KotlinExceptionWithAttachments(
@@ -16,12 +16,8 @@
package org.jetbrains.uast.kotlin 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.PsiMethod
import com.intellij.psi.PsiType 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.asJava.toLightClass
import org.jetbrains.kotlin.psi.KtObjectLiteralExpression import org.jetbrains.kotlin.psi.KtObjectLiteralExpression
import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry
@@ -34,17 +30,9 @@ class KotlinUObjectLiteralExpression(
) : KotlinAbstractUExpression(givenParent), UObjectLiteralExpression, UCallExpressionEx, KotlinUElementWithType { ) : KotlinAbstractUExpression(givenParent), UObjectLiteralExpression, UCallExpressionEx, KotlinUElementWithType {
override val declaration: UClass by lz { override val declaration: UClass by lz {
val lightClass: KtLightClass? = psi.objectDeclaration.toLightClass() psi.objectDeclaration.toLightClass()
if (lightClass != null) { ?.let { getLanguagePlugin().convert<UClass>(it, this) }
getLanguagePlugin().convert<UClass>(lightClass, this) ?: KotlinInvalidUClass("<invalid object code>", psi, this)
} else {
logger.error(
"Failed to create light class for object declaration",
Attachment(psi.containingFile.virtualFile?.path ?: "<no path>", psi.containingFile.text)
)
getLanguagePlugin().convert(LightPsiClassBuilder(psi, "<unnamed>"), this)
}
} }
override fun getExpressionType() = psi.objectDeclaration.toPsiType() override fun getExpressionType() = psi.objectDeclaration.toPsiType()
@@ -96,7 +84,4 @@ class KotlinUObjectLiteralExpression(
get() = psi.name ?: "<error>" get() = psi.name ?: "<error>"
} }
companion object {
val logger by lz { Logger.getInstance(KotlinUObjectLiteralExpression::class.java) }
}
} }
@@ -16,12 +16,8 @@
package org.jetbrains.uast.kotlin 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.PsiMethod
import com.intellij.psi.PsiType 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.asJava.toLightClass
import org.jetbrains.kotlin.psi.KtObjectLiteralExpression import org.jetbrains.kotlin.psi.KtObjectLiteralExpression
import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry
@@ -32,17 +28,9 @@ class KotlinUObjectLiteralExpression(
givenParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(givenParent), UObjectLiteralExpression, KotlinUElementWithType { ) : KotlinAbstractUExpression(givenParent), UObjectLiteralExpression, KotlinUElementWithType {
override val declaration: UClass by lz { override val declaration: UClass by lz {
val lightClass: KtLightClass? = psi.objectDeclaration.toLightClass() psi.objectDeclaration.toLightClass()
if (lightClass != null) { ?.let { getLanguagePlugin().convert<UClass>(it, this) }
getLanguagePlugin().convert<UClass>(lightClass, this) ?: KotlinInvalidUClass("<invalid object code>", psi, this)
} else {
logger.error(
"Failed to create light class for object declaration",
Attachment(psi.containingFile.virtualFile?.path ?: "<no path>", psi.containingFile.text)
)
getLanguagePlugin().convert(LightPsiClassBuilder(psi, "<unnamed>"), this)
}
} }
override fun getExpressionType() = psi.objectDeclaration.toPsiType() override fun getExpressionType() = psi.objectDeclaration.toPsiType()
@@ -91,7 +79,4 @@ class KotlinUObjectLiteralExpression(
get() = psi.name ?: "<error>" get() = psi.name ?: "<error>"
} }
companion object {
val logger by lz { Logger.getInstance(KotlinUObjectLiteralExpression::class.java) }
}
} }
@@ -29,3 +29,7 @@ foo -> UAnnotationMethod (name = foo)
read -> UAnnotationMethod (name = read) read -> UAnnotationMethod (name = read)
Int -> USimpleNameReferenceExpression (identifier = Int) Int -> USimpleNameReferenceExpression (identifier = Int)
run -> UAnnotationMethod (name = run) run -> UAnnotationMethod (name = run)
withErr -> UAnnotationMethod (name = withErr)
runnable -> ULocalVariable (name = runnable)
object -> UastEmptyExpression
Runnable -> null
+4
View File
@@ -9,4 +9,8 @@ fun foo() {
runnable2.run() runnable2.run()
val closeableRunnable = object : Runnable, Closeable { override fun close() {} override fun 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() {} } val runnableIs = object : InputStream(), Runnable { override fun read(): Int = 0; override fun run() {} }
}
fun withErr() {
val runnable = object Runnable {} // EA-122644
} }
+6
View File
@@ -51,3 +51,9 @@ UFile (package = )
UAnnotationMethod (name = run) UAnnotationMethod (name = run)
UBlockExpression UBlockExpression
UAnnotationMethod (name = AnonymousKt$foo$runnableIs$1) UAnnotationMethod (name = AnonymousKt$foo$runnableIs$1)
UAnnotationMethod (name = withErr)
UBlockExpression
UDeclarationsExpression
ULocalVariable (name = runnable)
UObjectLiteralExpression
UClass (name = <invalid object code>)
+3
View File
@@ -12,4 +12,7 @@ public final class AnonymousKt {
var closeableRunnable: <ErrorType> = anonymous object : Runnable, Closeable { override fun close() {} override fun run() {} } var closeableRunnable: <ErrorType> = anonymous object : Runnable, Closeable { override fun close() {} override fun run() {} }
var runnableIs: <ErrorType> = anonymous object : InputStream(), Runnable { override fun read(): Int = 0; override fun run() {} } var runnableIs: <ErrorType> = anonymous object : InputStream(), Runnable { override fun read(): Int = 0; override fun run() {} }
} }
public static final fun withErr() : void {
var runnable: <ErrorType> = anonymous null
}
} }