Uast: resolve reified callees from classpath (#4013, KT-41279)
This commit is contained in:
+2
-1
@@ -76,6 +76,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
|||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import org.jetbrains.uast.*
|
import org.jetbrains.uast.*
|
||||||
import org.jetbrains.uast.kotlin.expressions.KotlinLocalFunctionUVariable
|
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.UastFakeLightMethod
|
||||||
import org.jetbrains.uast.kotlin.psi.UastFakeLightPrimaryConstructor
|
import org.jetbrains.uast.kotlin.psi.UastFakeLightPrimaryConstructor
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
@@ -425,7 +426,7 @@ private fun resolveDeserialized(
|
|||||||
psiClass.getMethodBySignature(
|
psiClass.getMethodBySignature(
|
||||||
JvmProtoBufUtil.getJvmMethodSignature(proto, nameResolver, typeTable)
|
JvmProtoBufUtil.getJvmMethodSignature(proto, nameResolver, typeTable)
|
||||||
?: getMethodSignatureFromDescriptor(context, descriptor)
|
?: getMethodSignatureFromDescriptor(context, descriptor)
|
||||||
)
|
) ?: UastDescriptorLightMethod(descriptor as SimpleFunctionDescriptor, psiClass, context) // fake Java-invisible methods
|
||||||
}
|
}
|
||||||
is ProtoBuf.Constructor -> {
|
is ProtoBuf.Constructor -> {
|
||||||
val signature = JvmProtoBufUtil.getJvmConstructorSignature(proto, nameResolver, typeTable)
|
val signature = JvmProtoBufUtil.getJvmConstructorSignature(proto, nameResolver, typeTable)
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
|
}
|
||||||
@@ -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
|
||||||
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
|
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 = 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
|
UTypeReferenceExpression (name = java.lang.String) -> USimpleNameReferenceExpression (identifier = String) -> PsiClass:String: String
|
||||||
|
|||||||
Reference in New Issue
Block a user