[SLC] LazyAnnotationsBox: rewrite from SymbolLightAbstractAnnotationWithClassId to PsiAnnotation

and update AdditionalAnnotationsProvider interface

^KT-56046
This commit is contained in:
Dmitrii Gridin
2023-01-24 14:32:05 +01:00
committed by Space Team
parent a2ef4d28c4
commit 5f5abd1557
4 changed files with 43 additions and 48 deletions
@@ -5,7 +5,10 @@
package org.jetbrains.kotlin.light.classes.symbol.annotations package org.jetbrains.kotlin.light.classes.symbol.annotations
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiModifierList
internal interface AdditionalAnnotationsProvider { internal interface AdditionalAnnotationsProvider {
fun addAllAnnotations(currentRawAnnotations: MutableList<out SymbolLightAbstractAnnotationWithClassId>) fun addAllAnnotations(currentRawAnnotations: MutableList<in PsiAnnotation>, foundQualifiers: MutableSet<String>, owner: PsiModifierList)
fun findAdditionalAnnotation(box: LazyAnnotationsBox, qualifiedName: String): SymbolLightAbstractAnnotationWithClassId? fun findAdditionalAnnotation(annotationsBox: LazyAnnotationsBox, qualifiedName: String, owner: PsiModifierList): PsiAnnotation?
} }
@@ -25,45 +25,43 @@ internal class LazyAnnotationsBox(
private val annotatedSymbolPointer: KtSymbolPointer<KtAnnotatedSymbol>, private val annotatedSymbolPointer: KtSymbolPointer<KtAnnotatedSymbol>,
private val ktModule: KtModule, private val ktModule: KtModule,
private val owner: PsiModifierList, private val owner: PsiModifierList,
private val additionalAnnotationsProviders: Collection<AdditionalAnnotationsProvider>, private val additionalAnnotationsProvider: AdditionalAnnotationsProvider,
) : PsiAnnotationOwner { ) : PsiAnnotationOwner {
private inline fun <T> withAnnotatedSymbol(crossinline action: context(KtAnalysisSession) (KtAnnotatedSymbol) -> T): T = private inline fun <T> withAnnotatedSymbol(crossinline action: context(KtAnalysisSession) (KtAnnotatedSymbol) -> T): T =
annotatedSymbolPointer.withSymbol(ktModule, action) annotatedSymbolPointer.withSymbol(ktModule, action)
private val annotationsArray: AtomicReference<Array<SymbolLightAbstractAnnotationWithClassId>?> = AtomicReference() private val annotationsArray: AtomicReference<Array<PsiAnnotation>?> = AtomicReference()
private var specialAnnotations: SmartList<SymbolLightAbstractAnnotationWithClassId>? = null private var specialAnnotations: SmartList<PsiAnnotation>? = null
private val monitor = Any() private val monitor = Any()
override fun getAnnotations(): Array<SymbolLightAbstractAnnotationWithClassId> { override fun getAnnotations(): Array<PsiAnnotation> {
annotationsArray.get()?.let { return it } annotationsArray.get()?.let { return it }
val classIds = withAnnotatedSymbol { ktAnnotatedSymbol -> val classIds = withAnnotatedSymbol { ktAnnotatedSymbol ->
ktAnnotatedSymbol.annotationClassIds ktAnnotatedSymbol.annotationClassIds
} }
val annotations = classIds.withIndex().mapTo(SmartList<SymbolLightAbstractAnnotationWithClassId>()) { (index, classId) -> val annotations = classIds.withIndex().mapTo(SmartList<PsiAnnotation>()) { (index, classId) ->
SymbolLightLazyAnnotation(classId, annotatedSymbolPointer, ktModule, index, owner) SymbolLightLazyAnnotation(classId, annotatedSymbolPointer, ktModule, index, owner)
} }
val valueToReturn = if (annotations.isEmpty()) { val valueToReturn = if (annotations.isEmpty()) {
setAnnotationsArray(emptyArray) setAnnotationsArray(PsiAnnotation.EMPTY_ARRAY)
} else { } else {
synchronized(monitor) { synchronized(monitor) {
specialAnnotations?.forEach { lazyAnnotation -> specialAnnotations?.forEach { specialAnnotation ->
val index = annotations.indexOfFirst { it.classId == lazyAnnotation.classId } val index = annotations.indexOfFirst { it.qualifiedName == specialAnnotation.qualifiedName }
if (index != -1) { if (index != -1) {
annotations[index] = lazyAnnotation annotations[index] = specialAnnotation
} else { } else {
annotations += lazyAnnotation annotations += specialAnnotation
} }
} }
for (annotationsProvider in additionalAnnotationsProviders) { val foundQualifiers = hashSetOf<String>()
annotationsProvider.addAllAnnotations(annotations) additionalAnnotationsProvider.addAllAnnotations(annotations, foundQualifiers, owner)
}
specialAnnotations = null specialAnnotations = null
setAnnotationsArray(annotations.toTypedArray()) setAnnotationsArray(annotations.toTypedArray())
} }
} }
@@ -71,16 +69,18 @@ internal class LazyAnnotationsBox(
return valueToReturn return valueToReturn
} }
private fun setAnnotationsArray(array: Array<SymbolLightAbstractAnnotationWithClassId>): Array<SymbolLightAbstractAnnotationWithClassId> = private fun setAnnotationsArray(array: Array<PsiAnnotation>): Array<PsiAnnotation> =
if (annotationsArray.compareAndSet(null, array)) { if (annotationsArray.compareAndSet(null, array)) {
array array
} else { } else {
annotationsArray.get() ?: error("Unexpected state") annotationsArray.get() ?: error("Unexpected state")
} }
override fun getApplicableAnnotations(): Array<SymbolLightAbstractAnnotationWithClassId> = annotations override fun getApplicableAnnotations(): Array<PsiAnnotation> = annotations
override fun findAnnotation(qualifiedName: String): SymbolLightAbstractAnnotationWithClassId? { override fun findAnnotation(qualifiedName: String): PsiAnnotation? = findAnnotation(qualifiedName, withAdditionalAnnotations = true)
fun findAnnotation(qualifiedName: String, withAdditionalAnnotations: Boolean): PsiAnnotation? {
annotationsArray.get()?.let { array -> annotationsArray.get()?.let { array ->
return array.find { it.qualifiedName == qualifiedName } return array.find { it.qualifiedName == qualifiedName }
} }
@@ -98,8 +98,10 @@ internal class LazyAnnotationsBox(
annotationApplication, annotationApplication,
owner, owner,
) )
} else if (withAdditionalAnnotations) {
additionalAnnotationsProvider.findAdditionalAnnotation(this, qualifiedName, owner)
} else { } else {
additionalAnnotationsProviders.firstNotNullOfOrNull { it.findAdditionalAnnotation(this, qualifiedName) } null
} }
if (specialAnnotation == null) { if (specialAnnotation == null) {
@@ -113,7 +115,7 @@ internal class LazyAnnotationsBox(
if (specialAnnotations != null) { if (specialAnnotations != null) {
val specialAnnotations = specialAnnotations!! val specialAnnotations = specialAnnotations!!
val oldAnnotation = specialAnnotations.find { it.classId == specialAnnotation.classId } val oldAnnotation = specialAnnotations.find { it.qualifiedName == specialAnnotation.qualifiedName }
if (oldAnnotation != null) { if (oldAnnotation != null) {
oldAnnotation oldAnnotation
} else { } else {
@@ -149,14 +151,15 @@ internal class LazyAnnotationsBox(
private val specialAnnotationsList: Map<String, ClassId> = listOf( private val specialAnnotationsList: Map<String, ClassId> = listOf(
StandardClassIds.Annotations.Deprecated, StandardClassIds.Annotations.Deprecated,
// Annotations.Retention, // Annotations.Retention,
// Annotations.Java.Retention,
// Annotations.Target, // Annotations.Target,
// Annotations.Java.Target,
// Annotations.Java.Override,
StandardClassIds.Annotations.DeprecatedSinceKotlin, StandardClassIds.Annotations.DeprecatedSinceKotlin,
StandardClassIds.Annotations.WasExperimental, StandardClassIds.Annotations.WasExperimental,
StandardClassIds.Annotations.JvmRecord, StandardClassIds.Annotations.JvmRecord,
// Annotations.Repeatable, // Annotations.Repeatable,
// Annotations.Java.Repeatable, // Annotations.Java.Repeatable,
).associateBy { it.asFqNameString() } ).associateBy { it.asFqNameString() }
private val emptyArray: Array<SymbolLightAbstractAnnotationWithClassId> = emptyArray<SymbolLightAbstractAnnotationWithClassId>()
} }
} }
@@ -1,16 +0,0 @@
/*
* Copyright 2010-2023 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.annotations
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.name.ClassId
internal abstract class SymbolLightAbstractAnnotationWithClassId(
val classId: ClassId,
owner: PsiElement,
) : SymbolLightAbstractAnnotation(owner) {
override fun getQualifiedName(): String = classId.asFqNameString()
}
@@ -9,30 +9,35 @@ import com.intellij.psi.PsiAnnotationParameterList
import com.intellij.psi.PsiModifierList import com.intellij.psi.PsiModifierList
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplication import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplication
import org.jetbrains.kotlin.analysis.api.annotations.annotations import org.jetbrains.kotlin.analysis.api.annotations.annotationsByClassId
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.light.classes.symbol.withSymbol import org.jetbrains.kotlin.light.classes.symbol.withSymbol
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtCallElement import org.jetbrains.kotlin.psi.KtCallElement
internal class SymbolLightLazyAnnotation private constructor( internal class SymbolLightLazyAnnotation private constructor(
classId: ClassId, private val classId: ClassId,
private val annotatedSymbolPointer: KtSymbolPointer<KtAnnotatedSymbol>, private val annotatedSymbolPointer: KtSymbolPointer<KtAnnotatedSymbol>,
private val ktModule: KtModule, private val ktModule: KtModule,
private val index: Int?, private val index: Int?,
specialAnnotationApplication: KtAnnotationApplication?, specialAnnotationApplication: KtAnnotationApplication?,
owner: PsiModifierList, owner: PsiModifierList,
) : SymbolLightAbstractAnnotationWithClassId(classId, owner) { ) : SymbolLightAbstractAnnotation(owner) {
init { init {
require(index != null || specialAnnotationApplication != null) require(index != null || specialAnnotationApplication != null)
} }
private val annotationApplication: Lazy<KtAnnotationApplication> = specialAnnotationApplication?.let(::lazyOf) ?: lazyPub { private val fqName: FqName = classId.asSingleFqName()
val annotationApplication: Lazy<KtAnnotationApplication> = specialAnnotationApplication?.let(::lazyOf) ?: lazyPub {
withAnnotatedSymbol { ktAnnotatedSymbol -> withAnnotatedSymbol { ktAnnotatedSymbol ->
ktAnnotatedSymbol.annotations[index!!] val applications = ktAnnotatedSymbol.annotationsByClassId(classId)
applications.find { it.index == index }
?: error("expected index: $index, actual indices: ${applications.map { it.index }}")
} }
} }
@@ -66,12 +71,12 @@ internal class SymbolLightLazyAnnotation private constructor(
owner = owner, owner = owner,
) )
private inline fun <T> withAnnotatedSymbol(crossinline action: context(KtAnalysisSession) (KtAnnotatedSymbol) -> T): T = inline fun <T> withAnnotatedSymbol(crossinline action: context(KtAnalysisSession) (KtAnnotatedSymbol) -> T): T =
annotatedSymbolPointer.withSymbol(ktModule, action) annotatedSymbolPointer.withSymbol(ktModule, action)
override val kotlinOrigin: KtCallElement? get() = annotationApplication.value.psi override val kotlinOrigin: KtCallElement? get() = annotationApplication.value.psi
override fun getQualifiedName(): String = classId.asFqNameString() override fun getQualifiedName(): String = fqName.asString()
private val _parameterList: PsiAnnotationParameterList by lazyPub { private val _parameterList: PsiAnnotationParameterList by lazyPub {
SymbolLightLazyAnnotationParameterList(this, lazyPub { annotationApplication.value.arguments }) SymbolLightLazyAnnotationParameterList(this, lazyPub { annotationApplication.value.arguments })
@@ -81,10 +86,10 @@ internal class SymbolLightLazyAnnotation private constructor(
override fun equals(other: Any?): Boolean = this === other || override fun equals(other: Any?): Boolean = this === other ||
other is SymbolLightLazyAnnotation && other is SymbolLightLazyAnnotation &&
other.classId == classId && other.fqName == fqName &&
other.index == index && other.index == index &&
other.ktModule == ktModule && other.ktModule == ktModule &&
other.parent == parent other.parent == parent
override fun hashCode(): Int = classId.hashCode() override fun hashCode(): Int = fqName.hashCode()
} }