Uast: making AbstractKotlinUClass not inherit from AbstractJavaUClass

This commit is contained in:
Nicolay Mitropolsky
2017-12-04 17:58:45 +03:00
committed by Nikolay Krasko
parent 084da3665a
commit e22e466485
8 changed files with 119 additions and 19 deletions
@@ -18,6 +18,7 @@ package org.jetbrains.uast.kotlin
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.asJava.LightClassUtil import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.classes.KtLightClassForLocalDeclaration
import org.jetbrains.kotlin.asJava.toLightGetter import org.jetbrains.kotlin.asJava.toLightGetter
import org.jetbrains.kotlin.asJava.toLightSetter import org.jetbrains.kotlin.asJava.toLightSetter
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
@@ -40,6 +41,14 @@ abstract class KotlinAbstractUElement(private val givenParent: UElement?) : UEle
val psi = psi val psi = psi
var parent = psi?.parent ?: psi?.containingFile var parent = psi?.parent ?: psi?.containingFile
if (psi is KtLightClassForLocalDeclaration) {
val originParent = psi.kotlinOrigin.parent
parent = when (originParent) {
is KtClassBody -> originParent.parent
else -> originParent
}
}
if (psi is KtAnnotationEntry) { if (psi is KtAnnotationEntry) {
val parentUnwrapped = KotlinConverter.unwrapElements(parent) ?: return null val parentUnwrapped = KotlinConverter.unwrapElements(parent) ?: return null
val target = psi.useSiteTarget?.getAnnotationUseSiteTarget() val target = psi.useSiteTarget?.getAnnotationUseSiteTarget()
@@ -18,7 +18,6 @@ package org.jetbrains.uast.kotlin
import com.intellij.psi.* import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.classes.KtLightClass 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.classes.KtLightClassForScript
import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
@@ -27,21 +26,38 @@ import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.uast.* import org.jetbrains.uast.*
import org.jetbrains.uast.java.AbstractJavaUClass
import org.jetbrains.uast.kotlin.declarations.KotlinUMethod import org.jetbrains.uast.kotlin.declarations.KotlinUMethod
import org.jetbrains.uast.kotlin.declarations.UastLightIdentifier import org.jetbrains.uast.kotlin.declarations.UastLightIdentifier
abstract class AbstractKotlinUClass(private val givenParent: UElement?) : AbstractJavaUClass(), JvmDeclarationUElement { abstract class AbstractKotlinUClass(givenParent: UElement?) : KotlinAbstractUElement(givenParent), UClass, JvmDeclarationUElement {
override val uastParent: UElement? by lz { givenParent ?: convertParent() }
override val uastDeclarations by lz {
mutableListOf<UDeclaration>().apply {
addAll(fields)
addAll(initializers)
addAll(methods)
addAll(innerClasses)
}
}
override val uastSuperTypes: List<UTypeReferenceExpression>
get() {
val ktClass = (psi as? KtLightClass)?.kotlinOrigin ?: return emptyList()
return ktClass.superTypeListEntries.mapNotNull { it.typeReference }.map {
LazyKotlinUTypeReferenceExpression(it, this)
}
}
override val uastAnchor: UElement?
get() = UIdentifier(psi.nameIdentifier, this)
override val annotations: List<UAnnotation> by lz {
(sourcePsi as? KtModifierListOwner)?.annotationEntries.orEmpty().map { KotlinUAnnotation(it, this) }
}
override fun equals(other: Any?) = other is AbstractKotlinUClass && psi == other.psi
override fun hashCode() = psi.hashCode()
//TODO: should be merged with KotlinAbstractUElement.convertParent() after detaching from AbstractJavaUClass
override 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( open class KotlinUClass private constructor(
@@ -63,9 +79,6 @@ open class KotlinUClass private constructor(
override fun getContainingFile(): PsiFile? = unwrapFakeFileForLightClass(psi.containingFile) override fun getContainingFile(): PsiFile? = unwrapFakeFileForLightClass(psi.containingFile)
override val annotations: List<UAnnotation>
get() = ktClass?.annotationEntries?.map { KotlinUAnnotation(it, this) } ?: emptyList()
override val uastAnchor: UElement override val uastAnchor: UElement
get() = UIdentifier(nameIdentifier, this) get() = UIdentifier(nameIdentifier, this)
@@ -209,8 +222,8 @@ class KotlinUAnonymousClass(
class KotlinScriptUClass( class KotlinScriptUClass(
psi: KtLightClassForScript, psi: KtLightClassForScript,
override val uastParent: UElement? givenParent: UElement?
) : AbstractJavaUClass(), PsiClass by psi { ) : AbstractKotlinUClass(givenParent), PsiClass by psi {
override fun getContainingFile(): PsiFile = unwrapFakeFileForLightClass(psi.containingFile) override fun getContainingFile(): PsiFile = unwrapFakeFileForLightClass(psi.containingFile)
override fun getNameIdentifier(): PsiIdentifier? = UastLightIdentifier(psi, psi.kotlinOrigin) override fun getNameIdentifier(): PsiIdentifier? = UastLightIdentifier(psi, psi.kotlinOrigin)
+22
View File
@@ -0,0 +1,22 @@
@Test
class A
annotation class MyAnnotation(val text: String)
@MyAnnotation("class")
class B {
@MyAnnotation("inB class")
class InB {
}
@MyAnnotation("companion")
companion object {
}
}
@MyAnnotation("object")
object Obj
+30
View File
@@ -0,0 +1,30 @@
UFile (package = )
UClass (name = A)
UAnnotation (fqName = null)
UAnnotationMethod (name = A)
UClass (name = MyAnnotation)
UAnnotationMethod (name = text)
UClass (name = B)
UAnnotation (fqName = MyAnnotation)
UNamedExpression (name = text)
ULiteralExpression (value = "class")
UField (name = Companion)
UAnnotation (fqName = null)
UAnnotationMethod (name = B)
UClass (name = InB)
UAnnotation (fqName = MyAnnotation)
UNamedExpression (name = text)
ULiteralExpression (value = "inB class")
UAnnotationMethod (name = InB)
UClass (name = Companion)
UAnnotation (fqName = MyAnnotation)
UNamedExpression (name = text)
ULiteralExpression (value = "companion")
UAnnotationMethod (name = Companion)
UClass (name = Obj)
UAnnotation (fqName = MyAnnotation)
UNamedExpression (name = text)
ULiteralExpression (value = "object")
UField (name = INSTANCE)
UAnnotation (fqName = null)
UAnnotationMethod (name = Obj)
+23
View File
@@ -0,0 +1,23 @@
public final class A {
public fun A() = UastEmptyExpression
}
public abstract annotation MyAnnotation {
public abstract fun text() : java.lang.String = UastEmptyExpression
}
public final class B {
@null public static final var Companion: B.Companion
public fun B() = UastEmptyExpression
public static final class InB {
public fun InB() = UastEmptyExpression
}
public static final class Companion {
private fun Companion() = UastEmptyExpression
}
}
public final class Obj {
@null public static final var INSTANCE: Obj
private fun Obj() = UastEmptyExpression
}
+1 -1
View File
@@ -1,4 +1,4 @@
public class SimpleScript : kotlin.script.templates.standard.ScriptTemplateWithArgs { public class SimpleScript {
public final fun getBarOrNull(@org.jetbrains.annotations.NotNull flag: boolean) : SimpleScript.Bar { public final fun getBarOrNull(@org.jetbrains.annotations.NotNull flag: boolean) : SimpleScript.Bar {
return if (flag) <init>(42) else null return if (flag) <init>(42) else null
} }
@@ -26,7 +26,7 @@ UFile (package = ) [public abstract interface Callback {...]
ULambdaExpression [{ ...}] : PsiType:<ErrorType> ULambdaExpression [{ ...}] : PsiType:<ErrorType>
UBlockExpression [{...}] UBlockExpression [{...}]
UObjectLiteralExpression [anonymous object : Callback {... }] : PsiType:Callback UObjectLiteralExpression [anonymous object : Callback {... }] : PsiType:Callback
UClass (name = null) [final class null {...}] UClass (name = null) [final class null : Callback {...}]
UAnnotationMethod (name = onError) [public fun onError(@org.jetbrains.annotations.NotNull throwable: java.lang.Throwable) : void {...}] UAnnotationMethod (name = onError) [public fun onError(@org.jetbrains.annotations.NotNull throwable: java.lang.Throwable) : void {...}]
UParameter (name = throwable) [@org.jetbrains.annotations.NotNull var throwable: java.lang.Throwable] UParameter (name = throwable) [@org.jetbrains.annotations.NotNull var throwable: java.lang.Throwable]
UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull]
@@ -61,4 +61,7 @@ class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() {
@Test @Test
fun testConstructors() = doTest("Constructors") fun testConstructors() = doTest("Constructors")
@Test
fun testClassAnnotation() = doTest("ClassAnnotation")
} }