Uast: resolve reified callees from classpath (#4013, KT-41279)

This commit is contained in:
Kevin Bierhoff
2021-01-14 09:29:03 -08:00
committed by GitHub
parent c0dd731818
commit c1360c5a7a
4 changed files with 179 additions and 3 deletions

View File

@@ -76,6 +76,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.uast.*
import org.jetbrains.uast.kotlin.expressions.KotlinLocalFunctionUVariable
import org.jetbrains.uast.kotlin.psi.UastDescriptorLightMethod
import org.jetbrains.uast.kotlin.psi.UastFakeLightMethod
import org.jetbrains.uast.kotlin.psi.UastFakeLightPrimaryConstructor
import java.lang.ref.WeakReference
@@ -425,7 +426,7 @@ private fun resolveDeserialized(
psiClass.getMethodBySignature(
JvmProtoBufUtil.getJvmMethodSignature(proto, nameResolver, typeTable)
?: getMethodSignatureFromDescriptor(context, descriptor)
)
) ?: UastDescriptorLightMethod(descriptor as SimpleFunctionDescriptor, psiClass, context) // fake Java-invisible methods
}
is ProtoBuf.Constructor -> {
val signature = JvmProtoBufUtil.getJvmConstructorSignature(proto, nameResolver, typeTable)

View File

@@ -0,0 +1,126 @@
/*
* 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.*
import org.jetbrains.kotlin.asJava.elements.KotlinLightTypeParameterListBuilder
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtNamedFunction
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 UastDescriptorLightMethod(original: SimpleFunctionDescriptor, containingClass: PsiClass, context: KtElement) :
UastDescriptorLightMethodBase<SimpleFunctionDescriptor>(original, containingClass, context) {
private val _buildTypeParameterList by lazy {
KotlinLightTypeParameterListBuilder(this).also { paramList ->
for ((i, p) in original.typeParameters.withIndex()) {
paramList.addParameter(
object : LightTypeParameterBuilder(
p.name.identifier,
this,
i
) {
private val myExtendsList by lazy {
super.getExtendsList().apply {
p.upperBounds.forEach { bound ->
bound.toPsiType(this@UastDescriptorLightMethod, context, false)
.safeAs<PsiClassType>()
?.let { addReference(it) }
}
}
}
override fun getExtendsList(): LightReferenceListBuilder = myExtendsList
}
)
}
}
}
override fun getTypeParameterList(): PsiTypeParameterList = _buildTypeParameterList
private val paramsList: PsiParameterList by lazy {
object : LightParameterListBuilder(containingClass.manager, containingClass.language) {
override fun getParent(): PsiElement = this@UastDescriptorLightMethod
override fun getContainingFile(): PsiFile = parent.containingFile
init {
val parameterList = this
original.extensionReceiverParameter?.let { receiver ->
this.addParameter(
UastDescriptorLightParameterBase(
"\$this\$${original.name.identifier}",
receiver.type.toPsiType(this@UastDescriptorLightMethod, context, false),
parameterList,
receiver
)
)
}
for ((i, p) in original.valueParameters.withIndex()) {
this.addParameter(
UastDescriptorLightParameter(
p.name.identifier,
p.type.toPsiType(this@UastDescriptorLightMethod, context, false),
parameterList,
p
)
)
}
}
}
}
override fun getParameterList(): PsiParameterList = paramsList
}
internal abstract class UastDescriptorLightMethodBase<T: CallableMemberDescriptor>(
internal val original: T, containingClass: PsiClass, protected val context: KtElement
) : LightMethodBuilder(
containingClass.manager, containingClass.language, original.name.identifier,
LightParameterListBuilder(containingClass.manager, containingClass.language),
LightModifierList(containingClass.manager)
) {
init {
this.containingClass = containingClass
if (original.dispatchReceiverParameter == null) {
addModifier(PsiModifier.STATIC)
}
}
override fun getReturnType(): PsiType? {
return original.returnType?.toPsiType(this, context, 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 UastDescriptorLightMethodBase<*>
if (original != other.original) return false
return true
}
override fun hashCode(): Int = original.hashCode()
}

View File

@@ -0,0 +1,49 @@
package org.jetbrains.uast.kotlin.psi
import com.intellij.lang.Language
import com.intellij.psi.*
import com.intellij.psi.impl.light.LightParameter
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.components.isVararg
import org.jetbrains.uast.UDeclaration
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UastErrorType
import org.jetbrains.uast.getParentOfType
import org.jetbrains.uast.kotlin.analyze
import org.jetbrains.uast.kotlin.toPsiType
internal class UastDescriptorLightParameter(
name: String,
type: PsiType,
parent: PsiElement,
ktParameter: ValueParameterDescriptor,
language: Language = parent.language,
) : UastDescriptorLightParameterBase<ValueParameterDescriptor>(name, type, parent, ktParameter, language)
internal open class UastDescriptorLightParameterBase<T : ParameterDescriptor>(
name: String,
type: PsiType,
private val parent: PsiElement,
val ktOrigin: T,
language: Language = parent.language,
) : LightParameter(name, type, parent, language, ktOrigin.isVararg) {
override fun getParent(): PsiElement = parent
override fun getContainingFile(): PsiFile? = parent.containingFile
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || other::class.java != this::class.java) return false
return ktOrigin == (other as? UastDescriptorLightParameterBase<*>)?.ktOrigin
}
override fun hashCode(): Int = ktOrigin.hashCode()
}

View File

@@ -16,7 +16,7 @@ UTypeReferenceExpression (name = T) -> USimpleNameReferenceExpression (identifie
UTypeReferenceExpression (name = java.lang.String) -> USimpleNameReferenceExpression (identifier = String) -> PsiClass:String: String
UTypeReferenceExpression (name = java.lang.String) -> USimpleNameReferenceExpression (identifier = String) -> PsiClass:String: String
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))(resolves to KtUltraLightMethodForSourceDeclaration:bar) -> USimpleNameReferenceExpression (identifier = bar) -> KtUltraLightMethodForSourceDeclaration:bar: bar
ULocalVariable (name = z) -> UQualifiedReferenceExpression -> null: null
ULocalVariable (name = z) -> UQualifiedReferenceExpression -> LightMethodBuilder:filterIsInstance: filterIsInstance
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to PsiMethod:listOf) -> USimpleNameReferenceExpression (identifier = listOf) -> PsiMethod:listOf: listOf
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))(resolves to null) -> USimpleNameReferenceExpression (identifier = filterIsInstance) -> null: null
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))(resolves to LightMethodBuilder:filterIsInstance) -> USimpleNameReferenceExpression (identifier = filterIsInstance) -> LightMethodBuilder:filterIsInstance: filterIsInstance
UTypeReferenceExpression (name = java.lang.String) -> USimpleNameReferenceExpression (identifier = String) -> PsiClass:String: String