mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
Uast: resolve reified callees from classpath (#4013, KT-41279)
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user