Fix UL classes descriptors leaks

UL classes built upon descriptors and UL support classes are saving a descriptors.
This could lead to descriptors leakage so we have to eliminate any fields with descriptor references.

Fixed #KT-34337
This commit is contained in:
Igor Yakovlev
2019-10-14 17:59:47 +03:00
parent b01014982f
commit bc66834c3c
11 changed files with 311 additions and 204 deletions
@@ -11,46 +11,21 @@ import com.intellij.psi.impl.PsiImplUtil
import com.intellij.psi.impl.light.LightIdentifier
import com.intellij.psi.meta.PsiMetaData
import com.intellij.psi.util.TypeConversionUtil
import org.jetbrains.annotations.NotNull
import org.jetbrains.annotations.Nullable
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase
import org.jetbrains.kotlin.asJava.elements.KtLightNullabilityAnnotation
import org.jetbrains.kotlin.asJava.elements.psiType
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtCallElement
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.constants.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.isError
import org.jetbrains.kotlin.types.typeUtil.TypeNullability
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
import org.jetbrains.kotlin.types.typeUtil.nullability
class KtUltraLightNullabilityAnnotation(
member: KtUltraLightElementWithNullabilityAnnotation<*, *>,
parent: PsiElement
) : KtLightNullabilityAnnotation<KtUltraLightElementWithNullabilityAnnotation<*, *>>(member, parent) {
override fun getQualifiedName(): String? {
val kotlinType = member.kotlinTypeForNullabilityAnnotation?.takeUnless(KotlinType::isError) ?: return null
val psiType = member.psiTypeForNullabilityAnnotation ?: return null
if (psiType is PsiPrimitiveType) return null
if (kotlinType.isTypeParameter()) {
if (!TypeUtils.hasNullableSuperType(kotlinType)) return NotNull::class.java.name
if (!kotlinType.isMarkedNullable) return null
}
val nullability = kotlinType.nullability()
return when (nullability) {
TypeNullability.NOT_NULL -> NotNull::class.java.name
TypeNullability.NULLABLE -> Nullable::class.java.name
TypeNullability.FLEXIBLE -> null
}
}
override fun getQualifiedName(): String? = member.qualifiedNameForNullabilityAnnotation
}
fun AnnotationDescriptor.toLightAnnotation(ultraLightSupport: KtUltraLightSupport, parent: PsiElement) =
@@ -160,7 +160,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
return forExtendsList == !JvmCodegenUtil.isJvmInterface(supertype)
}
override fun buildTypeParameterList(): PsiTypeParameterList = buildTypeParameterList(classOrObject, this, support)
override fun buildTypeParameterList(): PsiTypeParameterList = buildTypeParameterListForSourceDeclaration(classOrObject, this, support)
// the following logic should be in the platform (super), overrides can be removed once that happens
override fun getInterfaces(): Array<PsiClass> = PsiClassImplUtil.getInterfaces(this)
@@ -6,13 +6,39 @@
package org.jetbrains.kotlin.asJava.classes
import com.intellij.psi.PsiModifierListOwner
import com.intellij.psi.PsiPrimitiveType
import com.intellij.psi.PsiType
import org.jetbrains.annotations.NotNull
import org.jetbrains.annotations.Nullable
import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.isError
import org.jetbrains.kotlin.types.typeUtil.TypeNullability
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
import org.jetbrains.kotlin.types.typeUtil.nullability
interface KtUltraLightElementWithNullabilityAnnotation<out T : KtDeclaration, out D : PsiModifierListOwner> : KtLightDeclaration<T, D>,
PsiModifierListOwner {
val kotlinTypeForNullabilityAnnotation: KotlinType?
fun computeQualifiedNameForNullabilityAnnotation(kotlinType: KotlinType?): String? {
val notErrorKotlinType = kotlinType?.takeUnless(KotlinType::isError) ?: return null
val psiType = psiTypeForNullabilityAnnotation ?: return null
if (psiType is PsiPrimitiveType) return null
if (notErrorKotlinType.isTypeParameter()) {
if (!TypeUtils.hasNullableSuperType(notErrorKotlinType)) return NotNull::class.java.name
if (!notErrorKotlinType.isMarkedNullable) return null
}
return when (notErrorKotlinType.nullability()) {
TypeNullability.NOT_NULL -> NotNull::class.java.name
TypeNullability.NULLABLE -> Nullable::class.java.name
TypeNullability.FLEXIBLE -> null
}
}
val qualifiedNameForNullabilityAnnotation: String?
val psiTypeForNullabilityAnnotation: PsiType?
}
@@ -82,10 +82,10 @@ internal open class KtUltraLightFieldImpl protected constructor(
override fun getLanguage(): Language = KotlinLanguage.INSTANCE
private val propertyDescriptor: PropertyDescriptor? by lazyPub { declaration.resolve() as? PropertyDescriptor }
private val propertyDescriptor: PropertyDescriptor? get() = declaration.resolve() as? PropertyDescriptor
private val kotlinType: KotlinType? by lazyPub {
when {
private val kotlinType: KotlinType?
get() = when {
declaration is KtProperty && declaration.hasDelegate() ->
propertyDescriptor?.let {
val context = LightClassGenerationSupport.getInstance(project).analyze(declaration)
@@ -100,11 +100,13 @@ internal open class KtUltraLightFieldImpl protected constructor(
declaration.getKotlinType()
}
}
}
override val kotlinTypeForNullabilityAnnotation: KotlinType?
// We don't generate nullability annotations for non-backing fields in backend
get() = kotlinType?.takeUnless { declaration is KtEnumEntry || declaration is KtObjectDeclaration }
override val qualifiedNameForNullabilityAnnotation: String?
get() {
// We don't generate nullability annotations for non-backing fields in backend
val typeForAnnotation = kotlinType?.takeUnless { declaration is KtEnumEntry || declaration is KtObjectDeclaration }
return computeQualifiedNameForNullabilityAnnotation(typeForAnnotation)
}
override val psiTypeForNullabilityAnnotation: PsiType?
get() = type
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.asJava.builder.MemberIndex
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
import org.jetbrains.kotlin.asJava.elements.KtLightMethodImpl
import org.jetbrains.kotlin.codegen.FunctionCodegen
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.getSpecialSignatureInfo
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
@@ -25,7 +26,6 @@ import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtTypeParameterListOwner
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
import org.jetbrains.kotlin.types.KotlinType
internal abstract class KtUltraLightMethod(
internal val delegate: PsiMethod,
@@ -38,6 +38,37 @@ internal abstract class KtUltraLightMethod(
containingClass
), KtUltraLightElementWithNullabilityAnnotation<KtDeclaration, PsiMethod> {
private class KtUltraLightThrowsReferenceListBuilder(private val parentMethod: PsiMethod) :
KotlinLightReferenceListBuilder(parentMethod.manager, parentMethod.language, PsiReferenceList.Role.THROWS_LIST) {
override fun getParent() = parentMethod
override fun getContainingFile() = parentMethod.containingFile
}
protected fun computeThrowsList(methodDescriptor: FunctionDescriptor?): PsiReferenceList {
val builder = KtUltraLightThrowsReferenceListBuilder(parentMethod = this)
if (methodDescriptor !== null) {
for (ex in FunctionCodegen.getThrownExceptions(methodDescriptor)) {
val psiClassType = ex.defaultType.asPsiType(support, TypeMappingMode.DEFAULT, builder) as? PsiClassType
psiClassType ?: continue
builder.addReference(psiClassType)
}
}
return builder
}
protected fun computeCheckNeedToErasureParametersTypes(methodDescriptor: FunctionDescriptor?): Boolean {
return methodDescriptor
?.getSpecialSignatureInfo()
?.let { it.valueParametersSignature !== null }
?: false
}
abstract override fun buildTypeParameterList(): PsiTypeParameterList
abstract val checkNeedToErasureParametersTypes: Boolean
override val memberIndex: MemberIndex? = null
override val psiTypeForNullabilityAnnotation: PsiType?
@@ -54,23 +85,6 @@ internal abstract class KtUltraLightMethod(
// should be in super
override fun isVarArgs() = PsiImplUtil.isVarArgs(this)
abstract override fun buildTypeParameterList(): PsiTypeParameterList
private val _throwsList: PsiReferenceList by lazyPub {
val list =
object : KotlinLightReferenceListBuilder(manager, language, PsiReferenceList.Role.THROWS_LIST) {
override fun getParent() = this@KtUltraLightMethod
override fun getContainingFile() = this@KtUltraLightMethod.containingFile
}
methodDescriptor?.let {
for (ex in FunctionCodegen.getThrownExceptions(it)) {
val psiClassType = ex.defaultType.asPsiType(support, TypeMappingMode.DEFAULT, list) as? PsiClassType ?: continue
list.addReference(psiClassType)
}
}
list
}
private val _deprecated: Boolean by lazyPub { kotlinOrigin?.isDeprecated(support) ?: false }
override fun getHierarchicalMethodSignature() = PsiSuperMethodImplUtil.getHierarchicalMethodSignature(this)
@@ -90,17 +104,6 @@ internal abstract class KtUltraLightMethod(
override fun findSuperMethods(parentClass: PsiClass?): Array<out PsiMethod> =
PsiSuperMethodImplUtil.findSuperMethods(this, parentClass)
override fun getThrowsList(): PsiReferenceList = _throwsList
abstract val methodDescriptor: FunctionDescriptor?
val checkNeedToErasureParametersTypes: Boolean by lazyPub {
methodDescriptor
?.getSpecialSignatureInfo()
?.let { it.valueParametersSignature !== null }
?: false
}
override fun equals(other: Any?): Boolean = this === other
override fun hashCode(): Int = name.hashCode()
@@ -127,21 +130,29 @@ internal class KtUltraLightMethodForSourceDeclaration(
containingClass: KtLightClass
) : this(delegate, LightMemberOriginForDeclaration(declaration, JvmDeclarationOriginKind.OTHER), support, containingClass)
override val kotlinTypeForNullabilityAnnotation: KotlinType?
get() = if (forceToSkipNullabilityAnnotation) null else kotlinOrigin?.getKotlinType()
override val qualifiedNameForNullabilityAnnotation: String?
get() {
val typeForAnnotation = if (forceToSkipNullabilityAnnotation) null else kotlinOrigin?.getKotlinType()
return computeQualifiedNameForNullabilityAnnotation(typeForAnnotation)
}
override fun buildTypeParameterList(): PsiTypeParameterList {
val origin = kotlinOrigin
return if (origin is KtFunction || origin is KtProperty)
buildTypeParameterList(origin as KtTypeParameterListOwner, this, support)
buildTypeParameterListForSourceDeclaration(origin as KtTypeParameterListOwner, this, support)
else LightTypeParameterListBuilder(manager, language)
}
override val methodDescriptor = kotlinOrigin?.resolve() as? FunctionDescriptor
private val methodDescriptor get() = kotlinOrigin?.resolve() as? FunctionDescriptor
private val _throwsList: PsiReferenceList by lazyPub { computeThrowsList(methodDescriptor) }
override fun getThrowsList(): PsiReferenceList = _throwsList
override val checkNeedToErasureParametersTypes: Boolean by lazyPub { computeCheckNeedToErasureParametersTypes(methodDescriptor) }
}
internal class KtUltraLightMethodForDescriptor(
override val methodDescriptor: FunctionDescriptor,
methodDescriptor: FunctionDescriptor,
delegate: LightMethodBuilder,
lightMemberOrigin: LightMemberOrigin?,
support: KtUltraLightSupport,
@@ -152,11 +163,62 @@ internal class KtUltraLightMethodForDescriptor(
support,
containingClass
) {
override fun buildTypeParameterList() = buildTypeParameterList(methodDescriptor, this, support)
// This is greedy realization of UL class.
// This means that all data that depends on descriptor evaluated in ctor so the descriptor will be released on the end.
// Be aware to save descriptor in class instance or any depending references
override val kotlinTypeForNullabilityAnnotation: KotlinType?
get() = methodDescriptor.returnType
private val lazyInitializers = mutableListOf<Lazy<*>>()
private inline fun <T> getAndAddLazy(crossinline initializer: () -> T): Lazy<T> =
lazyPub { initializer() }.also { lazyInitializers.add(it) }
override val givenAnnotations: List<KtLightAbstractAnnotation>
get() = methodDescriptor.obtainLightAnnotations(support, this)
private val _buildTypeParameterList by getAndAddLazy {
buildTypeParameterListForDescriptor(methodDescriptor, this, support)
}
override fun buildTypeParameterList() = _buildTypeParameterList
private val _throwsList: PsiReferenceList by getAndAddLazy {
computeThrowsList(methodDescriptor)
}
override fun getThrowsList(): PsiReferenceList = _throwsList
override val givenAnnotations: List<KtLightAbstractAnnotation> by getAndAddLazy {
methodDescriptor.obtainLightAnnotations(support, this)
}
override val qualifiedNameForNullabilityAnnotation: String? by getAndAddLazy {
computeQualifiedNameForNullabilityAnnotation(methodDescriptor.returnType)
}
override val checkNeedToErasureParametersTypes: Boolean by getAndAddLazy {
computeCheckNeedToErasureParametersTypes(methodDescriptor)
}
init {
methodDescriptor.extensionReceiverParameter?.let { receiver ->
delegate.addParameter(KtUltraLightParameterForDescriptor(receiver, support, this))
}
for (valueParameter in methodDescriptor.valueParameters) {
delegate.addParameter(KtUltraLightParameterForDescriptor(valueParameter, support, this))
}
val returnType = if (methodDescriptor is ConstructorDescriptor) {
delegate.isConstructor = true
PsiType.VOID
} else {
support.mapType(this) { typeMapper, signatureWriter ->
typeMapper.mapReturnType(methodDescriptor, signatureWriter)
}
}
delegate.setMethodReturnType(returnType)
//We should force computations on all lazy delegates to release descriptor on the end of ctor call
with(lazyInitializers) {
forEach { it.value }
clear()
}
}
}
@@ -27,16 +27,19 @@ internal class KtUltraLightSuspendContinuationParameter(
KtLightParameter,
KtUltraLightElementWithNullabilityAnnotation<KtParameter, PsiParameter> {
override val kotlinTypeForNullabilityAnnotation: KotlinType? get() = ktType
override val qualifiedNameForNullabilityAnnotation: String?
get() = computeQualifiedNameForNullabilityAnnotation(ktType)
override val psiTypeForNullabilityAnnotation: PsiType? get() = psiType
override val kotlinOrigin: KtParameter? = null
override val clsDelegate: PsiParameter get() = invalidAccess()
private val ktType by lazyPub {
val descriptor = ktFunction.resolve() as? FunctionDescriptor
val returnType = descriptor?.returnType ?: return@lazyPub null
support.moduleDescriptor.getContinuationOfTypeOrAny(returnType, support.isReleasedCoroutine)
}
private val ktType: KotlinType?
get() {
val descriptor = ktFunction.resolve() as? FunctionDescriptor
val returnType = descriptor?.returnType ?: return null
return support.moduleDescriptor.getContinuationOfTypeOrAny(returnType, support.isReleasedCoroutine)
}
private val psiType by lazyPub {
ktType?.asPsiType(support, TypeMappingMode.DEFAULT, method) ?: PsiType.NULL
@@ -68,12 +71,12 @@ internal abstract class KtUltraLightParameter(
name: String,
override val kotlinOrigin: KtParameter?,
protected val support: KtUltraLightSupport,
method: KtUltraLightMethod
private val ultraLightMethod: KtUltraLightMethod
) : org.jetbrains.kotlin.asJava.elements.LightParameter(
name,
PsiType.NULL,
method,
method.language
ultraLightMethod,
ultraLightMethod.language
), KtUltraLightElementWithNullabilityAnnotation<KtParameter, PsiParameter>, KtLightParameter {
override fun isEquivalentTo(another: PsiElement?): Boolean = kotlinOrigin == another
@@ -89,41 +92,31 @@ internal abstract class KtUltraLightParameter(
override fun isValid() = parent.isValid
protected abstract val kotlinType: KotlinType?
protected abstract val containingDescriptor: CallableDescriptor?
override val kotlinTypeForNullabilityAnnotation: KotlinType?
get() {
val type = kotlinType
return if (isVarArgs && type != null && KotlinBuiltIns.isArray(type)) {
type.arguments[0].type
} else {
type
}
}
override fun computeQualifiedNameForNullabilityAnnotation(kotlinType: KotlinType?): String? {
val typeForAnnotation =
if (isVarArgs && kotlinType != null && KotlinBuiltIns.isArray(kotlinType)) kotlinType.arguments[0].type else kotlinType
return super.computeQualifiedNameForNullabilityAnnotation(typeForAnnotation)
}
override val psiTypeForNullabilityAnnotation: PsiType?
get() = type
private val _type: PsiType by lazyPub {
val kotlinType = kotlinType ?: return@lazyPub PsiType.NULL
protected fun computeParameterType(kotlinType: KotlinType?, containingDeclaration: CallableDescriptor?): PsiType {
kotlinType ?: return PsiType.NULL
if (kotlinType.isSuspendFunctionType) {
kotlinType.asPsiType(support, TypeMappingMode.DEFAULT, this)
return kotlinType.asPsiType(support, TypeMappingMode.DEFAULT, this)
} else {
val containingDescriptor = containingDescriptor ?: return@lazyPub PsiType.NULL
val containingDescriptor = containingDeclaration ?: return PsiType.NULL
val mappedType = support.mapType(this) { typeMapper, sw ->
typeMapper.writeParameterType(sw, kotlinType, containingDescriptor)
}
if (method.checkNeedToErasureParametersTypes)
TypeConversionUtil.erasure(mappedType)
else mappedType
return if (ultraLightMethod.checkNeedToErasureParametersTypes) TypeConversionUtil.erasure(mappedType) else mappedType
}
}
override fun getType(): PsiType = _type
abstract override fun getType(): PsiType
override fun getContainingFile(): PsiFile = method.containingFile
override fun getParent(): PsiElement = method.parameterList
@@ -143,7 +136,21 @@ internal abstract class KtAbstractUltraLightParameterForDeclaration(
method: KtUltraLightMethod,
protected val containingDeclaration: KtCallableDeclaration
) : KtUltraLightParameter(name, kotlinOrigin, support, method) {
override val containingDescriptor: CallableDescriptor? = containingDeclaration.resolve() as? CallableMemberDescriptor
protected fun tryGetContainingDescriptor(): CallableDescriptor? =
containingDeclaration.resolve() as? CallableMemberDescriptor
protected abstract fun tryGetKotlinType(): KotlinType?
private val _parameterType: PsiType by lazyPub {
computeParameterType(tryGetKotlinType(), tryGetContainingDescriptor())
}
override fun getType(): PsiType = _parameterType
override val qualifiedNameForNullabilityAnnotation: String? by lazyPub {
computeQualifiedNameForNullabilityAnnotation(tryGetKotlinType())
}
}
internal class KtUltraLightParameterForSource(
@@ -154,9 +161,7 @@ internal class KtUltraLightParameterForSource(
containingDeclaration: KtCallableDeclaration
) : KtAbstractUltraLightParameterForDeclaration(name, kotlinOrigin, support, method, containingDeclaration) {
override val kotlinType: KotlinType? by lazyPub {
kotlinOrigin.getKotlinType()
}
override fun tryGetKotlinType(): KotlinType? = kotlinOrigin.getKotlinType()
override fun isVarArgs(): Boolean = kotlinOrigin.isVarArg && method.parameterList.parameters.last() == this
@@ -175,7 +180,7 @@ internal class KtUltraLightParameterForSetterParameter(
containingDeclaration: KtCallableDeclaration
) : KtAbstractUltraLightParameterForDeclaration(name, null, support, method, containingDeclaration) {
override val kotlinType: KotlinType? by lazyPub { property.getKotlinType() }
override fun tryGetKotlinType(): KotlinType? = property.getKotlinType()
override fun isVarArgs(): Boolean = false
}
@@ -188,24 +193,51 @@ internal class KtUltraLightReceiverParameter(
override fun isVarArgs(): Boolean = false
override val kotlinType: KotlinType? by lazyPub { containingDescriptor?.extensionReceiverParameter?.type }
override fun tryGetKotlinType(): KotlinType? =
tryGetContainingDescriptor()?.extensionReceiverParameter?.type
}
internal class KtUltraLightParameterForDescriptor(
private val descriptor: ParameterDescriptor,
descriptor: ParameterDescriptor,
support: KtUltraLightSupport,
method: KtUltraLightMethod
) : KtUltraLightParameter(
if (descriptor.name.isSpecial) "\$self" else descriptor.name.identifier,
null, support, method
) {
override val kotlinType: KotlinType?
get() = descriptor.type
// This is greedy realization of UL class.
// This means that all data that depends on descriptor evaluated in ctor so the descriptor will be released on the end.
// Be aware to save descriptor in class instance or any depending references
override val containingDescriptor: CallableDescriptor? = descriptor.containingDeclaration as? CallableMemberDescriptor
private val lazyInitializers = mutableListOf<Lazy<*>>()
private inline fun <T> getAndAddLazy(crossinline initializer: () -> T): Lazy<T> =
lazyPub { initializer() }.also { lazyInitializers.add(it) }
override fun isVarArgs() = (descriptor as? ValueParameterDescriptor)?.varargElementType != null
override val qualifiedNameForNullabilityAnnotation: String? by getAndAddLazy {
computeQualifiedNameForNullabilityAnnotation(descriptor.type)
}
override val givenAnnotations: List<KtLightAbstractAnnotation>
get() = descriptor.obtainLightAnnotations(support, this)
private val _isVarArgs: Boolean by getAndAddLazy {
(descriptor as? ValueParameterDescriptor)?.varargElementType != null
}
override fun isVarArgs() = _isVarArgs
override val givenAnnotations: List<KtLightAbstractAnnotation> by getAndAddLazy {
descriptor.obtainLightAnnotations(support, this)
}
private val _parameterType by getAndAddLazy {
computeParameterType(descriptor.type, descriptor.containingDeclaration as? CallableMemberDescriptor)
}
override fun getType(): PsiType = _parameterType
init {
//We should force computations on all lazy delegates to release descriptor on the end of ctor call
with(lazyInitializers) {
forEach { it.value }
clear()
}
}
}
@@ -51,53 +51,55 @@ import org.jetbrains.kotlin.types.typeUtil.supertypes
import org.jetbrains.org.objectweb.asm.Opcodes
import java.text.StringCharacterIterator
internal fun buildTypeParameterList(
declaration: CallableMemberDescriptor,
owner: PsiTypeParameterListOwner,
support: KtUltraLightSupport
): PsiTypeParameterList = buildTypeParameterList(
declaration, owner, support,
object : TypeParametersSupport<CallableMemberDescriptor, TypeParameterDescriptor> {
override fun parameters(declaration: CallableMemberDescriptor) = declaration.typeParameters
override fun name(typeParameter: TypeParameterDescriptor) = typeParameter.name.asString()
override fun hasNonTrivialBounds(
declaration: CallableMemberDescriptor,
typeParameter: TypeParameterDescriptor
) = typeParameter.upperBounds.any { !KotlinBuiltIns.isDefaultBound(it) }
override fun asDescriptor(typeParameter: TypeParameterDescriptor) = typeParameter
}
)
internal fun buildTypeParameterList(
declaration: KtTypeParameterListOwner,
owner: PsiTypeParameterListOwner,
support: KtUltraLightSupport
): PsiTypeParameterList = buildTypeParameterList(
declaration, owner, support,
object : TypeParametersSupport<KtTypeParameterListOwner, KtTypeParameter> {
override fun parameters(declaration: KtTypeParameterListOwner) = declaration.typeParameters
override fun name(typeParameter: KtTypeParameter) = typeParameter.name
override fun hasNonTrivialBounds(
declaration: KtTypeParameterListOwner,
typeParameter: KtTypeParameter
) = typeParameter.extendsBound != null || declaration.typeConstraints.isNotEmpty()
override fun asDescriptor(typeParameter: KtTypeParameter) = typeParameter.resolve() as? TypeParameterDescriptor
}
)
interface TypeParametersSupport<D, T> {
private interface TypeParametersSupport<D, T> {
fun parameters(declaration: D): List<T>
fun name(typeParameter: T): String?
fun hasNonTrivialBounds(declaration: D, typeParameter: T): Boolean
fun asDescriptor(typeParameter: T): TypeParameterDescriptor?
}
internal fun <D, T> buildTypeParameterList(
private val supportForDescriptor = object : TypeParametersSupport<CallableMemberDescriptor, TypeParameterDescriptor> {
override fun parameters(declaration: CallableMemberDescriptor) = declaration.typeParameters
override fun name(typeParameter: TypeParameterDescriptor) = typeParameter.name.asString()
override fun hasNonTrivialBounds(
declaration: CallableMemberDescriptor,
typeParameter: TypeParameterDescriptor
) = typeParameter.upperBounds.any { !KotlinBuiltIns.isDefaultBound(it) }
override fun asDescriptor(typeParameter: TypeParameterDescriptor) = typeParameter
}
private val supportForSourceDeclaration = object : TypeParametersSupport<KtTypeParameterListOwner, KtTypeParameter> {
override fun parameters(declaration: KtTypeParameterListOwner) = declaration.typeParameters
override fun name(typeParameter: KtTypeParameter) = typeParameter.name
override fun hasNonTrivialBounds(
declaration: KtTypeParameterListOwner,
typeParameter: KtTypeParameter
) = typeParameter.extendsBound != null || declaration.typeConstraints.isNotEmpty()
override fun asDescriptor(typeParameter: KtTypeParameter) = typeParameter.resolve() as? TypeParameterDescriptor
}
internal fun buildTypeParameterListForDescriptor(
declaration: CallableMemberDescriptor,
owner: PsiTypeParameterListOwner,
support: KtUltraLightSupport
): PsiTypeParameterList = buildTypeParameterList(declaration, owner, support, supportForDescriptor)
internal fun buildTypeParameterListForSourceDeclaration(
declaration: KtTypeParameterListOwner,
owner: PsiTypeParameterListOwner,
support: KtUltraLightSupport
): PsiTypeParameterList = buildTypeParameterList(declaration, owner, support, supportForSourceDeclaration)
private fun <D, T> buildTypeParameterList(
declaration: D,
owner: PsiTypeParameterListOwner,
support: KtUltraLightSupport,
@@ -226,35 +228,15 @@ fun KtUltraLightClass.createGeneratedMethodFromDescriptor(
descriptor: FunctionDescriptor,
declarationForOrigin: KtDeclaration? = null
): KtLightMethod {
val lightMethod = lightMethod(descriptor)
val kotlinOrigin =
declarationForOrigin
?: DescriptorToSourceUtils.descriptorToDeclaration(descriptor) as? KtDeclaration
?: kotlinOrigin
val lightMemberOrigin = LightMemberOriginForDeclaration(kotlinOrigin, JvmDeclarationOriginKind.OTHER)
val wrapper = KtUltraLightMethodForDescriptor(descriptor, lightMethod, lightMemberOrigin, support, this)
descriptor.extensionReceiverParameter?.let { receiver ->
lightMethod.addParameter(KtUltraLightParameterForDescriptor(receiver, support, wrapper))
}
for (valueParameter in descriptor.valueParameters) {
lightMethod.addParameter(KtUltraLightParameterForDescriptor(valueParameter, support, wrapper))
}
if (descriptor is ConstructorDescriptor) {
lightMethod.isConstructor = true
lightMethod.setMethodReturnType(PsiType.VOID)
} else {
lightMethod.setMethodReturnType {
support.mapType(wrapper) { typeMapper, signatureWriter ->
typeMapper.mapReturnType(descriptor, signatureWriter)
}
}
}
return wrapper
return KtUltraLightMethodForDescriptor(descriptor, lightMethod(descriptor), lightMemberOrigin, support, this)
}
private fun KtUltraLightClass.lightMethod(