From 1e1525bae57208914c62e073f8117e1f20df6ff0 Mon Sep 17 00:00:00 2001 From: Dmitrii Gridin Date: Tue, 13 Dec 2022 23:57:40 +0100 Subject: [PATCH] [SLC] implement light class for RepeatableContainer ^KT-55470 Fixed --- .../SymbolLightClassForAnnotationClass.kt | 34 ++++---- ...ymbolLightClassForInterfaceDefaultImpls.kt | 15 ++-- ...LightClassForInterfaceOrAnnotationClass.kt | 30 +++---- ...htClassForRepeatableAnnotationContainer.kt | 80 +++++++++++++++++++ .../symbol/classes/symbolLightClassUtils.kt | 12 ++- ...ightRepeatableAnnotationContainerMethod.kt | 61 ++++++++++++++ .../AnnotationRepeatable.fir.java | 8 +- ...ecialAnnotationsOnAnnotationClass.fir.java | 10 ++- 8 files changed, 208 insertions(+), 42 deletions(-) create mode 100644 analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForRepeatableAnnotationContainer.kt create mode 100644 analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightRepeatableAnnotationContainerMethod.kt diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForAnnotationClass.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForAnnotationClass.kt index 22a562bf8ef..5d29d24ca19 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForAnnotationClass.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForAnnotationClass.kt @@ -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, ktModule: KtModule, @@ -54,22 +52,28 @@ internal class SymbolLightClassForAnnotationClass : SymbolLightClassForInterface override fun isAnnotationType(): Boolean = true - private val _ownMethods: List by lazyPub { - withClassOrObjectSymbol { classOrObjectSymbol -> - val result = mutableListOf() - val visibleDeclarations = classOrObjectSymbol.getDeclaredMemberScope().getCallableSymbols() - .filterNot { it is KtFunctionSymbol && it.visibility.isPrivateOrPrivateToThis() } - .filterNot { it is KtConstructorSymbol } + protected open fun computeOwnMethods(): List = withClassOrObjectSymbol { classOrObjectSymbol -> + val result = mutableListOf() + 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 = _ownMethods + private val _ownMethods: List by lazyPub { + computeOwnMethods() + } + final override fun getOwnMethods(): List = _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, diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForInterfaceDefaultImpls.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForInterfaceDefaultImpls.kt index 388a1a33503..9c0d721c39e 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForInterfaceDefaultImpls.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForInterfaceDefaultImpls.kt @@ -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 = 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 diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForInterfaceOrAnnotationClass.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForInterfaceOrAnnotationClass.kt index 1af402e6295..68238e12f5c 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForInterfaceOrAnnotationClass.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForInterfaceOrAnnotationClass.kt @@ -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 by lazyPub { withClassOrObjectSymbol { classOrObjectSymbol -> diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForRepeatableAnnotationContainer.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForRepeatableAnnotationContainer.kt new file mode 100644 index 00000000000..4badbc5b15c --- /dev/null +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForRepeatableAnnotationContainer.kt @@ -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.EMPTY_ARRAY + override fun getContainingClass(): KtLightClass = containerOwner + override fun getScope(): PsiElement = containerOwner + override fun getOwnInnerClasses(): List = emptyList() + override fun getOwnFields(): List = 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 = 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" + } +} diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt index 82b91cd6cf6..5d6c93812f7 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt @@ -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 SymbolLightClassBase.createJvmOverloadsIfNeeded( +private inline fun createJvmOverloadsIfNeeded( declaration: T, result: MutableList, 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 } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightRepeatableAnnotationContainerMethod.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightRepeatableAnnotationContainerMethod.kt new file mode 100644 index 00000000000..12bf0b649e3 --- /dev/null +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightRepeatableAnnotationContainerMethod.kt @@ -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.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) +} diff --git a/compiler/testData/asJava/lightClasses/AnnotationRepeatable.fir.java b/compiler/testData/asJava/lightClasses/AnnotationRepeatable.fir.java index 9e5410e7f85..729eb0b562d 100644 --- a/compiler/testData/asJava/lightClasses/AnnotationRepeatable.fir.java +++ b/compiler/testData/asJava/lightClasses/AnnotationRepeatable.fir.java @@ -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() + +}} diff --git a/compiler/testData/asJava/lightClasses/SpecialAnnotationsOnAnnotationClass.fir.java b/compiler/testData/asJava/lightClasses/SpecialAnnotationsOnAnnotationClass.fir.java index c465613a787..d8f8154fcc7 100644 --- a/compiler/testData/asJava/lightClasses/SpecialAnnotationsOnAnnotationClass.fir.java +++ b/compiler/testData/asJava/lightClasses/SpecialAnnotationsOnAnnotationClass.fir.java @@ -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() + +}}