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 f85287d48bf..9b8ac64d3fc 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 @@ -877,6 +877,12 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val PROPERTY_FIELD_DECLARATION_MISSING_INITIALIZER by error() val PROPERTY_MUST_HAVE_GETTER by error() val PROPERTY_MUST_HAVE_SETTER by error() + val INAPPLICABLE_BACKING_FIELD_VISIBILITY by error { + parameter("modifier") + } + val INAPPLICABLE_BACKING_FIELD_MODIFIER by error { + parameter("modifier") + } val ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS by error(PositioningStrategy.ABSTRACT_MODIFIER) val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING by warning(PositioningStrategy.TYPE_PARAMETERS_LIST) val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS by error(PositioningStrategy.TYPE_PARAMETERS_LIST) 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 1c23c763cbf..837d6f5210d 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 @@ -484,6 +484,8 @@ object FirErrors { val PROPERTY_FIELD_DECLARATION_MISSING_INITIALIZER by error0() val PROPERTY_MUST_HAVE_GETTER by error0() val PROPERTY_MUST_HAVE_SETTER by error0() + val INAPPLICABLE_BACKING_FIELD_VISIBILITY by error1() + val INAPPLICABLE_BACKING_FIELD_MODIFIER by error1() val ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS by error0(SourceElementPositioningStrategies.ABSTRACT_MODIFIER) val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING by warning0(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST) val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS by error0(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST) 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 5cf4d1c21f0..d8cafe95338 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 @@ -60,6 +60,11 @@ object CommonDeclarationCheckers : DeclarationCheckers() { FirLocalVariableTypeParametersSyntaxChecker, ) + override val backingFieldCheckers: Set + get() = setOf( + FirBackingFieldModifiersChecker, + ) + override val classCheckers: Set get() = setOf( FirOverrideChecker, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirBackingFieldModifiersChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirBackingFieldModifiersChecker.kt new file mode 100644 index 00000000000..c387ef30e5f --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirBackingFieldModifiersChecker.kt @@ -0,0 +1,46 @@ +/* + * 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.checkers.declaration + +import org.jetbrains.kotlin.fir.analysis.checkers.FirModifier +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList +import org.jetbrains.kotlin.fir.analysis.checkers.toVisibilityOrNull +import org.jetbrains.kotlin.fir.analysis.diagnostics.* +import org.jetbrains.kotlin.fir.declarations.FirBackingField +import org.jetbrains.kotlin.lexer.KtModifierKeywordToken +import org.jetbrains.kotlin.lexer.KtTokens + +object FirBackingFieldModifiersChecker : FirBackingFieldChecker() { + private val ALLOWED_MODIFIERS = setOf( + KtTokens.PRIVATE_KEYWORD, + KtTokens.INTERNAL_KEYWORD, + ) + + override fun check(declaration: FirBackingField, context: CheckerContext, reporter: DiagnosticReporter) { + val modifiers = declaration.source + ?.getModifierList() + ?.modifiers + ?: return + + modifiers.forEach { + if (it.token in ALLOWED_MODIFIERS) { + return@forEach + } + + val diagnostic = reportInapplicable(it) + reporter.reportOn(it.source, diagnostic, it.token, context) + } + } + + private fun reportInapplicable(modifier: FirModifier<*>): FirDiagnosticFactory1 { + return if (modifier.token.toVisibilityOrNull() != null) { + FirErrors.INAPPLICABLE_BACKING_FIELD_VISIBILITY + } else { + FirErrors.INAPPLICABLE_BACKING_FIELD_MODIFIER + } + } +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index 32471ab77e2..a4019de6f0a 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -268,6 +268,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_LAMBDA_EXPRE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.METHOD_OF_ANY_IMPLEMENTED_IN_INTERFACE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISPLACED_TYPE_PARAMETER_CONSTRAINTS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_BACKING_FIELD_MODIFIER +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_BACKING_FIELD_VISIBILITY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_VARARG_PARAMETERS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED @@ -1287,6 +1289,16 @@ class FirDefaultErrorMessages { PROPERTY_MUST_HAVE_SETTER, "This property needs a custom setter, because it's type is not a subtype of the backing field's type" ) + map.put( + INAPPLICABLE_BACKING_FIELD_VISIBILITY, + "Explicit backing field declarations may only be private or internal, but not ''{0}''", + TO_STRING + ) + map.put( + INAPPLICABLE_BACKING_FIELD_MODIFIER, + "Modifier ''{0}'' is not applicable to explicit backing field declarations", + TO_STRING + ) map.put(ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS, "This property cannot be declared abstract") map.put(LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING, "Type parameters for local variables are deprecated") map.put(LOCAL_VARIABLE_WITH_TYPE_PARAMETERS, "Local variables are not allowed to have type parameters") 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 d28a05fe6ff..63e4169f606 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 @@ -2430,6 +2430,20 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.INAPPLICABLE_BACKING_FIELD_VISIBILITY) { firDiagnostic -> + InapplicableBackingFieldVisibilityImpl( + firDiagnostic.a, + firDiagnostic as FirPsiDiagnostic, + token, + ) + } + add(FirErrors.INAPPLICABLE_BACKING_FIELD_MODIFIER) { firDiagnostic -> + InapplicableBackingFieldModifierImpl( + firDiagnostic.a, + firDiagnostic as FirPsiDiagnostic, + token, + ) + } add(FirErrors.ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS) { firDiagnostic -> AbstractPropertyInPrimaryConstructorParametersImpl( 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 d2d0b2e5111..ba9ee98711b 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 @@ -1719,6 +1719,16 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = PropertyMustHaveSetter::class } + abstract class InapplicableBackingFieldVisibility : KtFirDiagnostic() { + override val diagnosticClass get() = InapplicableBackingFieldVisibility::class + abstract val modifier: KtModifierKeywordToken + } + + abstract class InapplicableBackingFieldModifier : KtFirDiagnostic() { + override val diagnosticClass get() = InapplicableBackingFieldModifier::class + abstract val modifier: KtModifierKeywordToken + } + abstract class AbstractPropertyInPrimaryConstructorParameters : KtFirDiagnostic() { override val diagnosticClass get() = AbstractPropertyInPrimaryConstructorParameters::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 9ba22ac0da3..83c349fe306 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 @@ -2788,6 +2788,22 @@ internal class LocalVariableWithTypeParametersImpl( override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) } +internal class InapplicableBackingFieldVisibilityImpl( + override val modifier: KtModifierKeywordToken, + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.InapplicableBackingFieldVisibility(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + +internal class InapplicableBackingFieldModifierImpl( + override val modifier: KtModifierKeywordToken, + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.InapplicableBackingFieldModifier(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + internal class ExpectedDeclarationWithBodyImpl( firDiagnostic: FirPsiDiagnostic, override val token: ValidityToken,