From 7ba8e0d9cc6517fbef0a9d54b42d455db4f5638d Mon Sep 17 00:00:00 2001 From: Andrey Zinovyev Date: Tue, 17 Aug 2021 14:00:35 +0300 Subject: [PATCH] [FIR] Add VOLATILE_ON_VALUE/VOLATILE_ON_DELEGATE diagnostic --- .../diagnostics/FirJvmDiagnosticsList.kt | 2 ++ .../analysis/diagnostics/jvm/FirJvmErrors.kt | 2 ++ .../jvm/checkers/JvmDeclarationCheckers.kt | 7 ++++ .../FirVolatileAnnotationChecker.kt | 36 +++++++++++++++++++ .../fir/declarations/FirAnnotationUtils.kt | 5 +++ .../annotations/Volatile.fir.kt | 13 ------- .../testsWithStdLib/annotations/Volatile.kt | 1 + .../diagnostics/KtFirDataClassConverters.kt | 12 +++++++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 8 +++++ .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 14 ++++++++ 10 files changed, 87 insertions(+), 13 deletions(-) create mode 100644 compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirVolatileAnnotationChecker.kt delete mode 100644 compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.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 b88bb43c823..d04c77df4d0 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 @@ -19,6 +19,8 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") { val DECLARATIONS by object : DiagnosticGroup("Declarations") { val CONFLICTING_JVM_DECLARATIONS by error() val STRICTFP_ON_CLASS by error() + val VOLATILE_ON_VALUE by error() + val VOLATILE_ON_DELEGATE by error() } val TYPES by object : DiagnosticGroup("Types") { 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 add4a584fcc..1e8de724cb6 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 @@ -20,6 +20,8 @@ object FirJvmErrors { // Declarations val CONFLICTING_JVM_DECLARATIONS by error0() val STRICTFP_ON_CLASS by error0() + val VOLATILE_ON_VALUE by error0() + val VOLATILE_ON_DELEGATE by error0() // Types val JAVA_TYPE_MISMATCH by error2() 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 ea4b9327506..0ffd9981740 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 @@ -8,8 +8,10 @@ package org.jetbrains.kotlin.fir.analysis.jvm.checkers import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassChecker +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirPropertyChecker import org.jetbrains.kotlin.fir.analysis.jvm.checkers.declaration.FirJvmExternalDeclarationChecker import org.jetbrains.kotlin.fir.analysis.jvm.checkers.declaration.FirStrictfpApplicabilityChecker +import org.jetbrains.kotlin.fir.analysis.jvm.checkers.declaration.FirVolatileAnnotationChecker object JvmDeclarationCheckers : DeclarationCheckers() { override val basicDeclarationCheckers: Set @@ -21,4 +23,9 @@ object JvmDeclarationCheckers : DeclarationCheckers() { get() = setOf( FirStrictfpApplicabilityChecker ) + + override val propertyCheckers: Set + get() = setOf( + FirVolatileAnnotationChecker, + ) } 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 new file mode 100644 index 00000000000..fe0243307e2 --- /dev/null +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirVolatileAnnotationChecker.kt @@ -0,0 +1,36 @@ +/* + * 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.fir.FirRealSourceElementKind +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirPropertyChecker +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.declarations.FirProperty +import org.jetbrains.kotlin.fir.declarations.getAnnotationByFqName +import org.jetbrains.kotlin.name.FqName + +object FirVolatileAnnotationChecker : FirPropertyChecker() { + + private val VOLATILE_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.Volatile") + + override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) { + if (declaration.source?.kind != FirRealSourceElementKind) return + + val fieldAnnotation = declaration.backingFieldSymbol.getAnnotationByFqName(VOLATILE_ANNOTATION_FQ_NAME) + if (fieldAnnotation != null && !declaration.isVar) { + reporter.reportOn(fieldAnnotation.source, FirJvmErrors.VOLATILE_ON_VALUE, context) + } + + val delegateAnnotation = declaration.delegateFieldSymbol?.getAnnotationByFqName(VOLATILE_ANNOTATION_FQ_NAME) + if (delegateAnnotation != null) { + reporter.reportOn(delegateAnnotation.source, FirJvmErrors.VOLATILE_ON_DELEGATE, context) + } + } + +} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt index 3b91f809832..6cd3d977086 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.coneType @@ -97,6 +98,10 @@ fun FirAnnotationContainer.getAnnotationByFqName(fqName: FqName): FirAnnotationC } } +fun FirBasedSymbol.getAnnotationByFqName(fqName: FqName): FirAnnotationCall? where D : FirAnnotationContainer, D : FirDeclaration { + return fir.getAnnotationByFqName(fqName) +} + fun FirAnnotationContainer.getAnnotationsByFqName(fqName: FqName): List = annotations.getAnnotationsByFqName(fqName) fun List.getAnnotationsByFqName(fqName: FqName): List { 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 2d571e84c78..00000000000 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.fir.kt +++ /dev/null @@ -1,13 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_ANONYMOUS_PARAMETER -import kotlin.jvm.Volatile -import kotlin.properties.Delegates - -class My { - @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 -} diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.kt index 416a48e121f..c700ab16947 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 import kotlin.jvm.Volatile import kotlin.properties.Delegates 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 9d0a98f7bfe..38a113a0dc6 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 @@ -3445,6 +3445,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirJvmErrors.VOLATILE_ON_VALUE) { firDiagnostic -> + VolatileOnValueImpl( + firDiagnostic as FirPsiDiagnostic, + token, + ) + } + add(FirJvmErrors.VOLATILE_ON_DELEGATE) { firDiagnostic -> + VolatileOnDelegateImpl( + firDiagnostic as FirPsiDiagnostic, + token, + ) + } add(FirJvmErrors.JAVA_TYPE_MISMATCH) { firDiagnostic -> JavaTypeMismatchImpl( firSymbolBuilder.typeBuilder.buildKtType(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 ffb4f06af40..94fc33b37bd 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 @@ -2402,6 +2402,14 @@ 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 JavaTypeMismatch : KtFirDiagnostic() { override val diagnosticClass get() = JavaTypeMismatch::class abstract val expectedType: KtType 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 14afebe7414..51a3d34539c 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 @@ -3885,6 +3885,20 @@ internal class StrictfpOnClassImpl( override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) } +internal class VolatileOnValueImpl( + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.VolatileOnValue(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + +internal class VolatileOnDelegateImpl( + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.VolatileOnDelegate(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + internal class JavaTypeMismatchImpl( override val expectedType: KtType, override val actualType: KtType,