From 085df96afeb8ea5ed9e21f3fd9b94623dc502af6 Mon Sep 17 00:00:00 2001 From: Kirill Rakhman Date: Mon, 3 Apr 2023 17:58:23 +0200 Subject: [PATCH] [FIR] Make Volatile diagnostics applicable to kotlin.concurrent.Volatile #KT-55628 Fixed --- .../diagnostics/KtFirDataClassConverters.kt | 24 +++---- .../api/fir/diagnostics/KtFirDiagnostics.kt | 16 ++--- .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 20 +++--- .../diagnostics/FirDiagnosticsList.kt | 3 + .../diagnostics/FirJvmDiagnosticsList.kt | 2 - .../analysis/diagnostics/jvm/FirJvmErrors.kt | 2 - .../jvm/FirJvmErrorsDefaultMessages.kt | 7 +-- .../jvm/checkers/JvmDeclarationCheckers.kt | 1 - .../FirVolatileAnnotationChecker.kt | 33 ---------- .../fir/analysis/diagnostics/FirErrors.kt | 2 + .../checkers/CommonDeclarationCheckers.kt | 1 + .../FirVolatileAnnotationChecker.kt | 39 ++++++++++++ .../diagnostics/FirErrorsDefaultMessages.kt | 4 ++ .../fir/declarations/FirAnnotationUtils.kt | 6 ++ .../annotations/Volatile.fir.kt | 63 ------------------- .../testsWithStdLib/annotations/Volatile.kt | 9 +-- .../testsWithStdLib/annotations/Volatile.txt | 12 ---- .../jetbrains/kotlin/name/StandardClassIds.kt | 5 ++ 18 files changed, 96 insertions(+), 153 deletions(-) delete mode 100644 compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirVolatileAnnotationChecker.kt create mode 100644 compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirVolatileAnnotationChecker.kt delete mode 100644 compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.fir.kt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index ae2b0feda3e..de2453d0b08 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -1023,6 +1023,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.VOLATILE_ON_VALUE) { firDiagnostic -> + VolatileOnValueImpl( + firDiagnostic as KtPsiDiagnostic, + token, + ) + } + add(FirErrors.VOLATILE_ON_DELEGATE) { firDiagnostic -> + VolatileOnDelegateImpl( + firDiagnostic as KtPsiDiagnostic, + token, + ) + } add(FirJsErrors.WRONG_JS_QUALIFIER) { firDiagnostic -> WrongJsQualifierImpl( firDiagnostic as KtPsiDiagnostic, @@ -4400,18 +4412,6 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } - add(FirJvmErrors.VOLATILE_ON_VALUE) { firDiagnostic -> - VolatileOnValueImpl( - firDiagnostic as KtPsiDiagnostic, - token, - ) - } - add(FirJvmErrors.VOLATILE_ON_DELEGATE) { firDiagnostic -> - VolatileOnDelegateImpl( - firDiagnostic as KtPsiDiagnostic, - token, - ) - } add(FirJvmErrors.SYNCHRONIZED_ON_ABSTRACT) { firDiagnostic -> SynchronizedOnAbstractImpl( firDiagnostic as KtPsiDiagnostic, diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index 4e386836148..6fa02823dc2 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -739,6 +739,14 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val symbols: List } + abstract class VolatileOnValue : KtFirDiagnostic() { + override val diagnosticClass get() = VolatileOnValue::class + } + + abstract class VolatileOnDelegate : KtFirDiagnostic() { + override val diagnosticClass get() = VolatileOnDelegate::class + } + abstract class WrongJsQualifier : KtFirDiagnostic() { override val diagnosticClass get() = WrongJsQualifier::class } @@ -3066,14 +3074,6 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = StrictfpOnClass::class } - abstract class VolatileOnValue : KtFirDiagnostic() { - override val diagnosticClass get() = VolatileOnValue::class - } - - abstract class VolatileOnDelegate : KtFirDiagnostic() { - override val diagnosticClass get() = VolatileOnDelegate::class - } - abstract class SynchronizedOnAbstract : KtFirDiagnostic() { override val diagnosticClass get() = SynchronizedOnAbstract::class } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 6b50261787f..5e9519c2487 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -886,6 +886,16 @@ internal class AmbiguousAnnotationArgumentImpl( override val token: KtLifetimeToken, ) : KtFirDiagnostic.AmbiguousAnnotationArgument(), KtAbstractFirDiagnostic +internal class VolatileOnValueImpl( + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.VolatileOnValue(), KtAbstractFirDiagnostic + +internal class VolatileOnDelegateImpl( + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.VolatileOnDelegate(), KtAbstractFirDiagnostic + internal class WrongJsQualifierImpl( override val firDiagnostic: KtPsiDiagnostic, override val token: KtLifetimeToken, @@ -3702,16 +3712,6 @@ internal class StrictfpOnClassImpl( override val token: KtLifetimeToken, ) : KtFirDiagnostic.StrictfpOnClass(), KtAbstractFirDiagnostic -internal class VolatileOnValueImpl( - override val firDiagnostic: KtPsiDiagnostic, - override val token: KtLifetimeToken, -) : KtFirDiagnostic.VolatileOnValue(), KtAbstractFirDiagnostic - -internal class VolatileOnDelegateImpl( - override val firDiagnostic: KtPsiDiagnostic, - override val token: KtLifetimeToken, -) : KtFirDiagnostic.VolatileOnDelegate(), KtAbstractFirDiagnostic - internal class SynchronizedOnAbstractImpl( override val firDiagnostic: KtPsiDiagnostic, override val token: KtLifetimeToken, diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index dfe7592e50c..6c27139551a 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -321,6 +321,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val AMBIGUOUS_ANNOTATION_ARGUMENT by error { parameter>>("symbols") } + + val VOLATILE_ON_VALUE by error() + val VOLATILE_ON_DELEGATE by error() } val OPT_IN by object : DiagnosticGroup("OptIn") { 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 c74e0d3cc82..b35cd3f2e78 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 @@ -55,8 +55,6 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") { val ANNOTATIONS by object : DiagnosticGroup("annotations") { val STRICTFP_ON_CLASS by error() - val VOLATILE_ON_VALUE by error() - val VOLATILE_ON_DELEGATE by error() val SYNCHRONIZED_ON_ABSTRACT by error() val SYNCHRONIZED_IN_INTERFACE by error() val SYNCHRONIZED_ON_INLINE by warning() 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 a89d39ed489..85b859a7523 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 @@ -54,8 +54,6 @@ object FirJvmErrors { // annotations val STRICTFP_ON_CLASS by error0() - val VOLATILE_ON_VALUE by error0() - val VOLATILE_ON_DELEGATE by error0() val SYNCHRONIZED_ON_ABSTRACT by error0() val SYNCHRONIZED_IN_INTERFACE by error0() val SYNCHRONIZED_ON_INLINE by warning0() diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrorsDefaultMessages.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrorsDefaultMessages.kt index 0e0b72081de..291edcd2467 100644 --- a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrorsDefaultMessages.kt @@ -11,7 +11,6 @@ import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_TYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOL -import org.jetbrains.kotlin.fir.analysis.diagnostics.checkMissingMessages import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.CONCURRENT_HASH_MAP_CONTAINS_OPERATOR import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.CONFLICTING_JVM_DECLARATIONS import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.DEFAULT_METHOD_CALL_FROM_JAVA6_TARGET @@ -87,8 +86,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZED_ON_SUSPEND import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.UPPER_BOUND_CANNOT_BE_ARRAY import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION -import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.VOLATILE_ON_DELEGATE -import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.VOLATILE_ON_VALUE object FirJvmErrorsDefaultMessages : BaseDiagnosticRendererFactory() { @@ -97,8 +94,6 @@ object FirJvmErrorsDefaultMessages : BaseDiagnosticRendererFactory() { map.put(JAVA_TYPE_MISMATCH, "Java type mismatch expected {0} but found {1}. Use explicit cast", RENDER_TYPE, RENDER_TYPE) map.put(UPPER_BOUND_CANNOT_BE_ARRAY, "Upper bound of a type parameter cannot be an array") map.put(STRICTFP_ON_CLASS, "'@Strictfp' annotation on classes is unsupported yet") - map.put(VOLATILE_ON_VALUE, "'@Volatile' annotation cannot be used on immutable properties") - map.put(VOLATILE_ON_DELEGATE, "'@Volatile' annotation cannot be used on delegated properties") map.put(SYNCHRONIZED_ON_ABSTRACT, "'@Synchronized' annotation cannot be used on abstract functions") map.put(SYNCHRONIZED_ON_INLINE, "'@Synchronized' annotation has no effect on inline functions") map.put(SYNCHRONIZED_ON_SUSPEND, "@Synchronized annotation is not applicable to suspend functions and lambdas") @@ -302,4 +297,4 @@ object FirJvmErrorsDefaultMessages : BaseDiagnosticRendererFactory() { TO_STRING, ) } -} \ No newline at end of file +} diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmDeclarationCheckers.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmDeclarationCheckers.kt index 97599ae95ed..27b0ea4d839 100644 --- a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmDeclarationCheckers.kt +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmDeclarationCheckers.kt @@ -35,7 +35,6 @@ object JvmDeclarationCheckers : DeclarationCheckers() { override val propertyCheckers: Set get() = setOf( - FirVolatileAnnotationChecker, FirJvmFieldApplicabilityChecker, FirJvmSyntheticApplicabilityChecker, FirJvmInlinePropertyChecker, diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirVolatileAnnotationChecker.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirVolatileAnnotationChecker.kt deleted file mode 100644 index ecdeb378dac..00000000000 --- a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirVolatileAnnotationChecker.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2010-2021 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.jvm.checkers.declaration - -import org.jetbrains.kotlin.KtRealSourceElementKind -import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext -import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirPropertyChecker -import org.jetbrains.kotlin.diagnostics.DiagnosticReporter -import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors -import org.jetbrains.kotlin.diagnostics.reportOn -import org.jetbrains.kotlin.fir.declarations.FirProperty -import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId -import org.jetbrains.kotlin.name.JvmNames.VOLATILE_ANNOTATION_CLASS_ID - -object FirVolatileAnnotationChecker : FirPropertyChecker() { - override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) { - if (declaration.source?.kind != KtRealSourceElementKind) return - - val fieldAnnotation = declaration.getAnnotationByClassId(VOLATILE_ANNOTATION_CLASS_ID, context.session) - if (fieldAnnotation != null && !declaration.isVar) { - reporter.reportOn(fieldAnnotation.source, FirJvmErrors.VOLATILE_ON_VALUE, context) - } - - val delegateAnnotation = declaration.delegateFieldSymbol?.getAnnotationByClassId(VOLATILE_ANNOTATION_CLASS_ID, context.session) - if (delegateAnnotation != null) { - reporter.reportOn(delegateAnnotation.source, FirJvmErrors.VOLATILE_ON_DELEGATE, context) - } - } - -} \ No newline at end of file diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index d2de7227d19..4d619bf3ee4 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -268,6 +268,8 @@ object FirErrors { val ANNOTATION_IN_WHERE_CLAUSE_ERROR by error0() val PLUGIN_ANNOTATION_AMBIGUITY by error2() val AMBIGUOUS_ANNOTATION_ARGUMENT by error1>>() + val VOLATILE_ON_VALUE by error0() + val VOLATILE_ON_DELEGATE by error0() // OptIn val OPT_IN_USAGE by warning2(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt index fa4d5f91a61..014461811aa 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt @@ -76,6 +76,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() { FirTopLevelPropertiesChecker, FirLocalExtensionPropertyChecker, ContractSyntaxV2PropertyChecker, + FirVolatileAnnotationChecker, ) override val backingFieldCheckers: Set diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirVolatileAnnotationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirVolatileAnnotationChecker.kt new file mode 100644 index 00000000000..c51108d8f1d --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirVolatileAnnotationChecker.kt @@ -0,0 +1,39 @@ +/* + * 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.checkers.declaration + +import org.jetbrains.kotlin.KtRealSourceElementKind +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory0 +import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.FirAnnotationContainer +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId +import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassIds +import org.jetbrains.kotlin.fir.symbols.SymbolInternals +import org.jetbrains.kotlin.name.StandardClassIds + +object FirVolatileAnnotationChecker : FirPropertyChecker() { + private val VOLATILE_CLASS_IDS = listOf(StandardClassIds.Annotations.Volatile, StandardClassIds.Annotations.JvmVolatile) + + override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) { + if (declaration.source?.kind != KtRealSourceElementKind) return + + val fieldAnnotation = declaration.annotations.getAnnotationByClassIds(VOLATILE_CLASS_IDS, context.session) + ?: declaration.backingField?.annotations?.getAnnotationByClassIds(VOLATILE_CLASS_IDS, context.session) + ?: return + + if (!declaration.isVar) { + reporter.reportOn(fieldAnnotation.source, FirErrors.VOLATILE_ON_VALUE, context) + } + + if (declaration.delegateFieldSymbol != null) { + reporter.reportOn(fieldAnnotation.source, FirErrors.VOLATILE_ON_DELEGATE, context) + } + } +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt index 995eda1320d..b65bcf21c56 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt @@ -608,6 +608,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_OVERRIDDEN_BY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_TYPE_MISMATCH_ON_INHERITANCE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_TYPE_MISMATCH_ON_OVERRIDE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VIRTUAL_MEMBER_HIDDEN +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VOLATILE_ON_DELEGATE +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VOLATILE_ON_VALUE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_ANNOTATION_TARGET import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_EXTENSION_FUNCTION_TYPE @@ -891,6 +893,8 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { map.put(REPEATED_ANNOTATION, "This annotation is not repeatable") map.put(REPEATED_ANNOTATION_WARNING, "This annotation is not repeatable") map.put(NON_INTERNAL_PUBLISHED_API, "@PublishedApi annotation is only applicable to internal declaration") + map.put(VOLATILE_ON_VALUE, "'@Volatile' annotation cannot be used on immutable properties") + map.put(VOLATILE_ON_DELEGATE, "'@Volatile' annotation cannot be used on delegated properties") // OptIn map.put(OPT_IN_USAGE, "{1}", TO_STRING, STRING) diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt index 820c3050d28..0bce4b75e82 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt @@ -178,6 +178,12 @@ fun List.getAnnotationsByClassId(classId: ClassId, session: FirSe } } +fun List.getAnnotationByClassIds(classIds: Collection, session: FirSession): FirAnnotation? { + return firstOrNull { + it.annotationTypeRef.coneTypeSafe()?.fullyExpandedType(session)?.lookupTag?.classId in classIds + } +} + inline fun List.mapAnnotationsWithClassIdTo( classId: ClassId, destination: MutableCollection, diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.fir.kt deleted file mode 100644 index afa8ac4c5bc..00000000000 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.fir.kt +++ /dev/null @@ -1,63 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_ANONYMOUS_PARAMETER -// !API_VERSION: 1.9 -// !LANGUAGE: +MultiPlatformProjects - -// MODULE: common -// FILE: common.kt -// TARGET_PLATFORM: Common -import kotlin.concurrent.Volatile -import kotlin.properties.Delegates - -@OptIn(ExperimentalStdlibApi::class) -class ConcurrentVolatile { - @Volatile val x = 0 - // ok - @Volatile var y = 1 - - @delegate:Volatile var z: String by Delegates.observable("?") { prop, old, new -> old.hashCode() } - - @field:Volatile val w = 2 - - @Volatile - var noBacking: String - get() = "" - set(value) {} -} - -// MODULE: jvm -// FILE: jvm.kt -// TARGET_PLATFORM: JVM -import kotlin.jvm.Volatile as JvmVolatile -import kotlin.concurrent.Volatile -import kotlin.properties.Delegates - -@OptIn(ExperimentalStdlibApi::class) -class ConcurrentVolatileOnJvm { - @Volatile val x = 0 - // ok - @Volatile var y = 1 - - @delegate:Volatile var z: String by Delegates.observable("?") { prop, old, new -> old.hashCode() } - - @field:Volatile val w = 2 - - @Volatile - var noBacking: String - get() = "" - set(value) {} -} - -class JvmVolatile { - @JvmVolatile val x = 0 - // ok - @JvmVolatile var y = 1 - - @delegate:JvmVolatile var z: String by Delegates.observable("?") { prop, old, new -> old.hashCode() } - - @field:JvmVolatile val w = 2 - - @JvmVolatile - var noBacking: String - get() = "" - set(value) {} -} diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.kt index a20d23592b0..4c247506497 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_ANONYMOUS_PARAMETER // !API_VERSION: 1.9 // !LANGUAGE: +MultiPlatformProjects @@ -10,15 +11,15 @@ import kotlin.properties.Delegates @OptIn(ExperimentalStdlibApi::class) class ConcurrentVolatile { - @Volatile val x = 0 + @Volatile val x = 0 // ok @Volatile var y = 1 - @delegate:Volatile var z: String by Delegates.observable("?") { prop, old, new -> old.hashCode() } + @delegate:Volatile var z: String by Delegates.observable("?") { prop, old, new -> old.hashCode() } - @field:Volatile val w = 2 + @field:Volatile val w = 2 - @Volatile + @Volatile var noBacking: String get() = "" set(value) {} diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.txt b/compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.txt index a95d7e0b3d8..5500f0407c9 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.txt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.txt @@ -16,18 +16,6 @@ package // -- Module: -- package -@kotlin.OptIn(markerClass = {kotlin.ExperimentalStdlibApi::class}) public final class ConcurrentVolatile { - public constructor ConcurrentVolatile() - @field:kotlin.concurrent.Volatile /* = kotlin.jvm.Volatile */ public final var noBacking: kotlin.String - @field:kotlin.concurrent.Volatile /* = kotlin.jvm.Volatile */ public final val w: kotlin.Int = 2 - @field:kotlin.concurrent.Volatile /* = kotlin.jvm.Volatile */ public final val x: kotlin.Int = 0 - @field:kotlin.concurrent.Volatile /* = kotlin.jvm.Volatile */ public final var y: kotlin.Int - @delegate:kotlin.concurrent.Volatile /* = kotlin.jvm.Volatile */ public final var z: kotlin.String - public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean - public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int - public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String -} - @kotlin.OptIn(markerClass = {kotlin.ExperimentalStdlibApi::class}) public final class ConcurrentVolatileOnJvm { public constructor ConcurrentVolatileOnJvm() @field:kotlin.concurrent.Volatile /* = kotlin.jvm.Volatile */ public final var noBacking: kotlin.String diff --git a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt index 41084f9f2b5..e35f4aee0d1 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt @@ -18,6 +18,7 @@ object StandardClassIds { val BASE_COROUTINES_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("coroutines")) val BASE_ENUMS_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("enums")) val BASE_CONTRACTS_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("contracts")) + val BASE_CONCURRENT_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("concurrent")) val builtInsPackages = setOf( BASE_KOTLIN_PACKAGE, @@ -164,8 +165,11 @@ object StandardClassIds { val JvmDefault = "JvmDefault".jvmId() val JvmRepeatable = "JvmRepeatable".jvmId() val JvmRecord = "JvmRecord".jvmId() + val JvmVolatile = "Volatile".jvmId() val Throws = "Throws".jvmId() + val Volatile = "Volatile".concurrentId() + val RawTypeAnnotation = "RawType".internalIrId() val FlexibleNullability = "FlexibleNullability".internalIrId() val EnhancedNullability = "EnhancedNullability".jvmInternalId() @@ -255,6 +259,7 @@ private fun String.internalId() = ClassId(StandardClassIds.BASE_INTERNAL_PACKAGE private fun String.internalIrId() = ClassId(StandardClassIds.BASE_INTERNAL_IR_PACKAGE, Name.identifier(this)) private fun String.coroutinesId() = ClassId(StandardClassIds.BASE_COROUTINES_PACKAGE, Name.identifier(this)) private fun String.enumsId() = ClassId(StandardClassIds.BASE_ENUMS_PACKAGE, Name.identifier(this)) +private fun String.concurrentId() = ClassId(StandardClassIds.BASE_CONCURRENT_PACKAGE, Name.identifier(this)) private fun String.callableId(packageName: FqName) = CallableId(packageName, Name.identifier(this)) private fun String.callableId(classId: ClassId) = CallableId(classId, Name.identifier(this))