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 f825340cf84..289a74b0815 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 @@ -25,6 +25,7 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") { val JVM_STATIC_NOT_IN_OBJECT_OR_CLASS_COMPANION by error(PositioningStrategy.DECLARATION_SIGNATURE) val JVM_STATIC_NOT_IN_OBJECT_OR_COMPANION by error(PositioningStrategy.DECLARATION_SIGNATURE) val JVM_STATIC_ON_NON_PUBLIC_MEMBER by error(PositioningStrategy.DECLARATION_SIGNATURE) + val JVM_STATIC_ON_CONST_OR_JVM_FIELD by error(PositioningStrategy.DECLARATION_SIGNATURE) val INAPPLICABLE_JVM_NAME by error() val ILLEGAL_JVM_NAME by error() 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 967d5d1c812..3c448a77617 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 @@ -26,6 +26,7 @@ object FirJvmErrors { val JVM_STATIC_NOT_IN_OBJECT_OR_CLASS_COMPANION by error0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) val JVM_STATIC_NOT_IN_OBJECT_OR_COMPANION by error0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) val JVM_STATIC_ON_NON_PUBLIC_MEMBER by error0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) + val JVM_STATIC_ON_CONST_OR_JVM_FIELD by error0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) val INAPPLICABLE_JVM_NAME by error0() val ILLEGAL_JVM_NAME by error0() diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmStaticChecker.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmStaticChecker.kt index 8bc17addb9e..349c5206cae 100644 --- a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmStaticChecker.kt +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmStaticChecker.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.isCompanion +import org.jetbrains.kotlin.fir.declarations.utils.isConst import org.jetbrains.kotlin.fir.declarations.utils.isOverride import org.jetbrains.kotlin.fir.declarations.utils.visibility import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall @@ -51,6 +52,22 @@ object FirJvmStaticChecker : FirBasicDeclarationChecker() { checkOverrideCannotBeStatic(declaration, context, reporter, annotatedParts) checkStaticNotInProperObject(context, reporter, annotatedParts) checkStaticNonPublic(declaration, context, reporter, annotatedParts) + checkStaticOnConstOrJvmField(context, reporter, annotatedParts) + } + + private fun checkStaticOnConstOrJvmField( + context: CheckerContext, + reporter: DiagnosticReporter, + annotatedParts: List, + ) { + annotatedParts.forEach { + if ( + it is FirProperty && it.isConst || + it.hasAnnotationNamedAs(StandardClassIds.JvmField) + ) { + reporter.reportOn(it.source, FirJvmErrors.JVM_STATIC_ON_CONST_OR_JVM_FIELD, context) + } + } } private fun checkStaticNonPublic( 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 770414d810d..1ed27b0f235 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 @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JVM_RECORD import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JVM_RECORD_WITHOUT_PRIMARY_CONSTRUCTOR_PARAMETERS import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JVM_STATIC_NOT_IN_OBJECT_OR_CLASS_COMPANION import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JVM_STATIC_NOT_IN_OBJECT_OR_COMPANION +import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JVM_STATIC_ON_CONST_OR_JVM_FIELD import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JVM_STATIC_ON_NON_PUBLIC_MEMBER import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.LOCAL_JVM_RECORD import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.NON_DATA_CLASS_JVM_RECORD @@ -113,6 +114,10 @@ object FirJvmDefaultErrorMessages { JVM_STATIC_ON_NON_PUBLIC_MEMBER, "Only public members in interface companion objects can be annotated with '@JvmStatic'" ) + map.put( + JVM_STATIC_ON_CONST_OR_JVM_FIELD, + "'@JvmStatic' annotation is useless for const or '@JvmField' properties", + ) map.put(INAPPLICABLE_JVM_NAME, "'@JvmName' annotation is not applicable to this declaration") map.put(ILLEGAL_JVM_NAME, "Illegal JVM name") diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/constOrJvmFieldProperty.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/constOrJvmFieldProperty.fir.kt deleted file mode 100644 index 3a29c08a590..00000000000 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/constOrJvmFieldProperty.fir.kt +++ /dev/null @@ -1,18 +0,0 @@ -class A { - - companion object { - - @JvmStatic const val z = 1; - - @JvmStatic @JvmField val x = 1; - } - -} - - -object B { - - @JvmStatic const val z = 1; - - @JvmStatic @JvmField val x = 1; -} diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/constOrJvmFieldProperty.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/constOrJvmFieldProperty.kt index 4d444686de5..4988573577e 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/constOrJvmFieldProperty.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/constOrJvmFieldProperty.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL class A { companion object { 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 c2b14439226..b4465323251 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt @@ -119,6 +119,7 @@ object StandardClassIds { val JvmStatic = "JvmStatic".jvmId() val JvmName = "JvmName".jvmId() + val JvmField = "JvmField".jvmId() val Result = "Result".baseId() } 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 21e6a8b913b..e9da3bfa61d 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 @@ -3688,6 +3688,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirJvmErrors.JVM_STATIC_ON_CONST_OR_JVM_FIELD) { firDiagnostic -> + JvmStaticOnConstOrJvmFieldImpl( + firDiagnostic as FirPsiDiagnostic, + token, + ) + } add(FirJvmErrors.INAPPLICABLE_JVM_NAME) { firDiagnostic -> InapplicableJvmNameImpl( firDiagnostic as FirPsiDiagnostic, 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 04ec7fcf8ec..dc1318e3d79 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 @@ -2566,6 +2566,10 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = JvmStaticOnNonPublicMember::class } + abstract class JvmStaticOnConstOrJvmField : KtFirDiagnostic() { + override val diagnosticClass get() = JvmStaticOnConstOrJvmField::class + } + abstract class InapplicableJvmName : KtFirDiagnostic() { override val diagnosticClass get() = InapplicableJvmName::class } 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 47cdab997d1..561cee683b6 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 @@ -4166,6 +4166,13 @@ internal class JvmStaticOnNonPublicMemberImpl( override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) } +internal class JvmStaticOnConstOrJvmFieldImpl( + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.JvmStaticOnConstOrJvmField(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + internal class InapplicableJvmNameImpl( firDiagnostic: FirPsiDiagnostic, override val token: ValidityToken,