Uast: support for KtDelegatedSuperTypeEntry (KT-30033)

This commit is contained in:
Nicolay Mitropolsky
2019-02-25 15:43:02 +03:00
parent 2f5843f764
commit 9c674cb7c3
13 changed files with 242 additions and 10 deletions
@@ -157,6 +157,7 @@ internal object KotlinConverter {
is KtSimpleNameStringTemplateEntry -> unwrapElements(element.parent)
is KtLightParameterList -> unwrapElements(element.parent)
is KtTypeElement -> unwrapElements(element.parent)
is KtSuperTypeList -> unwrapElements(element.parent)
else -> element
}
@@ -489,6 +490,9 @@ internal object KotlinConverter {
el<UAnnotation> { KotlinUNestedAnnotation.tryCreate(original, givenParent) }
} else null
is KtLightAnnotationForSourceEntry -> convertDeclarationOrElement(original.kotlinOrigin, givenParent, requiredType)
is KtDelegatedSuperTypeEntry -> el<KotlinSupertypeDelegationUExpression> {
KotlinSupertypeDelegationUExpression(original, givenParent)
}
else -> null
}
}
@@ -565,3 +569,5 @@ private fun convertVariablesDeclaration(
}
return declarationsExpression.apply { declarations = listOf(variable) }
}
val kotlinUastPlugin get() = UastLanguagePlugin.getInstances().find { it.language == KotlinLanguage.INSTANCE } ?: KotlinUastLanguagePlugin()
@@ -155,6 +155,7 @@ internal object KotlinConverter {
is KtSimpleNameStringTemplateEntry -> unwrapElements(element.parent)
is KtLightParameterList -> unwrapElements(element.parent)
is KtTypeElement -> unwrapElements(element.parent)
is KtSuperTypeList -> unwrapElements(element.parent)
else -> element
}
@@ -487,6 +488,9 @@ internal object KotlinConverter {
el<UAnnotation> { KotlinUNestedAnnotation.tryCreate(original, givenParent) }
} else null
is KtLightAnnotationForSourceEntry -> convertDeclarationOrElement(original.kotlinOrigin, givenParent, requiredType)
is KtDelegatedSuperTypeEntry -> el<KotlinSupertypeDelegationUExpression> {
KotlinSupertypeDelegationUExpression(original, givenParent)
}
else -> null
}
}
@@ -563,3 +567,5 @@ private fun convertVariablesDeclaration(
}
return declarationsExpression.apply { declarations = listOf(variable) }
}
val kotlinUastPlugin get() = UastLanguagePlugin.getInstances().find { it.language == KotlinLanguage.INSTANCE } ?: KotlinUastLanguagePlugin()
@@ -187,6 +187,7 @@ internal object KotlinConverter {
is KtSimpleNameStringTemplateEntry -> unwrapElements(element.parent)
is KtLightParameterList -> unwrapElements(element.parent)
is KtTypeElement -> unwrapElements(element.parent)
is KtSuperTypeList -> unwrapElements(element.parent)
else -> element
}
@@ -515,6 +516,9 @@ internal object KotlinConverter {
el<UAnnotation> { KotlinUNestedAnnotation.tryCreate(original, givenParent) }
} else null
is KtLightAnnotationForSourceEntry -> convertDeclarationOrElement(original.kotlinOrigin, givenParent, expectedTypes)
is KtDelegatedSuperTypeEntry -> el<KotlinSupertypeDelegationUExpression> {
KotlinSupertypeDelegationUExpression(original, givenParent)
}
else -> null
}
}
@@ -640,6 +644,8 @@ private fun convertVariablesDeclaration(
return declarationsExpression.apply { declarations = listOf(variable) }
}
val kotlinUastPlugin get() = UastLanguagePlugin.getInstances().find { it.language == KotlinLanguage.INSTANCE } ?: KotlinUastLanguagePlugin()
private fun expressionTypes(requiredType: Class<out UElement>?) = requiredType?.let { arrayOf(it) } ?: DEFAULT_EXPRESSION_TYPES_LIST
private fun elementTypes(requiredType: Class<out UElement>?) = requiredType?.let { arrayOf(it) } ?: DEFAULT_TYPES_LIST
@@ -27,9 +27,12 @@ import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.uast.*
import org.jetbrains.uast.internal.acceptList
import org.jetbrains.uast.kotlin.declarations.KotlinUIdentifier
import org.jetbrains.uast.kotlin.declarations.KotlinUMethod
import org.jetbrains.uast.kotlin.declarations.UastLightIdentifier
import org.jetbrains.uast.kotlin.kinds.KotlinSpecialExpressionKinds
import org.jetbrains.uast.visitor.UastVisitor
abstract class AbstractKotlinUClass(givenParent: UElement?) : KotlinAbstractUElement(givenParent), UClassTypeSpecific, UAnchorOwner,
JvmDeclarationUElementPlaceholder {
@@ -43,14 +46,26 @@ abstract class AbstractKotlinUClass(givenParent: UElement?) : KotlinAbstractUEle
}
}
open val ktClass: KtClassOrObject? get() = (psi as? KtLightClass)?.kotlinOrigin
override val uastSuperTypes: List<UTypeReferenceExpression>
get() {
val ktClass = (psi as? KtLightClass)?.kotlinOrigin ?: return emptyList()
return ktClass.superTypeListEntries.mapNotNull { it.typeReference }.map {
LazyKotlinUTypeReferenceExpression(it, this)
}
get() = ktClass?.superTypeListEntries.orEmpty().mapNotNull { it.typeReference }.map {
LazyKotlinUTypeReferenceExpression(it, this)
}
val delegateExpressions: List<UExpression>
get() = ktClass?.superTypeListEntries.orEmpty()
.filterIsInstance<KtDelegatedSuperTypeEntry>()
.map { KotlinSupertypeDelegationUExpression(it, this) }
override fun accept(visitor: UastVisitor) {
if (visitor.visitClass(this)) return
delegateExpressions.acceptList(visitor)
annotations.acceptList(visitor)
uastDeclarations.acceptList(visitor)
visitor.afterVisitClass(this)
}
override val annotations: List<UAnnotation> by lz {
(sourcePsi as? KtModifierListOwner)?.annotationEntries.orEmpty().map { KotlinUAnnotation(it, this) }
}
@@ -60,12 +75,32 @@ abstract class AbstractKotlinUClass(givenParent: UElement?) : KotlinAbstractUEle
}
class KotlinSupertypeDelegationUExpression(override val sourcePsi: KtDelegatedSuperTypeEntry, givenParent: UElement?) :
KotlinAbstractUExpression(givenParent), UExpressionList {
override val psi: PsiElement? get() = sourcePsi
val typeReference: UTypeReferenceExpression? by lazy {
sourcePsi.typeReference?.let { KotlinUTypeReferenceExpression(it.toPsiType(this), it, this) }
}
val delegateExpression: UExpression? by lazy {
sourcePsi.delegateExpression?.let { kotlinUastPlugin.convertElement(it, this, UExpression::class.java) as? UExpression }
}
override val expressions: List<UExpression>
get() = listOfNotNull(typeReference, delegateExpression)
override val kind: UastSpecialExpressionKind get() = KotlinSpecialExpressionKinds.SUPER_DELEGATION
}
open class KotlinUClass private constructor(
psi: KtLightClass,
givenParent: UElement?
) : AbstractKotlinUClass(givenParent), PsiClass by psi {
val ktClass = psi.kotlinOrigin
final override val ktClass = psi.kotlinOrigin
override val javaPsi: KtLightClass = psi
@@ -214,7 +249,7 @@ class KotlinUAnonymousClass(
override val javaPsi: PsiAnonymousClass = psi
override val sourcePsi: KtClassOrObject? = (psi as? KtLightClass)?.kotlinOrigin
override val sourcePsi: KtClassOrObject? = ktClass
override fun getOriginalElement(): PsiElement? = super<AbstractKotlinUClass>.getOriginalElement()
@@ -22,7 +22,6 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.PsiRecursiveElementWalkingVisitor
import org.jetbrains.kotlin.asJava.findFacadeClass
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.uast.*
@@ -30,8 +29,7 @@ import java.util.*
class KotlinUFile(
override val psi: KtFile,
override val languagePlugin: UastLanguagePlugin =
UastLanguagePlugin.getInstances().find { it.language == KotlinLanguage.INSTANCE } ?: KotlinUastLanguagePlugin()
override val languagePlugin: UastLanguagePlugin = kotlinUastPlugin
) : UFile, JvmDeclarationUElementPlaceholder {
override val packageName: String
get() = psi.packageFqName.asString()
@@ -30,4 +30,7 @@ object KotlinSpecialExpressionKinds {
@JvmField
val ELVIS = UastSpecialExpressionKind("elvis")
@JvmField
val SUPER_DELEGATION = UastSpecialExpressionKind("super_delegation")
}
+15
View File
@@ -0,0 +1,15 @@
interface Base {
fun print()
}
class BaseImpl(val x: Int) : Base {
override fun print() {
print(x)
}
}
class Derived(b: Base) : Base by createBase(10), CharSequence by "abc"
fun createBase(i: Int): Base {
return BaseImpl(i)
}
@@ -0,0 +1,48 @@
UFile (package = )
UClass (name = ConstructorDelegateKt)
UAnnotationMethod (name = createBase)
UParameter (name = i)
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
UBlockExpression
UReturnExpression
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1))
UIdentifier (Identifier (BaseImpl))
USimpleNameReferenceExpression (identifier = <init>, resolvesTo = BaseImpl)
USimpleNameReferenceExpression (identifier = i)
UClass (name = Base)
UAnnotationMethod (name = print)
UClass (name = BaseImpl)
UField (name = x)
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
UAnnotationMethod (name = print)
UBlockExpression
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
UIdentifier (Identifier (print))
USimpleNameReferenceExpression (identifier = print, resolvesTo = null)
USimpleNameReferenceExpression (identifier = x)
UAnnotationMethod (name = getX)
UAnnotationMethod (name = BaseImpl)
UParameter (name = x)
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
UClass (name = Derived)
UExpressionList (super_delegation)
UTypeReferenceExpression (name = Base)
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
UIdentifier (Identifier (createBase))
USimpleNameReferenceExpression (identifier = createBase, resolvesTo = null)
ULiteralExpression (value = 10)
UExpressionList (super_delegation)
UTypeReferenceExpression (name = java.lang.CharSequence)
ULiteralExpression (value = "abc")
UAnnotationMethod (name = Derived)
UParameter (name = b)
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
UAnnotationMethod (name = getLength)
UAnnotationMethod (name = get)
UParameter (name = index)
UAnnotation (fqName = null)
UAnnotationMethod (name = subSequence)
UParameter (name = startIndex)
UAnnotation (fqName = null)
UParameter (name = endIndex)
UAnnotation (fqName = null)
@@ -0,0 +1,25 @@
public final class ConstructorDelegateKt {
public static final fun createBase(@org.jetbrains.annotations.NotNull i: int) : Base {
return <init>(i)
}
}
public abstract interface Base {
public abstract fun print() : void = UastEmptyExpression
}
public final class BaseImpl : Base {
@org.jetbrains.annotations.NotNull private final var x: int
public fun print() : void {
print(x)
}
public final fun getX() : int = UastEmptyExpression
public fun BaseImpl(@org.jetbrains.annotations.NotNull x: int) = UastEmptyExpression
}
public final class Derived : Base, java.lang.CharSequence {
public fun Derived(@org.jetbrains.annotations.NotNull b: Base) = UastEmptyExpression
public fun getLength() : int = UastEmptyExpression
public fun get(@null index: int) : char = UastEmptyExpression
public fun subSequence(@null startIndex: int, @null endIndex: int) : java.lang.CharSequence = UastEmptyExpression
}
+57
View File
@@ -0,0 +1,57 @@
UFile (package = )
UClass (name = MyColor)
UField (name = x)
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
UField (name = y)
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
UField (name = z)
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
UAnnotationMethod (name = getX)
UAnnotationMethod (name = getY)
UAnnotationMethod (name = getZ)
UAnnotationMethod (name = MyColor)
UParameter (name = x)
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
UParameter (name = y)
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
UParameter (name = z)
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
UClass (name = Some)
UField (name = delegate$delegate)
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
UIdentifier (Identifier (lazy))
USimpleNameReferenceExpression (identifier = lazy, resolvesTo = null)
ULambdaExpression
UBlockExpression
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 3))
UIdentifier (Identifier (MyColor))
USimpleNameReferenceExpression (identifier = <init>, resolvesTo = MyColor)
ULiteralExpression (value = 18)
ULiteralExpression (value = 2)
ULiteralExpression (value = 3)
UField (name = lambda)
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
UIdentifier (Identifier (lazy))
USimpleNameReferenceExpression (identifier = lazy, resolvesTo = null)
ULambdaExpression
UBlockExpression
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 3))
UIdentifier (Identifier (MyColor))
USimpleNameReferenceExpression (identifier = <init>, resolvesTo = MyColor)
ULiteralExpression (value = 1)
ULiteralExpression (value = 2)
ULiteralExpression (value = 3)
UField (name = nonLazy)
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 3))
UIdentifier (Identifier (MyColor))
USimpleNameReferenceExpression (identifier = <init>, resolvesTo = MyColor)
ULiteralExpression (value = 1)
ULiteralExpression (value = 2)
ULiteralExpression (value = 3)
UAnnotationMethod (name = getDelegate)
UAnnotationMethod (name = getLambda)
UAnnotationMethod (name = getNonLazy)
UAnnotationMethod (name = Some)
+21
View File
@@ -0,0 +1,21 @@
public final class MyColor {
@org.jetbrains.annotations.NotNull private final var x: int
@org.jetbrains.annotations.NotNull private final var y: int
@org.jetbrains.annotations.NotNull private final var z: int
public final fun getX() : int = UastEmptyExpression
public final fun getY() : int = UastEmptyExpression
public final fun getZ() : int = UastEmptyExpression
public fun MyColor(@org.jetbrains.annotations.NotNull x: int, @org.jetbrains.annotations.NotNull y: int, @org.jetbrains.annotations.NotNull z: int) = UastEmptyExpression
}
public final class Some {
@org.jetbrains.annotations.NotNull private final var delegate$delegate: kotlin.Lazy
@org.jetbrains.annotations.NotNull private final var lambda: kotlin.Lazy<MyColor> = lazy({
<init>(1, 2, 3)
})
@org.jetbrains.annotations.NotNull private final var nonLazy: MyColor = <init>(1, 2, 3)
public final fun getDelegate() : MyColor = UastEmptyExpression
public final fun getLambda() : kotlin.Lazy<MyColor> = UastEmptyExpression
public final fun getNonLazy() : MyColor = UastEmptyExpression
public fun Some() = UastEmptyExpression
}
@@ -84,4 +84,10 @@ class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() {
@Test
fun testLambdas() = doTest("Lambdas")
@Test
fun testDelegate() = doTest("Delegate")
@Test
fun testConstructorDelegate() = doTest("ConstructorDelegate")
}
@@ -90,6 +90,12 @@ class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() {
@Test
fun testLambdas() = doTest("Lambdas")
@Test
fun testDelegate() = doTest("Delegate")
@Test
fun testConstructorDelegate() = doTest("ConstructorDelegate")
}
fun withForceUInjectionHostValue(call: () -> Unit) {