From f1d5570ca12e523722a7f2f95bf2a2eb797ccf9b Mon Sep 17 00:00:00 2001 From: Nicolay Mitropolsky Date: Sat, 21 Mar 2020 20:18:13 +0300 Subject: [PATCH] Uast: include parameters of reified methods to uast tree (KT-37613) --- .../uast/kotlin/KotlinAbstractUElement.kt | 13 ++- .../uast/kotlin/KotlinUastLanguagePlugin.kt | 13 ++- .../uast/kotlin/declarations/KotlinUMethod.kt | 66 +++-------- .../kotlin/declarations/KotlinUMethod.kt.191 | 66 +++-------- .../uast/kotlin/psi/UastFakeLightMethod.kt | 93 ++++++++++++++++ .../uast/kotlin/psi/UastKotlinPsiParameter.kt | 16 +-- .../uast-kotlin/testData/ReifiedParameters.kt | 7 ++ .../testData/ReifiedParameters.log.txt | 43 ++++++++ .../testData/ReifiedParameters.render.txt | 14 +++ .../uast-kotlin/testData/ReifiedReturnType.kt | 22 ++-- .../testData/ReifiedReturnType.log.txt | 104 ++++++++++++++++++ .../testData/ReifiedReturnType.render.txt | 33 ++++++ .../tests/KotlinIDERenderLogTest.kt | 7 +- .../uast-kotlin/tests/KotlinUastApiTest.kt | 27 +++++ .../tests/SimpleKotlinRenderLogTest.kt | 6 + 15 files changed, 402 insertions(+), 128 deletions(-) create mode 100644 plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/psi/UastFakeLightMethod.kt create mode 100644 plugins/uast-kotlin/testData/ReifiedParameters.kt create mode 100644 plugins/uast-kotlin/testData/ReifiedParameters.log.txt create mode 100644 plugins/uast-kotlin/testData/ReifiedParameters.render.txt create mode 100644 plugins/uast-kotlin/testData/ReifiedReturnType.log.txt create mode 100644 plugins/uast-kotlin/testData/ReifiedReturnType.render.txt diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt index 5f03a513dc4..610da7a5a2c 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt @@ -34,6 +34,7 @@ import org.jetbrains.uast.* import org.jetbrains.uast.kotlin.expressions.KotlinLocalFunctionULambdaExpression import org.jetbrains.uast.kotlin.expressions.KotlinUElvisExpression import org.jetbrains.uast.kotlin.internal.KotlinUElementWithComments +import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable abstract class KotlinAbstractUElement(private val givenParent: UElement?) : KotlinUElementWithComments, @@ -86,16 +87,16 @@ abstract class KotlinAbstractUElement(private val givenParent: UElement?) : Kotl ?: parent AnnotationUseSiteTarget.FIELD -> parent = (parentUnwrapped as? KtProperty) - ?: (parentUnwrapped as? KtParameter) - ?.takeIf { it.isPropertyParameter() } - ?.let(LightClassUtil::getLightClassBackingField) - ?: parent + ?: (parentUnwrapped as? KtParameter) + ?.takeIf { it.isPropertyParameter() } + ?.let(LightClassUtil::getLightClassBackingField) + ?: parent AnnotationUseSiteTarget.SETTER_PARAMETER -> parent = (parentUnwrapped as? KtParameter) - ?.toLightSetter()?.parameterList?.parameters?.firstOrNull() ?: parent + ?.toLightSetter()?.parameterList?.parameters?.firstOrNull() ?: parent } } - if (psi is UastKotlinPsiVariable && parent != null) { + if ((psi is UastKotlinPsiVariable || psi is UastKotlinPsiParameter) && parent != null) { parent = parent.parent } diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt index d75999e697a..1956f91af5d 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt @@ -51,6 +51,7 @@ import org.jetbrains.uast.kotlin.declarations.KotlinUIdentifier import org.jetbrains.uast.kotlin.declarations.KotlinUMethod import org.jetbrains.uast.kotlin.declarations.KotlinUMethodWithFakeLightDelegate import org.jetbrains.uast.kotlin.expressions.* +import org.jetbrains.uast.kotlin.psi.UastFakeLightMethod import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable @@ -487,6 +488,7 @@ internal object KotlinConverter { return with(expectedTypes) { when (original) { is KtLightMethod -> el(build(KotlinUMethod.Companion::create)) // .Companion is needed because of KT-13934 + is UastFakeLightMethod -> el { KotlinUMethodWithFakeLightDelegate(original.original, original, givenParent) } is KtLightClass -> when (original.kotlinOrigin) { is KtEnumEntry -> el { convertEnumEntry(original.kotlinOrigin as KtEnumEntry, givenParent) @@ -526,9 +528,7 @@ internal object KotlinConverter { if (lightMethod != null) convertDeclaration(lightMethod, givenParent, expectedTypes) else { - val ktLightClass = original.containingClassOrObject?.toLightClass() - ?: original.containingKtFile.findFacadeClass() - ?: return null + val ktLightClass = getLightClassForFakeMethod(original) ?: return null KotlinUMethodWithFakeLightDelegate(original, ktLightClass, givenParent) } } @@ -564,6 +564,10 @@ internal object KotlinConverter { } } + private fun getLightClassForFakeMethod(original: KtFunction): KtLightClass? { + if (original.isLocal) return null + return (original.containingClassOrObject?.toLightClass() ?: original.containingKtFile.findFacadeClass()) + } fun convertDeclarationOrElement( element: PsiElement, @@ -613,6 +617,9 @@ internal object KotlinConverter { alternative uParam@{ val lightMethod = when (val ownerFunction = element.ownerFunction) { is KtFunction -> LightClassUtil.getLightClassMethod(ownerFunction) + ?: getLightClassForFakeMethod(ownerFunction) + ?.takeIf { !it.isAnnotationType } + ?.let { UastFakeLightMethod(ownerFunction, it) } is KtPropertyAccessor -> LightClassUtil.getLightClassAccessorMethod(ownerFunction) else -> null } ?: return@uParam null diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt index 3530126f2bf..c5d7e6ede03 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt @@ -17,21 +17,16 @@ package org.jetbrains.uast.kotlin.declarations import com.intellij.psi.* -import com.intellij.psi.impl.light.LightMethodBuilder -import com.intellij.psi.impl.light.LightModifierList -import com.intellij.psi.impl.light.LightParameterListBuilder -import com.intellij.psi.impl.light.LightTypeParameterBuilder import org.jetbrains.kotlin.asJava.elements.* -import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject import org.jetbrains.kotlin.psi.psiUtil.getParentOfType -import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.utils.SmartList -import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.uast.* import org.jetbrains.uast.java.internal.JavaUElementWithComments import org.jetbrains.uast.kotlin.* +import org.jetbrains.uast.kotlin.psi.UastFakeLightMethod +import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter open class KotlinUMethod( psi: PsiMethod, @@ -70,7 +65,13 @@ open class KotlinUMethod( override val uastParameters by lz { val lightParams = psi.parameterList.parameters val receiver = receiver ?: return@lz lightParams.map { - KotlinUParameter(it, (it as? KtLightElement<*, *>)?.kotlinOrigin, this) + KotlinUParameter( + it, when (it) { + is KtLightElement<*, *> -> it.kotlinOrigin + is UastKotlinPsiParameter -> it.ktParameter + else -> null + }, this + ) } val receiverLight = lightParams.firstOrNull() ?: return@lz emptyList() val uParameters = SmartList(KotlinReceiverUParameter(receiverLight, receiver, this)) @@ -158,50 +159,15 @@ open class KotlinUAnnotationMethod( } -private class UastFakeLightMethod(private val original: KtFunction, containingClass: PsiClass) : LightMethodBuilder( - original.manager, original.language, original.name ?: "", - LightParameterListBuilder(original.manager, original.language), - LightModifierList(original.manager) -) { +class KotlinUMethodWithFakeLightDelegate internal constructor( + val original: KtFunction, + fakePsi: UastFakeLightMethod, + givenParent: UElement? +) : KotlinUMethod(fakePsi, original, givenParent) { - init { - this.containingClass = containingClass - } + constructor(original: KtFunction, containingLightClass: PsiClass, givenParent: UElement?) + : this(original, UastFakeLightMethod(original, containingLightClass), givenParent) - private val _buildTypeParameterList by lazy { - KotlinLightTypeParameterListBuilder(this).also { paramList -> - for ((i, p) in original.typeParameters.withIndex()) { - paramList.addParameter(LightTypeParameterBuilder(p.name ?: "__no_name__", this, i)) - } - } - } - - override fun getTypeParameterList(): PsiTypeParameterList? = _buildTypeParameterList - - override fun getReturnType(): PsiType? { - val context = original.analyze() - val descriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, original).safeAs() ?: return null - return descriptor.returnType?.toPsiType(this, original, false) - } - - override fun getParent(): PsiElement? = containingClass - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as UastFakeLightMethod - - if (original != other.original) return false - - return true - } - - override fun hashCode(): Int = original.hashCode() -} - -class KotlinUMethodWithFakeLightDelegate(val original: KtFunction, containingLightClass: PsiClass, givenParent: UElement?) : - KotlinUMethod(UastFakeLightMethod(original, containingLightClass), original, givenParent) { override val annotations: List get() = original.annotationEntries.mapNotNull { it.toUElementOfType() } diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt.191 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt.191 index d3797ee7a3b..1e6179cb8dd 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt.191 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt.191 @@ -17,22 +17,17 @@ package org.jetbrains.uast.kotlin.declarations import com.intellij.psi.* -import com.intellij.psi.impl.light.LightMethodBuilder -import com.intellij.psi.impl.light.LightModifierList -import com.intellij.psi.impl.light.LightParameterListBuilder -import com.intellij.psi.impl.light.LightTypeParameterBuilder import org.jetbrains.kotlin.asJava.elements.* import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject import org.jetbrains.kotlin.psi.psiUtil.getParentOfType -import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.utils.SmartList -import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.uast.* import org.jetbrains.uast.java.internal.JavaUElementWithComments import org.jetbrains.uast.kotlin.* +import org.jetbrains.uast.kotlin.psi.UastFakeLightMethod +import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter open class KotlinUMethod( psi: PsiMethod, @@ -71,7 +66,13 @@ open class KotlinUMethod( override val uastParameters by lz { val lightParams = psi.parameterList.parameters val receiver = receiver ?: return@lz lightParams.map { - KotlinUParameter(it, (it as? KtLightElement<*, *>)?.kotlinOrigin, this) + KotlinUParameter( + it, when (it) { + is KtLightElement<*, *> -> it.kotlinOrigin + is UastKotlinPsiParameter -> it.ktParameter + else -> null + }, this + ) } val receiverLight = lightParams.firstOrNull() ?: return@lz emptyList() val uParameters = SmartList(KotlinReceiverUParameter(receiverLight, receiver, this)) @@ -161,50 +162,15 @@ open class KotlinUAnnotationMethod( } -private class UastFakeLightMethod(private val original: KtFunction, containingClass: PsiClass) : LightMethodBuilder( - original.manager, original.language, original.name, - LightParameterListBuilder(original.manager, original.language), - LightModifierList(original.manager) -) { +class KotlinUMethodWithFakeLightDelegate internal constructor( + val original: KtFunction, + fakePsi: UastFakeLightMethod, + givenParent: UElement? +) : KotlinUMethod(fakePsi, original, givenParent) { - init { - this.containingClass = containingClass - } + constructor(original: KtFunction, containingLightClass: PsiClass, givenParent: UElement?) + : this(original, UastFakeLightMethod(original, containingLightClass), givenParent) - private val _buildTypeParameterList by lazy { - KotlinLightTypeParameterListBuilder(this).also { paramList -> - for ((i, p) in original.typeParameters.withIndex()) { - paramList.addParameter(LightTypeParameterBuilder(p.name ?: "__no_name__", this, i)) - } - } - } - - override fun getTypeParameterList(): PsiTypeParameterList? = _buildTypeParameterList - - override fun getReturnType(): PsiType? { - val context = original.analyze() - val descriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, original).safeAs() ?: return null - return descriptor.returnType?.toPsiType(this, original, false) - } - - override fun getParent(): PsiElement? = containingClass - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as UastFakeLightMethod - - if (original != other.original) return false - - return true - } - - override fun hashCode(): Int = original.hashCode() -} - -class KotlinUMethodWithFakeLightDelegate(val original: KtFunction, containingLightClass: PsiClass, givenParent: UElement?) : - KotlinUMethod(UastFakeLightMethod(original, containingLightClass), original, givenParent) { override val annotations: List get() = original.annotationEntries.mapNotNull { it.toUElementOfType() } diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/psi/UastFakeLightMethod.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/psi/UastFakeLightMethod.kt new file mode 100644 index 00000000000..eb06b4e97a9 --- /dev/null +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/psi/UastFakeLightMethod.kt @@ -0,0 +1,93 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.uast.kotlin.psi + +import com.intellij.psi.* +import com.intellij.psi.impl.light.LightMethodBuilder +import com.intellij.psi.impl.light.LightModifierList +import com.intellij.psi.impl.light.LightParameterListBuilder +import com.intellij.psi.impl.light.LightTypeParameterBuilder +import org.jetbrains.kotlin.asJava.elements.KotlinLightTypeParameterListBuilder +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.psi.KtFunction +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.utils.addToStdlib.safeAs +import org.jetbrains.uast.UastErrorType +import org.jetbrains.uast.kotlin.analyze +import org.jetbrains.uast.kotlin.getType +import org.jetbrains.uast.kotlin.toPsiType + +internal class UastFakeLightMethod(internal val original: KtFunction, containingClass: PsiClass) : LightMethodBuilder( + original.manager, original.language, original.name ?: "", + LightParameterListBuilder(original.manager, original.language), + LightModifierList(original.manager) +) { + + init { + this.containingClass = containingClass + } + + private val _buildTypeParameterList by lazy { + KotlinLightTypeParameterListBuilder(this).also { paramList -> + for ((i, p) in original.typeParameters.withIndex()) { + paramList.addParameter( + LightTypeParameterBuilder( + p.name ?: "__no_name__", + this, + i + ) + ) + } + } + } + + override fun getTypeParameterList(): PsiTypeParameterList? = _buildTypeParameterList + + private val paramsList: PsiParameterList by lazy { + object : LightParameterListBuilder(original.manager, original.language) { + override fun getParent(): PsiElement = this@UastFakeLightMethod + override fun getContainingFile(): PsiFile = parent.containingFile + + init { + val parameterList = this + for ((i, p) in original.valueParameters.withIndex()) { + this.addParameter( + UastKotlinPsiParameter( + p.name ?: "p$i", + p.typeReference?.getType() + ?.toPsiType(this@UastFakeLightMethod, original, false) + ?: UastErrorType, + parameterList, original.language, p.isVarArg, p.defaultValue, p + ) + ) + } + } + } + } + + override fun getParameterList(): PsiParameterList = paramsList + + override fun getReturnType(): PsiType? { + val context = original.analyze() + val descriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, original).safeAs() ?: return null + return descriptor.returnType?.toPsiType(this, original, false) + } + + override fun getParent(): PsiElement? = containingClass + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as UastFakeLightMethod + + if (original != other.original) return false + + return true + } + + override fun hashCode(): Int = original.hashCode() +} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/psi/UastKotlinPsiParameter.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/psi/UastKotlinPsiParameter.kt index 93542442a88..657e8d10153 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/psi/UastKotlinPsiParameter.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/psi/UastKotlinPsiParameter.kt @@ -19,13 +19,13 @@ import org.jetbrains.uast.kotlin.analyze import org.jetbrains.uast.kotlin.toPsiType class UastKotlinPsiParameter( - name: String, - type: PsiType, - parent: PsiElement, - language: Language, - isVarArgs: Boolean, - val ktDefaultValue: KtExpression?, - val ktParameter: KtParameter + name: String, + type: PsiType, + private val parent: PsiElement, + language: Language, + isVarArgs: Boolean, + val ktDefaultValue: KtExpression?, + val ktParameter: KtParameter ) : LightParameter(name, type, parent, language, isVarArgs) { companion object { fun create(parameter: KtParameter, parent: PsiElement, containingElement: UElement, index: Int): PsiParameter { @@ -42,6 +42,8 @@ class UastKotlinPsiParameter( } } + override fun getParent(): PsiElement = parent + override fun getContainingFile(): PsiFile? = ktParameter.containingFile override fun equals(other: Any?): Boolean { diff --git a/plugins/uast-kotlin/testData/ReifiedParameters.kt b/plugins/uast-kotlin/testData/ReifiedParameters.kt new file mode 100644 index 00000000000..4f9d48f6b88 --- /dev/null +++ b/plugins/uast-kotlin/testData/ReifiedParameters.kt @@ -0,0 +1,7 @@ +inline fun functionWithLambda(t: T, process: (T) -> Int): Int = process(t) + +inline fun functionWithVararg(i: Int?, vararg t: T): T = t[0] + +inline fun functionWithParamAnnotation(@Suppress("s") t: T): T = t + +inline fun functionUnresolved(@Suppress("s") t: Unresolved): T = t \ No newline at end of file diff --git a/plugins/uast-kotlin/testData/ReifiedParameters.log.txt b/plugins/uast-kotlin/testData/ReifiedParameters.log.txt new file mode 100644 index 00000000000..e059403c12f --- /dev/null +++ b/plugins/uast-kotlin/testData/ReifiedParameters.log.txt @@ -0,0 +1,43 @@ +UFile (package = ) + UClass (name = ReifiedParametersKt) + UMethod (name = functionWithLambda) + UParameter (name = t) + UAnnotation (fqName = org.jetbrains.annotations.Nullable) + UParameter (name = process) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UReturnExpression + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) + UIdentifier (Identifier (process)) + USimpleNameReferenceExpression (identifier = invoke, resolvesTo = null) + USimpleNameReferenceExpression (identifier = t) + UMethod (name = functionWithVararg) + UParameter (name = i) + UAnnotation (fqName = org.jetbrains.annotations.Nullable) + UParameter (name = t) + UAnnotation (fqName = org.jetbrains.annotations.Nullable) + UBlockExpression + UReturnExpression + UArrayAccessExpression + USimpleNameReferenceExpression (identifier = t) + ULiteralExpression (value = 0) + UMethod (name = functionWithParamAnnotation) + UParameter (name = t) + UAnnotation (fqName = org.jetbrains.annotations.Nullable) + UAnnotation (fqName = kotlin.Suppress) + UNamedExpression (name = names) + UPolyadicExpression (operator = +) + ULiteralExpression (value = "s") + UBlockExpression + UReturnExpression + USimpleNameReferenceExpression (identifier = t) + UMethod (name = functionUnresolved) + UParameter (name = t) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UAnnotation (fqName = kotlin.Suppress) + UNamedExpression (name = names) + UPolyadicExpression (operator = +) + ULiteralExpression (value = "s") + UBlockExpression + UReturnExpression + USimpleNameReferenceExpression (identifier = t) diff --git a/plugins/uast-kotlin/testData/ReifiedParameters.render.txt b/plugins/uast-kotlin/testData/ReifiedParameters.render.txt new file mode 100644 index 00000000000..2ac1bb3a20b --- /dev/null +++ b/plugins/uast-kotlin/testData/ReifiedParameters.render.txt @@ -0,0 +1,14 @@ +public final class ReifiedParametersKt { + fun functionWithLambda(@org.jetbrains.annotations.Nullable t: T, @org.jetbrains.annotations.NotNull process: kotlin.jvm.functions.Function1) : int { + return invoke(t) + } + fun functionWithVararg(@org.jetbrains.annotations.Nullable i: int, @org.jetbrains.annotations.Nullable t: T) : T { + return t[0] + } + fun functionWithParamAnnotation(@org.jetbrains.annotations.Nullable @kotlin.Suppress(names = "s") t: T) : T { + return t + } + fun functionUnresolved(@org.jetbrains.annotations.NotNull @kotlin.Suppress(names = "s") t: ) : T { + return t + } +} diff --git a/plugins/uast-kotlin/testData/ReifiedReturnType.kt b/plugins/uast-kotlin/testData/ReifiedReturnType.kt index 541d6cbb6c0..1522ac927a0 100644 --- a/plugins/uast-kotlin/testData/ReifiedReturnType.kt +++ b/plugins/uast-kotlin/testData/ReifiedReturnType.kt @@ -1,11 +1,11 @@ -inline fun function1(t: T) {} -inline fun function2(t: T): T = t -inline fun function3(t: T) {} -inline fun function4(t: T): T = t -inline fun function5(t: T): Int = 42 -inline fun T.function6(t: T): T = t -inline fun function7(t: T): T = t -private inline fun function8(t: T): T = t -internal inline fun function9(t: T): T = t -public inline fun function10(t: T): T = t -inline fun T.function11(t: T): T = t \ No newline at end of file +inline fun function1(t: T, i: Int, s: String) {} +inline fun function2(t: T, i: Int, s: String): T = t +inline fun function3(t: T, i: Int, s: String) {} +inline fun function4(t: T, i: Int, s: String): T = t +inline fun function5(t: T, i: Int, s: String): Int = 42 +inline fun T.function6(t: T, i: Int, s: String): T = t +inline fun function7(t: T, i: Int, s: String): T = t +private inline fun function8(t: T, i: Int, s: String): T = t +internal inline fun function9(t: T, i: Int, s: String): T = t +public inline fun function10(t: T, i: Int, s: String): T = t +inline fun T.function11(t: T, i: Int, s: String): T = t \ No newline at end of file diff --git a/plugins/uast-kotlin/testData/ReifiedReturnType.log.txt b/plugins/uast-kotlin/testData/ReifiedReturnType.log.txt new file mode 100644 index 00000000000..c54c361a63b --- /dev/null +++ b/plugins/uast-kotlin/testData/ReifiedReturnType.log.txt @@ -0,0 +1,104 @@ +UFile (package = ) + UClass (name = ReifiedReturnTypeKt) + UMethod (name = function1) + UParameter (name = t) + UAnnotation (fqName = org.jetbrains.annotations.Nullable) + UParameter (name = i) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UParameter (name = s) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UMethod (name = function2) + UParameter (name = t) + UAnnotation (fqName = org.jetbrains.annotations.Nullable) + UParameter (name = i) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UParameter (name = s) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UReturnExpression + USimpleNameReferenceExpression (identifier = t) + UMethod (name = function3) + UParameter (name = t) + UAnnotation (fqName = org.jetbrains.annotations.Nullable) + UParameter (name = i) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UParameter (name = s) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UMethod (name = function4) + UParameter (name = t) + UAnnotation (fqName = org.jetbrains.annotations.Nullable) + UParameter (name = i) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UParameter (name = s) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UReturnExpression + USimpleNameReferenceExpression (identifier = t) + UMethod (name = function5) + UParameter (name = t) + UAnnotation (fqName = org.jetbrains.annotations.Nullable) + UParameter (name = i) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UParameter (name = s) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UReturnExpression + ULiteralExpression (value = 42) + UMethod (name = function6) + UParameter (name = t) + UAnnotation (fqName = org.jetbrains.annotations.Nullable) + UParameter (name = i) + UParameter (name = s) + UBlockExpression + UReturnExpression + USimpleNameReferenceExpression (identifier = t) + UMethod (name = function7) + UParameter (name = t) + UAnnotation (fqName = org.jetbrains.annotations.Nullable) + UParameter (name = i) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UParameter (name = s) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UReturnExpression + USimpleNameReferenceExpression (identifier = t) + UMethod (name = function8) + UParameter (name = t) + UAnnotation (fqName = org.jetbrains.annotations.Nullable) + UParameter (name = i) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UParameter (name = s) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UReturnExpression + USimpleNameReferenceExpression (identifier = t) + UMethod (name = function9) + UParameter (name = t) + UAnnotation (fqName = org.jetbrains.annotations.Nullable) + UParameter (name = i) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UParameter (name = s) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UReturnExpression + USimpleNameReferenceExpression (identifier = t) + UMethod (name = function10) + UParameter (name = t) + UAnnotation (fqName = org.jetbrains.annotations.Nullable) + UParameter (name = i) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UParameter (name = s) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UReturnExpression + USimpleNameReferenceExpression (identifier = t) + UMethod (name = function11) + UParameter (name = t) + UAnnotation (fqName = org.jetbrains.annotations.Nullable) + UParameter (name = i) + UParameter (name = s) + UBlockExpression + UReturnExpression + USimpleNameReferenceExpression (identifier = t) diff --git a/plugins/uast-kotlin/testData/ReifiedReturnType.render.txt b/plugins/uast-kotlin/testData/ReifiedReturnType.render.txt new file mode 100644 index 00000000000..139732c387c --- /dev/null +++ b/plugins/uast-kotlin/testData/ReifiedReturnType.render.txt @@ -0,0 +1,33 @@ +public final class ReifiedReturnTypeKt { + public static final fun function1(@org.jetbrains.annotations.Nullable t: T, @org.jetbrains.annotations.NotNull i: int, @org.jetbrains.annotations.NotNull s: java.lang.String) : void { + } + public static final fun function2(@org.jetbrains.annotations.Nullable t: T, @org.jetbrains.annotations.NotNull i: int, @org.jetbrains.annotations.NotNull s: java.lang.String) : T { + return t + } + fun function3(@org.jetbrains.annotations.Nullable t: T, @org.jetbrains.annotations.NotNull i: int, @org.jetbrains.annotations.NotNull s: java.lang.String) : void { + } + fun function4(@org.jetbrains.annotations.Nullable t: T, @org.jetbrains.annotations.NotNull i: int, @org.jetbrains.annotations.NotNull s: java.lang.String) : T { + return t + } + fun function5(@org.jetbrains.annotations.Nullable t: T, @org.jetbrains.annotations.NotNull i: int, @org.jetbrains.annotations.NotNull s: java.lang.String) : int { + return 42 + } + fun function6(@org.jetbrains.annotations.Nullable t: T, i: int, s: java.lang.String) : T { + return t + } + fun function7(@org.jetbrains.annotations.Nullable t: T, @org.jetbrains.annotations.NotNull i: int, @org.jetbrains.annotations.NotNull s: java.lang.String) : T { + return t + } + fun function8(@org.jetbrains.annotations.Nullable t: T, @org.jetbrains.annotations.NotNull i: int, @org.jetbrains.annotations.NotNull s: java.lang.String) : T { + return t + } + fun function9(@org.jetbrains.annotations.Nullable t: T, @org.jetbrains.annotations.NotNull i: int, @org.jetbrains.annotations.NotNull s: java.lang.String) : T { + return t + } + fun function10(@org.jetbrains.annotations.Nullable t: T, @org.jetbrains.annotations.NotNull i: int, @org.jetbrains.annotations.NotNull s: java.lang.String) : T { + return t + } + fun function11(@org.jetbrains.annotations.Nullable t: T, i: int, s: java.lang.String) : T { + return t + } +} diff --git a/plugins/uast-kotlin/tests/KotlinIDERenderLogTest.kt b/plugins/uast-kotlin/tests/KotlinIDERenderLogTest.kt index c6a97379ff7..20e740ccc79 100644 --- a/plugins/uast-kotlin/tests/KotlinIDERenderLogTest.kt +++ b/plugins/uast-kotlin/tests/KotlinIDERenderLogTest.kt @@ -17,7 +17,6 @@ class KotlinIDERenderLogTest : AbstractKotlinUastLightCodeInsightFixtureTest(), override fun check(testName: String, file: UFile) = super.check(testName, file) - @Test fun testLocalDeclarations() = doTest("LocalDeclarations") @@ -153,6 +152,12 @@ class KotlinIDERenderLogTest : AbstractKotlinUastLightCodeInsightFixtureTest(), @Test fun testReified() = doTest("Reified") + @Test + fun testReifiedReturnType() = doTest("ReifiedReturnType") + + @Test + fun testReifiedParameters() = doTest("ReifiedParameters") + @Test fun testSuspend() = doTest("Suspend") diff --git a/plugins/uast-kotlin/tests/KotlinUastApiTest.kt b/plugins/uast-kotlin/tests/KotlinUastApiTest.kt index 5b232cd145e..2354241a768 100644 --- a/plugins/uast-kotlin/tests/KotlinUastApiTest.kt +++ b/plugins/uast-kotlin/tests/KotlinUastApiTest.kt @@ -644,6 +644,33 @@ class KotlinUastApiTest : AbstractKotlinUastTest() { } } + @Test + fun testReifiedParameters() { + doTest("ReifiedParameters") { _, file -> + val methods = file.classes.flatMap { it.methods.asIterable() } + + for (method in methods) { + assertNotNull("method ${method.name} should have source", method.sourcePsi) + assertEquals("method ${method.name} should be equals to converted from sourcePsi", method, method.sourcePsi.toUElement()) + assertEquals("method ${method.name} should be equals to converted from javaPsi", method, method.javaPsi.toUElement()) + + for (parameter in method.uastParameters) { + assertNotNull("parameter ${parameter.name} should have source", parameter.sourcePsi) + assertEquals( + "parameter ${parameter.name} of method ${method.name} should be equals to converted from sourcePsi", + parameter, + parameter.sourcePsi.toUElement() + ) + assertEquals( + "parameter ${parameter.name} of method ${method.name} should be equals to converted from javaPsi", + parameter, + parameter.javaPsi.toUElement() + ) + } + } + } + } + } fun Iterable.assertedFind(value: R, transform: (T) -> R): T = diff --git a/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt b/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt index 5432d7a8bff..cb3b277f8cc 100644 --- a/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt +++ b/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt @@ -130,6 +130,12 @@ class SimpleKotlinRenderLogTest : AbstractKotlinUastTest(), AbstractKotlinRender @Test fun testReified() = doTest("Reified") + @Test + fun testReifiedReturnType() = doTest("ReifiedReturnType") + + @Test + fun testReifiedParameters() = doTest("ReifiedParameters") + @Test fun testSuspend() = doTest("Suspend")