[SLC] extract AnnotationsProvider

^KT-56046
This commit is contained in:
Dmitrii Gridin
2023-01-24 15:07:32 +01:00
committed by Space Team
parent 4dbce37c0f
commit d76e902b21
5 changed files with 79 additions and 53 deletions
@@ -0,0 +1,17 @@
/*
* 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 org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplication
import org.jetbrains.kotlin.name.ClassId
interface AnnotationsProvider {
fun classIds(): Collection<ClassId>
operator fun get(classId: ClassId): Collection<KtAnnotationApplication>
operator fun contains(classId: ClassId): Boolean
fun isTheSameAs(other: Any?): Boolean
fun ownerClassId(): ClassId?
}
@@ -10,7 +10,6 @@ import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiModifierList import com.intellij.psi.PsiModifierList
import org.jetbrains.kotlin.analysis.api.annotations.* import org.jetbrains.kotlin.analysis.api.annotations.*
import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol
import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightMethod import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightMethod
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
@@ -189,9 +188,7 @@ private fun SymbolLightLazyAnnotation.tryConvertToRepeatableJavaAnnotation(
) )
private fun SymbolLightJavaAnnotation.computeRepeatableJavaAnnotationArguments(): List<KtNamedAnnotationValue> { private fun SymbolLightJavaAnnotation.computeRepeatableJavaAnnotationArguments(): List<KtNamedAnnotationValue> {
val annotationClassId = originalLightAnnotation.withAnnotatedSymbol { ktAnnotatedSymbol -> val annotationClassId = originalLightAnnotation.annotationsProvider.ownerClassId() ?: return emptyList()
(ktAnnotatedSymbol as? KtClassLikeSymbol)?.classIdIfNonLocal
} ?: return emptyList()
return listOf( return listOf(
KtNamedAnnotationValue( KtNamedAnnotationValue(
@@ -8,28 +8,16 @@ package org.jetbrains.kotlin.light.classes.symbol.annotations
import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiAnnotationOwner import com.intellij.psi.PsiAnnotationOwner
import com.intellij.psi.PsiModifierList import com.intellij.psi.PsiModifierList
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.annotations.annotationClassIds
import org.jetbrains.kotlin.analysis.api.annotations.annotationsByClassId
import org.jetbrains.kotlin.analysis.api.annotations.hasAnnotation
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.analysis.project.structure.KtModule
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.StandardClassIds import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartList
import java.util.concurrent.atomic.AtomicReference import java.util.concurrent.atomic.AtomicReference
internal class LazyAnnotationsBox( internal class LazyAnnotationsBox(
private val annotatedSymbolPointer: KtSymbolPointer<KtAnnotatedSymbol>,
private val ktModule: KtModule,
private val owner: PsiModifierList, private val owner: PsiModifierList,
private val annotationsProvider: AnnotationsProvider,
private val additionalAnnotationsProvider: AdditionalAnnotationsProvider = DefaultAnnotationsProvider, private val additionalAnnotationsProvider: AdditionalAnnotationsProvider = DefaultAnnotationsProvider,
) : PsiAnnotationOwner { ) : PsiAnnotationOwner {
private inline fun <T> withAnnotatedSymbol(crossinline action: context(KtAnalysisSession) (KtAnnotatedSymbol) -> T): T =
annotatedSymbolPointer.withSymbol(ktModule, action)
private val annotationsArray: AtomicReference<Array<PsiAnnotation>?> = AtomicReference() private val annotationsArray: AtomicReference<Array<PsiAnnotation>?> = AtomicReference()
private var specialAnnotations: SmartList<PsiAnnotation>? = null private var specialAnnotations: SmartList<PsiAnnotation>? = null
private val monitor = Any() private val monitor = Any()
@@ -37,12 +25,9 @@ internal class LazyAnnotationsBox(
override fun getAnnotations(): Array<PsiAnnotation> { override fun getAnnotations(): Array<PsiAnnotation> {
annotationsArray.get()?.let { return it } annotationsArray.get()?.let { return it }
val classIds = withAnnotatedSymbol { ktAnnotatedSymbol -> val classIds = annotationsProvider.classIds()
ktAnnotatedSymbol.annotationClassIds
}
val annotations = classIds.withIndex().mapTo(SmartList<PsiAnnotation>()) { (index, classId) -> val annotations = classIds.withIndex().mapTo(SmartList<PsiAnnotation>()) { (index, classId) ->
SymbolLightLazyAnnotation(classId, annotatedSymbolPointer, ktModule, index, owner) SymbolLightLazyAnnotation(classId, annotationsProvider, index, owner)
} }
val valueToReturn = if (annotations.isEmpty()) { val valueToReturn = if (annotations.isEmpty()) {
@@ -87,14 +72,11 @@ internal class LazyAnnotationsBox(
val specialAnnotationClassId = specialAnnotationsList[qualifiedName] val specialAnnotationClassId = specialAnnotationsList[qualifiedName]
val specialAnnotation = if (specialAnnotationClassId != null) { val specialAnnotation = if (specialAnnotationClassId != null) {
val annotationApplication = withAnnotatedSymbol { ktAnnotatedSymbol -> val annotationApplication = annotationsProvider[specialAnnotationClassId].firstOrNull() ?: return null
ktAnnotatedSymbol.annotationsByClassId(specialAnnotationClassId).firstOrNull()
} ?: return null
SymbolLightLazyAnnotation( SymbolLightLazyAnnotation(
specialAnnotationClassId, specialAnnotationClassId,
annotatedSymbolPointer, annotationsProvider,
ktModule,
annotationApplication, annotationApplication,
owner, owner,
) )
@@ -136,7 +118,7 @@ internal class LazyAnnotationsBox(
val specialAnnotationClassId = specialAnnotationsList[qualifiedName] val specialAnnotationClassId = specialAnnotationsList[qualifiedName]
return if (specialAnnotationClassId != null) { return if (specialAnnotationClassId != null) {
withAnnotatedSymbol { ktAnnotatedSymbol -> ktAnnotatedSymbol.hasAnnotation(specialAnnotationClassId) } specialAnnotationClassId in annotationsProvider
} else { } else {
annotations.any { it.qualifiedName == qualifiedName } annotations.any { it.qualifiedName == qualifiedName }
} }
@@ -0,0 +1,47 @@
/*
* 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 org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplication
import org.jetbrains.kotlin.analysis.api.annotations.annotationClassIds
import org.jetbrains.kotlin.analysis.api.annotations.annotationsByClassId
import org.jetbrains.kotlin.analysis.api.annotations.hasAnnotation
import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.light.classes.symbol.withSymbol
import org.jetbrains.kotlin.name.ClassId
internal class SymbolAnnotationsProvider<T : KtAnnotatedSymbol>(
private val ktModule: KtModule,
private val annotatedSymbolPointer: KtSymbolPointer<T>
) : AnnotationsProvider {
private inline fun <T> withAnnotatedSymbol(crossinline action: context(KtAnalysisSession) (KtAnnotatedSymbol) -> T): T =
annotatedSymbolPointer.withSymbol(ktModule, action)
override fun classIds(): Collection<ClassId> = withAnnotatedSymbol { annotatedSymbol ->
annotatedSymbol.annotationClassIds
}
override fun get(classId: ClassId): Collection<KtAnnotationApplication> = withAnnotatedSymbol { annotatedSymbol ->
annotatedSymbol.annotationsByClassId(classId)
}
override fun contains(classId: ClassId): Boolean = withAnnotatedSymbol { annotatedSymbol ->
annotatedSymbol.hasAnnotation(classId)
}
override fun isTheSameAs(other: Any?): Boolean = other === this ||
other is SymbolAnnotationsProvider<*> &&
other.ktModule == ktModule &&
annotatedSymbolPointer.pointsToTheSameSymbolAs(other.annotatedSymbolPointer)
override fun ownerClassId(): ClassId? = withAnnotatedSymbol { annotatedSymbol ->
(annotatedSymbol as? KtClassLikeSymbol)?.classIdIfNonLocal
}
}
@@ -7,22 +7,15 @@ package org.jetbrains.kotlin.light.classes.symbol.annotations
import com.intellij.psi.PsiAnnotationParameterList 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.annotations.KtAnnotationApplication import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplication
import org.jetbrains.kotlin.analysis.api.annotations.annotationsByClassId
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
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.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName 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(
private val classId: ClassId, private val classId: ClassId,
private val annotatedSymbolPointer: KtSymbolPointer<KtAnnotatedSymbol>, val annotationsProvider: AnnotationsProvider,
private val ktModule: KtModule,
private val index: Int?, private val index: Int?,
specialAnnotationApplication: KtAnnotationApplication?, specialAnnotationApplication: KtAnnotationApplication?,
owner: PsiModifierList, owner: PsiModifierList,
@@ -34,23 +27,18 @@ internal class SymbolLightLazyAnnotation private constructor(
private val fqName: FqName = classId.asSingleFqName() private val fqName: FqName = classId.asSingleFqName()
val annotationApplication: Lazy<KtAnnotationApplication> = specialAnnotationApplication?.let(::lazyOf) ?: lazyPub { val annotationApplication: Lazy<KtAnnotationApplication> = specialAnnotationApplication?.let(::lazyOf) ?: lazyPub {
withAnnotatedSymbol { ktAnnotatedSymbol -> val applications = annotationsProvider[classId]
val applications = ktAnnotatedSymbol.annotationsByClassId(classId) applications.find { it.index == index } ?: error("expected index: $index, actual indices: ${applications.map { it.index }}")
applications.find { it.index == index }
?: error("expected index: $index, actual indices: ${applications.map { it.index }}")
}
} }
constructor( constructor(
classId: ClassId, classId: ClassId,
annotatedSymbolPointer: KtSymbolPointer<KtAnnotatedSymbol>, annotationsProvider: AnnotationsProvider,
ktModule: KtModule,
index: Int, index: Int,
owner: PsiModifierList, owner: PsiModifierList,
) : this( ) : this(
classId = classId, classId = classId,
annotatedSymbolPointer = annotatedSymbolPointer, annotationsProvider = annotationsProvider,
ktModule = ktModule,
index = index, index = index,
specialAnnotationApplication = null, specialAnnotationApplication = null,
owner = owner, owner = owner,
@@ -58,22 +46,17 @@ internal class SymbolLightLazyAnnotation private constructor(
constructor( constructor(
classId: ClassId, classId: ClassId,
annotatedSymbolPointer: KtSymbolPointer<KtAnnotatedSymbol>, annotationsProvider: AnnotationsProvider,
ktModule: KtModule,
annotationApplication: KtAnnotationApplication, annotationApplication: KtAnnotationApplication,
owner: PsiModifierList, owner: PsiModifierList,
) : this( ) : this(
classId = classId, classId = classId,
annotatedSymbolPointer = annotatedSymbolPointer, annotationsProvider = annotationsProvider,
ktModule = ktModule,
index = null, index = null,
specialAnnotationApplication = annotationApplication, specialAnnotationApplication = annotationApplication,
owner = owner, owner = owner,
) )
inline fun <T> withAnnotatedSymbol(crossinline action: context(KtAnalysisSession) (KtAnnotatedSymbol) -> T): T =
annotatedSymbolPointer.withSymbol(ktModule, action)
override val kotlinOrigin: KtCallElement? get() = annotationApplication.value.psi override val kotlinOrigin: KtCallElement? get() = annotationApplication.value.psi
override fun getQualifiedName(): String = fqName.asString() override fun getQualifiedName(): String = fqName.asString()
@@ -88,7 +71,7 @@ internal class SymbolLightLazyAnnotation private constructor(
other is SymbolLightLazyAnnotation && other is SymbolLightLazyAnnotation &&
other.fqName == fqName && other.fqName == fqName &&
other.index == index && other.index == index &&
other.ktModule == ktModule && annotationsProvider.isTheSameAs(other.annotationsProvider) &&
other.parent == parent other.parent == parent
override fun hashCode(): Int = fqName.hashCode() override fun hashCode(): Int = fqName.hashCode()