From fa12e725519db67eae425d865341b9302b1f0d74 Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Thu, 2 Sep 2021 16:03:46 +0300 Subject: [PATCH] [FIR] Add REPEATABLE_CONTAINER_* diagnostics REPEATABLE_CONTAINER_MUST_HAVE_VALUE_ARRAY REPEATABLE_CONTAINER_HAS_NON_DEFAULT_PARAMETER REPEATABLE_CONTAINER_HAS_SHORTER_RETENTION REPEATABLE_CONTAINER_TARGET_SET_NOT_A_SUBSET REPEATABLE_ANNOTATION_HAS_NESTED_CLASS_NAMED_CONTAINER --- .../diagnostics/FirJvmDiagnosticsList.kt | 23 +++ .../analysis/diagnostics/jvm/FirJvmErrors.kt | 8 + .../FirRepeatableAnnotationChecker.kt | 194 ++++++++++++++++-- .../diagnostics/FirJvmDefaultErrorMessages.kt | 36 ++++ .../analysis/checkers/FirAnnotationHelpers.kt | 35 ++-- .../kotlin/fir/java/JavaSymbolProvider.kt | 2 +- .../repeatable/containerArguments_1_5.fir.kt | 50 ----- .../repeatable/containerArguments_1_5.kt | 1 + .../repeatable/containerArguments_1_6.fir.kt | 50 ----- .../repeatable/containerArguments_1_6.kt | 1 + .../repeatable/containerRetention_1_5.fir.kt | 40 ---- .../repeatable/containerRetention_1_5.kt | 1 + .../repeatable/containerRetention_1_6.fir.kt | 40 ---- .../repeatable/containerRetention_1_6.kt | 1 + .../repeatable/containerTarget_1_6.fir.kt | 53 ----- .../repeatable/containerTarget_1_6.kt | 1 + .../nestedClassContainer_1_5.fir.kt | 21 -- .../repeatable/nestedClassContainer_1_5.kt | 1 + .../nestedClassContainer_1_6.fir.kt | 21 -- .../repeatable/nestedClassContainer_1_6.kt | 1 + .../fir/generator/HLDiagnosticConverter.kt | 2 + .../diagnostics/KtFirDataClassConverters.kt | 86 +++++++- .../api/fir/diagnostics/KtFirDiagnostics.kt | 61 ++++++ .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 91 ++++++++ 24 files changed, 501 insertions(+), 319 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_5.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_6.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_5.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_6.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/annotations/repeatable/containerTarget_1_6.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_5.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_6.fir.kt diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirJvmDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirJvmDiagnosticsList.kt index 9ad230759b8..d4d4eba60e9 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirJvmDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirJvmDiagnosticsList.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.PrivateForInline import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticList import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.PositioningStrategy import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtAnnotationEntry @@ -122,6 +123,28 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") { parameter("name") parameter("explicitContainerName") } + + val REPEATABLE_CONTAINER_MUST_HAVE_VALUE_ARRAY by deprecationError(RepeatableAnnotationContainerConstraints) { + parameter("container") + parameter("annotation") + } + val REPEATABLE_CONTAINER_HAS_NON_DEFAULT_PARAMETER by deprecationError(RepeatableAnnotationContainerConstraints) { + parameter("container") + parameter("nonDefault") + } + val REPEATABLE_CONTAINER_HAS_SHORTER_RETENTION by deprecationError(RepeatableAnnotationContainerConstraints) { + parameter("container") + parameter("retention") + parameter("annotation") + parameter("annotationRetention") + } + val REPEATABLE_CONTAINER_TARGET_SET_NOT_A_SUBSET by deprecationError(RepeatableAnnotationContainerConstraints) { + parameter("container") + parameter("annotation") + } + val REPEATABLE_ANNOTATION_HAS_NESTED_CLASS_NAMED_CONTAINER by deprecationError( + RepeatableAnnotationContainerConstraints + ) } val MISC by object : DiagnosticGroup("Misc") { diff --git a/compiler/fir/checkers/checkers.jvm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrors.kt b/compiler/fir/checkers/checkers.jvm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrors.kt index d02ce39d590..9e28bf08f0a 100644 --- a/compiler/fir/checkers/checkers.jvm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrors.kt +++ b/compiler/fir/checkers/checkers.jvm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrors.kt @@ -8,10 +8,13 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics.jvm import com.intellij.psi.PsiElement import org.jetbrains.kotlin.config.LanguageFeature.DefaultMethodsCallFromJava6TargetError import org.jetbrains.kotlin.config.LanguageFeature.ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses +import org.jetbrains.kotlin.config.LanguageFeature.RepeatableAnnotationContainerConstraints import org.jetbrains.kotlin.fir.analysis.diagnostics.* import org.jetbrains.kotlin.fir.analysis.diagnostics.SourceElementPositioningStrategies import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtAnnotationEntry import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtElement @@ -95,6 +98,11 @@ object FirJvmErrors { val NON_SOURCE_REPEATED_ANNOTATION by error0() val REPEATED_ANNOTATION_TARGET6 by error0() val REPEATED_ANNOTATION_WITH_CONTAINER by error2() + val REPEATABLE_CONTAINER_MUST_HAVE_VALUE_ARRAY by deprecationError2(RepeatableAnnotationContainerConstraints) + val REPEATABLE_CONTAINER_HAS_NON_DEFAULT_PARAMETER by deprecationError2(RepeatableAnnotationContainerConstraints) + val REPEATABLE_CONTAINER_HAS_SHORTER_RETENTION by deprecationError4(RepeatableAnnotationContainerConstraints) + val REPEATABLE_CONTAINER_TARGET_SET_NOT_A_SUBSET by deprecationError2(RepeatableAnnotationContainerConstraints) + val REPEATABLE_ANNOTATION_HAS_NESTED_CLASS_NAMED_CONTAINER by deprecationError0(RepeatableAnnotationContainerConstraints) // Misc val INAPPLICABLE_JVM_FIELD by error1() diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirRepeatableAnnotationChecker.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirRepeatableAnnotationChecker.kt index dab097b3c6f..274ac74c4f3 100644 --- a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirRepeatableAnnotationChecker.kt +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirRepeatableAnnotationChecker.kt @@ -7,34 +7,41 @@ package org.jetbrains.kotlin.fir.analysis.jvm.checkers.declaration import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirAnnotatedDeclarationChecker +import org.jetbrains.kotlin.fir.analysis.checkers.getAllowedAnnotationTargets +import org.jetbrains.kotlin.fir.analysis.checkers.getRetention +import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.analysis.diagnostics.withSuppressedDiagnostics import org.jetbrains.kotlin.fir.analysis.jvm.checkers.isJvm6 import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.expressions.FirClassReferenceExpression -import org.jetbrains.kotlin.fir.expressions.FirGetClassCall -import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier -import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol +import org.jetbrains.kotlin.fir.declarations.utils.classId +import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.java.JavaSymbolProvider import org.jetbrains.kotlin.fir.languageVersionSettings +import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.resolve.fqName import org.jetbrains.kotlin.fir.resolve.symbolProvider +import org.jetbrains.kotlin.fir.scopes.getSingleClassifier import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirEnumEntrySymbol -import org.jetbrains.kotlin.fir.types.ConeClassLikeType -import org.jetbrains.kotlin.fir.types.coneType -import org.jetbrains.kotlin.fir.types.lowerBoundIfFlexible +import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol +import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.load.java.JvmAbi +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name object FirRepeatableAnnotationChecker : FirAnnotatedDeclarationChecker() { - private val RETENTION_PARAMETER_NAME = Name.identifier("value") private val REPEATABLE_PARAMETER_NAME = Name.identifier("value") - private val JAVA_REPEATABLE_ANNOTATION = FqName("java.lang.annotation.Repeatable") + private val JAVA_REPEATABLE_ANNOTATION = ClassId.fromString("java/lang/annotation/Repeatable") + private val REPEATABLE_ANNOTATION_CONTAINER_NAME = Name.identifier(JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME) override fun check(declaration: FirAnnotatedDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { val annotationsSet = hashSetOf() @@ -75,6 +82,154 @@ object FirRepeatableAnnotationChecker : FirAnnotatedDeclarationChecker() { annotationsSet.add(fqName) } + + if (declaration is FirRegularClass) { + val javaRepeatable = annotations.find { it.fqName(session) == JAVA_REPEATABLE_ANNOTATION } + if (javaRepeatable != null) { + checkJavaRepeatableAnnotationDeclaration(javaRepeatable, declaration, context, reporter) + } else { + val kotlinRepeatable = annotations.find { it.fqName(session) == StandardNames.FqNames.repeatable } + if (kotlinRepeatable != null) { + checkKotlinRepeatableAnnotationDeclaration(kotlinRepeatable, declaration, context, reporter) + } + } + } + } + + private fun checkJavaRepeatableAnnotationDeclaration( + javaRepeatable: FirAnnotationCall, + annotationClass: FirRegularClass, + context: CheckerContext, + reporter: DiagnosticReporter + ) { + val containerClassId = javaRepeatable.resolveContainerAnnotation() ?: return + val containerClassSymbol = context.session.symbolProvider.getClassLikeSymbolByClassId(containerClassId) as? FirRegularClassSymbol ?: return + + checkRepeatableAnnotationContainer(annotationClass, containerClassSymbol, javaRepeatable.source, context, reporter) + } + + private fun checkKotlinRepeatableAnnotationDeclaration( + kotlinRepeatable: FirAnnotationCall, + declaration: FirRegularClass, + context: CheckerContext, + reporter: DiagnosticReporter + ) { + val unsubsitutedScope = declaration.unsubstitutedScope(context) + if (unsubsitutedScope.getSingleClassifier(REPEATABLE_ANNOTATION_CONTAINER_NAME) != null) { + reporter.reportOn(kotlinRepeatable.source, FirJvmErrors.REPEATABLE_ANNOTATION_HAS_NESTED_CLASS_NAMED_CONTAINER, context) + } + } + + private fun checkRepeatableAnnotationContainer( + annotationClass: FirRegularClass, + containerClass: FirRegularClassSymbol, + annotationSource: FirSourceElement?, + context: CheckerContext, + reporter: DiagnosticReporter + ) { + checkContainerParameters(containerClass, annotationClass, annotationSource, context, reporter) + checkContainerRetention(containerClass, annotationClass, annotationSource, context, reporter) + checkContainerTarget(containerClass, annotationClass, annotationSource, context, reporter) + } + + private fun checkContainerParameters( + containerClass: FirRegularClassSymbol, + annotationClass: FirRegularClass, + annotationSource: FirSourceElement?, + context: CheckerContext, + reporter: DiagnosticReporter + ) { + val containerCtor = + containerClass.declarationSymbols.find { it is FirConstructorSymbol && it.isPrimary } as? FirConstructorSymbol + ?: return + + val valueParameterSymbols = containerCtor.valueParameterSymbols + val parameterName = JavaSymbolProvider.VALUE_METHOD_NAME + val value = valueParameterSymbols.find { it.name == parameterName } + if (value == null || !value.resolvedReturnTypeRef.isArrayType || + value.resolvedReturnTypeRef.type.typeArguments.single().type != annotationClass.defaultType() + ) { + reporter.reportOn( + annotationSource, + FirJvmErrors.REPEATABLE_CONTAINER_MUST_HAVE_VALUE_ARRAY, + containerClass.classId, + annotationClass.classId, + context + ) + return + } + + val otherNonDefault = valueParameterSymbols.find { it.name != parameterName && !it.hasDefaultValue } + if (otherNonDefault != null) { + reporter.reportOn( + annotationSource, + FirJvmErrors.REPEATABLE_CONTAINER_HAS_NON_DEFAULT_PARAMETER, + containerClass.classId, + otherNonDefault.name, + context + ) + return + } + } + + private fun checkContainerRetention( + containerClass: FirRegularClassSymbol, + annotationClass: FirRegularClass, + annotationSource: FirSourceElement?, + context: CheckerContext, + reporter: DiagnosticReporter + ) { + val annotationRetention = annotationClass.symbol.getAnnotationRetention() + val containerRetention = containerClass.getAnnotationRetention() + if (containerRetention < annotationRetention) { + reporter.reportOn( + annotationSource, + FirJvmErrors.REPEATABLE_CONTAINER_HAS_SHORTER_RETENTION, + containerClass.classId, + containerRetention.name, + annotationClass.classId, + annotationRetention.name, + context + ) + } + } + + private fun checkContainerTarget( + containerClass: FirRegularClassSymbol, + annotationClass: FirRegularClass, + annotationSource: FirSourceElement?, + context: CheckerContext, + reporter: DiagnosticReporter + ) { + val annotationTargets = annotationClass.getAllowedAnnotationTargets() + val containerTargets = containerClass.getAllowedAnnotationTargets() + + // See https://docs.oracle.com/javase/specs/jls/se16/html/jls-9.html#jls-9.6.3. + // (TBH, the rules about TYPE/TYPE_USE and TYPE_PARAMETER/TYPE_USE don't seem to make a lot of sense, but it's JLS + // so we better obey it for full interop with the Java language and reflection.) + for (target in containerTargets) { + val ok = when (target) { + in annotationTargets -> true + KotlinTarget.ANNOTATION_CLASS -> + KotlinTarget.CLASS in annotationTargets || + KotlinTarget.TYPE in annotationTargets + KotlinTarget.CLASS -> + KotlinTarget.TYPE in annotationTargets + KotlinTarget.TYPE_PARAMETER -> + KotlinTarget.TYPE in annotationTargets + else -> false + } + if (!ok) { + reporter.reportOn( + annotationSource, + FirJvmErrors.REPEATABLE_CONTAINER_TARGET_SET_NOT_A_SUBSET, + containerClass.classId, + annotationClass.classId, + context + ) + return + } + } } private fun FirClassLikeSymbol<*>.isRepeatableAnnotation(session: FirSession): Boolean { @@ -85,25 +240,24 @@ object FirRepeatableAnnotationChecker : FirAnnotatedDeclarationChecker() { getAnnotationRetention() == AnnotationRetention.SOURCE } - private fun FirClassLikeSymbol<*>.getAnnotationRetention(): AnnotationRetention? { - val repeatableAnnotation = getAnnotationByFqName(StandardNames.FqNames.retention) ?: return null - val retentionValue = repeatableAnnotation.findArgumentByName(RETENTION_PARAMETER_NAME) ?: return null - val resolvedSymbol = retentionValue.toResolvedCallableSymbol() as? FirEnumEntrySymbol ?: return null - val name = resolvedSymbol.name.asString() - - return AnnotationRetention.values().firstOrNull { it.name == name } + private fun FirClassLikeSymbol<*>.getAnnotationRetention(): AnnotationRetention { + return getAnnotationByFqName(StandardNames.FqNames.retention)?.getRetention() ?: AnnotationRetention.RUNTIME } private fun FirClassLikeSymbol<*>.resolveContainerAnnotation(): FqName? { val repeatableAnnotation = getAnnotationByFqName(StandardNames.FqNames.repeatable) ?: getAnnotationByFqName(JAVA_REPEATABLE_ANNOTATION) ?: return null - val value = repeatableAnnotation.findArgumentByName(REPEATABLE_PARAMETER_NAME) ?: return null + return repeatableAnnotation.resolveContainerAnnotation()?.asSingleFqName() + } + + private fun FirAnnotationCall.resolveContainerAnnotation(): ClassId? { + val value = findArgumentByName(REPEATABLE_PARAMETER_NAME) ?: return null val classCallArgument = (value as? FirGetClassCall)?.argument ?: return null if (classCallArgument is FirResolvedQualifier) { - return classCallArgument.relativeClassFqName + return classCallArgument.classId } else if (classCallArgument is FirClassReferenceExpression) { val type = classCallArgument.classTypeRef.coneType.lowerBoundIfFlexible() as? ConeClassLikeType ?: return null - return type.lookupTag.classId.asSingleFqName() + return type.lookupTag.classId } return null } diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/diagnostics/FirJvmDefaultErrorMessages.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/diagnostics/FirJvmDefaultErrorMessages.kt index 146252a2773..b2f9467a2fe 100644 --- a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/diagnostics/FirJvmDefaultErrorMessages.kt +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/diagnostics/FirJvmDefaultErrorMessages.kt @@ -59,6 +59,11 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_PRIVATE import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERRIDE_CANNOT_BE_STATIC +import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.REPEATABLE_ANNOTATION_HAS_NESTED_CLASS_NAMED_CONTAINER +import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.REPEATABLE_CONTAINER_HAS_NON_DEFAULT_PARAMETER +import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.REPEATABLE_CONTAINER_HAS_SHORTER_RETENTION +import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.REPEATABLE_CONTAINER_MUST_HAVE_VALUE_ARRAY +import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.REPEATABLE_CONTAINER_TARGET_SET_NOT_A_SUBSET import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.REPEATED_ANNOTATION_TARGET6 import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.REPEATED_ANNOTATION_WITH_CONTAINER import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.STRICTFP_ON_CLASS @@ -219,6 +224,37 @@ object FirJvmDefaultErrorMessages { INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER, "Interfaces can call default methods via super only within @JvmDefault members. Please annotate the containing interface member with @JvmDefault" ) + + map.put( + REPEATABLE_CONTAINER_MUST_HAVE_VALUE_ARRAY, + "Container annotation ''{0}'' must have a property ''value'' of type ''Array<{1}>''.", + TO_STRING, + TO_STRING + ) + map.put( + REPEATABLE_CONTAINER_HAS_NON_DEFAULT_PARAMETER, + "Container annotation ''{0}'' does not have a default value for ''{1}''.", + TO_STRING, + TO_STRING + ) + map.put( + REPEATABLE_CONTAINER_HAS_SHORTER_RETENTION, + "Container annotation ''{0}'' has shorter retention (''{1}'') than the repeatable annotation ''{2}'' (''{3}'').", + TO_STRING, + TO_STRING, + TO_STRING, + TO_STRING + ) + map.put( + REPEATABLE_CONTAINER_TARGET_SET_NOT_A_SUBSET, + "Target set of container annotation ''{0}'' must be a subset of the target set of contained annotation ''{1}''.", + TO_STRING, + TO_STRING + ) + map.put( + REPEATABLE_ANNOTATION_HAS_NESTED_CLASS_NAMED_CONTAINER, + "Repeatable annotation cannot have a nested class named 'Container'. This name is reserved for auto-generated container class" + ) } } } \ No newline at end of file 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 93bf9c4a28b..650c4853bba 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 @@ -9,17 +9,13 @@ import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.fir.FirAnnotationContainer import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirAnnotatedDeclaration -import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import org.jetbrains.kotlin.fir.declarations.findArgumentByName -import org.jetbrains.kotlin.fir.declarations.getAnnotationByFqName -import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.toSymbol -import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.ensureResolved +import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.FirErrorTypeRef @@ -30,19 +26,12 @@ import org.jetbrains.kotlin.name.Name private val RETENTION_PARAMETER_NAME = Name.identifier("value") private val TARGET_PARAMETER_NAME = Name.identifier("allowedTargets") -@OptIn(SymbolInternals::class) -fun FirAnnotationCall.getRetention(session: FirSession): AnnotationRetention { - val annotationClassSymbol = - (this.annotationTypeRef.coneType as? ConeClassLikeType)?.lookupTag?.toSymbol(session) as? FirRegularClassSymbol - ?: return AnnotationRetention.RUNTIME - annotationClassSymbol.ensureResolved(FirResolvePhase.BODY_RESOLVE) - val annotationClass = annotationClassSymbol.fir - return annotationClass.getRetention() +fun FirRegularClass.getRetention(): AnnotationRetention { + return getRetentionAnnotation()?.getRetention() ?: AnnotationRetention.RUNTIME } -fun FirRegularClass.getRetention(): AnnotationRetention { - val retentionAnnotation = getRetentionAnnotation() ?: return AnnotationRetention.RUNTIME - val retentionArgument = retentionAnnotation.findArgumentByName(RETENTION_PARAMETER_NAME) as? FirQualifiedAccessExpression +fun FirAnnotationCall.getRetention(): AnnotationRetention { + val retentionArgument = findArgumentByName(RETENTION_PARAMETER_NAME) as? FirQualifiedAccessExpression ?: return AnnotationRetention.RUNTIME val retentionName = (retentionArgument.calleeReference as? FirResolvedNamedReference)?.name?.asString() ?: return AnnotationRetention.RUNTIME @@ -51,17 +40,19 @@ fun FirRegularClass.getRetention(): AnnotationRetention { private val defaultAnnotationTargets = KotlinTarget.DEFAULT_TARGET_SET -@OptIn(SymbolInternals::class) fun FirAnnotationCall.getAllowedAnnotationTargets(session: FirSession): Set { if (annotationTypeRef is FirErrorTypeRef) return KotlinTarget.values().toSet() val annotationClassSymbol = (this.annotationTypeRef.coneType as? ConeClassLikeType) ?.fullyExpandedType(session)?.lookupTag?.toSymbol(session) ?: return defaultAnnotationTargets annotationClassSymbol.ensureResolved(FirResolvePhase.BODY_RESOLVE) - val annotationClass = annotationClassSymbol.fir as? FirRegularClass - return annotationClass?.getAllowedAnnotationTargets() ?: defaultAnnotationTargets + return annotationClassSymbol.getAllowedAnnotationTargets() } fun FirRegularClass.getAllowedAnnotationTargets(): Set { + return symbol.getAllowedAnnotationTargets() +} + +fun FirClassLikeSymbol<*>.getAllowedAnnotationTargets(): Set { val targetAnnotation = getTargetAnnotation() ?: return defaultAnnotationTargets if (targetAnnotation.argumentList.arguments.isEmpty()) return emptySet() val arguments = targetAnnotation.findArgumentByName(TARGET_PARAMETER_NAME)?.unfoldArrayOrVararg().orEmpty() @@ -81,6 +72,10 @@ fun FirAnnotatedDeclaration.getTargetAnnotation(): FirAnnotationCall? { return getAnnotationByFqName(StandardNames.FqNames.target) } +fun FirClassLikeSymbol<*>.getTargetAnnotation(): FirAnnotationCall? { + return getAnnotationByFqName(StandardNames.FqNames.target) +} + fun FirAnnotationContainer.getAnnotationByClassId(classId: ClassId): FirAnnotationCall? { return annotations.find { (it.annotationTypeRef.coneType as? ConeClassLikeType)?.lookupTag?.classId == classId diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt index 61061220c16..32b93208920 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt @@ -59,7 +59,7 @@ class JavaSymbolProvider( private val searchScope: GlobalSearchScope, ) : FirSymbolProvider(session) { companion object { - internal val VALUE_METHOD_NAME = Name.identifier("value") + val VALUE_METHOD_NAME = Name.identifier("value") } private val classCache = diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_5.fir.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_5.fir.kt deleted file mode 100644 index db6844ff75b..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_5.fir.kt +++ /dev/null @@ -1,50 +0,0 @@ -// !LANGUAGE: -RepeatableAnnotations -RepeatableAnnotationContainerConstraints -// FULL_JDK - -import java.lang.annotation.Repeatable as R - -@R(C1::class) -annotation class A1 -annotation class C1 - -@R(C2::class) -annotation class A2 -annotation class C2(val value: A2) - -@R(C3::class) -annotation class A3 -annotation class C3(val value: Array) - -@R(C4::class) -annotation class A4 -annotation class C4(val notValue: Array) - -@R(C5::class) -annotation class A5 -annotation class C5(val value: Array, val irrelevant: String) - -@R(C6::class) -annotation class A6 -annotation class C6(val irrelevant: Double, val value: Array = []) - -// Should be an error after fixing KT-47932. -@R(A7::class) -annotation class A7(val value: Array) - - - -@R(D1::class) -annotation class B1 -annotation class D1(val value: Array) - -@R(D2::class) -annotation class B2 -annotation class D2(val value: Array = []) - -@R(D3::class) -annotation class B3 -annotation class D3(val value: Array, val other1: String = "", val other2: Int = 42) - -@R(D4::class) -annotation class B4 -annotation class D4(val value1: Array = [], val value: Array) diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_5.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_5.kt index 9ef38567382..e356520f29f 100644 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_5.kt +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_5.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: -RepeatableAnnotations -RepeatableAnnotationContainerConstraints // FULL_JDK diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_6.fir.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_6.fir.kt deleted file mode 100644 index a45006f4e49..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_6.fir.kt +++ /dev/null @@ -1,50 +0,0 @@ -// !LANGUAGE: +RepeatableAnnotations +RepeatableAnnotationContainerConstraints -// FULL_JDK - -import java.lang.annotation.Repeatable as R - -@R(C1::class) -annotation class A1 -annotation class C1 - -@R(C2::class) -annotation class A2 -annotation class C2(val value: A2) - -@R(C3::class) -annotation class A3 -annotation class C3(val value: Array) - -@R(C4::class) -annotation class A4 -annotation class C4(val notValue: Array) - -@R(C5::class) -annotation class A5 -annotation class C5(val value: Array, val irrelevant: String) - -@R(C6::class) -annotation class A6 -annotation class C6(val irrelevant: Double, val value: Array = []) - -// Should be an error after fixing KT-47932. -@R(A7::class) -annotation class A7(val value: Array) - - - -@R(D1::class) -annotation class B1 -annotation class D1(val value: Array) - -@R(D2::class) -annotation class B2 -annotation class D2(val value: Array = []) - -@R(D3::class) -annotation class B3 -annotation class D3(val value: Array, val other1: String = "", val other2: Int = 42) - -@R(D4::class) -annotation class B4 -annotation class D4(val value1: Array = [], val value: Array) diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_6.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_6.kt index 9f342eb5267..1d6c96178ca 100644 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_6.kt +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/containerArguments_1_6.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +RepeatableAnnotations +RepeatableAnnotationContainerConstraints // FULL_JDK diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_5.fir.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_5.fir.kt deleted file mode 100644 index 303659f3f5b..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_5.fir.kt +++ /dev/null @@ -1,40 +0,0 @@ -// !LANGUAGE: -RepeatableAnnotations -RepeatableAnnotationContainerConstraints -// FULL_JDK - -import java.lang.annotation.Repeatable as R -import kotlin.annotation.AnnotationRetention.* - -@R(C1::class) -@Retention(RUNTIME) -annotation class A1 -@Retention(BINARY) -annotation class C1(val value: Array) - -@R(C2::class) -@Retention(BINARY) -annotation class A2 -@Retention(SOURCE) -annotation class C2(val value: Array) - -@R(C3::class) -annotation class A3 -@Retention(SOURCE) -annotation class C3(val value: Array) - - - -@R(D1::class) -annotation class B1 -@Retention(RUNTIME) -annotation class D1(val value: Array) - -@R(D2::class) -@Retention(SOURCE) -annotation class B2 -@Retention(BINARY) -annotation class D2(val value: Array) - -@R(D3::class) -@Retention(BINARY) -annotation class B3 -annotation class D3(val value: Array) diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_5.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_5.kt index 079f6563014..94156d6396d 100644 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_5.kt +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_5.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: -RepeatableAnnotations -RepeatableAnnotationContainerConstraints // FULL_JDK diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_6.fir.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_6.fir.kt deleted file mode 100644 index 6111d2eb0c6..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_6.fir.kt +++ /dev/null @@ -1,40 +0,0 @@ -// !LANGUAGE: +RepeatableAnnotations +RepeatableAnnotationContainerConstraints -// FULL_JDK - -import java.lang.annotation.Repeatable as R -import kotlin.annotation.AnnotationRetention.* - -@R(C1::class) -@Retention(RUNTIME) -annotation class A1 -@Retention(BINARY) -annotation class C1(val value: Array) - -@R(C2::class) -@Retention(BINARY) -annotation class A2 -@Retention(SOURCE) -annotation class C2(val value: Array) - -@R(C3::class) -annotation class A3 -@Retention(SOURCE) -annotation class C3(val value: Array) - - - -@R(D1::class) -annotation class B1 -@Retention(RUNTIME) -annotation class D1(val value: Array) - -@R(D2::class) -@Retention(SOURCE) -annotation class B2 -@Retention(BINARY) -annotation class D2(val value: Array) - -@R(D3::class) -@Retention(BINARY) -annotation class B3 -annotation class D3(val value: Array) diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_6.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_6.kt index 1b05aa9a640..b108e2d35ba 100644 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_6.kt +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/containerRetention_1_6.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +RepeatableAnnotations +RepeatableAnnotationContainerConstraints // FULL_JDK diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/containerTarget_1_6.fir.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/containerTarget_1_6.fir.kt deleted file mode 100644 index 7f5c118db9a..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/containerTarget_1_6.fir.kt +++ /dev/null @@ -1,53 +0,0 @@ -// !LANGUAGE: +RepeatableAnnotations +RepeatableAnnotationContainerConstraints -// FULL_JDK - -import java.lang.annotation.Repeatable as R -import kotlin.annotation.AnnotationTarget.* - -@R(C1::class) -annotation class A1 -@Target(FILE) -annotation class C1(val value: Array) - -@R(C2::class) -@Target(CLASS) -annotation class A2 -@Target(CLASS, FUNCTION) -annotation class C2(val value: Array) - -@R(C3::class) -@Target(TYPE) -annotation class A3 -annotation class C3(val value: Array) - -@R(C4::class) -@Target(ANNOTATION_CLASS) -annotation class A4 -@Target(CLASS) -annotation class C4(val value: Array) - - - - -@R(D1::class) -annotation class B1 -@Target(CLASS, ANNOTATION_CLASS, PROPERTY, FIELD, LOCAL_VARIABLE, VALUE_PARAMETER, CONSTRUCTOR, FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER) // Default target set -annotation class D1(val value: Array) - -@R(D2::class) -@Target(CLASS, FILE) -annotation class B2 -@Target(CLASS) -annotation class D2(val value: Array) - -@R(D3::class) -@Target(CLASS) -annotation class B3 -@Target(ANNOTATION_CLASS) -annotation class D3(val value: Array) - -@R(D4::class) -@Target(TYPE) -annotation class B4 -@Target(ANNOTATION_CLASS, CLASS, TYPE_PARAMETER) -annotation class D4(val value: Array) \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/containerTarget_1_6.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/containerTarget_1_6.kt index 658155fc41d..a8a0381fc1a 100644 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/containerTarget_1_6.kt +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/containerTarget_1_6.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +RepeatableAnnotations +RepeatableAnnotationContainerConstraints // FULL_JDK diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_5.fir.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_5.fir.kt deleted file mode 100644 index 77d90f161a4..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_5.fir.kt +++ /dev/null @@ -1,21 +0,0 @@ -// !LANGUAGE: -RepeatableAnnotations -RepeatableAnnotationContainerConstraints -// FULL_JDK - -@Repeatable -annotation class A1 { - class Container -} - - -@java.lang.annotation.Repeatable(D1::class) -annotation class B1 { - class Container -} -annotation class D1(val value: Array) - -@Repeatable -@java.lang.annotation.Repeatable(D2::class) -annotation class B2 { - class Container -} -annotation class D2(val value: Array) diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_5.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_5.kt index 5da4525c51a..cbbe9d23344 100644 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_5.kt +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_5.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: -RepeatableAnnotations -RepeatableAnnotationContainerConstraints // FULL_JDK diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_6.fir.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_6.fir.kt deleted file mode 100644 index c7c21af8fa6..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_6.fir.kt +++ /dev/null @@ -1,21 +0,0 @@ -// !LANGUAGE: +RepeatableAnnotations +RepeatableAnnotationContainerConstraints -// FULL_JDK - -@Repeatable -annotation class A1 { - class Container -} - - -@java.lang.annotation.Repeatable(D1::class) -annotation class B1 { - class Container -} -annotation class D1(val value: Array) - -@Repeatable -@java.lang.annotation.Repeatable(D2::class) -annotation class B2 { - class Container -} -annotation class D2(val value: Array) diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_6.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_6.kt index 09b1221c190..c2b5217774a 100644 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_6.kt +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_6.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +RepeatableAnnotations +RepeatableAnnotationContainerConstraints // FULL_JDK diff --git a/idea/idea-frontend-fir/idea-frontend-fir-generator/src/org/jetbrains/kotlin/idea/frontend/api/fir/generator/HLDiagnosticConverter.kt b/idea/idea-frontend-fir/idea-frontend-fir-generator/src/org/jetbrains/kotlin/idea/frontend/api/fir/generator/HLDiagnosticConverter.kt index 39be11d6f36..edd8c7fff8b 100644 --- a/idea/idea-frontend-fir/idea-frontend-fir-generator/src/org/jetbrains/kotlin/idea/frontend/api/fir/generator/HLDiagnosticConverter.kt +++ b/idea/idea-frontend-fir/idea-frontend-fir-generator/src/org/jetbrains/kotlin/idea/frontend/api/fir/generator/HLDiagnosticConverter.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.* import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.lexer.KtKeywordToken import org.jetbrains.kotlin.lexer.KtModifierKeywordToken +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtExpression @@ -335,6 +336,7 @@ private object FirToKtConversionCreator { LanguageVersionSettings::class, Variance::class, FqName::class, + ClassId::class, FirModuleData::class, ExpectActualCompatibility.Incompatible::class, DeprecationInfo::class, diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt index 9fa99d1197c..40ea8718190 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -2526,7 +2526,7 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert firDiagnostic.b, firDiagnostic.c.mapKeys { (incompatible, _) -> incompatible - }.mapValues { (_, collection) -> + }.mapValues { (_, collection) -> collection.map { firBasedSymbol -> firSymbolBuilder.buildSymbol(firBasedSymbol.fir) } @@ -2540,7 +2540,7 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert firSymbolBuilder.buildSymbol(firDiagnostic.a.fir), firDiagnostic.b.mapKeys { (incompatible, _) -> incompatible - }.mapValues { (_, collection) -> + }.mapValues { (_, collection) -> collection.map { firBasedSymbol -> firSymbolBuilder.buildSymbol(firBasedSymbol.fir) } @@ -2575,7 +2575,7 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert firDiagnostic.b.map { pair -> firSymbolBuilder.buildSymbol(pair.first.fir) to pair.second.mapKeys { (incompatible, _) -> incompatible - }.mapValues { (_, collection) -> + }.mapValues { (_, collection) -> collection.map { firBasedSymbol -> firSymbolBuilder.buildSymbol(firBasedSymbol.fir) } @@ -3806,6 +3806,86 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirJvmErrors.REPEATABLE_CONTAINER_MUST_HAVE_VALUE_ARRAY.errorFactory) { firDiagnostic -> + RepeatableContainerMustHaveValueArrayErrorImpl( + firDiagnostic.a, + firDiagnostic.b, + firDiagnostic as FirPsiDiagnostic, + token, + ) + } + add(FirJvmErrors.REPEATABLE_CONTAINER_MUST_HAVE_VALUE_ARRAY.warningFactory) { firDiagnostic -> + RepeatableContainerMustHaveValueArrayWarningImpl( + firDiagnostic.a, + firDiagnostic.b, + firDiagnostic as FirPsiDiagnostic, + token, + ) + } + add(FirJvmErrors.REPEATABLE_CONTAINER_HAS_NON_DEFAULT_PARAMETER.errorFactory) { firDiagnostic -> + RepeatableContainerHasNonDefaultParameterErrorImpl( + firDiagnostic.a, + firDiagnostic.b, + firDiagnostic as FirPsiDiagnostic, + token, + ) + } + add(FirJvmErrors.REPEATABLE_CONTAINER_HAS_NON_DEFAULT_PARAMETER.warningFactory) { firDiagnostic -> + RepeatableContainerHasNonDefaultParameterWarningImpl( + firDiagnostic.a, + firDiagnostic.b, + firDiagnostic as FirPsiDiagnostic, + token, + ) + } + add(FirJvmErrors.REPEATABLE_CONTAINER_HAS_SHORTER_RETENTION.errorFactory) { firDiagnostic -> + RepeatableContainerHasShorterRetentionErrorImpl( + firDiagnostic.a, + firDiagnostic.b, + firDiagnostic.c, + firDiagnostic.d, + firDiagnostic as FirPsiDiagnostic, + token, + ) + } + add(FirJvmErrors.REPEATABLE_CONTAINER_HAS_SHORTER_RETENTION.warningFactory) { firDiagnostic -> + RepeatableContainerHasShorterRetentionWarningImpl( + firDiagnostic.a, + firDiagnostic.b, + firDiagnostic.c, + firDiagnostic.d, + firDiagnostic as FirPsiDiagnostic, + token, + ) + } + add(FirJvmErrors.REPEATABLE_CONTAINER_TARGET_SET_NOT_A_SUBSET.errorFactory) { firDiagnostic -> + RepeatableContainerTargetSetNotASubsetErrorImpl( + firDiagnostic.a, + firDiagnostic.b, + firDiagnostic as FirPsiDiagnostic, + token, + ) + } + add(FirJvmErrors.REPEATABLE_CONTAINER_TARGET_SET_NOT_A_SUBSET.warningFactory) { firDiagnostic -> + RepeatableContainerTargetSetNotASubsetWarningImpl( + firDiagnostic.a, + firDiagnostic.b, + firDiagnostic as FirPsiDiagnostic, + token, + ) + } + add(FirJvmErrors.REPEATABLE_ANNOTATION_HAS_NESTED_CLASS_NAMED_CONTAINER.errorFactory) { firDiagnostic -> + RepeatableAnnotationHasNestedClassNamedContainerErrorImpl( + firDiagnostic as FirPsiDiagnostic, + token, + ) + } + add(FirJvmErrors.REPEATABLE_ANNOTATION_HAS_NESTED_CLASS_NAMED_CONTAINER.warningFactory) { firDiagnostic -> + RepeatableAnnotationHasNestedClassNamedContainerWarningImpl( + firDiagnostic as FirPsiDiagnostic, + token, + ) + } add(FirJvmErrors.INAPPLICABLE_JVM_FIELD) { firDiagnostic -> InapplicableJvmFieldImpl( firDiagnostic.a, diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt index 1d5b1708d33..02bd0bf2e4b 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableSymbol import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.lexer.KtKeywordToken import org.jetbrains.kotlin.lexer.KtModifierKeywordToken +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtAnnotationEntry @@ -2646,6 +2647,66 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val explicitContainerName: FqName } + abstract class RepeatableContainerMustHaveValueArrayError : KtFirDiagnostic() { + override val diagnosticClass get() = RepeatableContainerMustHaveValueArrayError::class + abstract val container: ClassId + abstract val annotation: ClassId + } + + abstract class RepeatableContainerMustHaveValueArrayWarning : KtFirDiagnostic() { + override val diagnosticClass get() = RepeatableContainerMustHaveValueArrayWarning::class + abstract val container: ClassId + abstract val annotation: ClassId + } + + abstract class RepeatableContainerHasNonDefaultParameterError : KtFirDiagnostic() { + override val diagnosticClass get() = RepeatableContainerHasNonDefaultParameterError::class + abstract val container: ClassId + abstract val nonDefault: Name + } + + abstract class RepeatableContainerHasNonDefaultParameterWarning : KtFirDiagnostic() { + override val diagnosticClass get() = RepeatableContainerHasNonDefaultParameterWarning::class + abstract val container: ClassId + abstract val nonDefault: Name + } + + abstract class RepeatableContainerHasShorterRetentionError : KtFirDiagnostic() { + override val diagnosticClass get() = RepeatableContainerHasShorterRetentionError::class + abstract val container: ClassId + abstract val retention: String + abstract val annotation: ClassId + abstract val annotationRetention: String + } + + abstract class RepeatableContainerHasShorterRetentionWarning : KtFirDiagnostic() { + override val diagnosticClass get() = RepeatableContainerHasShorterRetentionWarning::class + abstract val container: ClassId + abstract val retention: String + abstract val annotation: ClassId + abstract val annotationRetention: String + } + + abstract class RepeatableContainerTargetSetNotASubsetError : KtFirDiagnostic() { + override val diagnosticClass get() = RepeatableContainerTargetSetNotASubsetError::class + abstract val container: ClassId + abstract val annotation: ClassId + } + + abstract class RepeatableContainerTargetSetNotASubsetWarning : KtFirDiagnostic() { + override val diagnosticClass get() = RepeatableContainerTargetSetNotASubsetWarning::class + abstract val container: ClassId + abstract val annotation: ClassId + } + + abstract class RepeatableAnnotationHasNestedClassNamedContainerError : KtFirDiagnostic() { + override val diagnosticClass get() = RepeatableAnnotationHasNestedClassNamedContainerError::class + } + + abstract class RepeatableAnnotationHasNestedClassNamedContainerWarning : KtFirDiagnostic() { + override val diagnosticClass get() = RepeatableAnnotationHasNestedClassNamedContainerWarning::class + } + abstract class InapplicableJvmField : KtFirDiagnostic() { override val diagnosticClass get() = InapplicableJvmField::class abstract val message: String diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index bfbdabce7fa..c22c0572635 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.lexer.KtKeywordToken import org.jetbrains.kotlin.lexer.KtModifierKeywordToken +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtAnnotationEntry @@ -4303,6 +4304,96 @@ internal class RepeatedAnnotationWithContainerImpl( override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) } +internal class RepeatableContainerMustHaveValueArrayErrorImpl( + override val container: ClassId, + override val annotation: ClassId, + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.RepeatableContainerMustHaveValueArrayError(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + +internal class RepeatableContainerMustHaveValueArrayWarningImpl( + override val container: ClassId, + override val annotation: ClassId, + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.RepeatableContainerMustHaveValueArrayWarning(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + +internal class RepeatableContainerHasNonDefaultParameterErrorImpl( + override val container: ClassId, + override val nonDefault: Name, + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.RepeatableContainerHasNonDefaultParameterError(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + +internal class RepeatableContainerHasNonDefaultParameterWarningImpl( + override val container: ClassId, + override val nonDefault: Name, + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.RepeatableContainerHasNonDefaultParameterWarning(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + +internal class RepeatableContainerHasShorterRetentionErrorImpl( + override val container: ClassId, + override val retention: String, + override val annotation: ClassId, + override val annotationRetention: String, + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.RepeatableContainerHasShorterRetentionError(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + +internal class RepeatableContainerHasShorterRetentionWarningImpl( + override val container: ClassId, + override val retention: String, + override val annotation: ClassId, + override val annotationRetention: String, + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.RepeatableContainerHasShorterRetentionWarning(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + +internal class RepeatableContainerTargetSetNotASubsetErrorImpl( + override val container: ClassId, + override val annotation: ClassId, + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.RepeatableContainerTargetSetNotASubsetError(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + +internal class RepeatableContainerTargetSetNotASubsetWarningImpl( + override val container: ClassId, + override val annotation: ClassId, + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.RepeatableContainerTargetSetNotASubsetWarning(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + +internal class RepeatableAnnotationHasNestedClassNamedContainerErrorImpl( + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.RepeatableAnnotationHasNestedClassNamedContainerError(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + +internal class RepeatableAnnotationHasNestedClassNamedContainerWarningImpl( + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.RepeatableAnnotationHasNestedClassNamedContainerWarning(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + internal class InapplicableJvmFieldImpl( override val message: String, firDiagnostic: FirPsiDiagnostic,