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 4c4fdd9c391..108128ef4e7 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 @@ -32,7 +32,7 @@ fun FirAnnotationCall.getRetention(session: FirSession): AnnotationRetention { fun FirRegularClass.getRetention(): AnnotationRetention { val retentionAnnotation = getRetentionAnnotation() ?: return AnnotationRetention.RUNTIME - val retentionArgument = retentionAnnotation.findSingleArgumentByName(RETENTION_PARAMETER_NAME) as? FirQualifiedAccessExpression + val retentionArgument = retentionAnnotation.findArgumentByName(RETENTION_PARAMETER_NAME) as? FirQualifiedAccessExpression ?: return AnnotationRetention.RUNTIME val retentionName = (retentionArgument.calleeReference as? FirResolvedNamedReference)?.name?.asString() ?: return AnnotationRetention.RUNTIME @@ -51,7 +51,7 @@ fun FirAnnotationCall.getAllowedAnnotationTargets(session: FirSession): Set { val targetAnnotation = getTargetAnnotation() ?: return defaultAnnotationTargets if (targetAnnotation.argumentList.arguments.isEmpty()) return emptySet() - val arguments = targetAnnotation.findSingleArgumentByName(TARGET_PARAMETER_NAME)?.unfoldArrayOrVararg().orEmpty() + val arguments = targetAnnotation.findArgumentByName(TARGET_PARAMETER_NAME)?.unfoldArrayOrVararg().orEmpty() return arguments.mapNotNullTo(mutableSetOf()) { argument -> val targetExpression = argument as? FirQualifiedAccessExpression @@ -74,15 +74,20 @@ fun FirAnnotationContainer.getAnnotationByFqName(fqName: FqName): FirAnnotationC } } -fun FirAnnotationCall.findSingleArgumentByName(name: Name): FirExpression? { +fun FirAnnotationCall.findArgumentByName(name: Name): FirExpression? { val argumentMapping = argumentMapping if (argumentMapping != null) { - return argumentMapping.keys.firstOrNull()?.takeIf { argumentMapping[it]?.name == name }?.unwrapArgument() + return argumentMapping.keys.find { argumentMapping[it]?.name == name }?.unwrapArgument() } // NB: we have to consider both cases, because deserializer does not create argument mapping - val arguments = argumentList.arguments - val firstArgument = arguments.firstOrNull() as? FirNamedArgumentExpression ?: return arguments.singleOrNull() - return firstArgument.takeIf { it.name == name }?.expression + for (argument in arguments) { + if (argument is FirNamedArgumentExpression && argument.name == name) { + return argument.expression + } + } + // I'm lucky today! + // TODO: this line is still needed. However it should be replaced with 'return null' + return arguments.singleOrNull() } fun FirExpression.extractClassesFromArgument(): List { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirSinceKotlinHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirSinceKotlinHelpers.kt index f3fbdc1f239..1c441dd275a 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirSinceKotlinHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirSinceKotlinHelpers.kt @@ -92,7 +92,7 @@ private fun FirAnnotatedDeclaration.getOwnSinceKotlinVersion(session: FirSession private fun FirAnnotatedDeclaration.loadWasExperimentalMarkerClasses(): List { val wasExperimental = getAnnotationByFqName(OptInNames.WAS_EXPERIMENTAL_FQ_NAME) ?: return emptyList() - val annotationClasses = wasExperimental.findSingleArgumentByName(OptInNames.WAS_EXPERIMENTAL_ANNOTATION_CLASS) ?: return emptyList() + val annotationClasses = wasExperimental.findArgumentByName(OptInNames.WAS_EXPERIMENTAL_ANNOTATION_CLASS) ?: return emptyList() return annotationClasses.extractClassesFromArgument() } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnnotationArgumentChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnnotationArgumentChecker.kt index c9f736e88d9..2f3a48b1f6d 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnnotationArgumentChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnnotationArgumentChecker.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.analysis.checkers.ConstantArgumentKind import org.jetbrains.kotlin.fir.analysis.checkers.checkConstantArguments import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext -import org.jetbrains.kotlin.fir.analysis.checkers.findSingleArgumentByName +import org.jetbrains.kotlin.fir.analysis.checkers.findArgumentByName import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0 import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors @@ -136,7 +136,7 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() { reporter: DiagnosticReporter ) { if (!annotationFqNamesWithVersion.contains(fqName)) return - val versionExpression = annotationCall.findSingleArgumentByName(versionArgumentName) ?: return + val versionExpression = annotationCall.findArgumentByName(versionArgumentName) ?: return val version = parseVersionExpressionOrReport(versionExpression, context, reporter) ?: return if (fqName == sinceKotlinFqName) { val specified = context.session.languageVersionSettings.apiVersion diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInAnnotationCallChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInAnnotationCallChecker.kt index 93962a8c218..52837a49f52 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInAnnotationCallChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInAnnotationCallChecker.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.config.AnalysisFlags import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.extractClassesFromArgument -import org.jetbrains.kotlin.fir.analysis.checkers.findSingleArgumentByName +import org.jetbrains.kotlin.fir.analysis.checkers.findArgumentByName import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn @@ -32,7 +32,7 @@ object FirOptInAnnotationCallChecker : FirAnnotationCallChecker() { if (arguments.isEmpty()) { reporter.reportOn(expression.source, FirErrors.USE_EXPERIMENTAL_WITHOUT_ARGUMENTS, context) } else { - val annotationClasses = expression.findSingleArgumentByName(OptInNames.USE_EXPERIMENTAL_ANNOTATION_CLASS) + val annotationClasses = expression.findArgumentByName(OptInNames.USE_EXPERIMENTAL_ANNOTATION_CLASS) for (classSymbol in annotationClasses?.extractClassesFromArgument().orEmpty()) { with(FirOptInUsageBaseChecker) { if (classSymbol.fir.loadExperimentalityForMarkerAnnotation() == null) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageBaseChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageBaseChecker.kt index c88318858c1..5bb31db5b29 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageBaseChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageBaseChecker.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression -import org.jetbrains.kotlin.fir.analysis.checkers.findSingleArgumentByName +import org.jetbrains.kotlin.fir.analysis.checkers.findArgumentByName import org.jetbrains.kotlin.fir.analysis.checkers.getAnnotationByFqName import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.expressions.FirConstExpression @@ -19,10 +19,10 @@ object FirOptInUsageBaseChecker { internal fun FirRegularClass.loadExperimentalityForMarkerAnnotation(): Experimentality? { val experimental = getAnnotationByFqName(OptInNames.REQUIRES_OPT_IN_FQ_NAME) ?: return null - val levelArgument = experimental.findSingleArgumentByName(LEVEL) as? FirQualifiedAccessExpression + val levelArgument = experimental.findArgumentByName(LEVEL) as? FirQualifiedAccessExpression val levelName = (levelArgument?.calleeReference as? FirResolvedNamedReference)?.name?.asString() val level = OptInLevel.values().firstOrNull { it.name == levelName } ?: OptInLevel.DEFAULT - val message = (experimental.findSingleArgumentByName(MESSAGE) as? FirConstExpression<*>)?.value as? String + val message = (experimental.findArgumentByName(MESSAGE) as? FirConstExpression<*>)?.value as? String return Experimentality(symbol.classId.asSingleFqName(), level.severity, message) }