Uast: the returnType support for light methods for reified functions (KT-35610)

This commit is contained in:
Nicolay Mitropolsky
2020-01-08 15:26:42 +03:00
parent c04ba009e6
commit ed4e73c8e9
7 changed files with 80 additions and 18 deletions
@@ -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<CallableDescriptor>() ?: return null
return descriptor.returnType?.toPsiType(this, original, false)
}
override fun getParent(): PsiElement? = containingClass
}
@@ -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<CallableDescriptor>() ?: return null
return descriptor.returnType?.toPsiType(this, original, false)
}
override fun getParent(): PsiElement? = containingClass
}
+1 -1
View File
@@ -5,6 +5,6 @@ public final class Test {
}
public fun Test() = UastEmptyExpression
@kotlin.Deprecated(level = DeprecationLevel.HIDDEN, message = "nothing")
fun test2() {
fun test2() : void {
}
}
+4 -4
View File
@@ -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 <anonymous class>(java.lang.String.java)
}
fun systemService1() {
return <anonymous class>(java.lang.Object.java)
fun systemService1() : <ErrorType> {
return <anonymous class>(T.java)
}
}
@@ -14,7 +14,7 @@ public final class Context {
return <anonymous class>(java.lang.String.java)
}
public fun Context() = UastEmptyExpression
fun ownSystemService1() {
return <anonymous class>(java.lang.Object.java)
fun ownSystemService1() : <ErrorType> {
return <anonymous class>(T.java)
}
}
+11
View File
@@ -0,0 +1,11 @@
inline fun <T> function1(t: T) {}
inline fun <T> function2(t: T): T = t
inline fun <reified T> function3(t: T) {}
inline fun <reified T> function4(t: T): T = t
inline fun <reified T> function5(t: T): Int = 42
inline fun <reified T : Activity> T.function6(t: T): T = t
inline fun <reified T> function7(t: T): T = t
private inline fun <reified T> function8(t: T): T = t
internal inline fun <reified T> function9(t: T): T = t
public inline fun <reified T> function10(t: T): T = t
inline fun <reified T> T.function11(t: T): T = t
+1 -1
View File
@@ -11,7 +11,7 @@ public final class Context {
return suspendPrivate()
}
public fun Context() = UastEmptyExpression
fun suspendPrivate() {
fun suspendPrivate() : int {
return inner()
}
}
@@ -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 <T, R> Iterable<T>.assertedFind(value: R, transform: (T) -> R): T =