From 3725c587949cb9960fa3dfb01809314a2d4f4579 Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Wed, 8 Sep 2021 16:05:27 +0300 Subject: [PATCH] [FIR] Add INAPPLICABLE_JVM_FIELD, INAPPLICABLE_JVM_FIELD_WARNING --- .../diagnostics/FirJvmDiagnosticsList.kt | 9 ++ .../analysis/diagnostics/jvm/FirJvmErrors.kt | 4 + .../jvm/checkers/JvmDeclarationCheckers.kt | 1 + .../FirJvmFieldApplicabilityChecker.kt | 137 ++++++++++++++++++ .../diagnostics/FirJvmDefaultErrorMessages.kt | 5 + .../fir/symbols/impl/FirCallableSymbol.kt | 1 + .../jvmField/inMultiFileFacade.fir.kt | 13 -- .../annotations/jvmField/inMultiFileFacade.kt | 1 + .../annotations/jvmField/interface13.fir.kt | 59 -------- .../annotations/jvmField/interface13.kt | 1 + .../jvmField/jvmFieldApplicability_1_5.fir.kt | 48 +++--- .../jvmField/jvmFieldApplicability_1_6.fir.kt | 48 +++--- .../diagnostics/KtFirDataClassConverters.kt | 14 ++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 10 ++ .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 16 ++ 15 files changed, 247 insertions(+), 120 deletions(-) create mode 100644 compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmFieldApplicabilityChecker.kt delete mode 100644 compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/inMultiFileFacade.fir.kt delete mode 100644 compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.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 7d385c23c52..b48bdd98674 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 @@ -110,4 +110,13 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") { val EXTERNAL_DECLARATION_IN_INTERFACE by error(PositioningStrategy.DECLARATION_SIGNATURE) val EXTERNAL_DECLARATION_CANNOT_BE_INLINED by error(PositioningStrategy.DECLARATION_SIGNATURE) } + + val INAPPLICABLE by object : DiagnosticGroup("Inapplicable") { + val INAPPLICABLE_JVM_FIELD by error { + parameter("message") + } + val INAPPLICABLE_JVM_FIELD_WARNING by warning { + parameter("message") + } + } } 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 c4898b9fced..fc148b72269 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 @@ -89,4 +89,8 @@ object FirJvmErrors { val EXTERNAL_DECLARATION_IN_INTERFACE by error0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) val EXTERNAL_DECLARATION_CANNOT_BE_INLINED by error0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) + // Inapplicable + val INAPPLICABLE_JVM_FIELD by error1() + val INAPPLICABLE_JVM_FIELD_WARNING by warning1() + } 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 78260144ca3..c034e7aae47 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 @@ -34,6 +34,7 @@ object JvmDeclarationCheckers : DeclarationCheckers() { override val propertyCheckers: Set get() = setOf( FirVolatileAnnotationChecker, + FirJvmFieldApplicabilityChecker ) override val functionCheckers: Set diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmFieldApplicabilityChecker.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmFieldApplicabilityChecker.kt new file mode 100644 index 00000000000..02c8e5fcd40 --- /dev/null +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmFieldApplicabilityChecker.kt @@ -0,0 +1,137 @@ +/* + * 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.builtins.StandardNames +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.fir.FirFakeSourceElementKind +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirPropertyChecker +import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol +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.containingClass +import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.declarations.FirRegularClass +import org.jetbrains.kotlin.fir.declarations.getAnnotationByFqName +import org.jetbrains.kotlin.fir.declarations.utils.* +import org.jetbrains.kotlin.fir.languageVersionSettings +import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference +import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.types.coneType +import org.jetbrains.kotlin.JvmFieldApplicabilityProblem.* +import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_CLASS_ID +import org.jetbrains.kotlin.JvmNames.JVM_MULTIFILE_CLASS_SHORT +import org.jetbrains.kotlin.fir.analysis.checkers.getContainingDeclarationSymbol +import org.jetbrains.kotlin.psi.stubs.elements.KtParameterElementType + +object FirJvmFieldApplicabilityChecker : FirPropertyChecker() { + override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) { + val annotation = declaration.getAnnotationByFqName(JVM_FIELD_ANNOTATION_FQ_NAME) ?: return + val session = context.session + val containingClass = declaration.containingClass()?.toFirRegularClass(session) + + val problem = when { + declaration.delegate != null -> DELEGATE + !declaration.hasBackingField -> return + declaration.isOverridable(containingClass) -> NOT_FINAL + Visibilities.isPrivate(declaration.visibility) -> PRIVATE + declaration.hasCustomAccessor() -> CUSTOM_ACCESSOR + declaration.isOverride -> OVERRIDES + declaration.isLateInit -> LATEINIT + declaration.isConst -> CONST + containingClassSymbol != null && containingClassSymbol.isInsideCompanionObjectOfInterface(session) -> { + if (!session.languageVersionSettings.supportsFeature(LanguageFeature.JvmFieldInInterface)) { + INSIDE_COMPANION_OF_INTERFACE + } else { + if (!isInterfaceCompanionWithPublicJvmFieldProperties(containingClassSymbol)) { + NOT_PUBLIC_VAL_WITH_JVMFIELD + } else { + return + } + } + } + containingClass == null && isInsideJvmMultifileClassFile(context) -> + TOP_LEVEL_PROPERTY_OF_MULTIFILE_FACADE + declaration.returnTypeRef.isInlineClassThatRequiresMangling(session) -> RETURN_TYPE_IS_INLINE_CLASS + else -> return + } + + val factory = if (declaration.fromPrimaryConstructor == true && + !context.session.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitJvmFieldOnOverrideFromInterfaceInPrimaryConstructor) + ) { + FirJvmErrors.INAPPLICABLE_JVM_FIELD_WARNING + } else { + FirJvmErrors.INAPPLICABLE_JVM_FIELD + } + + reporter.reportOn(annotation.source, factory, problem.errorMessage, context) + } + + private fun FirTypeRef.isInlineClassThatRequiresMangling(session: FirSession): Boolean { + val symbol = this.coneType.toRegularClassSymbol(session) ?: return false + return symbol.isInline && !symbol.isDontMangleClass() + } + + private fun FirRegularClassSymbol.isDontMangleClass(): Boolean { + return this.classId.relativeClassName.asString() == StandardNames.RESULT_FQ_NAME.asString() + } + + private fun FirProperty.isOverridable(containingClass: FirRegularClass?): Boolean { + return visibility != Visibilities.Private && modality != Modality.FINAL && + containingClass?.isFinal != true + } + + private fun FirProperty.hasCustomAccessor(): Boolean { + return (getter != null && getter?.source?.kind !is FirFakeSourceElementKind) || + (setter != null && setter?.source?.kind !is FirFakeSourceElementKind) + } + + private fun FirRegularClassSymbol.isInsideCompanionObjectOfInterface(session: FirSession): Boolean { + if (!isCompanion) { + return false + } + + val outerClassKind = (getContainingDeclarationSymbol(session) as? FirRegularClass)?.classKind + return outerClassKind == ClassKind.INTERFACE || outerClassKind == ClassKind.ANNOTATION_CLASS + } + + private fun isInterfaceCompanionWithPublicJvmFieldProperties(containingClass: FirRegularClassSymbol): Boolean { + for (symbol in containingClass.declarationSymbols) { + if (symbol !is FirPropertySymbol) continue + + if (symbol.visibility != Visibilities.Public || symbol.isVar || symbol.modality != Modality.FINAL) { + return false + } + + if (!symbol.hasJvmFieldAnnotation()) { + return false + } + } + + return true + } + + private fun FirPropertySymbol.hasJvmFieldAnnotation(): Boolean { + return getAnnotationByFqName(JVM_FIELD_ANNOTATION_FQ_NAME) != null + } + + private fun isInsideJvmMultifileClassFile(context: CheckerContext): Boolean { + return context.findClosest()?.annotations?.any { + (it.calleeReference as? FirResolvedNamedReference)?.name?.asString() == JVM_MULTIFILE_CLASS_SHORT + } == true + } +} \ No newline at end of file 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 f2299cfc2de..eb640042434 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 @@ -21,6 +21,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.FIELD_IN_J import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.ILLEGAL_JAVA_LANG_RECORD_SUPERTYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.ILLEGAL_JVM_NAME import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INAPPLICABLE_JVM_NAME +import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INAPPLICABLE_JVM_FIELD +import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INAPPLICABLE_JVM_FIELD_WARNING import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INNER_JVM_RECORD import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JAVA_TYPE_MISMATCH import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JVM_DEFAULT_IN_DECLARATION @@ -164,6 +166,9 @@ object FirJvmDefaultErrorMessages { map.put(EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT, "External declaration can not be abstract") map.put(EXTERNAL_DECLARATION_CANNOT_HAVE_BODY, "External declaration can not have a body") map.put(EXTERNAL_DECLARATION_CANNOT_BE_INLINED, "Inline functions can not be external") + + map.put(INAPPLICABLE_JVM_FIELD, "{0}", STRING) + map.put(INAPPLICABLE_JVM_FIELD_WARNING, "{0}. This warning will become an error in further releases", STRING) } } } \ No newline at end of file diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirCallableSymbol.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirCallableSymbol.kt index 7767e582c79..c7b4dca855d 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirCallableSymbol.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirCallableSymbol.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.symbols.impl import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.ensureResolved import org.jetbrains.kotlin.fir.types.* diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/inMultiFileFacade.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/inMultiFileFacade.fir.kt deleted file mode 100644 index 968c887cb2a..00000000000 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/inMultiFileFacade.fir.kt +++ /dev/null @@ -1,13 +0,0 @@ -@file:kotlin.jvm.JvmMultifileClass -@file:JvmName("SomeName") - -@JvmField -val c = 4 - -@JvmField -var g = 5 - -class C { - @JvmField - var g = 5 -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/inMultiFileFacade.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/inMultiFileFacade.kt index 68d41dd5109..b7dc157cf7d 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/inMultiFileFacade.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/inMultiFileFacade.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL @file:kotlin.jvm.JvmMultifileClass @file:JvmName("SomeName") diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.fir.kt deleted file mode 100644 index c79dc2e47fc..00000000000 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.fir.kt +++ /dev/null @@ -1,59 +0,0 @@ -// !LANGUAGE: +JvmFieldInInterface - -interface A { - - companion object { - @JvmField - val c = 3 - } -} - - -interface B { - - companion object { - @JvmField - val c = 3 - - @JvmField - val a = 3 - } -} - -interface C { - companion object { - @JvmField - val c = 3 - - val a = 3 - } -} - -interface D { - companion object { - @JvmField - var c = 3 - } -} - - -interface E { - companion object { - @JvmField - private val a = 3 - - @JvmField - internal val b = 3 - - @JvmField - protected val c = 3 - } -} - - -interface F { - companion object { - @JvmField - open val a = 3 - } -} diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.kt index 2cf5fc7f17b..bfcb3e0bb05 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +JvmFieldInInterface interface A { diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability_1_5.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability_1_5.fir.kt index d4b9fa89c19..aa9065bcb7e 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability_1_5.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability_1_5.fir.kt @@ -17,33 +17,33 @@ abstract class C : I{ @kotlin.jvm.JvmField private fun foo(s: String = "OK") { } - @JvmField val a: String by lazy { "A" } + @JvmField val a: String by lazy { "A" } - @JvmField open val b: Int = 3 + @JvmField open val b: Int = 3 @JvmField abstract val c: Int - @JvmField + @JvmField val customGetter: String = "" get() = field - @JvmField + @JvmField val explicitDefaultGetter: String = "" get - @JvmField + @JvmField var explicitDefaultSetter: String = "" set - @JvmField + @JvmField val explicitDefaultAnnotatedGetter: String = "" @DemoAnnotation get - @JvmField + @JvmField var explicitDefaultAnnotatedSetter: String = "" @DemoAnnotation set - @JvmField + @JvmField var customSetter: String = "" set(s) { field = s @@ -53,10 +53,10 @@ abstract class C : I{ val noBackingField: String get() = "a" - @JvmField + @JvmField final override val ai = 3 - @JvmField + @JvmField private val private = 3 } @@ -67,14 +67,14 @@ interface I { } class G { - @JvmField + @JvmField lateinit var lateInit: String - @delegate:JvmField + @delegate:JvmField val s: String by lazy { "s" } } -@JvmField +@JvmField const val Const = 4 @JvmField @@ -93,7 +93,7 @@ interface K { val j: Int companion object { - @JvmField + @JvmField var c = 3 var x = 3 @@ -101,27 +101,27 @@ interface K { } class KK : K { - @JvmField + @JvmField override val i: Int = 0 - @JvmField + @JvmField override final val j: Int = 0 } open class KKK : K { - @JvmField + @JvmField override val i: Int = 0 - @JvmField + @JvmField override final val j: Int = 0 } class JK( override val i: Int, - @JvmField override val j: Int, + @JvmField override val j: Int, ) : K annotation class L { companion object { - @JvmField + @JvmField var c = 3 } } @@ -131,18 +131,18 @@ object O { val c = 3 } -@JvmField +@JvmField private val private = 3 inline class Foo(val x: Int) object IObject { - @JvmField + @JvmField val c: Foo = Foo(42) - @JvmField + @JvmField val u = 42u - @JvmField + @JvmField private val r: Result = TODO() } diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability_1_6.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability_1_6.fir.kt index 733c97503df..7dccd0455cb 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability_1_6.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability_1_6.fir.kt @@ -17,33 +17,33 @@ abstract class C : I{ @kotlin.jvm.JvmField private fun foo(s: String = "OK") { } - @JvmField val a: String by lazy { "A" } + @JvmField val a: String by lazy { "A" } - @JvmField open val b: Int = 3 + @JvmField open val b: Int = 3 @JvmField abstract val c: Int - @JvmField + @JvmField val customGetter: String = "" get() = field - @JvmField + @JvmField val explicitDefaultGetter: String = "" get - @JvmField + @JvmField var explicitDefaultSetter: String = "" set - @JvmField + @JvmField val explicitDefaultAnnotatedGetter: String = "" @DemoAnnotation get - @JvmField + @JvmField var explicitDefaultAnnotatedSetter: String = "" @DemoAnnotation set - @JvmField + @JvmField var customSetter: String = "" set(s) { field = s @@ -53,10 +53,10 @@ abstract class C : I{ val noBackingField: String get() = "a" - @JvmField + @JvmField final override val ai = 3 - @JvmField + @JvmField private val private = 3 } @@ -67,14 +67,14 @@ interface I { } class G { - @JvmField + @JvmField lateinit var lateInit: String - @delegate:JvmField + @delegate:JvmField val s: String by lazy { "s" } } -@JvmField +@JvmField const val Const = 4 @JvmField @@ -93,7 +93,7 @@ interface K { val j: Int companion object { - @JvmField + @JvmField var c = 3 var x = 3 @@ -101,27 +101,27 @@ interface K { } class KK : K { - @JvmField + @JvmField override val i: Int = 0 - @JvmField + @JvmField override final val j: Int = 0 } open class KKK : K { - @JvmField + @JvmField override val i: Int = 0 - @JvmField + @JvmField override final val j: Int = 0 } class JK( override val i: Int, - @JvmField override val j: Int, + @JvmField override val j: Int, ) : K annotation class L { companion object { - @JvmField + @JvmField var c = 3 } } @@ -131,18 +131,18 @@ object O { val c = 3 } -@JvmField +@JvmField private val private = 3 inline class Foo(val x: Int) object IObject { - @JvmField + @JvmField val c: Foo = Foo(42) - @JvmField + @JvmField val u = 42u - @JvmField + @JvmField private val r: Result = TODO() } 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 28fc7176cb2..0d57725802c 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 @@ -3780,4 +3780,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirJvmErrors.INAPPLICABLE_JVM_FIELD) { firDiagnostic -> + InapplicableJvmFieldImpl( + firDiagnostic.a, + firDiagnostic as FirPsiDiagnostic, + token, + ) + } + add(FirJvmErrors.INAPPLICABLE_JVM_FIELD_WARNING) { firDiagnostic -> + InapplicableJvmFieldWarningImpl( + firDiagnostic.a, + firDiagnostic as FirPsiDiagnostic, + token, + ) + } } 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 52214d3e8af..16a1dc5dc27 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 @@ -2628,4 +2628,14 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = ExternalDeclarationCannotBeInlined::class } + abstract class InapplicableJvmField : KtFirDiagnostic() { + override val diagnosticClass get() = InapplicableJvmField::class + abstract val message: String + } + + abstract class InapplicableJvmFieldWarning : KtFirDiagnostic() { + override val diagnosticClass get() = InapplicableJvmFieldWarning::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 9874ea76e89..64f8d4f1880 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 @@ -4273,3 +4273,19 @@ internal class ExternalDeclarationCannotBeInlinedImpl( override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) } +internal class InapplicableJvmFieldImpl( + override val message: String, + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.InapplicableJvmField(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + +internal class InapplicableJvmFieldWarningImpl( + override val message: String, + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.InapplicableJvmFieldWarning(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} +