[SLC] implement light class for RepeatableContainer

^KT-55470 Fixed
This commit is contained in:
Dmitrii Gridin
2022-12-13 23:57:40 +01:00
committed by Space Team
parent cd0ae20c38
commit 1e1525bae5
8 changed files with 208 additions and 42 deletions
@@ -5,9 +5,7 @@
package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiReferenceList
import com.intellij.psi.*
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.KtClassKind
import org.jetbrains.kotlin.analysis.api.symbols.KtConstructorSymbol
@@ -21,7 +19,7 @@ import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
internal class SymbolLightClassForAnnotationClass : SymbolLightClassForInterfaceOrAnnotationClass {
internal open class SymbolLightClassForAnnotationClass : SymbolLightClassForInterfaceOrAnnotationClass {
constructor(
ktAnalysisSession: KtAnalysisSession,
ktModule: KtModule,
@@ -40,7 +38,7 @@ internal class SymbolLightClassForAnnotationClass : SymbolLightClassForInterface
require(classOrObject is KtClass && classOrObject.isAnnotation())
}
private constructor(
constructor(
classOrObjectDeclaration: KtClassOrObject?,
classOrObjectSymbolPointer: KtSymbolPointer<KtNamedClassOrObjectSymbol>,
ktModule: KtModule,
@@ -54,22 +52,28 @@ internal class SymbolLightClassForAnnotationClass : SymbolLightClassForInterface
override fun isAnnotationType(): Boolean = true
private val _ownMethods: List<KtLightMethod> by lazyPub {
withClassOrObjectSymbol { classOrObjectSymbol ->
val result = mutableListOf<KtLightMethod>()
val visibleDeclarations = classOrObjectSymbol.getDeclaredMemberScope().getCallableSymbols()
.filterNot { it is KtFunctionSymbol && it.visibility.isPrivateOrPrivateToThis() }
.filterNot { it is KtConstructorSymbol }
protected open fun computeOwnMethods(): List<PsiMethod> = withClassOrObjectSymbol { classOrObjectSymbol ->
val result = mutableListOf<KtLightMethod>()
val visibleDeclarations = classOrObjectSymbol.getDeclaredMemberScope().getCallableSymbols()
.filterNot { it is KtFunctionSymbol && it.visibility.isPrivateOrPrivateToThis() }
.filterNot { it is KtConstructorSymbol }
createMethods(visibleDeclarations, result)
result
}
createMethods(visibleDeclarations, result)
result
}
override fun getOwnMethods(): List<PsiMethod> = _ownMethods
private val _ownMethods: List<PsiMethod> by lazyPub {
computeOwnMethods()
}
final override fun getOwnMethods(): List<PsiMethod> = _ownMethods
override fun getExtendsList(): PsiReferenceList? = null
final override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean {
val qualifiedName = baseClass.qualifiedName
return qualifiedName == CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION || qualifiedName == CommonClassNames.JAVA_LANG_OBJECT
}
override fun copy(): SymbolLightClassForAnnotationClass = SymbolLightClassForAnnotationClass(
classOrObjectDeclaration = classOrObjectDeclaration,
classOrObjectSymbolPointer = classOrObjectSymbolPointer,
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.*
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightClassModifierList
import org.jetbrains.kotlin.load.java.JvmAbi
@@ -33,15 +32,11 @@ internal class SymbolLightClassForInterfaceDefaultImpls(private val containingCl
override fun getTypeParameterList(): PsiTypeParameterList? = null
override fun getTypeParameters(): Array<PsiTypeParameter> = emptyArray()
private val _modifierList: PsiModifierList? by lazyPub {
SymbolLightClassModifierList(
containingDeclaration = this,
staticModifiers = setOf(PsiModifier.PUBLIC, PsiModifier.STATIC, PsiModifier.FINAL),
annotationsComputer = null,
)
}
override fun getModifierList(): PsiModifierList? = _modifierList
override fun computeModifierList(): PsiModifierList = SymbolLightClassModifierList(
containingDeclaration = this,
staticModifiers = setOf(PsiModifier.PUBLIC, PsiModifier.STATIC, PsiModifier.FINAL),
annotationsComputer = null,
)
override fun isInterface(): Boolean = false
override fun isDeprecated(): Boolean = false
@@ -65,26 +65,28 @@ internal abstract class SymbolLightClassForInterfaceOrAnnotationClass : SymbolLi
manager = manager,
)
private val _modifierList: PsiModifierList? by lazyPub {
SymbolLightClassModifierList(
containingDeclaration = this,
initialValue = LazyModifiersBox.MODALITY_MODIFIERS_MAP.with(PsiModifier.ABSTRACT),
lazyModifiersComputer = ::computeModifiers
) { modifierList ->
withClassOrObjectSymbol { classOrObjectSymbol ->
classOrObjectSymbol.computeAnnotations(
modifierList = modifierList,
nullability = NullabilityType.Unknown,
annotationUseSiteTarget = null,
)
}
protected open fun computeModifierList(): PsiModifierList? = SymbolLightClassModifierList(
containingDeclaration = this,
initialValue = LazyModifiersBox.MODALITY_MODIFIERS_MAP.with(PsiModifier.ABSTRACT),
lazyModifiersComputer = ::computeModifiers
) { modifierList ->
withClassOrObjectSymbol { classOrObjectSymbol ->
classOrObjectSymbol.computeAnnotations(
modifierList = modifierList,
nullability = NullabilityType.Unknown,
annotationUseSiteTarget = null,
)
}
}
private val _modifierList: PsiModifierList? by lazyPub {
computeModifierList()
}
override fun isInterface(): Boolean = true
override fun isEnum(): Boolean = false
override fun getModifierList(): PsiModifierList? = _modifierList
final override fun getModifierList(): PsiModifierList? = _modifierList
private val _ownFields: List<KtLightField> by lazyPub {
withClassOrObjectSymbol { classOrObjectSymbol ->
@@ -0,0 +1,80 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.*
import kotlinx.collections.immutable.persistentHashSetOf
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.light.classes.symbol.NullabilityType
import org.jetbrains.kotlin.light.classes.symbol.annotations.SymbolLightSimpleAnnotation
import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations
import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightRepeatableAnnotationContainerMethod
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightClassModifierList
import org.jetbrains.kotlin.load.java.JvmAbi
internal class SymbolLightClassForRepeatableAnnotationContainer(private val containerOwner: SymbolLightClassForAnnotationClass) :
SymbolLightClassForAnnotationClass(
containerOwner.classOrObjectDeclaration,
containerOwner.classOrObjectSymbolPointer,
containerOwner.ktModule,
containerOwner.manager,
) {
override fun getQualifiedName(): String? = containerOwner.qualifiedName?.let { "$it.${JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME}" }
override fun getName(): String = JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME
override fun getParent(): SymbolLightClassForAnnotationClass = containerOwner
override fun getTypeParameterList(): PsiTypeParameterList? = null
override fun getTypeParameters(): Array<PsiTypeParameter> = PsiTypeParameter.EMPTY_ARRAY
override fun getContainingClass(): KtLightClass = containerOwner
override fun getScope(): PsiElement = containerOwner
override fun getOwnInnerClasses(): List<PsiClass> = emptyList()
override fun getOwnFields(): List<KtLightField> = emptyList()
override fun isDeprecated(): Boolean = false
override fun hasTypeParameters(): Boolean = false
override fun computeModifierList(): PsiModifierList = SymbolLightClassModifierList(
containingDeclaration = this,
// It is marked as Abstract because all the annotation classes are marked as Abstract
// It is marked as Static because all nested interfaces marked as Static
staticModifiers = setOf(PsiModifier.PUBLIC, PsiModifier.STATIC, PsiModifier.ABSTRACT),
annotationsComputer = { psiModifierList ->
val annotations = withClassOrObjectSymbol { classOrObjectSymbol ->
classOrObjectSymbol.computeAnnotations(
modifierList = psiModifierList,
nullability = NullabilityType.Unknown,
annotationUseSiteTarget = null,
)
}.filter {
it.qualifiedName in allowedAnnotations
}
annotations + SymbolLightSimpleAnnotation(fqName = KOTLIN_JVM_INTERNAL_REPEATABLE_CONTAINER, parent = psiModifierList)
},
)
override fun computeOwnMethods(): List<PsiMethod> = listOf(
SymbolLightRepeatableAnnotationContainerMethod(containerOwner.qualifiedName, this)
)
override fun copy(): SymbolLightClassForRepeatableAnnotationContainer = SymbolLightClassForRepeatableAnnotationContainer(containerOwner)
override fun equals(other: Any?): Boolean = this === other ||
other is SymbolLightClassForRepeatableAnnotationContainer && other.containerOwner == containerOwner
override fun hashCode(): Int = containerOwner.hashCode()
companion object {
private val allowedAnnotations = persistentHashSetOf(
CommonClassNames.JAVA_LANG_ANNOTATION_RETENTION,
StandardNames.FqNames.retention.asString(),
CommonClassNames.JAVA_LANG_ANNOTATION_TARGET,
StandardNames.FqNames.target.asString(),
)
private const val KOTLIN_JVM_INTERNAL_REPEATABLE_CONTAINER = "kotlin.jvm.internal.RepeatableContainer"
}
}
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.hasInterfaceDefaultImpls
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.config.JvmAnalysisFlags
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.descriptors.Modality
@@ -43,6 +44,7 @@ import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightConstructor
import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightNoArgConstructor
import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightSimpleMethod
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClass
@@ -251,7 +253,7 @@ internal fun SymbolLightClassBase.createMethods(
}
context(KtAnalysisSession)
private inline fun <T : KtFunctionLikeSymbol> SymbolLightClassBase.createJvmOverloadsIfNeeded(
private inline fun <T : KtFunctionLikeSymbol> createJvmOverloadsIfNeeded(
declaration: T,
result: MutableList<KtLightMethod>,
lightMethodCreator: (Int, BitSet) -> KtLightMethod
@@ -475,6 +477,14 @@ internal fun KtSymbolWithMembers.createInnerClasses(
result.add(SymbolLightClassForInterfaceDefaultImpls(containingClass))
}
if (containingClass is SymbolLightClassForAnnotationClass &&
this is KtNamedClassOrObjectSymbol &&
hasAnnotation(StandardNames.FqNames.repeatable, annotationUseSiteTarget = null) &&
!hasAnnotation(JvmAnnotationNames.REPEATABLE_ANNOTATION, annotationUseSiteTarget = null)
) {
result.add(SymbolLightClassForRepeatableAnnotationContainer(containingClass))
}
return result
}
@@ -0,0 +1,61 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.methods
import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.classes.METHOD_INDEX_BASE
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassBase
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightMemberModifierList
import org.jetbrains.kotlin.light.classes.symbol.parameters.SymbolLightParameterList
internal class SymbolLightRepeatableAnnotationContainerMethod(
private val annotationClassQualifier: String?,
containingClass: SymbolLightClassBase,
) : SymbolLightMethodBase(
lightMemberOrigin = null,
containingClass = containingClass,
methodIndex = METHOD_INDEX_BASE,
) {
override fun getNameIdentifier(): PsiIdentifier? = null
override fun isDeprecated(): Boolean = false
override fun getName(): String = "value"
override fun getTypeParameters(): Array<PsiTypeParameter> = PsiTypeParameter.EMPTY_ARRAY
override fun hasTypeParameters(): Boolean = false
override fun getTypeParameterList(): PsiTypeParameterList? = null
override fun isOverride(): Boolean = false
private val _modifierList by lazyPub {
SymbolLightMemberModifierList(
containingDeclaration = this,
staticModifiers = setOf(PsiModifier.PUBLIC, PsiModifier.ABSTRACT),
annotationsComputer = null,
)
}
override fun getModifierList(): PsiModifierList = _modifierList
private val _parameterList by lazyPub {
SymbolLightParameterList(this)
}
override fun getParameterList(): PsiParameterList = _parameterList
override fun isConstructor(): Boolean = false
private val _returnType by lazyPub {
val qualifier = annotationClassQualifier ?: return@lazyPub null
JavaPsiFacade.getElementFactory(project).createTypeByFQClassName(qualifier, resolveScope).createArrayType()
}
override fun getReturnType(): PsiType? = _returnType
override fun equals(other: Any?): Boolean =
this === other || other is SymbolLightRepeatableAnnotationContainerMethod && other.containingClass == containingClass
override fun hashCode(): Int = containingClass.hashCode()
override fun copy(): PsiElement = SymbolLightRepeatableAnnotationContainerMethod(annotationClassQualifier, containingClass)
}
@@ -3,4 +3,10 @@
public abstract @interface One /* simple.One*/ {
public abstract java.lang.String value();// value()
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@kotlin.jvm.internal.RepeatableContainer()
public static abstract @interface Container /* simple.One.Container*/ {
public abstract simple.One[] value();// value()
}}
@@ -6,4 +6,12 @@
public abstract @interface Anno /* Anno*/ {
public abstract int i();// i()
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.SOURCE)
@kotlin.annotation.Retention(value = kotlin.annotation.AnnotationRetention.SOURCE)
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.TYPE_PARAMETER, kotlin.annotation.AnnotationTarget.TYPE})
@kotlin.jvm.internal.RepeatableContainer()
public static abstract @interface Container /* Anno.Container*/ {
public abstract Anno[] value();// value()
}}