From 3a7602a38fdba2f930e7d1906514ce9ea321ef95 Mon Sep 17 00:00:00 2001 From: Dmitrii Gridin Date: Thu, 26 Jan 2023 14:54:27 +0100 Subject: [PATCH] [AA] KtAnnotationsList: introduce 'annotationOverviews' it provides a solution for several problems with redundant resolve. It is a more powerful tool than 'annotationClassIds' ^KT-56046 --- .../annotations/KtFe10AnnotationsList.kt | 18 ++++++- .../descriptorBased/base/Kt1DescUtils.kt | 35 ++++++++++---- .../kotlin/analysis/api/fir/FirUtils.kt | 36 +++++++++----- .../KtFirAnnotationListForDeclaration.kt | 6 +++ ...KtFirAnnotationListForReceiverParameter.kt | 7 ++- .../annotations/KtFirAnnotationListForType.kt | 9 ++++ .../api/fir/annotations/firAnnotationUtils.kt | 10 ++++ .../annotations/KtEmptyAnnotationsList.kt | 4 ++ .../analysis/api/annotations/KtAnnotated.kt | 10 +++- .../api/annotations/KtAnnotationOverview.kt | 48 +++++++++++++++++++ .../api/annotations/KtAnnotationsList.kt | 10 +++- 11 files changed, 166 insertions(+), 27 deletions(-) create mode 100644 analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotationOverview.kt diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/annotations/KtFe10AnnotationsList.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/annotations/KtFe10AnnotationsList.kt index ef6262692c0..1226bf8774e 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/annotations/KtFe10AnnotationsList.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/annotations/KtFe10AnnotationsList.kt @@ -6,10 +6,12 @@ package org.jetbrains.kotlin.analysis.api.descriptors.annotations import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplication +import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationOverview import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisContext import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.maybeLocalClassId import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtAnnotationApplication +import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtAnnotationOverview import org.jetbrains.kotlin.analysis.api.impl.base.annotations.KtEmptyAnnotationsList import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion @@ -30,8 +32,20 @@ internal class KtFe10AnnotationsList private constructor( override val annotations: List get() = withValidityAssertion { fe10Annotations.mapIndexedNotNull { index, annotation -> - if (annotation.annotationClass.classId in annotationsToIgnore) null - else annotation.toKtAnnotationApplication(analysisContext, index) + if (annotation.annotationClass.classId in annotationsToIgnore) + null + else + annotation.toKtAnnotationApplication(analysisContext, index) + } + } + + override val annotationOverviews: List + get() = withValidityAssertion { + fe10Annotations.mapIndexedNotNull { index, annotation -> + if (annotation.annotationClass.classId in annotationsToIgnore) + null + else + annotation.toKtAnnotationOverview(index) } } diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/base/Kt1DescUtils.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/base/Kt1DescUtils.kt index 0eb569cf390..7d5d369c1a6 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/base/Kt1DescUtils.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/base/Kt1DescUtils.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.descriptors.impl.* import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor @@ -608,27 +609,41 @@ internal fun createKtInitializerValue( return KtNonConstantInitializerValue(initializer) } -internal fun AnnotationDescriptor.toKtAnnotationApplication(analysisContext: Fe10AnalysisContext, index: Int): KtAnnotationApplication { - return KtAnnotationApplication( - annotationClass?.maybeLocalClassId, - (source as? PsiSourceElement)?.psi as? KtCallElement, - (this as? LazyAnnotationDescriptor)?.annotationEntry?.useSiteTarget?.getAnnotationUseSiteTarget(), - getKtNamedAnnotationArguments(analysisContext), - index, - ) -} +internal fun AnnotationDescriptor.toKtAnnotationApplication( + analysisContext: Fe10AnalysisContext, + index: Int, +): KtAnnotationApplication = KtAnnotationApplication( + classId = classIdIfNonLocal, + psi = psi, + useSiteTarget = useSiteTarget, + arguments = getKtNamedAnnotationArguments(analysisContext), + index = index, +) + +internal fun AnnotationDescriptor.toKtAnnotationOverview(index: Int): KtAnnotationOverview = KtAnnotationOverview( + classId = classIdIfNonLocal, + psi = psi, + useSiteTarget = useSiteTarget, + hasArguments = allValueArguments.isNotEmpty(), + index = index, +) + +private val AnnotationDescriptor.psi: KtCallElement? get() = (source as? PsiSourceElement)?.psi as? KtCallElement +private val AnnotationDescriptor.classIdIfNonLocal: ClassId? get() = annotationClass?.maybeLocalClassId +private val AnnotationDescriptor.useSiteTarget: AnnotationUseSiteTarget? + get() = (this as? LazyAnnotationDescriptor)?.annotationEntry?.useSiteTarget?.getAnnotationUseSiteTarget() internal fun AnnotationDescriptor.getKtNamedAnnotationArguments(analysisContext: Fe10AnalysisContext): List = allValueArguments.map { (name, value) -> KtNamedAnnotationValue(name, value.toKtAnnotationValue(analysisContext, index = -1)) } - internal fun CallableDescriptor.createContextReceivers( analysisContext: Fe10AnalysisContext ): List { return contextReceiverParameters.map { createContextReceiver(it, analysisContext) } } + internal fun ClassDescriptor.createContextReceivers( analysisContext: Fe10AnalysisContext ): List { diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/FirUtils.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/FirUtils.kt index a0dca2117cc..8496dc83032 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/FirUtils.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/FirUtils.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.analysis.api.fir import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplication +import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationOverview import org.jetbrains.kotlin.analysis.api.fir.annotations.mapAnnotationParameters import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirAnnotationValueConverter import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol @@ -13,7 +14,9 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.expressions.FirAnnotation +import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirFunctionCall +import org.jetbrains.kotlin.fir.expressions.arguments import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReference @@ -65,15 +68,24 @@ internal fun ConeDiagnostic.getCandidateSymbols(): Collection> else -> emptyList() } -internal fun FirAnnotation.toKtAnnotationApplication(useSiteSession: FirSession, index: Int): KtAnnotationApplication { - return KtAnnotationApplication( - toAnnotationClassId(useSiteSession), - psi as? KtCallElement, - useSiteTarget, - FirAnnotationValueConverter.toNamedConstantValue( - mapAnnotationParameters(this), - useSiteSession, - ), - index, - ) -} \ No newline at end of file +internal fun FirAnnotation.toKtAnnotationApplication( + useSiteSession: FirSession, + index: Int, +): KtAnnotationApplication = KtAnnotationApplication( + classId = toAnnotationClassId(useSiteSession), + psi = psi as? KtCallElement, + useSiteTarget = useSiteTarget, + arguments = FirAnnotationValueConverter.toNamedConstantValue( + mapAnnotationParameters(this), + useSiteSession, + ), + index = index, +) + +internal fun FirAnnotation.toKtAnnotationOverview(useSiteSession: FirSession, index: Int): KtAnnotationOverview = KtAnnotationOverview( + classId = toAnnotationClassId(useSiteSession), + psi = psi as? KtCallElement, + useSiteTarget = useSiteTarget, + hasArguments = this is FirAnnotationCall && arguments.isNotEmpty(), + index = index, +) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForDeclaration.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForDeclaration.kt index d0f9edec6f2..6a7db277c4e 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForDeclaration.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForDeclaration.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.analysis.api.fir.annotations import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplication +import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationOverview import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList import org.jetbrains.kotlin.analysis.api.impl.base.annotations.KtEmptyAnnotationsList import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken @@ -25,6 +26,11 @@ internal class KtFirAnnotationListForDeclaration private constructor( annotations(firSymbol, useSiteSession) } + override val annotationOverviews: List + get() = withValidityAssertion { + annotationOverviews(firSymbol, useSiteSession) + } + override fun hasAnnotation( classId: ClassId, useSiteTarget: AnnotationUseSiteTarget?, diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForReceiverParameter.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForReceiverParameter.kt index e1ba35fb63b..b7ed0ba1c23 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForReceiverParameter.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForReceiverParameter.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.analysis.api.fir.annotations import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplication +import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationOverview import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList import org.jetbrains.kotlin.analysis.api.impl.base.annotations.KtEmptyAnnotationsList import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken @@ -22,12 +23,16 @@ internal class KtFirAnnotationListForReceiverParameter private constructor( private val useSiteSession: FirSession, override val token: KtLifetimeToken, ) : KtAnnotationsList() { - override val annotations: List get() = withValidityAssertion { annotations(firCallableSymbol, useSiteSession, receiverParameter) } + override val annotationOverviews: List + get() = withValidityAssertion { + annotationOverviews(firCallableSymbol, useSiteSession, receiverParameter) + } + override fun hasAnnotation( classId: ClassId, useSiteTarget: AnnotationUseSiteTarget?, diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForType.kt index 65179628693..6032847e24f 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForType.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForType.kt @@ -6,8 +6,10 @@ package org.jetbrains.kotlin.analysis.api.fir.annotations import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplication +import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationOverview import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList import org.jetbrains.kotlin.analysis.api.fir.toKtAnnotationApplication +import org.jetbrains.kotlin.analysis.api.fir.toKtAnnotationOverview import org.jetbrains.kotlin.analysis.api.impl.base.annotations.KtEmptyAnnotationsList import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion @@ -36,6 +38,13 @@ internal class KtFirAnnotationListForType private constructor( } } + override val annotationOverviews: List + get() = withValidityAssertion { + coneType.customAnnotationsWithLazyResolve(FirResolvePhase.TYPES).mapIndexed { index, annotation -> + annotation.toKtAnnotationOverview(useSiteSession, index) + } + } + override fun hasAnnotation( classId: ClassId, useSiteTarget: AnnotationUseSiteTarget?, diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/firAnnotationUtils.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/firAnnotationUtils.kt index 1d9afb7fa5b..c9310ddaf23 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/firAnnotationUtils.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/firAnnotationUtils.kt @@ -6,7 +6,9 @@ package org.jetbrains.kotlin.analysis.api.fir.annotations import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplication +import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationOverview import org.jetbrains.kotlin.analysis.api.fir.toKtAnnotationApplication +import org.jetbrains.kotlin.analysis.api.fir.toKtAnnotationOverview import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry import org.jetbrains.kotlin.analysis.utils.errors.checkWithAttachmentBuilder import org.jetbrains.kotlin.analysis.utils.errors.withClassEntry @@ -64,6 +66,14 @@ internal fun annotations( annotation.toKtAnnotationApplication(useSiteSession, index) } +internal fun annotationOverviews( + firSymbol: FirBasedSymbol<*>, + useSiteSession: FirSession, + annotationContainer: FirAnnotationContainer = firSymbol.fir, +): List = annotationContainer.resolvedAnnotationsWithClassIds(firSymbol).mapIndexed { index, annotation -> + annotation.toKtAnnotationOverview(useSiteSession, index) +} + internal fun annotationClassIds( firSymbol: FirBasedSymbol<*>, useSiteSession: FirSession, diff --git a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/annotations/KtEmptyAnnotationsList.kt b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/annotations/KtEmptyAnnotationsList.kt index 53add953488..22ec4a742ae 100644 --- a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/annotations/KtEmptyAnnotationsList.kt +++ b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/annotations/KtEmptyAnnotationsList.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.analysis.api.impl.base.annotations import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplication +import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationOverview import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion @@ -16,6 +17,9 @@ class KtEmptyAnnotationsList(override val token: KtLifetimeToken) : KtAnnotation override val annotations: List get() = withValidityAssertion { emptyList() } + override val annotationOverviews: List + get() = withValidityAssertion { emptyList() } + override fun hasAnnotation( classId: ClassId, useSiteTarget: AnnotationUseSiteTarget?, diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotated.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotated.kt index b27ccd2c75d..c1f194e2983 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotated.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotated.kt @@ -23,6 +23,14 @@ public interface KtAnnotated { public val KtAnnotated.annotations: List get() = annotationsList.annotations +/** + * A list of annotation overviews. + * + * @see [KtAnnotationsList.annotationOverviews] + */ +public val KtAnnotated.annotationOverviews: List + get() = annotationsList.annotationOverviews + /** * Checks if entity has annotation with specified [classId]. * @@ -55,4 +63,4 @@ public fun KtAnnotated.annotationsByClassId(classId: ClassId): List - get() = annotationsList.annotationClassIds \ No newline at end of file + get() = annotationsList.annotationClassIds diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotationOverview.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotationOverview.kt new file mode 100644 index 00000000000..20bbfaea48b --- /dev/null +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotationOverview.kt @@ -0,0 +1,48 @@ +/* + * 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.analysis.api.annotations + +import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.psi.KtCallElement + +/** + * Overview of annotation to some declaration or type. + * + * Some examples: + * - For declarations: `@Deprecated("Should not be used") fun foo(){}` + * - For types: `fun foo(x: List<@A Int>){}` + */ +public data class KtAnnotationOverview( + /** + * The [ClassId] of applied annotation. [ClassId] is a fully qualified name on annotation class. + */ + public val classId: ClassId?, + + /** + * PsiElement which was used to apply annotation to declaration/type. + * + * Present only for declarations from sources. For declarations from other places (libraries, stdlib) it's `null` + */ + public val psi: KtCallElement?, + + /** + * [AnnotationUseSiteTarget] to which annotation was applied. May be not-null only for annotation applications for declarations. + * + * See in more details in [Kotlin Documentation](https://kotlinlang.org/docs/annotations.html#annotation-use-site-targets) for more information about annotation targets. + */ + public val useSiteTarget: AnnotationUseSiteTarget?, + + /** + * **true** if the annotation has any arguments + */ + public val hasArguments: Boolean, + + /** + * An index of the annotation in an owner + */ + public val index: Int, +) diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotationsList.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotationsList.kt index 2fbdccc11bc..3bd8c744e75 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotationsList.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotationsList.kt @@ -24,6 +24,15 @@ public abstract class KtAnnotationsList : KtLifetimeOwner { */ public abstract val annotations: List + /** + * A list of annotation overviews. + * + * Can be used instead of [annotations] if applicable to reduce resolve. + * + * @see KtAnnotationOverview + */ + public abstract val annotationOverviews: List + /** * Checks if entity contains annotation with specified [classId]. * @@ -81,4 +90,3 @@ public abstract class KtAnnotationsList : KtLifetimeOwner { */ public abstract val annotationClassIds: Collection } -