Work in progress on consistent UAST structure
This commit is contained in:
@@ -16,16 +16,31 @@
|
|||||||
|
|
||||||
package org.jetbrains.uast.kotlin
|
package org.jetbrains.uast.kotlin
|
||||||
|
|
||||||
import org.jetbrains.kotlin.psi.KtAnnotatedExpression
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtValueArgument
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
import org.jetbrains.uast.UAnnotation
|
import org.jetbrains.uast.*
|
||||||
import org.jetbrains.uast.UElement
|
|
||||||
import org.jetbrains.uast.UExpression
|
|
||||||
|
|
||||||
abstract class KotlinAbstractUElement(private val givenParent: UElement?) : UElement {
|
abstract class KotlinAbstractUElement(private val givenParent: UElement?) : UElement {
|
||||||
|
|
||||||
override val uastParent: UElement? by lz { convertParent(givenParent) }
|
override val uastParent: UElement? by lz {
|
||||||
|
givenParent ?: convertParent()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun convertParent(): UElement? {
|
||||||
|
var parent = psi?.parent ?: psi?.containingFile
|
||||||
|
|
||||||
|
if (parent is KtStringTemplateExpression && parent.entries.size == 1) {
|
||||||
|
parent = parent.parent
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = doConvertParent(this, parent)
|
||||||
|
if (result == this) {
|
||||||
|
throw IllegalStateException("Loop in parent structure when converting a $psi")
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (other !is UElement) {
|
if (other !is UElement) {
|
||||||
@@ -38,25 +53,35 @@ abstract class KotlinAbstractUElement(private val givenParent: UElement?) : UEle
|
|||||||
override fun hashCode() = psi?.hashCode() ?: 0
|
override fun hashCode() = psi?.hashCode() ?: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun UElement.convertParent(givenParent: UElement?): UElement? {
|
fun doConvertParent(element: UElement, parent: PsiElement?): UElement? {
|
||||||
return if (givenParent != null)
|
val parentUnwrapped = KotlinConverter.unwrapElements(parent) ?: return null
|
||||||
givenParent
|
if (parent is KtValueArgument && parentUnwrapped is KtAnnotationEntry) {
|
||||||
else {
|
return (KotlinUastLanguagePlugin().convertElementWithParent(parentUnwrapped, null) as? KotlinUAnnotation)
|
||||||
val parent = psi?.parent
|
?.findAttributeValueExpression(parent)
|
||||||
val result = KotlinConverter.unwrapElements(parent)?.let { parentUnwrapped ->
|
|
||||||
if (parent is KtValueArgument && parentUnwrapped is KtAnnotationEntry) {
|
|
||||||
val argumentName = parent.getArgumentName()?.asName?.asString() ?: ""
|
|
||||||
(KotlinUastLanguagePlugin().convertElementWithParent(parentUnwrapped, null) as? UAnnotation)
|
|
||||||
?.attributeValues?.find { it.name == argumentName }
|
|
||||||
}
|
|
||||||
else
|
|
||||||
KotlinUastLanguagePlugin().convertElementWithParent(parentUnwrapped, null)
|
|
||||||
}
|
|
||||||
if (result == this) {
|
|
||||||
throw IllegalStateException("Loop in parent structure")
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parent is KtParameter) {
|
||||||
|
val annotationClass = findAnnotationClassFromConstructorParameter(parent)
|
||||||
|
if (annotationClass != null) {
|
||||||
|
return annotationClass.methods.find { it.name == parent.name }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = KotlinUastLanguagePlugin().convertElementWithParent(parentUnwrapped, null)
|
||||||
|
|
||||||
|
if (result is UEnumConstant && element is UDeclaration) {
|
||||||
|
return result.initializingClass
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findAnnotationClassFromConstructorParameter(parameter: KtParameter): UClass? {
|
||||||
|
val primaryConstructor = parameter.getStrictParentOfType<KtPrimaryConstructor>() ?: return null
|
||||||
|
val containingClass = primaryConstructor.getContainingClassOrObject()
|
||||||
|
if (containingClass.isAnnotation()) {
|
||||||
|
return KotlinUastLanguagePlugin().convertElementWithParent(containingClass, null) as UClass
|
||||||
|
}
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class KotlinAbstractUExpression(givenParent: UElement?)
|
abstract class KotlinAbstractUExpression(givenParent: UElement?)
|
||||||
@@ -67,4 +92,5 @@ abstract class KotlinAbstractUExpression(givenParent: UElement?)
|
|||||||
val annotatedExpression = psi?.parent as? KtAnnotatedExpression ?: return emptyList()
|
val annotatedExpression = psi?.parent as? KtAnnotatedExpression ?: return emptyList()
|
||||||
return annotatedExpression.annotationEntries.map { KotlinUAnnotation(it, this) }
|
return annotatedExpression.annotationEntries.map { KotlinUAnnotation(it, this) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -137,13 +137,20 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
|
|||||||
return with(requiredType) {
|
return with(requiredType) {
|
||||||
when (original) {
|
when (original) {
|
||||||
is KtLightMethod -> el<UMethod>(build(KotlinUMethod.Companion::create)) // .Companion is needed because of KT-13934
|
is KtLightMethod -> el<UMethod>(build(KotlinUMethod.Companion::create)) // .Companion is needed because of KT-13934
|
||||||
is KtLightClass -> el<UClass>(build(KotlinUClass.Companion::create))
|
is KtLightClass -> el<UDeclaration> {
|
||||||
|
(original.kotlinOrigin as? KtEnumEntry)?.let { enumEntry ->
|
||||||
|
convertEnumEntry(enumEntry, givenParent)
|
||||||
|
} ?: KotlinUClass.create(original, givenParent)
|
||||||
|
}
|
||||||
|
|
||||||
is KtLightFieldImpl.KtLightEnumConstant -> el<UEnumConstant>(build(::KotlinUEnumConstant))
|
is KtLightFieldImpl.KtLightEnumConstant -> el<UEnumConstant>(build(::KotlinUEnumConstant))
|
||||||
is KtLightField -> el<UField>(build(::KotlinUField))
|
is KtLightField -> el<UField>(build(::KotlinUField))
|
||||||
is KtLightParameter, is UastKotlinPsiParameter -> el<UParameter>(build(::KotlinUParameter))
|
is KtLightParameter, is UastKotlinPsiParameter -> el<UParameter>(build(::KotlinUParameter))
|
||||||
is UastKotlinPsiVariable -> el<UVariable>(build(::KotlinUVariable))
|
is UastKotlinPsiVariable -> el<UVariable>(build(::KotlinUVariable))
|
||||||
|
|
||||||
|
is KtEnumEntry -> el<UEnumConstant> {
|
||||||
|
convertEnumEntry(original, givenParent)
|
||||||
|
}
|
||||||
is KtClassOrObject -> el<UClass> {
|
is KtClassOrObject -> el<UClass> {
|
||||||
original.toLightClass()?.let { lightClass ->
|
original.toLightClass()?.let { lightClass ->
|
||||||
KotlinUClass.create(lightClass, givenParent)
|
KotlinUClass.create(lightClass, givenParent)
|
||||||
@@ -154,13 +161,18 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
|
|||||||
convertDeclaration(lightMethod, givenParent, requiredType)
|
convertDeclaration(lightMethod, givenParent, requiredType)
|
||||||
}
|
}
|
||||||
is KtPropertyAccessor -> el<UMethod> {
|
is KtPropertyAccessor -> el<UMethod> {
|
||||||
javaPlugin.convertOpt<UMethod>(
|
val lightMethod = LightClassUtil.getLightClassAccessorMethod(original) ?: return null
|
||||||
LightClassUtil.getLightClassAccessorMethod(original), givenParent)
|
convertDeclaration(lightMethod, givenParent, requiredType)
|
||||||
}
|
}
|
||||||
is KtProperty -> el<UField> {
|
is KtProperty -> el<UVariable> {
|
||||||
javaPlugin.convertOpt<UField>(
|
if (original.isLocal) {
|
||||||
LightClassUtil.getLightClassBackingField(original), givenParent)
|
KotlinConverter.convertPsiElement(element, givenParent, requiredType)
|
||||||
?: convertDeclaration(element.parent, givenParent, requiredType)
|
}
|
||||||
|
else {
|
||||||
|
LightClassUtil.getLightClassBackingField(original)?.let {
|
||||||
|
KotlinUField(it, givenParent)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is KtFile -> el<UFile> { KotlinUFile(original, this@KotlinUastLanguagePlugin) }
|
is KtFile -> el<UFile> { KotlinUFile(original, this@KotlinUastLanguagePlugin) }
|
||||||
@@ -171,6 +183,17 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun convertEnumEntry(original: KtEnumEntry, givenParent: UElement?): UElement? {
|
||||||
|
return LightClassUtil.getLightClassBackingField(original)?.let { psiField ->
|
||||||
|
if (psiField is KtLightFieldImpl.KtLightEnumConstant) {
|
||||||
|
KotlinUEnumConstant(psiField, givenParent)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun isExpressionValueUsed(element: UExpression): Boolean {
|
override fun isExpressionValueUsed(element: UExpression): Boolean {
|
||||||
return when (element) {
|
return when (element) {
|
||||||
is KotlinUSimpleReferenceExpression.KotlinAccessorCallExpression -> element.setterValue != null
|
is KotlinUSimpleReferenceExpression.KotlinAccessorCallExpression -> element.setterValue != null
|
||||||
@@ -191,14 +214,13 @@ internal inline fun <reified ActualT : UElement> Class<out UElement>?.expr(f: ()
|
|||||||
return if (this == null || isAssignableFrom(ActualT::class.java)) f() else null
|
return if (this == null || isAssignableFrom(ActualT::class.java)) f() else null
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun UElement?.toCallback() = if (this != null) fun(): UElement? { return this } else null
|
|
||||||
|
|
||||||
internal object KotlinConverter {
|
internal object KotlinConverter {
|
||||||
internal tailrec fun unwrapElements(element: PsiElement?): PsiElement? = when (element) {
|
internal tailrec fun unwrapElements(element: PsiElement?): PsiElement? = when (element) {
|
||||||
is KtValueArgumentList -> unwrapElements(element.parent)
|
is KtValueArgumentList -> unwrapElements(element.parent)
|
||||||
is KtValueArgument -> unwrapElements(element.parent)
|
is KtValueArgument -> unwrapElements(element.parent)
|
||||||
is KtDeclarationModifierList -> unwrapElements(element.parent)
|
is KtDeclarationModifierList -> unwrapElements(element.parent)
|
||||||
is KtContainerNode -> unwrapElements(element.parent)
|
is KtContainerNode -> unwrapElements(element.parent)
|
||||||
|
is KtSimpleNameStringTemplateEntry -> unwrapElements(element.parent)
|
||||||
else -> element
|
else -> element
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,6 +242,9 @@ internal object KotlinConverter {
|
|||||||
}
|
}
|
||||||
is KtClassBody -> el<UExpressionList>(build(KotlinUExpressionList.Companion::createClassBody))
|
is KtClassBody -> el<UExpressionList>(build(KotlinUExpressionList.Companion::createClassBody))
|
||||||
is KtCatchClause -> el<UCatchClause>(build(::KotlinUCatchClause))
|
is KtCatchClause -> el<UCatchClause>(build(::KotlinUCatchClause))
|
||||||
|
is KtVariableDeclaration -> el<UVariable> {
|
||||||
|
convertVariablesDeclaration(element, givenParent).declarations.singleOrNull()
|
||||||
|
}
|
||||||
is KtExpression -> KotlinConverter.convertExpression(element, givenParent, requiredType)
|
is KtExpression -> KotlinConverter.convertExpression(element, givenParent, requiredType)
|
||||||
is KtLambdaArgument -> KotlinConverter.convertExpression(element.getLambdaExpression(), givenParent, requiredType)
|
is KtLambdaArgument -> KotlinConverter.convertExpression(element.getLambdaExpression(), givenParent, requiredType)
|
||||||
is KtLightAnnotationForSourceEntry.LightExpressionValue<*> -> {
|
is KtLightAnnotationForSourceEntry.LightExpressionValue<*> -> {
|
||||||
@@ -231,6 +256,9 @@ internal object KotlinConverter {
|
|||||||
}
|
}
|
||||||
is KtLiteralStringTemplateEntry, is KtEscapeStringTemplateEntry -> el<ULiteralExpression>(build(::KotlinStringULiteralExpression))
|
is KtLiteralStringTemplateEntry, is KtEscapeStringTemplateEntry -> el<ULiteralExpression>(build(::KotlinStringULiteralExpression))
|
||||||
is KtStringTemplateEntry -> element.expression?.let { convertExpression(it, givenParent, requiredType) } ?: expr<UExpression> { UastEmptyExpression }
|
is KtStringTemplateEntry -> element.expression?.let { convertExpression(it, givenParent, requiredType) } ?: expr<UExpression> { UastEmptyExpression }
|
||||||
|
is KtWhenEntry -> el<USwitchClauseExpressionWithBody>(build(::KotlinUSwitchEntry))
|
||||||
|
is KtWhenCondition -> convertWhenCondition(element, givenParent)
|
||||||
|
is KtTypeReference -> el<UTypeReferenceExpression> { LazyKotlinUTypeReferenceExpression(element, givenParent) }
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
if (element is LeafPsiElement && element.elementType == KtTokens.IDENTIFIER) {
|
if (element is LeafPsiElement && element.elementType == KtTokens.IDENTIFIER) {
|
||||||
@@ -349,7 +377,33 @@ internal object KotlinConverter {
|
|||||||
else -> expr<UExpression>(build(::UnknownKotlinExpression))
|
else -> expr<UExpression>(build(::UnknownKotlinExpression))
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun convertWhenCondition(condition: KtWhenCondition, givenParent: UElement?): UExpression {
|
||||||
|
return when (condition) {
|
||||||
|
is KtWhenConditionInRange -> KotlinCustomUBinaryExpression(condition, givenParent).apply {
|
||||||
|
leftOperand = KotlinStringUSimpleReferenceExpression("it", this)
|
||||||
|
operator = when {
|
||||||
|
condition.isNegated -> KotlinBinaryOperators.NOT_IN
|
||||||
|
else -> KotlinBinaryOperators.IN
|
||||||
|
}
|
||||||
|
rightOperand = KotlinConverter.convertOrEmpty(condition.rangeExpression, this)
|
||||||
|
}
|
||||||
|
is KtWhenConditionIsPattern -> KotlinCustomUBinaryExpressionWithType(condition, givenParent).apply {
|
||||||
|
operand = KotlinStringUSimpleReferenceExpression("it", this)
|
||||||
|
operationKind = when {
|
||||||
|
condition.isNegated -> KotlinBinaryExpressionWithTypeKinds.NEGATED_INSTANCE_CHECK
|
||||||
|
else -> UastBinaryExpressionWithTypeKind.INSTANCE_CHECK
|
||||||
|
}
|
||||||
|
val typeRef = condition.typeReference
|
||||||
|
typeReference = typeRef?.let {
|
||||||
|
LazyKotlinUTypeReferenceExpression(it, this) { typeRef.toPsiType(this, boxed = true) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is KtWhenConditionWithExpression -> KotlinConverter.convertOrEmpty(condition.expression, givenParent)
|
||||||
|
else -> UastEmptyExpression
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal fun convertOrEmpty(expression: KtExpression?, parent: UElement?): UExpression {
|
internal fun convertOrEmpty(expression: KtExpression?, parent: UElement?): UExpression {
|
||||||
return expression?.let { convertExpression(it, parent, null) } ?: UastEmptyExpression
|
return expression?.let { convertExpression(it, parent, null) } ?: UastEmptyExpression
|
||||||
}
|
}
|
||||||
@@ -376,7 +430,7 @@ private fun convertVariablesDeclaration(
|
|||||||
psi: KtVariableDeclaration,
|
psi: KtVariableDeclaration,
|
||||||
parent: UElement?
|
parent: UElement?
|
||||||
): UDeclarationsExpression {
|
): UDeclarationsExpression {
|
||||||
val declarationsExpression = KotlinUDeclarationsExpression(parent)
|
val declarationsExpression = KotlinUDeclarationsExpression(null, parent, psi)
|
||||||
val parentPsiElement = parent?.psi
|
val parentPsiElement = parent?.psi
|
||||||
val variable = KotlinUAnnotatedLocalVariable(
|
val variable = KotlinUAnnotatedLocalVariable(
|
||||||
UastKotlinPsiVariable.create(psi, parentPsiElement, declarationsExpression), declarationsExpression) { annotationParent ->
|
UastKotlinPsiVariable.create(psi, parentPsiElement, declarationsExpression), declarationsExpression) { annotationParent ->
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ import com.intellij.psi.PsiClass
|
|||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
|
import org.jetbrains.kotlin.psi.ValueArgument
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
||||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||||
@@ -44,6 +46,14 @@ class KotlinUAnnotation(
|
|||||||
override fun findAttributeValue(name: String?): UExpression? =
|
override fun findAttributeValue(name: String?): UExpression? =
|
||||||
findDeclaredAttributeValue(name) ?: findAttributeDefaultValue(name ?: "value")
|
findDeclaredAttributeValue(name) ?: findAttributeDefaultValue(name ?: "value")
|
||||||
|
|
||||||
|
fun findAttributeValueExpression(arg: ValueArgument): UExpression? {
|
||||||
|
val mapping = resolvedCall?.getArgumentMapping(arg)
|
||||||
|
return (mapping as? ArgumentMatch)?.let { match ->
|
||||||
|
val namedExpression = attributeValues.find { it.name == match.valueParameter.name.asString() }
|
||||||
|
namedExpression?.expression as? KotlinUVarargExpression ?: namedExpression
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun findDeclaredAttributeValue(name: String?): UExpression? {
|
override fun findDeclaredAttributeValue(name: String?): UExpression? {
|
||||||
return attributeValues.find {
|
return attributeValues.find {
|
||||||
it.name == name ||
|
it.name == name ||
|
||||||
|
|||||||
@@ -28,15 +28,19 @@ 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() {
|
||||||
|
override val uastParent: UElement? by lz {
|
||||||
|
givenParent ?: KotlinUastLanguagePlugin().convertElementWithParent(psi.parent ?: psi.containingFile, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
open class KotlinUClass private constructor(
|
open class KotlinUClass private constructor(
|
||||||
psi: KtLightClass,
|
psi: KtLightClass,
|
||||||
private val givenParent: UElement?
|
givenParent: UElement?
|
||||||
) : AbstractJavaUClass(), PsiClass by psi {
|
) : AbstractKotlinUClass(givenParent), PsiClass by psi {
|
||||||
|
|
||||||
val ktClass = psi.kotlinOrigin
|
val ktClass = psi.kotlinOrigin
|
||||||
|
|
||||||
override val uastParent: UElement? by lz { convertParent(givenParent) }
|
|
||||||
|
|
||||||
override val psi = unwrap<UClass, PsiClass>(psi)
|
override val psi = unwrap<UClass, PsiClass>(psi)
|
||||||
|
|
||||||
override fun getOriginalElement(): PsiElement? = super.getOriginalElement()
|
override fun getOriginalElement(): PsiElement? = super.getOriginalElement()
|
||||||
@@ -56,8 +60,8 @@ open class KotlinUClass private constructor(
|
|||||||
// filter Enum entry classes to avoid duplication with PsiEnumConstant initializer class
|
// filter Enum entry classes to avoid duplication with PsiEnumConstant initializer class
|
||||||
return psi.innerClasses.filter {
|
return psi.innerClasses.filter {
|
||||||
it.name != JvmAbi.DEFAULT_IMPLS_CLASS_NAME && !it.isEnumEntryLightClass()
|
it.name != JvmAbi.DEFAULT_IMPLS_CLASS_NAME && !it.isEnumEntryLightClass()
|
||||||
}.map {
|
}.mapNotNull {
|
||||||
getLanguagePlugin().convert<UClass>(it, this)
|
getLanguagePlugin().convertOpt<UClass>(it, this)
|
||||||
}.toTypedArray()
|
}.toTypedArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,20 +116,18 @@ open class KotlinUClass private constructor(
|
|||||||
|
|
||||||
class KotlinUAnonymousClass(
|
class KotlinUAnonymousClass(
|
||||||
psi: PsiAnonymousClass,
|
psi: PsiAnonymousClass,
|
||||||
private val givenParent: UElement?
|
givenParent: UElement?
|
||||||
) : AbstractJavaUClass(), UAnonymousClass, PsiAnonymousClass by psi {
|
) : AbstractKotlinUClass(givenParent), UAnonymousClass, PsiAnonymousClass by psi {
|
||||||
|
|
||||||
override val uastParent: UElement? by lz { convertParent(givenParent) }
|
|
||||||
|
|
||||||
override val psi: PsiAnonymousClass = unwrap<UAnonymousClass, PsiAnonymousClass>(psi)
|
override val psi: PsiAnonymousClass = unwrap<UAnonymousClass, PsiAnonymousClass>(psi)
|
||||||
|
|
||||||
override fun getOriginalElement(): PsiElement? = super<AbstractJavaUClass>.getOriginalElement()
|
override fun getOriginalElement(): PsiElement? = super<AbstractKotlinUClass>.getOriginalElement()
|
||||||
|
|
||||||
override fun getSuperClass(): UClass? = super<AbstractJavaUClass>.getSuperClass()
|
override fun getSuperClass(): UClass? = super<AbstractKotlinUClass>.getSuperClass()
|
||||||
override fun getFields(): Array<UField> = super<AbstractJavaUClass>.getFields()
|
override fun getFields(): Array<UField> = super<AbstractKotlinUClass>.getFields()
|
||||||
override fun getMethods(): Array<UMethod> = super<AbstractJavaUClass>.getMethods()
|
override fun getMethods(): Array<UMethod> = super<AbstractKotlinUClass>.getMethods()
|
||||||
override fun getInitializers(): Array<UClassInitializer> = super<AbstractJavaUClass>.getInitializers()
|
override fun getInitializers(): Array<UClassInitializer> = super<AbstractKotlinUClass>.getInitializers()
|
||||||
override fun getInnerClasses(): Array<UClass> = super<AbstractJavaUClass>.getInnerClasses()
|
override fun getInnerClasses(): Array<UClass> = super<AbstractKotlinUClass>.getInnerClasses()
|
||||||
|
|
||||||
override fun getContainingFile(): PsiFile = unwrapFakeFileForLightClass(psi.containingFile)
|
override fun getContainingFile(): PsiFile = unwrapFakeFileForLightClass(psi.containingFile)
|
||||||
|
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ class KotlinUFile(override val psi: KtFile, override val languagePlugin: UastLan
|
|||||||
val facadeOrScriptClass = if (psi.isScript()) psi.script?.toLightClass() else psi.findFacadeClass()
|
val facadeOrScriptClass = if (psi.isScript()) psi.script?.toLightClass() else psi.findFacadeClass()
|
||||||
val classes = psi.declarations.mapNotNull { (it as? KtClassOrObject)?.toLightClass()?.toUClass() }
|
val classes = psi.declarations.mapNotNull { (it as? KtClassOrObject)?.toLightClass()?.toUClass() }
|
||||||
|
|
||||||
(facadeOrScriptClass?.let { listOf(it.toUClass()) } ?: emptyList()) + classes
|
(facadeOrScriptClass?.toUClass()?.let { listOf(it) } ?: emptyList()) + classes
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun PsiClass.toUClass() = languagePlugin.convert<UClass>(this, this@KotlinUFile)
|
private fun PsiClass.toUClass() = languagePlugin.convertOpt<UClass>(this, this@KotlinUFile)
|
||||||
}
|
}
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.uast.kotlin
|
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.elements.KtLightElement
|
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
||||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
@@ -215,6 +216,13 @@ open class KotlinUEnumConstant(
|
|||||||
psi: PsiEnumConstant,
|
psi: PsiEnumConstant,
|
||||||
givenParent: UElement?
|
givenParent: UElement?
|
||||||
) : AbstractKotlinUVariable(givenParent), UEnumConstant, PsiEnumConstant by psi {
|
) : AbstractKotlinUVariable(givenParent), UEnumConstant, PsiEnumConstant by psi {
|
||||||
|
override val initializingClass: UClass? by lz {
|
||||||
|
(psi.initializingClass as? KtLightClass)?.let { initializingClass ->
|
||||||
|
KotlinUClass.create(initializingClass, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val psi = unwrap<UEnumConstant, PsiEnumConstant>(psi)
|
||||||
|
|
||||||
override fun getContainingFile(): PsiFile {
|
override fun getContainingFile(): PsiFile {
|
||||||
return super.getContainingFile()
|
return super.getContainingFile()
|
||||||
@@ -224,10 +232,6 @@ open class KotlinUEnumConstant(
|
|||||||
return super.getNameIdentifier()
|
return super.getNameIdentifier()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val initializingClass: UClass? by lz { getLanguagePlugin().convertOpt<UClass>(psi.initializingClass, this) }
|
|
||||||
|
|
||||||
override val psi = unwrap<UEnumConstant, PsiEnumConstant>(psi)
|
|
||||||
|
|
||||||
override val kind: UastCallKind
|
override val kind: UastCallKind
|
||||||
get() = UastCallKind.CONSTRUCTOR_CALL
|
get() = UastCallKind.CONSTRUCTOR_CALL
|
||||||
|
|
||||||
@@ -270,7 +274,10 @@ open class KotlinUEnumConstant(
|
|||||||
override val psi: PsiEnumConstant,
|
override val psi: PsiEnumConstant,
|
||||||
private val givenParent: UElement?
|
private val givenParent: UElement?
|
||||||
) : JavaAbstractUExpression(), USimpleNameReferenceExpression {
|
) : JavaAbstractUExpression(), USimpleNameReferenceExpression {
|
||||||
override val uastParent: UElement? by lz { convertParent(givenParent) }
|
override val uastParent: UElement? by lz {
|
||||||
|
givenParent ?: KotlinUastLanguagePlugin().convertElementWithParent(psi.parent ?: psi.containingFile, null)
|
||||||
|
}
|
||||||
|
|
||||||
override fun resolve() = psi.containingClass
|
override fun resolve() = psi.containingClass
|
||||||
override val resolvedName: String?
|
override val resolvedName: String?
|
||||||
get() = psi.containingClass?.name
|
get() = psi.containingClass?.name
|
||||||
|
|||||||
@@ -68,14 +68,13 @@ private fun createElvisExpressions(
|
|||||||
return listOf(declaration, ifExpression)
|
return listOf(declaration, ifExpression)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createElvisExpression(elvisExpression: KtBinaryExpression, containingElement: UElement?): UExpression {
|
fun createElvisExpression(elvisExpression: KtBinaryExpression, givenParent: UElement?): UExpression {
|
||||||
val left = elvisExpression.left ?: return UastEmptyExpression
|
val left = elvisExpression.left ?: return UastEmptyExpression
|
||||||
val right = elvisExpression.right ?: return UastEmptyExpression
|
val right = elvisExpression.right ?: return UastEmptyExpression
|
||||||
|
|
||||||
return object : UExpressionList, KotlinEvaluatableUElement {
|
return object : KotlinAbstractUElement(givenParent), UExpressionList, KotlinEvaluatableUElement {
|
||||||
override val psi: PsiElement? = elvisExpression
|
override val psi: PsiElement? = elvisExpression
|
||||||
override val kind = KotlinSpecialExpressionKinds.ELVIS
|
override val kind = KotlinSpecialExpressionKinds.ELVIS
|
||||||
override val uastParent: UElement? = containingElement
|
|
||||||
override val annotations: List<UAnnotation> = emptyList()
|
override val annotations: List<UAnnotation> = emptyList()
|
||||||
override val expressions: List<UExpression> by lz {
|
override val expressions: List<UExpression> by lz {
|
||||||
createElvisExpressions(left, right, this, elvisExpression.parent)
|
createElvisExpressions(left, right, this, elvisExpression.parent)
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,7 @@ class KotlinUBinaryExpressionWithType(
|
|||||||
override val type by lz { psi.right.toPsiType(this) }
|
override val type by lz { psi.right.toPsiType(this) }
|
||||||
|
|
||||||
override val typeReference by lz {
|
override val typeReference by lz {
|
||||||
psi.right?.let { LazyKotlinUTypeReferenceExpression(it, this) { it.toPsiType(this) } }
|
psi.right?.let { LazyKotlinUTypeReferenceExpression(it, this) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override val operationKind = when (psi.operationReference.getReferencedNameElementType()) {
|
override val operationKind = when (psi.operationReference.getReferencedNameElementType()) {
|
||||||
|
|||||||
+6
-1
@@ -17,12 +17,17 @@ package org.jetbrains.uast
|
|||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.uast.kotlin.KotlinAbstractUExpression
|
import org.jetbrains.uast.kotlin.KotlinAbstractUExpression
|
||||||
|
import org.jetbrains.uast.kotlin.doConvertParent
|
||||||
|
|
||||||
class KotlinUDeclarationsExpression(
|
class KotlinUDeclarationsExpression(
|
||||||
override val psi: PsiElement?,
|
override val psi: PsiElement?,
|
||||||
givenParent: UElement?
|
givenParent: UElement?,
|
||||||
|
val psiAnchor: PsiElement? = null
|
||||||
) : KotlinAbstractUExpression(givenParent), UDeclarationsExpression {
|
) : KotlinAbstractUExpression(givenParent), UDeclarationsExpression {
|
||||||
|
|
||||||
|
override val uastParent: UElement?
|
||||||
|
get() = if (psiAnchor != null) doConvertParent(this, psiAnchor.parent) else super.uastParent
|
||||||
|
|
||||||
constructor(uastParent: UElement?) : this(null, uastParent)
|
constructor(uastParent: UElement?) : this(null, uastParent)
|
||||||
|
|
||||||
override lateinit var declarations: List<UDeclaration>
|
override lateinit var declarations: List<UDeclaration>
|
||||||
|
|||||||
+2
-1
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement
|
|||||||
import org.jetbrains.kotlin.KtNodeTypes
|
import org.jetbrains.kotlin.KtNodeTypes
|
||||||
import org.jetbrains.kotlin.psi.KtConstantExpression
|
import org.jetbrains.kotlin.psi.KtConstantExpression
|
||||||
import org.jetbrains.kotlin.psi.KtEscapeStringTemplateEntry
|
import org.jetbrains.kotlin.psi.KtEscapeStringTemplateEntry
|
||||||
|
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
|
||||||
import org.jetbrains.uast.UElement
|
import org.jetbrains.uast.UElement
|
||||||
import org.jetbrains.uast.ULiteralExpression
|
import org.jetbrains.uast.ULiteralExpression
|
||||||
|
|
||||||
@@ -45,4 +46,4 @@ class KotlinStringULiteralExpression(
|
|||||||
get() = text
|
get() = text
|
||||||
|
|
||||||
override fun evaluate() = value
|
override fun evaluate() = value
|
||||||
}
|
}
|
||||||
|
|||||||
+46
-46
@@ -45,52 +45,52 @@ class KotlinUNamedExpression private constructor(
|
|||||||
valueArguments: List<ValueArgument>,
|
valueArguments: List<ValueArgument>,
|
||||||
uastParent: UElement?): UNamedExpression {
|
uastParent: UElement?): UNamedExpression {
|
||||||
return KotlinUNamedExpression(name, uastParent) { expressionParent ->
|
return KotlinUNamedExpression(name, uastParent) { expressionParent ->
|
||||||
object : KotlinAbstractUExpression(uastParent), UCallExpression {
|
KotlinUVarargExpression(valueArguments, expressionParent)
|
||||||
override val uastParent: UElement? = expressionParent
|
|
||||||
|
|
||||||
override val kind: UastCallKind = UastCallKind.NESTED_ARRAY_INITIALIZER
|
|
||||||
|
|
||||||
override val valueArguments: List<UExpression> by lz {
|
|
||||||
valueArguments.map {
|
|
||||||
it.getArgumentExpression()?.let { argumentExpression ->
|
|
||||||
getLanguagePlugin().convert<UExpression>(argumentExpression, this)
|
|
||||||
} ?: UastEmptyExpression
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override val valueArgumentCount: Int
|
|
||||||
get() = valueArguments.size
|
|
||||||
|
|
||||||
override val psi: PsiElement?
|
|
||||||
get() = null
|
|
||||||
|
|
||||||
override val methodIdentifier: UIdentifier?
|
|
||||||
get() = null
|
|
||||||
|
|
||||||
override val classReference: UReferenceExpression?
|
|
||||||
get() = null
|
|
||||||
|
|
||||||
override val methodName: String?
|
|
||||||
get() = null
|
|
||||||
|
|
||||||
override val typeArgumentCount: Int
|
|
||||||
get() = 0
|
|
||||||
|
|
||||||
override val typeArguments: List<PsiType>
|
|
||||||
get() = emptyList()
|
|
||||||
|
|
||||||
override val returnType: PsiType?
|
|
||||||
get() = null
|
|
||||||
|
|
||||||
override fun resolve() = null
|
|
||||||
|
|
||||||
override val receiver: UExpression?
|
|
||||||
get() = null
|
|
||||||
|
|
||||||
override val receiverType: PsiType?
|
|
||||||
get() = null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class KotlinUVarargExpression(private val valueArgs: List<ValueArgument>,
|
||||||
|
uastParent: UElement?) : KotlinAbstractUExpression(uastParent), UCallExpression {
|
||||||
|
override val kind: UastCallKind = UastCallKind.NESTED_ARRAY_INITIALIZER
|
||||||
|
|
||||||
|
override val valueArguments: List<UExpression> by lz {
|
||||||
|
valueArgs.map {
|
||||||
|
it.getArgumentExpression()?.let { argumentExpression ->
|
||||||
|
getLanguagePlugin().convert<UExpression>(argumentExpression, this)
|
||||||
|
} ?: UastEmptyExpression
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val valueArgumentCount: Int
|
||||||
|
get() = valueArgs.size
|
||||||
|
|
||||||
|
override val psi: PsiElement?
|
||||||
|
get() = null
|
||||||
|
|
||||||
|
override val methodIdentifier: UIdentifier?
|
||||||
|
get() = null
|
||||||
|
|
||||||
|
override val classReference: UReferenceExpression?
|
||||||
|
get() = null
|
||||||
|
|
||||||
|
override val methodName: String?
|
||||||
|
get() = null
|
||||||
|
|
||||||
|
override val typeArgumentCount: Int
|
||||||
|
get() = 0
|
||||||
|
|
||||||
|
override val typeArguments: List<PsiType>
|
||||||
|
get() = emptyList()
|
||||||
|
|
||||||
|
override val returnType: PsiType?
|
||||||
|
get() = null
|
||||||
|
|
||||||
|
override fun resolve() = null
|
||||||
|
|
||||||
|
override val receiver: UExpression?
|
||||||
|
get() = null
|
||||||
|
|
||||||
|
override val receiverType: PsiType?
|
||||||
|
get() = null
|
||||||
|
}
|
||||||
|
|||||||
+12
-25
@@ -17,7 +17,9 @@
|
|||||||
package org.jetbrains.uast.kotlin
|
package org.jetbrains.uast.kotlin
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtWhenEntry
|
||||||
|
import org.jetbrains.kotlin.psi.KtWhenExpression
|
||||||
import org.jetbrains.uast.*
|
import org.jetbrains.uast.*
|
||||||
import org.jetbrains.uast.kotlin.kinds.KotlinSpecialExpressionKinds
|
import org.jetbrains.uast.kotlin.kinds.KotlinSpecialExpressionKinds
|
||||||
|
|
||||||
@@ -48,32 +50,10 @@ class KotlinUSwitchExpression(
|
|||||||
|
|
||||||
class KotlinUSwitchEntry(
|
class KotlinUSwitchEntry(
|
||||||
override val psi: KtWhenEntry,
|
override val psi: KtWhenEntry,
|
||||||
givenParent: UExpression
|
givenParent: UElement?
|
||||||
) : KotlinAbstractUExpression(givenParent), USwitchClauseExpressionWithBody {
|
) : KotlinAbstractUExpression(givenParent), USwitchClauseExpressionWithBody {
|
||||||
override val caseValues by lz {
|
override val caseValues by lz {
|
||||||
psi.conditions.map { when (it) {
|
psi.conditions.map { KotlinConverter.convertWhenCondition(it, this) }
|
||||||
is KtWhenConditionInRange -> KotlinCustomUBinaryExpression(it, this).apply {
|
|
||||||
leftOperand = KotlinStringUSimpleReferenceExpression("it", this)
|
|
||||||
operator = when {
|
|
||||||
it.isNegated -> KotlinBinaryOperators.NOT_IN
|
|
||||||
else -> KotlinBinaryOperators.IN
|
|
||||||
}
|
|
||||||
rightOperand = KotlinConverter.convertOrEmpty(it.rangeExpression, this)
|
|
||||||
}
|
|
||||||
is KtWhenConditionIsPattern -> KotlinCustomUBinaryExpressionWithType(it, this).apply {
|
|
||||||
operand = KotlinStringUSimpleReferenceExpression("it", this)
|
|
||||||
operationKind = when {
|
|
||||||
it.isNegated -> KotlinBinaryExpressionWithTypeKinds.NEGATED_INSTANCE_CHECK
|
|
||||||
else -> UastBinaryExpressionWithTypeKind.INSTANCE_CHECK
|
|
||||||
}
|
|
||||||
val typeRef = it.typeReference
|
|
||||||
typeReference = typeRef?.let {
|
|
||||||
LazyKotlinUTypeReferenceExpression(it, this) { typeRef.toPsiType(this, boxed = true) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is KtWhenConditionWithExpression -> KotlinConverter.convertOrEmpty(it.expression, this)
|
|
||||||
else -> UastEmptyExpression
|
|
||||||
}}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val body: UExpressionList by lz {
|
override val body: UExpressionList by lz {
|
||||||
@@ -101,4 +81,11 @@ class KotlinUSwitchEntry(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun convertParent(): UElement? {
|
||||||
|
val result = KotlinConverter.unwrapElements(psi.parent)?.let { parentUnwrapped ->
|
||||||
|
KotlinUastLanguagePlugin().convertElementWithParent(parentUnwrapped, null)
|
||||||
|
}
|
||||||
|
return (result as? KotlinUSwitchExpression)?.body ?: result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+7
-4
@@ -2,6 +2,7 @@ package org.jetbrains.uast.kotlin
|
|||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiType
|
import com.intellij.psi.PsiType
|
||||||
|
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||||
import org.jetbrains.uast.UElement
|
import org.jetbrains.uast.UElement
|
||||||
import org.jetbrains.uast.UTypeReferenceExpression
|
import org.jetbrains.uast.UTypeReferenceExpression
|
||||||
|
|
||||||
@@ -13,9 +14,11 @@ open class KotlinUTypeReferenceExpression(
|
|||||||
|
|
||||||
|
|
||||||
class LazyKotlinUTypeReferenceExpression(
|
class LazyKotlinUTypeReferenceExpression(
|
||||||
override val psi: PsiElement,
|
override val psi: KtTypeReference,
|
||||||
givenParent: UElement?,
|
givenParent: UElement?,
|
||||||
private val typeSupplier: () -> PsiType
|
private val typeSupplier: (() -> PsiType)? = null
|
||||||
) : KotlinAbstractUExpression(givenParent), UTypeReferenceExpression {
|
) : KotlinAbstractUExpression(givenParent), UTypeReferenceExpression {
|
||||||
override val type: PsiType by lz { typeSupplier() }
|
override val type: PsiType by lz {
|
||||||
}
|
typeSupplier?.invoke() ?: psi.toPsiType(uastParent ?: this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ import org.jetbrains.kotlin.builtins.createFunctionType
|
|||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
|
import org.jetbrains.uast.*
|
||||||
import org.jetbrains.kotlin.types.isError
|
import org.jetbrains.kotlin.types.isError
|
||||||
import org.jetbrains.uast.UDeclaration
|
import org.jetbrains.uast.UDeclaration
|
||||||
import org.jetbrains.uast.UElement
|
import org.jetbrains.uast.UElement
|
||||||
@@ -73,10 +75,11 @@ class UastKotlinPsiVariable private constructor(
|
|||||||
fun create(
|
fun create(
|
||||||
declaration: KtVariableDeclaration,
|
declaration: KtVariableDeclaration,
|
||||||
parent: PsiElement?,
|
parent: PsiElement?,
|
||||||
containingElement: UElement,
|
containingElement: KotlinUDeclarationsExpression,
|
||||||
initializer: KtExpression? = null
|
initializer: KtExpression? = null
|
||||||
): PsiLocalVariable {
|
): PsiLocalVariable {
|
||||||
val psiParent = containingElement.getParentOfType<UDeclaration>()?.psi ?: parent
|
val psi = containingElement.psiAnchor ?: containingElement.psi
|
||||||
|
val psiParent = psi?.getNonStrictParentOfType<KtDeclaration>() ?: parent
|
||||||
val initializerExpression = initializer ?: declaration.initializer
|
val initializerExpression = initializer ?: declaration.initializer
|
||||||
return UastKotlinPsiVariable(
|
return UastKotlinPsiVariable(
|
||||||
manager = declaration.manager,
|
manager = declaration.manager,
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fun foo(a: Int = 1, foo: String? = null) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
UFile (package = )
|
||||||
|
UClass (name = DefaultParameterValuesKt)
|
||||||
|
UAnnotationMethod (name = foo)
|
||||||
|
UParameter (name = a)
|
||||||
|
UAnnotation (fqName = null)
|
||||||
|
ULiteralExpression (value = 1)
|
||||||
|
UParameter (name = foo)
|
||||||
|
UAnnotation (fqName = org.jetbrains.annotations.Nullable)
|
||||||
|
ULiteralExpression (value = null)
|
||||||
|
UBlockExpression
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
public final class DefaultParameterValuesKt {
|
||||||
|
public static final fun foo(a: int, foo: java.lang.String) : void {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
package org.jetbrains.uast.test.kotlin
|
package org.jetbrains.uast.test.kotlin
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.PsiRecursiveElementVisitor
|
import com.intellij.psi.PsiRecursiveElementVisitor
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
|
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
|
||||||
import org.jetbrains.uast.UDeclaration
|
import org.jetbrains.uast.UDeclaration
|
||||||
import org.jetbrains.uast.UElement
|
import org.jetbrains.uast.UElement
|
||||||
import org.jetbrains.uast.UFile
|
import org.jetbrains.uast.UFile
|
||||||
|
import org.jetbrains.uast.kotlin.KOTLIN_CACHED_UELEMENT_KEY
|
||||||
import org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin
|
import org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin
|
||||||
import org.jetbrains.uast.test.common.RenderLogTestBase
|
import org.jetbrains.uast.test.common.RenderLogTestBase
|
||||||
import org.jetbrains.uast.visitor.UastVisitor
|
import org.jetbrains.uast.visitor.UastVisitor
|
||||||
@@ -21,12 +23,7 @@ abstract class AbstractKotlinRenderLogTest : AbstractKotlinUastTest(), RenderLog
|
|||||||
override fun check(testName: String, file: UFile) {
|
override fun check(testName: String, file: UFile) {
|
||||||
super.check(testName, file)
|
super.check(testName, file)
|
||||||
|
|
||||||
file.psi.accept(object : PsiRecursiveElementVisitor() {
|
val parentMap = mutableMapOf<PsiElement, String>()
|
||||||
override fun visitElement(element: PsiElement) {
|
|
||||||
KotlinUastLanguagePlugin().convertElementWithParent(element, null)
|
|
||||||
super.visitElement(element)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
file.accept(object : UastVisitor {
|
file.accept(object : UastVisitor {
|
||||||
private val parentStack = Stack<UElement>()
|
private val parentStack = Stack<UElement>()
|
||||||
@@ -39,6 +36,11 @@ abstract class AbstractKotlinRenderLogTest : AbstractKotlinUastTest(), RenderLog
|
|||||||
else {
|
else {
|
||||||
Assert.assertEquals("Wrong parent of $node", parentStack.peek(), parent)
|
Assert.assertEquals("Wrong parent of $node", parentStack.peek(), parent)
|
||||||
}
|
}
|
||||||
|
node.psi?.let {
|
||||||
|
if (it !in parentMap) {
|
||||||
|
parentMap[it] = parentStack.reversed().joinToString { it.asLogString() }
|
||||||
|
}
|
||||||
|
}
|
||||||
parentStack.push(node)
|
parentStack.push(node)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -48,6 +50,22 @@ abstract class AbstractKotlinRenderLogTest : AbstractKotlinUastTest(), RenderLog
|
|||||||
parentStack.pop()
|
parentStack.pop()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
file.psi.clearUastCaches()
|
||||||
|
|
||||||
|
file.psi.accept(object : PsiRecursiveElementVisitor() {
|
||||||
|
override fun visitElement(element: PsiElement) {
|
||||||
|
val uElement = KotlinUastLanguagePlugin().convertElementWithParent(element, null)
|
||||||
|
val expectedParents = parentMap[element]
|
||||||
|
if (expectedParents != null) {
|
||||||
|
assertNotNull("Expected to be able to convert PSI element $element", uElement)
|
||||||
|
val parents = generateSequence(uElement!!.uastParent) { it.uastParent }.joinToString { it.asLogString() }
|
||||||
|
assertEquals("Inconsistent parents for $uElement", expectedParents, parents)
|
||||||
|
}
|
||||||
|
super.visitElement(element)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
file.checkContainingFileForAllElements()
|
file.checkContainingFileForAllElements()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,3 +86,12 @@ abstract class AbstractKotlinRenderLogTest : AbstractKotlinUastTest(), RenderLog
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun PsiFile.clearUastCaches() {
|
||||||
|
accept(object : PsiRecursiveElementVisitor() {
|
||||||
|
override fun visitElement(element: PsiElement) {
|
||||||
|
super.visitElement(element)
|
||||||
|
element.putUserData(KOTLIN_CACHED_UELEMENT_KEY, null)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() {
|
|||||||
|
|
||||||
@Test fun testDestructuringDeclaration() = doTest("DestructuringDeclaration")
|
@Test fun testDestructuringDeclaration() = doTest("DestructuringDeclaration")
|
||||||
|
|
||||||
|
@Test fun testDefaultParameterValues() = doTest("DefaultParameterValues")
|
||||||
|
|
||||||
@Test fun testParameterPropertyWithAnnotation() = doTest("ParameterPropertyWithAnnotation")
|
@Test fun testParameterPropertyWithAnnotation() = doTest("ParameterPropertyWithAnnotation")
|
||||||
|
|
||||||
@Test fun testParametersWithDefaultValues() = doTest("ParametersWithDefaultValues")
|
@Test fun testParametersWithDefaultValues() = doTest("ParametersWithDefaultValues")
|
||||||
|
|||||||
Reference in New Issue
Block a user