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:
+1
-26
@@ -11,46 +11,21 @@ import com.intellij.psi.impl.PsiImplUtil
|
|||||||
import com.intellij.psi.impl.light.LightIdentifier
|
import com.intellij.psi.impl.light.LightIdentifier
|
||||||
import com.intellij.psi.meta.PsiMetaData
|
import com.intellij.psi.meta.PsiMetaData
|
||||||
import com.intellij.psi.util.TypeConversionUtil
|
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.KtLightAbstractAnnotation
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase
|
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightNullabilityAnnotation
|
import org.jetbrains.kotlin.asJava.elements.KtLightNullabilityAnnotation
|
||||||
import org.jetbrains.kotlin.asJava.elements.psiType
|
import org.jetbrains.kotlin.asJava.elements.psiType
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.psi.KtCallElement
|
import org.jetbrains.kotlin.psi.KtCallElement
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.resolve.constants.*
|
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(
|
class KtUltraLightNullabilityAnnotation(
|
||||||
member: KtUltraLightElementWithNullabilityAnnotation<*, *>,
|
member: KtUltraLightElementWithNullabilityAnnotation<*, *>,
|
||||||
parent: PsiElement
|
parent: PsiElement
|
||||||
) : KtLightNullabilityAnnotation<KtUltraLightElementWithNullabilityAnnotation<*, *>>(member, parent) {
|
) : KtLightNullabilityAnnotation<KtUltraLightElementWithNullabilityAnnotation<*, *>>(member, parent) {
|
||||||
override fun getQualifiedName(): String? {
|
override fun getQualifiedName(): String? = member.qualifiedNameForNullabilityAnnotation
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun AnnotationDescriptor.toLightAnnotation(ultraLightSupport: KtUltraLightSupport, parent: PsiElement) =
|
fun AnnotationDescriptor.toLightAnnotation(ultraLightSupport: KtUltraLightSupport, parent: PsiElement) =
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
|||||||
return forExtendsList == !JvmCodegenUtil.isJvmInterface(supertype)
|
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
|
// the following logic should be in the platform (super), overrides can be removed once that happens
|
||||||
override fun getInterfaces(): Array<PsiClass> = PsiClassImplUtil.getInterfaces(this)
|
override fun getInterfaces(): Array<PsiClass> = PsiClassImplUtil.getInterfaces(this)
|
||||||
|
|||||||
+27
-1
@@ -6,13 +6,39 @@
|
|||||||
package org.jetbrains.kotlin.asJava.classes
|
package org.jetbrains.kotlin.asJava.classes
|
||||||
|
|
||||||
import com.intellij.psi.PsiModifierListOwner
|
import com.intellij.psi.PsiModifierListOwner
|
||||||
|
import com.intellij.psi.PsiPrimitiveType
|
||||||
import com.intellij.psi.PsiType
|
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.asJava.elements.KtLightDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
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>,
|
interface KtUltraLightElementWithNullabilityAnnotation<out T : KtDeclaration, out D : PsiModifierListOwner> : KtLightDeclaration<T, D>,
|
||||||
PsiModifierListOwner {
|
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?
|
val psiTypeForNullabilityAnnotation: PsiType?
|
||||||
}
|
}
|
||||||
@@ -82,10 +82,10 @@ internal open class KtUltraLightFieldImpl protected constructor(
|
|||||||
|
|
||||||
override fun getLanguage(): Language = KotlinLanguage.INSTANCE
|
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 {
|
private val kotlinType: KotlinType?
|
||||||
when {
|
get() = when {
|
||||||
declaration is KtProperty && declaration.hasDelegate() ->
|
declaration is KtProperty && declaration.hasDelegate() ->
|
||||||
propertyDescriptor?.let {
|
propertyDescriptor?.let {
|
||||||
val context = LightClassGenerationSupport.getInstance(project).analyze(declaration)
|
val context = LightClassGenerationSupport.getInstance(project).analyze(declaration)
|
||||||
@@ -100,11 +100,13 @@ internal open class KtUltraLightFieldImpl protected constructor(
|
|||||||
declaration.getKotlinType()
|
declaration.getKotlinType()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override val kotlinTypeForNullabilityAnnotation: KotlinType?
|
override val qualifiedNameForNullabilityAnnotation: String?
|
||||||
// We don't generate nullability annotations for non-backing fields in backend
|
get() {
|
||||||
get() = kotlinType?.takeUnless { declaration is KtEnumEntry || declaration is KtObjectDeclaration }
|
// 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?
|
override val psiTypeForNullabilityAnnotation: PsiType?
|
||||||
get() = type
|
get() = type
|
||||||
|
|||||||
+101
-39
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.asJava.builder.MemberIndex
|
|||||||
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
|
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethodImpl
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethodImpl
|
||||||
import org.jetbrains.kotlin.codegen.FunctionCodegen
|
import org.jetbrains.kotlin.codegen.FunctionCodegen
|
||||||
|
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.getSpecialSignatureInfo
|
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.getSpecialSignatureInfo
|
||||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
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.KtProperty
|
||||||
import org.jetbrains.kotlin.psi.KtTypeParameterListOwner
|
import org.jetbrains.kotlin.psi.KtTypeParameterListOwner
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
|
|
||||||
internal abstract class KtUltraLightMethod(
|
internal abstract class KtUltraLightMethod(
|
||||||
internal val delegate: PsiMethod,
|
internal val delegate: PsiMethod,
|
||||||
@@ -38,6 +38,37 @@ internal abstract class KtUltraLightMethod(
|
|||||||
containingClass
|
containingClass
|
||||||
), KtUltraLightElementWithNullabilityAnnotation<KtDeclaration, PsiMethod> {
|
), 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 memberIndex: MemberIndex? = null
|
||||||
|
|
||||||
override val psiTypeForNullabilityAnnotation: PsiType?
|
override val psiTypeForNullabilityAnnotation: PsiType?
|
||||||
@@ -54,23 +85,6 @@ internal abstract class KtUltraLightMethod(
|
|||||||
// should be in super
|
// should be in super
|
||||||
override fun isVarArgs() = PsiImplUtil.isVarArgs(this)
|
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 }
|
private val _deprecated: Boolean by lazyPub { kotlinOrigin?.isDeprecated(support) ?: false }
|
||||||
|
|
||||||
override fun getHierarchicalMethodSignature() = PsiSuperMethodImplUtil.getHierarchicalMethodSignature(this)
|
override fun getHierarchicalMethodSignature() = PsiSuperMethodImplUtil.getHierarchicalMethodSignature(this)
|
||||||
@@ -90,17 +104,6 @@ internal abstract class KtUltraLightMethod(
|
|||||||
override fun findSuperMethods(parentClass: PsiClass?): Array<out PsiMethod> =
|
override fun findSuperMethods(parentClass: PsiClass?): Array<out PsiMethod> =
|
||||||
PsiSuperMethodImplUtil.findSuperMethods(this, parentClass)
|
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 equals(other: Any?): Boolean = this === other
|
||||||
|
|
||||||
override fun hashCode(): Int = name.hashCode()
|
override fun hashCode(): Int = name.hashCode()
|
||||||
@@ -127,21 +130,29 @@ internal class KtUltraLightMethodForSourceDeclaration(
|
|||||||
containingClass: KtLightClass
|
containingClass: KtLightClass
|
||||||
) : this(delegate, LightMemberOriginForDeclaration(declaration, JvmDeclarationOriginKind.OTHER), support, containingClass)
|
) : this(delegate, LightMemberOriginForDeclaration(declaration, JvmDeclarationOriginKind.OTHER), support, containingClass)
|
||||||
|
|
||||||
override val kotlinTypeForNullabilityAnnotation: KotlinType?
|
override val qualifiedNameForNullabilityAnnotation: String?
|
||||||
get() = if (forceToSkipNullabilityAnnotation) null else kotlinOrigin?.getKotlinType()
|
get() {
|
||||||
|
val typeForAnnotation = if (forceToSkipNullabilityAnnotation) null else kotlinOrigin?.getKotlinType()
|
||||||
|
return computeQualifiedNameForNullabilityAnnotation(typeForAnnotation)
|
||||||
|
}
|
||||||
|
|
||||||
override fun buildTypeParameterList(): PsiTypeParameterList {
|
override fun buildTypeParameterList(): PsiTypeParameterList {
|
||||||
val origin = kotlinOrigin
|
val origin = kotlinOrigin
|
||||||
return if (origin is KtFunction || origin is KtProperty)
|
return if (origin is KtFunction || origin is KtProperty)
|
||||||
buildTypeParameterList(origin as KtTypeParameterListOwner, this, support)
|
buildTypeParameterListForSourceDeclaration(origin as KtTypeParameterListOwner, this, support)
|
||||||
else LightTypeParameterListBuilder(manager, language)
|
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(
|
internal class KtUltraLightMethodForDescriptor(
|
||||||
override val methodDescriptor: FunctionDescriptor,
|
methodDescriptor: FunctionDescriptor,
|
||||||
delegate: LightMethodBuilder,
|
delegate: LightMethodBuilder,
|
||||||
lightMemberOrigin: LightMemberOrigin?,
|
lightMemberOrigin: LightMemberOrigin?,
|
||||||
support: KtUltraLightSupport,
|
support: KtUltraLightSupport,
|
||||||
@@ -152,11 +163,62 @@ internal class KtUltraLightMethodForDescriptor(
|
|||||||
support,
|
support,
|
||||||
containingClass
|
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?
|
private val lazyInitializers = mutableListOf<Lazy<*>>()
|
||||||
get() = methodDescriptor.returnType
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+75
-43
@@ -27,16 +27,19 @@ internal class KtUltraLightSuspendContinuationParameter(
|
|||||||
KtLightParameter,
|
KtLightParameter,
|
||||||
KtUltraLightElementWithNullabilityAnnotation<KtParameter, PsiParameter> {
|
KtUltraLightElementWithNullabilityAnnotation<KtParameter, PsiParameter> {
|
||||||
|
|
||||||
override val kotlinTypeForNullabilityAnnotation: KotlinType? get() = ktType
|
override val qualifiedNameForNullabilityAnnotation: String?
|
||||||
|
get() = computeQualifiedNameForNullabilityAnnotation(ktType)
|
||||||
|
|
||||||
override val psiTypeForNullabilityAnnotation: PsiType? get() = psiType
|
override val psiTypeForNullabilityAnnotation: PsiType? get() = psiType
|
||||||
override val kotlinOrigin: KtParameter? = null
|
override val kotlinOrigin: KtParameter? = null
|
||||||
override val clsDelegate: PsiParameter get() = invalidAccess()
|
override val clsDelegate: PsiParameter get() = invalidAccess()
|
||||||
|
|
||||||
private val ktType by lazyPub {
|
private val ktType: KotlinType?
|
||||||
val descriptor = ktFunction.resolve() as? FunctionDescriptor
|
get() {
|
||||||
val returnType = descriptor?.returnType ?: return@lazyPub null
|
val descriptor = ktFunction.resolve() as? FunctionDescriptor
|
||||||
support.moduleDescriptor.getContinuationOfTypeOrAny(returnType, support.isReleasedCoroutine)
|
val returnType = descriptor?.returnType ?: return null
|
||||||
}
|
return support.moduleDescriptor.getContinuationOfTypeOrAny(returnType, support.isReleasedCoroutine)
|
||||||
|
}
|
||||||
|
|
||||||
private val psiType by lazyPub {
|
private val psiType by lazyPub {
|
||||||
ktType?.asPsiType(support, TypeMappingMode.DEFAULT, method) ?: PsiType.NULL
|
ktType?.asPsiType(support, TypeMappingMode.DEFAULT, method) ?: PsiType.NULL
|
||||||
@@ -68,12 +71,12 @@ internal abstract class KtUltraLightParameter(
|
|||||||
name: String,
|
name: String,
|
||||||
override val kotlinOrigin: KtParameter?,
|
override val kotlinOrigin: KtParameter?,
|
||||||
protected val support: KtUltraLightSupport,
|
protected val support: KtUltraLightSupport,
|
||||||
method: KtUltraLightMethod
|
private val ultraLightMethod: KtUltraLightMethod
|
||||||
) : org.jetbrains.kotlin.asJava.elements.LightParameter(
|
) : org.jetbrains.kotlin.asJava.elements.LightParameter(
|
||||||
name,
|
name,
|
||||||
PsiType.NULL,
|
PsiType.NULL,
|
||||||
method,
|
ultraLightMethod,
|
||||||
method.language
|
ultraLightMethod.language
|
||||||
), KtUltraLightElementWithNullabilityAnnotation<KtParameter, PsiParameter>, KtLightParameter {
|
), KtUltraLightElementWithNullabilityAnnotation<KtParameter, PsiParameter>, KtLightParameter {
|
||||||
|
|
||||||
override fun isEquivalentTo(another: PsiElement?): Boolean = kotlinOrigin == another
|
override fun isEquivalentTo(another: PsiElement?): Boolean = kotlinOrigin == another
|
||||||
@@ -89,41 +92,31 @@ internal abstract class KtUltraLightParameter(
|
|||||||
|
|
||||||
override fun isValid() = parent.isValid
|
override fun isValid() = parent.isValid
|
||||||
|
|
||||||
protected abstract val kotlinType: KotlinType?
|
override fun computeQualifiedNameForNullabilityAnnotation(kotlinType: KotlinType?): String? {
|
||||||
protected abstract val containingDescriptor: CallableDescriptor?
|
val typeForAnnotation =
|
||||||
|
if (isVarArgs && kotlinType != null && KotlinBuiltIns.isArray(kotlinType)) kotlinType.arguments[0].type else kotlinType
|
||||||
override val kotlinTypeForNullabilityAnnotation: KotlinType?
|
return super.computeQualifiedNameForNullabilityAnnotation(typeForAnnotation)
|
||||||
get() {
|
}
|
||||||
val type = kotlinType
|
|
||||||
return if (isVarArgs && type != null && KotlinBuiltIns.isArray(type)) {
|
|
||||||
type.arguments[0].type
|
|
||||||
} else {
|
|
||||||
type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override val psiTypeForNullabilityAnnotation: PsiType?
|
override val psiTypeForNullabilityAnnotation: PsiType?
|
||||||
get() = type
|
get() = type
|
||||||
|
|
||||||
|
|
||||||
private val _type: PsiType by lazyPub {
|
protected fun computeParameterType(kotlinType: KotlinType?, containingDeclaration: CallableDescriptor?): PsiType {
|
||||||
val kotlinType = kotlinType ?: return@lazyPub PsiType.NULL
|
kotlinType ?: return PsiType.NULL
|
||||||
|
|
||||||
if (kotlinType.isSuspendFunctionType) {
|
if (kotlinType.isSuspendFunctionType) {
|
||||||
kotlinType.asPsiType(support, TypeMappingMode.DEFAULT, this)
|
return kotlinType.asPsiType(support, TypeMappingMode.DEFAULT, this)
|
||||||
} else {
|
} else {
|
||||||
val containingDescriptor = containingDescriptor ?: return@lazyPub PsiType.NULL
|
val containingDescriptor = containingDeclaration ?: return PsiType.NULL
|
||||||
val mappedType = support.mapType(this) { typeMapper, sw ->
|
val mappedType = support.mapType(this) { typeMapper, sw ->
|
||||||
typeMapper.writeParameterType(sw, kotlinType, containingDescriptor)
|
typeMapper.writeParameterType(sw, kotlinType, containingDescriptor)
|
||||||
}
|
}
|
||||||
|
return if (ultraLightMethod.checkNeedToErasureParametersTypes) TypeConversionUtil.erasure(mappedType) else mappedType
|
||||||
if (method.checkNeedToErasureParametersTypes)
|
|
||||||
TypeConversionUtil.erasure(mappedType)
|
|
||||||
else mappedType
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getType(): PsiType = _type
|
abstract override fun getType(): PsiType
|
||||||
|
|
||||||
override fun getContainingFile(): PsiFile = method.containingFile
|
override fun getContainingFile(): PsiFile = method.containingFile
|
||||||
override fun getParent(): PsiElement = method.parameterList
|
override fun getParent(): PsiElement = method.parameterList
|
||||||
@@ -143,7 +136,21 @@ internal abstract class KtAbstractUltraLightParameterForDeclaration(
|
|||||||
method: KtUltraLightMethod,
|
method: KtUltraLightMethod,
|
||||||
protected val containingDeclaration: KtCallableDeclaration
|
protected val containingDeclaration: KtCallableDeclaration
|
||||||
) : KtUltraLightParameter(name, kotlinOrigin, support, method) {
|
) : 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(
|
internal class KtUltraLightParameterForSource(
|
||||||
@@ -154,9 +161,7 @@ internal class KtUltraLightParameterForSource(
|
|||||||
containingDeclaration: KtCallableDeclaration
|
containingDeclaration: KtCallableDeclaration
|
||||||
) : KtAbstractUltraLightParameterForDeclaration(name, kotlinOrigin, support, method, containingDeclaration) {
|
) : KtAbstractUltraLightParameterForDeclaration(name, kotlinOrigin, support, method, containingDeclaration) {
|
||||||
|
|
||||||
override val kotlinType: KotlinType? by lazyPub {
|
override fun tryGetKotlinType(): KotlinType? = kotlinOrigin.getKotlinType()
|
||||||
kotlinOrigin.getKotlinType()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isVarArgs(): Boolean = kotlinOrigin.isVarArg && method.parameterList.parameters.last() == this
|
override fun isVarArgs(): Boolean = kotlinOrigin.isVarArg && method.parameterList.parameters.last() == this
|
||||||
|
|
||||||
@@ -175,7 +180,7 @@ internal class KtUltraLightParameterForSetterParameter(
|
|||||||
containingDeclaration: KtCallableDeclaration
|
containingDeclaration: KtCallableDeclaration
|
||||||
) : KtAbstractUltraLightParameterForDeclaration(name, null, support, method, containingDeclaration) {
|
) : 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
|
override fun isVarArgs(): Boolean = false
|
||||||
}
|
}
|
||||||
@@ -188,24 +193,51 @@ internal class KtUltraLightReceiverParameter(
|
|||||||
|
|
||||||
override fun isVarArgs(): Boolean = false
|
override fun isVarArgs(): Boolean = false
|
||||||
|
|
||||||
override val kotlinType: KotlinType? by lazyPub { containingDescriptor?.extensionReceiverParameter?.type }
|
override fun tryGetKotlinType(): KotlinType? =
|
||||||
|
tryGetContainingDescriptor()?.extensionReceiverParameter?.type
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class KtUltraLightParameterForDescriptor(
|
internal class KtUltraLightParameterForDescriptor(
|
||||||
private val descriptor: ParameterDescriptor,
|
descriptor: ParameterDescriptor,
|
||||||
support: KtUltraLightSupport,
|
support: KtUltraLightSupport,
|
||||||
method: KtUltraLightMethod
|
method: KtUltraLightMethod
|
||||||
) : KtUltraLightParameter(
|
) : KtUltraLightParameter(
|
||||||
if (descriptor.name.isSpecial) "\$self" else descriptor.name.identifier,
|
if (descriptor.name.isSpecial) "\$self" else descriptor.name.identifier,
|
||||||
null, support, method
|
null, support, method
|
||||||
) {
|
) {
|
||||||
override val kotlinType: KotlinType?
|
// This is greedy realization of UL class.
|
||||||
get() = descriptor.type
|
// 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>
|
private val _isVarArgs: Boolean by getAndAddLazy {
|
||||||
get() = descriptor.obtainLightAnnotations(support, this)
|
(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 org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import java.text.StringCharacterIterator
|
import java.text.StringCharacterIterator
|
||||||
|
|
||||||
internal fun buildTypeParameterList(
|
private interface TypeParametersSupport<D, T> {
|
||||||
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> {
|
|
||||||
fun parameters(declaration: D): List<T>
|
fun parameters(declaration: D): List<T>
|
||||||
fun name(typeParameter: T): String?
|
fun name(typeParameter: T): String?
|
||||||
fun hasNonTrivialBounds(declaration: D, typeParameter: T): Boolean
|
fun hasNonTrivialBounds(declaration: D, typeParameter: T): Boolean
|
||||||
fun asDescriptor(typeParameter: T): TypeParameterDescriptor?
|
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,
|
declaration: D,
|
||||||
owner: PsiTypeParameterListOwner,
|
owner: PsiTypeParameterListOwner,
|
||||||
support: KtUltraLightSupport,
|
support: KtUltraLightSupport,
|
||||||
@@ -226,35 +228,15 @@ fun KtUltraLightClass.createGeneratedMethodFromDescriptor(
|
|||||||
descriptor: FunctionDescriptor,
|
descriptor: FunctionDescriptor,
|
||||||
declarationForOrigin: KtDeclaration? = null
|
declarationForOrigin: KtDeclaration? = null
|
||||||
): KtLightMethod {
|
): KtLightMethod {
|
||||||
val lightMethod = lightMethod(descriptor)
|
|
||||||
val kotlinOrigin =
|
val kotlinOrigin =
|
||||||
declarationForOrigin
|
declarationForOrigin
|
||||||
?: DescriptorToSourceUtils.descriptorToDeclaration(descriptor) as? KtDeclaration
|
?: DescriptorToSourceUtils.descriptorToDeclaration(descriptor) as? KtDeclaration
|
||||||
?: kotlinOrigin
|
?: kotlinOrigin
|
||||||
|
|
||||||
val lightMemberOrigin = LightMemberOriginForDeclaration(kotlinOrigin, JvmDeclarationOriginKind.OTHER)
|
val lightMemberOrigin = LightMemberOriginForDeclaration(kotlinOrigin, JvmDeclarationOriginKind.OTHER)
|
||||||
val wrapper = KtUltraLightMethodForDescriptor(descriptor, lightMethod, lightMemberOrigin, support, this)
|
|
||||||
|
|
||||||
descriptor.extensionReceiverParameter?.let { receiver ->
|
return KtUltraLightMethodForDescriptor(descriptor, lightMethod(descriptor), lightMemberOrigin, support, this)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtUltraLightClass.lightMethod(
|
private fun KtUltraLightClass.lightMethod(
|
||||||
|
|||||||
+7
-19
@@ -1,17 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2016 JetBrains s.r.o.
|
* Copyright 2010-2019 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.
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.caches.resolve
|
package org.jetbrains.kotlin.idea.caches.resolve
|
||||||
@@ -65,9 +54,9 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
|
|||||||
override val isReleasedCoroutine
|
override val isReleasedCoroutine
|
||||||
get() = module?.languageVersionSettings?.supportsFeature(LanguageFeature.ReleaseCoroutines) ?: true
|
get() = module?.languageVersionSettings?.supportsFeature(LanguageFeature.ReleaseCoroutines) ?: true
|
||||||
|
|
||||||
override val moduleDescriptor by lazyPub {
|
private val resolutionFacade get() = element.getResolutionFacade()
|
||||||
element.getResolutionFacade().moduleDescriptor
|
|
||||||
}
|
override val moduleDescriptor get() = resolutionFacade.moduleDescriptor
|
||||||
|
|
||||||
override val moduleName: String by lazyPub {
|
override val moduleName: String by lazyPub {
|
||||||
JvmCodegenUtil.getModuleName(moduleDescriptor)
|
JvmCodegenUtil.getModuleName(moduleDescriptor)
|
||||||
@@ -102,9 +91,8 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
override val deprecationResolver: DeprecationResolver by lazyPub {
|
override val deprecationResolver: DeprecationResolver get() = resolutionFacade.getFrontendService(DeprecationResolver::class.java)
|
||||||
element.getResolutionFacade().getFrontendService(DeprecationResolver::class.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val typeMapper: KotlinTypeMapper by lazyPub {
|
override val typeMapper: KotlinTypeMapper by lazyPub {
|
||||||
KotlinTypeMapper(
|
KotlinTypeMapper(
|
||||||
|
|||||||
+8
-2
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.asJava.classes
|
|||||||
import com.intellij.testFramework.LightProjectDescriptor
|
import com.intellij.testFramework.LightProjectDescriptor
|
||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
import org.jetbrains.kotlin.idea.perf.UltraLightChecker
|
import org.jetbrains.kotlin.idea.perf.UltraLightChecker
|
||||||
|
import org.jetbrains.kotlin.idea.perf.UltraLightChecker.checkDescriptorsLeak
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
@@ -30,7 +31,9 @@ abstract class AbstractUltraLightClassLoadingTest : KotlinLightCodeInsightFixtur
|
|||||||
LightClassGenerationSupport.getInstance(ktClass.project).createUltraLightClass(ktClass)?.let { it to ktClass }
|
LightClassGenerationSupport.getInstance(ktClass.project).createUltraLightClass(ktClass)?.let { it to ktClass }
|
||||||
}.joinToString("\n\n") { (ultraLightClass, ktClass) ->
|
}.joinToString("\n\n") { (ultraLightClass, ktClass) ->
|
||||||
with(UltraLightChecker) {
|
with(UltraLightChecker) {
|
||||||
ultraLightClass.renderClass()
|
ultraLightClass.renderClass().also {
|
||||||
|
checkDescriptorsLeak(ultraLightClass)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +42,10 @@ abstract class AbstractUltraLightClassLoadingTest : KotlinLightCodeInsightFixtur
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (ktClass in UltraLightChecker.allClasses(file)) {
|
for (ktClass in UltraLightChecker.allClasses(file)) {
|
||||||
UltraLightChecker.checkClassEquivalence(ktClass)
|
val ultraLightClass = UltraLightChecker.checkClassEquivalence(ktClass)
|
||||||
|
if (ultraLightClass != null) {
|
||||||
|
checkDescriptorsLeak(ultraLightClass)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -33,7 +33,10 @@ abstract class AbstractUltraLightFacadeClassTest : KotlinLightCodeInsightFixture
|
|||||||
val facades = KotlinAsJavaSupport.getInstance(project).getFacadeNames(FqName.ROOT, scope)
|
val facades = KotlinAsJavaSupport.getInstance(project).getFacadeNames(FqName.ROOT, scope)
|
||||||
|
|
||||||
for (facadeName in facades) {
|
for (facadeName in facades) {
|
||||||
UltraLightChecker.checkFacadeEquivalence(FqName(facadeName), scope, project)
|
val ultraLightClass = UltraLightChecker.checkFacadeEquivalence(FqName(facadeName), scope, project)
|
||||||
|
if (ultraLightClass != null) {
|
||||||
|
UltraLightChecker.checkDescriptorsLeak(ultraLightClass)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,23 +8,29 @@ package org.jetbrains.kotlin.idea.perf
|
|||||||
import com.intellij.openapi.Disposable
|
import com.intellij.openapi.Disposable
|
||||||
import com.intellij.openapi.module.Module
|
import com.intellij.openapi.module.Module
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.util.Conditions
|
||||||
import com.intellij.openapi.util.Disposer
|
import com.intellij.openapi.util.Disposer
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
|
import com.intellij.psi.impl.light.LightElement
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.intellij.testFramework.UsefulTestCase
|
import com.intellij.testFramework.UsefulTestCase
|
||||||
|
import com.intellij.util.PairProcessor
|
||||||
|
import com.intellij.util.ref.DebugReflectionUtil
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
import org.jetbrains.kotlin.asJava.classes.*
|
import org.jetbrains.kotlin.asJava.classes.*
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightNullabilityAnnotation
|
import org.jetbrains.kotlin.asJava.elements.KtLightNullabilityAnnotation
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightPsiArrayInitializerMemberValue
|
import org.jetbrains.kotlin.asJava.elements.KtLightPsiArrayInitializerMemberValue
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.idea.project.languageVersionSettings
|
import org.jetbrains.kotlin.idea.project.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.load.kotlin.NON_EXISTENT_CLASS_NAME
|
import org.jetbrains.kotlin.load.kotlin.NON_EXISTENT_CLASS_NAME
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
|
import kotlin.test.assertFails
|
||||||
|
|
||||||
fun UsefulTestCase.forceUsingOldLightClassesForTest() {
|
fun UsefulTestCase.forceUsingOldLightClassesForTest() {
|
||||||
KtUltraLightSupport.forceUsingOldLightClasses = true
|
KtUltraLightSupport.forceUsingOldLightClasses = true
|
||||||
@@ -263,4 +269,29 @@ object UltraLightChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun String.prependDefaultIndent() = prependIndent(" ")
|
private fun String.prependDefaultIndent() = prependIndent(" ")
|
||||||
}
|
|
||||||
|
private fun checkDescriptorLeakOnElement(element: PsiElement) {
|
||||||
|
DebugReflectionUtil.walkObjects(
|
||||||
|
10,
|
||||||
|
mapOf(element to element.javaClass.name),
|
||||||
|
Any::class.java,
|
||||||
|
Conditions.alwaysTrue(),
|
||||||
|
PairProcessor { value, backLink ->
|
||||||
|
if (value is DeclarationDescriptor) {
|
||||||
|
assertFails {
|
||||||
|
"""Leaked descriptor ${value.javaClass.name} in ${element.javaClass.name}\n$backLink"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkDescriptorsLeak(lightClass: KtLightClass) {
|
||||||
|
checkDescriptorLeakOnElement(lightClass)
|
||||||
|
lightClass.methods.forEach {
|
||||||
|
checkDescriptorLeakOnElement(it)
|
||||||
|
it.parameterList.parameters.forEach { parameter -> checkDescriptorLeakOnElement(parameter) }
|
||||||
|
}
|
||||||
|
lightClass.fields.forEach { checkDescriptorLeakOnElement(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user