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 d04c77df4d0..5434e11574c 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 @@ -21,6 +21,9 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") { 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() } 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 1e8de724cb6..4d2981b614f 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 @@ -22,6 +22,9 @@ object FirJvmErrors { 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() // 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 0ffd9981740..8a794305b7e 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 @@ -5,12 +5,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.checkers.declaration.* 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.FirSynchronizedAnnotationChecker import org.jetbrains.kotlin.fir.analysis.jvm.checkers.declaration.FirVolatileAnnotationChecker object JvmDeclarationCheckers : DeclarationCheckers() { @@ -28,4 +26,9 @@ object JvmDeclarationCheckers : DeclarationCheckers() { get() = setOf( FirVolatileAnnotationChecker, ) + + override val functionCheckers: Set + get() = setOf( + FirSynchronizedAnnotationChecker, + ) } diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirSynchronizedAnnotationChecker.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirSynchronizedAnnotationChecker.kt new file mode 100644 index 00000000000..fdabc991210 --- /dev/null +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirSynchronizedAnnotationChecker.kt @@ -0,0 +1,41 @@ +/* + * 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.descriptors.ClassKind +import org.jetbrains.kotlin.fir.analysis.checkers.classKind +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirFunctionChecker +import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol +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.FirFunction +import org.jetbrains.kotlin.fir.declarations.getAnnotationByFqName +import org.jetbrains.kotlin.fir.declarations.utils.isAbstract +import org.jetbrains.kotlin.fir.declarations.utils.isInline +import org.jetbrains.kotlin.name.FqName + +object FirSynchronizedAnnotationChecker : FirFunctionChecker() { + + private val SYNCHRONIZED_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.Synchronized") + + override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) { + val annotation = declaration.getAnnotationByFqName(SYNCHRONIZED_ANNOTATION_FQ_NAME) ?: return + + if (declaration.isInline) { + reporter.reportOn(annotation.source, FirJvmErrors.SYNCHRONIZED_ON_INLINE, context) + return + } + + val containingClass = declaration.getContainingClassSymbol(context.session) ?: return + if (containingClass.classKind == ClassKind.INTERFACE) { + reporter.reportOn(annotation.source, FirJvmErrors.SYNCHRONIZED_IN_INTERFACE, context) + } else if (declaration.isAbstract) { + reporter.reportOn(annotation.source, FirJvmErrors.SYNCHRONIZED_ON_ABSTRACT, context) + } + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/Synchronized.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/Synchronized.fir.kt deleted file mode 100644 index cf98d083a93..00000000000 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/Synchronized.fir.kt +++ /dev/null @@ -1,31 +0,0 @@ -import kotlin.jvm.Synchronized - -interface My { - @Synchronized fun foo() - - @Synchronized fun bar() = 1 - - @Synchronized fun baz(): String { - return "abc" - } - - var v: String - @Synchronized get() = "" - @Synchronized set(value) {} -} - -abstract class Your { - @Synchronized abstract fun foo() - - @Synchronized fun bar() = 1 - - @Synchronized open fun baz(): String { - return "xyz" - } - - var v: String - @Synchronized get() = "" - @Synchronized set(value) {} -} - -@Synchronized fun gav() = 1 diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/Synchronized.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/Synchronized.kt index 5c4d6457a57..028bab14b46 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/Synchronized.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/Synchronized.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL import kotlin.jvm.Synchronized interface My { diff --git a/compiler/testData/diagnostics/testsWithStdLib/inline/synchronizedOnInline.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/inline/synchronizedOnInline.fir.kt deleted file mode 100644 index fecc57b0e10..00000000000 --- a/compiler/testData/diagnostics/testsWithStdLib/inline/synchronizedOnInline.fir.kt +++ /dev/null @@ -1,16 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_PARAMETER - -@Synchronized -inline fun foo(f: () -> Unit): Unit = f() - -var bar: String - @Synchronized - inline get() = "" - @Synchronized - inline set(value) {} - -inline var baz: String - @Synchronized - get() = "" - @Synchronized - set(value) {} diff --git a/compiler/testData/diagnostics/testsWithStdLib/inline/synchronizedOnInline.kt b/compiler/testData/diagnostics/testsWithStdLib/inline/synchronizedOnInline.kt index c4b037fafaa..4239b0ffc2c 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/inline/synchronizedOnInline.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/inline/synchronizedOnInline.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER @Synchronized 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 38a113a0dc6..7a37354d3b5 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 @@ -3457,6 +3457,24 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirJvmErrors.SYNCHRONIZED_ON_ABSTRACT) { firDiagnostic -> + SynchronizedOnAbstractImpl( + firDiagnostic as FirPsiDiagnostic, + token, + ) + } + add(FirJvmErrors.SYNCHRONIZED_IN_INTERFACE) { firDiagnostic -> + SynchronizedInInterfaceImpl( + firDiagnostic as FirPsiDiagnostic, + token, + ) + } + add(FirJvmErrors.SYNCHRONIZED_ON_INLINE) { firDiagnostic -> + SynchronizedOnInlineImpl( + 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 94fc33b37bd..d48232a0a67 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 @@ -2410,6 +2410,18 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = VolatileOnDelegate::class } + abstract class SynchronizedOnAbstract : KtFirDiagnostic() { + override val diagnosticClass get() = SynchronizedOnAbstract::class + } + + abstract class SynchronizedInInterface : KtFirDiagnostic() { + override val diagnosticClass get() = SynchronizedInInterface::class + } + + abstract class SynchronizedOnInline : KtFirDiagnostic() { + override val diagnosticClass get() = SynchronizedOnInline::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 51a3d34539c..1908e1da7a6 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 @@ -3899,6 +3899,27 @@ internal class VolatileOnDelegateImpl( override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) } +internal class SynchronizedOnAbstractImpl( + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.SynchronizedOnAbstract(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + +internal class SynchronizedInInterfaceImpl( + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.SynchronizedInInterface(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + +internal class SynchronizedOnInlineImpl( + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.SynchronizedOnInline(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + internal class JavaTypeMismatchImpl( override val expectedType: KtType, override val actualType: KtType,