Uast: making AbstractKotlinUClass not inherit from AbstractJavaUClass
This commit is contained in:
committed by
Nikolay Krasko
parent
084da3665a
commit
e22e466485
@@ -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
@@ -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
|
||||||
@@ -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)
|
||||||
@@ -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
@@ -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")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user