Remove class delegate requests from annotations and modifier lists
(#EA-144876 and #EA-144882 Fixed)
This commit is contained in:
+11
-11
@@ -56,6 +56,16 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import java.util.*
|
||||
import javax.swing.Icon
|
||||
|
||||
private class KtLightClassModifierList(containingClass: KtLightClassForSourceDeclaration, computeModifiers: () -> Set<String>) :
|
||||
KtLightModifierList<KtLightClassForSourceDeclaration>(containingClass) {
|
||||
|
||||
private val modifiers by lazyPub { computeModifiers() }
|
||||
|
||||
override fun hasModifierProperty(name: String): Boolean =
|
||||
if (name != PsiModifier.FINAL) name in modifiers else owner.isFinal(PsiModifier.FINAL in modifiers)
|
||||
|
||||
}
|
||||
|
||||
abstract class KtLightClassForSourceDeclaration(
|
||||
protected val classOrObject: KtClassOrObject,
|
||||
private val forceUsingOldLightClasses: Boolean = false
|
||||
@@ -182,7 +192,7 @@ abstract class KtLightClassForSourceDeclaration(
|
||||
|
||||
override fun getName(): String? = classOrObject.nameAsName?.asString()
|
||||
|
||||
private val _modifierList: PsiModifierList by lazyPub { KtLightClassModifierList(this) }
|
||||
private val _modifierList: PsiModifierList by lazyPub { KtLightClassModifierList(this) { computeModifiers() } }
|
||||
|
||||
override fun getModifierList(): PsiModifierList? = _modifierList
|
||||
|
||||
@@ -437,16 +447,6 @@ abstract class KtLightClassForSourceDeclaration(
|
||||
override val originKind: LightClassOriginKind
|
||||
get() = LightClassOriginKind.SOURCE
|
||||
|
||||
private class KtLightClassModifierList(containingClass: KtLightClassForSourceDeclaration) :
|
||||
KtLightModifierList<KtLightClassForSourceDeclaration>(containingClass) {
|
||||
|
||||
private val modifiers by lazyPub { containingClass.computeModifiers() }
|
||||
|
||||
override fun hasModifierProperty(name: String): Boolean =
|
||||
if (name != PsiModifier.FINAL) name in modifiers else owner.isFinal(PsiModifier.FINAL in modifiers)
|
||||
|
||||
}
|
||||
|
||||
open fun isFinal(isFinalByPsi: Boolean): Boolean {
|
||||
// annotations can make class open via 'allopen' plugin
|
||||
if (!isPossiblyAffectedByAllOpen() || !isFinalByPsi) return isFinalByPsi
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ class KtUltraLightAnnotationForDescriptor(
|
||||
private val annotationDescriptor: AnnotationDescriptor,
|
||||
private val ultraLightSupport: KtUltraLightSupport,
|
||||
parent: PsiElement
|
||||
) : KtLightAbstractAnnotation(parent, { error("clsDelegate for annotation based on descriptor: $annotationDescriptor") }) {
|
||||
) : KtLightAbstractAnnotation(parent, computeDelegate = null) {
|
||||
override fun getNameReferenceElement(): PsiJavaCodeReferenceElement? = null
|
||||
|
||||
override fun getMetaData(): PsiMetaData? = null
|
||||
|
||||
@@ -14,6 +14,8 @@ import com.intellij.psi.impl.light.LightMethodBuilder
|
||||
import org.jetbrains.kotlin.asJava.builder.LightClassData
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightField
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightModifierList
|
||||
import org.jetbrains.kotlin.asJava.elements.KtUltraLightModifierList
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
@@ -40,6 +42,20 @@ import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
||||
open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val support: KtUltraLightSupport) :
|
||||
KtLightClassImpl(classOrObject) {
|
||||
|
||||
private class KtUltraLightClassModifierList(
|
||||
private val containingClass: KtLightClassForSourceDeclaration,
|
||||
private val computeModifiers: () -> Set<String>
|
||||
) :
|
||||
KtUltraLightModifierList<KtLightClassForSourceDeclaration>(containingClass) {
|
||||
private val modifiers by lazyPub { computeModifiers() }
|
||||
|
||||
override fun hasModifierProperty(name: String): Boolean =
|
||||
if (name != PsiModifier.FINAL) name in modifiers else owner.isFinal(PsiModifier.FINAL in modifiers)
|
||||
|
||||
override fun copy(): PsiElement = KtUltraLightClassModifierList(containingClass, computeModifiers)
|
||||
}
|
||||
|
||||
|
||||
private val membersBuilder by lazyPub {
|
||||
UltraLightMembersCreator(
|
||||
this,
|
||||
@@ -74,6 +90,12 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
||||
|
||||
override fun getDelegate(): PsiClass = forTooComplex { super.getDelegate() }
|
||||
|
||||
private val _modifierList: PsiModifierList? by lazyPub {
|
||||
if (tooComplex) super.getModifierList() else KtUltraLightClassModifierList(this) { computeModifiers() }
|
||||
}
|
||||
|
||||
override fun getModifierList(): PsiModifierList? = _modifierList
|
||||
|
||||
private fun allSuperTypes() =
|
||||
getDescriptor()?.typeConstructor?.supertypes.orEmpty().asSequence()
|
||||
|
||||
@@ -170,7 +192,8 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
||||
// Probably, the same should work for const vals but it doesn't at the moment (see KT-28294)
|
||||
if (isCompanion && (containingClass?.isInterface == false || property.isJvmField())) continue
|
||||
|
||||
membersBuilder.createPropertyField(property, usedNames, forceStatic = this.classOrObject is KtObjectDeclaration)?.let(result::add)
|
||||
membersBuilder.createPropertyField(property, usedNames, forceStatic = this.classOrObject is KtObjectDeclaration)
|
||||
?.let(result::add)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,8 +12,10 @@ import com.intellij.psi.util.TypeConversionUtil
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightField
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightSimpleModifierList
|
||||
import org.jetbrains.kotlin.asJava.elements.KtUltraLightSimpleModifierList
|
||||
import org.jetbrains.kotlin.codegen.PropertyCodegen
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
@@ -28,6 +30,30 @@ import org.jetbrains.kotlin.resolve.jvm.annotations.VOLATILE_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
private class KtUltraLightSimpleModifierListField(
|
||||
private val support: KtUltraLightSupport,
|
||||
private val declaration: KtNamedDeclaration,
|
||||
owner: KtLightElement<KtModifierListOwner, PsiModifierListOwner>,
|
||||
private val modifiers: Set<String>
|
||||
) : KtUltraLightSimpleModifierList(owner, modifiers) {
|
||||
override fun hasModifierProperty(name: String): Boolean = when (name) {
|
||||
PsiModifier.VOLATILE -> hasFieldAnnotation(VOLATILE_ANNOTATION_FQ_NAME)
|
||||
PsiModifier.TRANSIENT -> hasFieldAnnotation(TRANSIENT_ANNOTATION_FQ_NAME)
|
||||
else -> super.hasModifierProperty(name)
|
||||
}
|
||||
|
||||
private fun hasFieldAnnotation(fqName: FqName): Boolean {
|
||||
val annotation = support.findAnnotation(declaration, fqName)?.first ?: return false
|
||||
val target = annotation.useSiteTarget?.getAnnotationUseSiteTarget() ?: return true
|
||||
val expectedTarget =
|
||||
if (declaration is KtProperty && declaration.hasDelegate()) AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD
|
||||
else AnnotationUseSiteTarget.FIELD
|
||||
return target == expectedTarget
|
||||
}
|
||||
|
||||
override fun copy() = KtUltraLightSimpleModifierListField(support, declaration, owner, modifiers)
|
||||
}
|
||||
|
||||
internal open class KtUltraLightField(
|
||||
protected val declaration: KtNamedDeclaration,
|
||||
name: String,
|
||||
@@ -37,26 +63,13 @@ internal open class KtUltraLightField(
|
||||
) : LightFieldBuilder(name, PsiType.NULL, declaration), KtLightField,
|
||||
KtUltraLightElementWithNullabilityAnnotation<KtDeclaration, PsiField> {
|
||||
|
||||
private val modList = object : KtLightSimpleModifierList(this, modifiers) {
|
||||
override fun hasModifierProperty(name: String): Boolean = when (name) {
|
||||
PsiModifier.VOLATILE -> hasFieldAnnotation(VOLATILE_ANNOTATION_FQ_NAME)
|
||||
PsiModifier.TRANSIENT -> hasFieldAnnotation(TRANSIENT_ANNOTATION_FQ_NAME)
|
||||
else -> super.hasModifierProperty(name)
|
||||
}
|
||||
|
||||
private fun hasFieldAnnotation(fqName: FqName): Boolean {
|
||||
val annotation = support.findAnnotation(declaration, fqName)?.first ?: return false
|
||||
val target = annotation.useSiteTarget?.getAnnotationUseSiteTarget() ?: return true
|
||||
val expectedTarget =
|
||||
if (declaration is KtProperty && declaration.hasDelegate()) AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD
|
||||
else AnnotationUseSiteTarget.FIELD
|
||||
return target == expectedTarget
|
||||
}
|
||||
private val modifierList by lazyPub {
|
||||
KtUltraLightSimpleModifierListField(support, declaration, this, modifiers)
|
||||
}
|
||||
|
||||
override fun isEquivalentTo(another: PsiElement?): Boolean = kotlinOrigin == another
|
||||
|
||||
override fun getModifierList(): PsiModifierList = modList
|
||||
override fun getModifierList(): PsiModifierList = modifierList
|
||||
|
||||
override fun hasModifierProperty(name: String): Boolean =
|
||||
modifierList.hasModifierProperty(name) //can be removed after IDEA platform does the same
|
||||
|
||||
+36
-4
@@ -20,12 +20,14 @@ import com.intellij.psi.PsiAnnotation
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiModifierList
|
||||
import com.intellij.psi.PsiModifierListOwner
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
||||
import org.jetbrains.kotlin.asJava.classes.KtUltraLightElementWithNullabilityAnnotation
|
||||
import org.jetbrains.kotlin.asJava.classes.KtUltraLightNullabilityAnnotation
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.asJava.toLightAnnotation
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
@@ -91,6 +93,29 @@ abstract class KtLightModifierList<out T : KtLightElement<KtModifierListOwner, P
|
||||
|
||||
}
|
||||
|
||||
open class KtUltraLightSimpleModifierList(
|
||||
owner: KtLightElement<KtModifierListOwner, PsiModifierListOwner>, private val modifiers: Set<String>
|
||||
) : KtUltraLightModifierList<KtLightElement<KtModifierListOwner, PsiModifierListOwner>>(owner) {
|
||||
override fun hasModifierProperty(name: String) = name in modifiers
|
||||
|
||||
override fun copy() = KtUltraLightSimpleModifierList(owner, modifiers)
|
||||
}
|
||||
|
||||
abstract class KtUltraLightModifierList<out T : KtLightElement<KtModifierListOwner, PsiModifierListOwner>>(owner: T) :
|
||||
KtLightModifierList<T>(owner) {
|
||||
|
||||
override val clsDelegate: PsiModifierList
|
||||
get() = throw IllegalStateException("Cls delegate shouldn't be loaded for ultra-light PSI!")
|
||||
|
||||
private fun throwInvalidOperation(): Nothing = throw IncorrectOperationException()
|
||||
|
||||
override fun setModifierProperty(name: String, value: Boolean): Unit = throwInvalidOperation()
|
||||
|
||||
override fun checkSetModifierProperty(name: String, value: Boolean): Unit = throwInvalidOperation()
|
||||
|
||||
override fun addAnnotation(qualifiedName: String): PsiAnnotation = throwInvalidOperation()
|
||||
}
|
||||
|
||||
open class KtLightSimpleModifierList(
|
||||
owner: KtLightElement<KtModifierListOwner, PsiModifierListOwner>, private val modifiers: Set<String>
|
||||
) : KtLightModifierList<KtLightElement<KtModifierListOwner, PsiModifierListOwner>>(owner) {
|
||||
@@ -119,10 +144,17 @@ private fun lightAnnotationsForEntries(lightModifierList: KtLightModifierList<*>
|
||||
.groupBy({ it.first }) { it.second }
|
||||
.flatMap { (fqName, entries) ->
|
||||
entries.mapIndexed { index, entry ->
|
||||
KtLightAnnotationForSourceEntry(fqName, entry, lightModifierList) {
|
||||
lightModifierList.clsDelegate.annotations.filter { it.qualifiedName == fqName }.getOrNull(index)
|
||||
?: KtLightNonExistentAnnotation(lightModifierList)
|
||||
}
|
||||
|
||||
val lazyClsDelegate = if (lightModifierList !is KtUltraLightModifierList) {
|
||||
lazyPub {
|
||||
lightModifierList.clsDelegate.annotations
|
||||
.filter { it.qualifiedName == fqName }
|
||||
.getOrNull(index)
|
||||
?: KtLightNonExistentAnnotation(lightModifierList)
|
||||
}
|
||||
} else null
|
||||
|
||||
KtLightAnnotationForSourceEntry(fqName, entry, lightModifierList, lazyClsDelegate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-19
@@ -54,17 +54,14 @@ import org.jetbrains.kotlin.types.typeUtil.nullability
|
||||
|
||||
private val LOG = Logger.getInstance("#org.jetbrains.kotlin.asJava.elements.lightAnnotations")
|
||||
|
||||
abstract class KtLightAbstractAnnotation(parent: PsiElement, computeDelegate: () -> PsiAnnotation) :
|
||||
abstract class KtLightAbstractAnnotation(parent: PsiElement, computeDelegate: Lazy<PsiAnnotation>?) :
|
||||
KtLightElementBase(parent), PsiAnnotation, KtLightElement<KtCallElement, PsiAnnotation> {
|
||||
|
||||
private val _clsDelegate: PsiAnnotation by lazyPub(computeDelegate)
|
||||
|
||||
override val clsDelegate: PsiAnnotation
|
||||
get() {
|
||||
if (!accessAnnotationsClsDelegateIsAllowed && ApplicationManager.getApplication().isUnitTestMode && this !is KtLightNonSourceAnnotation)
|
||||
LOG.error("KtLightAbstractAnnotation clsDelegate requested for ${this.javaClass}")
|
||||
return _clsDelegate
|
||||
}
|
||||
override val clsDelegate: PsiAnnotation by lazyPub {
|
||||
if (!accessAnnotationsClsDelegateIsAllowed && ApplicationManager.getApplication().isUnitTestMode && this !is KtLightNonSourceAnnotation)
|
||||
LOG.error("KtLightAbstractAnnotation clsDelegate requested for ${this.javaClass}")
|
||||
computeDelegate?.value ?: throw IllegalStateException("Cannot get class delegate for annotation light class")
|
||||
}
|
||||
|
||||
override fun getNameReferenceElement() = clsDelegate.nameReferenceElement
|
||||
|
||||
@@ -87,8 +84,12 @@ class KtLightAnnotationForSourceEntry(
|
||||
private val qualifiedName: String,
|
||||
override val kotlinOrigin: KtCallElement,
|
||||
parent: PsiElement,
|
||||
computeDelegate: () -> PsiAnnotation
|
||||
) : KtLightAbstractAnnotation(parent, computeDelegate) {
|
||||
private val lazyClsDelegate: Lazy<PsiAnnotation>?
|
||||
) : KtLightAbstractAnnotation(parent, lazyClsDelegate) {
|
||||
|
||||
override fun getOwner() = parent as? PsiAnnotationOwner
|
||||
|
||||
override fun getMetaData() = lazyClsDelegate?.value?.metaData
|
||||
|
||||
override fun getQualifiedName() = qualifiedName
|
||||
|
||||
@@ -114,8 +115,7 @@ class KtLightAnnotationForSourceEntry(
|
||||
}
|
||||
|
||||
if (useDefault && callEntry.key.declaresOrInheritsDefaultValue()) {
|
||||
val psiElement = callEntry.key.source.getPsi()
|
||||
when (psiElement) {
|
||||
when (val psiElement = callEntry.key.source.getPsi()) {
|
||||
is KtParameter ->
|
||||
return psiElement.defaultValue?.let { convertToLightAnnotationMemberValue(this, it) }
|
||||
is PsiAnnotationMethod ->
|
||||
@@ -125,17 +125,15 @@ class KtLightAnnotationForSourceEntry(
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
override fun getNameReferenceElement(): PsiJavaCodeReferenceElement? = KtLightPsiJavaCodeReferenceElement(
|
||||
kotlinOrigin.navigationElement,
|
||||
{
|
||||
(kotlinOrigin as? KtAnnotationEntry)?.typeReference?.reference
|
||||
?: (kotlinOrigin.calleeExpression?.nameReference)?.references?.firstOrNull()
|
||||
},
|
||||
{ super.getNameReferenceElement() }
|
||||
{ lazyClsDelegate?.value?.nameReferenceElement }
|
||||
)
|
||||
|
||||
|
||||
private val ktLightAnnotationParameterList by lazyPub { KtLightAnnotationParameterList() }
|
||||
|
||||
override fun getParameterList(): PsiAnnotationParameterList = ktLightAnnotationParameterList
|
||||
@@ -202,7 +200,7 @@ class KtLightAnnotationForSourceEntry(
|
||||
|
||||
class KtLightNonSourceAnnotation(
|
||||
parent: PsiElement, clsDelegate: PsiAnnotation
|
||||
) : KtLightAbstractAnnotation(parent, { clsDelegate }) {
|
||||
) : KtLightAbstractAnnotation(parent, lazyPub { clsDelegate }) {
|
||||
override val kotlinOrigin: KtAnnotationEntry? get() = null
|
||||
override fun getQualifiedName() = kotlinOrigin?.name ?: clsDelegate.qualifiedName
|
||||
override fun <T : PsiAnnotationMemberValue?> setDeclaredAttributeValue(attributeName: String?, value: T?) = cannotModify()
|
||||
@@ -237,7 +235,7 @@ class KtLightEmptyAnnotationParameterList(parent: PsiElement) : KtLightElementBa
|
||||
}
|
||||
|
||||
open class KtLightNullabilityAnnotation<D : KtLightElement<*, PsiModifierListOwner>>(val member: D, parent: PsiElement) :
|
||||
KtLightAbstractAnnotation(parent, {
|
||||
KtLightAbstractAnnotation(parent, lazyPub {
|
||||
// searching for last because nullability annotations are generated after backend generates source annotations
|
||||
getClsNullabilityAnnotation(member) ?: KtLightNonExistentAnnotation(member)
|
||||
}) {
|
||||
@@ -362,7 +360,8 @@ fun convertToLightAnnotationMemberValue(lightParent: PsiElement, argument: KtExp
|
||||
annotationName,
|
||||
argument,
|
||||
lightParent,
|
||||
{ throw UnsupportedOperationException("cls delegate is not supported for nested annotations") })
|
||||
lazyClsDelegate = null
|
||||
)
|
||||
}
|
||||
val resolvedCall = argument.getResolvedCall()
|
||||
if (resolvedCall != null && CompileTimeConstantUtils.isArrayFunctionCall(resolvedCall))
|
||||
|
||||
Reference in New Issue
Block a user