From 59f1a0dd8e81021aa881977ab4bac9580e9b4772 Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Fri, 23 Jun 2023 14:41:30 +0200 Subject: [PATCH] [FIR, IR] Refactor: move annotation retention helper functions Will be needed in subsequent commit to be accessible in ExpectActualMatchingContext implementations. ^KT-58551 --- .../analysis/checkers/FirAnnotationHelpers.kt | 29 ++++----------- .../FirAnnotationClassDeclarationChecker.kt | 2 ++ .../FirOptInAnnotationClassChecker.kt | 2 ++ .../analysis/FirRetentionAnnotationHelpers.kt | 35 +++++++++++++++++++ .../AdditionalClassAnnotationLowering.kt | 2 -- .../kotlin/backend/jvm/ir/JvmIrUtils.kt | 16 --------- .../org/jetbrains/kotlin/ir/util/IrUtils.kt | 17 +++++++++ 7 files changed, 62 insertions(+), 41 deletions(-) create mode 100644 compiler/fir/semantics/src/org/jetbrains/kotlin/fir/analysis/FirRetentionAnnotationHelpers.kt diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirAnnotationHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirAnnotationHelpers.kt index f8d32e1ee88..e4a9eafbcb3 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirAnnotationHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirAnnotationHelpers.kt @@ -10,43 +10,30 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.reportOn -import org.jetbrains.kotlin.fir.* +import org.jetbrains.kotlin.fir.FirAnnotationContainer +import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.fir.analysis.getRetention import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.impl.FirPrimaryConstructor import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.references.FirFromMissingDependenciesNamedReference +import org.jetbrains.kotlin.fir.references.resolved import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.toSymbol -import org.jetbrains.kotlin.fir.references.resolved -import org.jetbrains.kotlin.fir.references.toResolvedEnumEntrySymbol -import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol +import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.name.StandardClassIds.Annotations.ParameterNames import org.jetbrains.kotlin.resolve.UseSiteTargetsList import org.jetbrains.kotlin.resolve.checkers.OptInNames -fun FirRegularClass.getRetention(session: FirSession): AnnotationRetention { - return getRetentionAnnotation(session)?.getRetention() ?: AnnotationRetention.RUNTIME -} - -private fun FirAnnotation.getRetention(): AnnotationRetention? { - val propertyAccess = findArgumentByName(ParameterNames.retentionValue) as? FirQualifiedAccessExpression - val callableId = propertyAccess?.calleeReference?.toResolvedEnumEntrySymbol()?.callableId ?: return null - - if (callableId.classId != StandardClassIds.AnnotationRetention) { - return null - } - - return AnnotationRetention.values().firstOrNull { it.name == callableId.callableName.asString() } -} - private val defaultAnnotationTargets = KotlinTarget.DEFAULT_TARGET_SET fun FirAnnotation.getAllowedAnnotationTargets(session: FirSession): Set { @@ -89,10 +76,6 @@ fun FirClassLikeSymbol<*>.getAllowedAnnotationTargets(session: FirSession): Set< } } -fun FirDeclaration.getRetentionAnnotation(session: FirSession): FirAnnotation? { - return getAnnotationByClassId(StandardClassIds.Annotations.Retention, session) -} - fun FirDeclaration.getTargetAnnotation(session: FirSession): FirAnnotation? { return getAnnotationByClassId(StandardClassIds.Annotations.Target, session) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt index c0783259aef..9692477c4e8 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt @@ -18,6 +18,8 @@ import org.jetbrains.kotlin.fir.analysis.checkers.* import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.diagnostics.* import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLE_IN_ANNOTATION_PARAMETER +import org.jetbrains.kotlin.fir.analysis.getRetention +import org.jetbrains.kotlin.fir.analysis.getRetentionAnnotation import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.isLocal import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOptInAnnotationClassChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOptInAnnotationClassChecker.kt index 01d83483b72..c69d281d660 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOptInAnnotationClassChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOptInAnnotationClassChecker.kt @@ -12,6 +12,8 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.analysis.getRetention +import org.jetbrains.kotlin.fir.analysis.getRetentionAnnotation import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId import org.jetbrains.kotlin.resolve.checkers.OptInDescription diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/analysis/FirRetentionAnnotationHelpers.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/analysis/FirRetentionAnnotationHelpers.kt new file mode 100644 index 00000000000..000f71bb2a0 --- /dev/null +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/analysis/FirRetentionAnnotationHelpers.kt @@ -0,0 +1,35 @@ +/* + * 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.fir.analysis + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirRegularClass +import org.jetbrains.kotlin.fir.declarations.findArgumentByName +import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId +import org.jetbrains.kotlin.fir.expressions.FirAnnotation +import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression +import org.jetbrains.kotlin.fir.references.toResolvedEnumEntrySymbol +import org.jetbrains.kotlin.name.StandardClassIds + +fun FirRegularClass.getRetention(session: FirSession): AnnotationRetention { + return getRetentionAnnotation(session)?.getRetention() ?: AnnotationRetention.RUNTIME +} + +fun FirAnnotation.getRetention(): AnnotationRetention? { + val propertyAccess = findArgumentByName(StandardClassIds.Annotations.ParameterNames.retentionValue) as? FirQualifiedAccessExpression + val callableId = propertyAccess?.calleeReference?.toResolvedEnumEntrySymbol()?.callableId ?: return null + + if (callableId.classId != StandardClassIds.AnnotationRetention) { + return null + } + + return AnnotationRetention.entries.firstOrNull { it.name == callableId.callableName.asString() } +} + +fun FirDeclaration.getRetentionAnnotation(session: FirSession): FirAnnotation? { + return getAnnotationByClassId(StandardClassIds.Annotations.Retention, session) +} diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/AdditionalClassAnnotationLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/AdditionalClassAnnotationLowering.kt index 3b29acb771a..9ab5da6f012 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/AdditionalClassAnnotationLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/AdditionalClassAnnotationLowering.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext -import org.jetbrains.kotlin.backend.jvm.ir.getAnnotationRetention import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET @@ -27,7 +26,6 @@ import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.name.Name -import org.jetbrains.org.objectweb.asm.Type import java.lang.annotation.ElementType internal val additionalClassAnnotationPhase = makeIrFilePhase( diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrUtils.kt index 34eb0bf27e1..9954cd70020 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrUtils.kt @@ -453,22 +453,6 @@ val IrDeclaration.fileParentOrNull: IrFile? else -> null } -private val RETENTION_PARAMETER_NAME = Name.identifier("value") - -fun IrClass.getAnnotationRetention(): KotlinRetention? { - val retentionArgument = - getAnnotation(StandardNames.FqNames.retention)?.getValueArgument(RETENTION_PARAMETER_NAME) - as? IrGetEnumValue ?: return null - val retentionArgumentValue = retentionArgument.symbol.owner - return KotlinRetention.valueOf(retentionArgumentValue.name.asString()) -} - -// To be generalized to IrMemberAccessExpression as soon as properties get symbols. -fun IrConstructorCall.getValueArgument(name: Name): IrExpression? { - val index = symbol.owner.valueParameters.find { it.name == name }?.index ?: return null - return getValueArgument(index) -} - val IrMemberWithContainerSource.parentClassId: ClassId? get() = ((this as? IrSimpleFunction)?.correspondingPropertySymbol?.owner ?: this).let { directMember -> (directMember.containerSource as? JvmPackagePartSource)?.classId ?: (directMember.parent as? IrClass)?.classId diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt index 04aad007b0a..ca175c6084a 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt @@ -6,8 +6,10 @@ package org.jetbrains.kotlin.ir.util import org.jetbrains.kotlin.builtins.PrimitiveType +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.UnsignedType import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope import org.jetbrains.kotlin.ir.builders.declarations.* @@ -29,6 +31,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames +import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.utils.* import java.io.StringWriter @@ -348,6 +351,20 @@ fun IrAnnotationContainer.hasAnnotation(symbol: IrClassSymbol) = it.symbol.owner.parentAsClass.symbol == symbol } +fun IrClass.getAnnotationRetention(): KotlinRetention? { + val retentionArgument = + getAnnotation(StandardNames.FqNames.retention)?.getValueArgument(StandardClassIds.Annotations.ParameterNames.retentionValue) + as? IrGetEnumValue ?: return null + val retentionArgumentValue = retentionArgument.symbol.owner + return KotlinRetention.valueOf(retentionArgumentValue.name.asString()) +} + +// To be generalized to IrMemberAccessExpression as soon as properties get symbols. +fun IrConstructorCall.getValueArgument(name: Name): IrExpression? { + val index = symbol.owner.valueParameters.find { it.name == name }?.index ?: return null + return getValueArgument(index) +} + val IrConstructor.constructedClassType get() = (parent as IrClass).thisReceiver?.type!!