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 bf7cca30a43..3d118d0e048 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 @@ -16,23 +16,21 @@ package org.jetbrains.uast.kotlin.declarations -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile -import com.intellij.psi.PsiMethod -import com.intellij.psi.PsiNameIdentifierOwner +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 org.jetbrains.kotlin.asJava.elements.KtLightElement -import org.jetbrains.kotlin.asJava.elements.KtLightMethod -import org.jetbrains.kotlin.asJava.elements.isGetter -import org.jetbrains.kotlin.asJava.elements.isSetter +import com.intellij.psi.impl.light.LightTypeParameterBuilder +import org.jetbrains.kotlin.asJava.elements.* import org.jetbrains.kotlin.asJava.findFacadeClass import org.jetbrains.kotlin.asJava.toLightClass +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.* @@ -164,6 +162,22 @@ private fun buildLightMethodFake(original: KtFunction): PsiMethod = object : Lig containingClass = original.containingClassOrObject?.toLightClass() ?: original.containingKtFile.findFacadeClass() } + 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 } 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 4eba77f3f94..40bdeb55b9e 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 @@ -20,17 +20,18 @@ 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 org.jetbrains.kotlin.asJava.elements.KtLightElement -import org.jetbrains.kotlin.asJava.elements.KtLightMethod -import org.jetbrains.kotlin.asJava.elements.isGetter -import org.jetbrains.kotlin.asJava.elements.isSetter +import com.intellij.psi.impl.light.LightTypeParameterBuilder +import org.jetbrains.kotlin.asJava.elements.* import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.asJava.findFacadeClass import org.jetbrains.kotlin.asJava.toLightClass +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.* @@ -164,6 +165,22 @@ private fun buildLightMethodFake(original: KtFunction): PsiMethod = object : Lig containingClass = original.containingClassOrObject?.toLightClass() ?: original.containingKtFile.findFacadeClass() } + 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 } diff --git a/plugins/uast-kotlin/testData/DeprecatedHidden.render.txt b/plugins/uast-kotlin/testData/DeprecatedHidden.render.txt index 484136b1f79..b0fae3381ab 100644 --- a/plugins/uast-kotlin/testData/DeprecatedHidden.render.txt +++ b/plugins/uast-kotlin/testData/DeprecatedHidden.render.txt @@ -5,6 +5,6 @@ public final class Test { } public fun Test() = UastEmptyExpression @kotlin.Deprecated(level = DeprecationLevel.HIDDEN, message = "nothing") - fun test2() { + fun test2() : void { } } diff --git a/plugins/uast-kotlin/testData/Reified.render.txt b/plugins/uast-kotlin/testData/Reified.render.txt index a11b5f51472..ed9b5a576b1 100644 --- a/plugins/uast-kotlin/testData/Reified.render.txt +++ b/plugins/uast-kotlin/testData/Reified.render.txt @@ -4,8 +4,8 @@ public final class ReifiedKt { public static final fun systemService2(@org.jetbrains.annotations.NotNull $this$systemService2: test.pkg.Context) : error.NonExistentClass { return (java.lang.String.java) } - fun systemService1() { - return (java.lang.Object.java) + fun systemService1() : { + return (T.java) } } @@ -14,7 +14,7 @@ public final class Context { return (java.lang.String.java) } public fun Context() = UastEmptyExpression - fun ownSystemService1() { - return (java.lang.Object.java) + fun ownSystemService1() : { + return (T.java) } } diff --git a/plugins/uast-kotlin/testData/ReifiedReturnType.kt b/plugins/uast-kotlin/testData/ReifiedReturnType.kt new file mode 100644 index 00000000000..541d6cbb6c0 --- /dev/null +++ b/plugins/uast-kotlin/testData/ReifiedReturnType.kt @@ -0,0 +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 diff --git a/plugins/uast-kotlin/testData/Suspend.render.txt b/plugins/uast-kotlin/testData/Suspend.render.txt index d580927d7db..974b4d51199 100644 --- a/plugins/uast-kotlin/testData/Suspend.render.txt +++ b/plugins/uast-kotlin/testData/Suspend.render.txt @@ -11,7 +11,7 @@ public final class Context { return suspendPrivate() } public fun Context() = UastEmptyExpression - fun suspendPrivate() { + fun suspendPrivate() : int { return inner() } } diff --git a/plugins/uast-kotlin/tests/KotlinUastApiTest.kt b/plugins/uast-kotlin/tests/KotlinUastApiTest.kt index 8d328472a12..cc38f027399 100644 --- a/plugins/uast-kotlin/tests/KotlinUastApiTest.kt +++ b/plugins/uast-kotlin/tests/KotlinUastApiTest.kt @@ -595,6 +595,26 @@ class KotlinUastApiTest : AbstractKotlinUastTest() { } } + @Test + fun testReifiedReturnTypes() { + doTest("ReifiedReturnType") { _, file -> + val methods = file.classes.flatMap { it.methods.asIterable() } + assertEquals(""" + function1 -> PsiType:void + function2 -> PsiType:T + function3 -> PsiType:void + function4 -> PsiType:T + function5 -> PsiType:int + function6 -> PsiType:T + function7 -> PsiType:T + function8 -> PsiType:T + function9 -> PsiType:T + function10 -> PsiType:T + function11 -> PsiType:T + """.trimIndent(), methods.joinToString("\n") { m -> m.name + " -> " + m.returnType.toString() }) + } + } + } fun Iterable.assertedFind(value: R, transform: (T) -> R): T =