diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index bc8a07c0585..8d2327f3d4f 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -925,6 +925,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.INAPPLICABLE_TARGET_ON_PROPERTY_WARNING) { firDiagnostic -> + InapplicableTargetOnPropertyWarningImpl( + firDiagnostic.a, + firDiagnostic as KtPsiDiagnostic, + token, + ) + } add(FirErrors.INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE) { firDiagnostic -> InapplicableTargetPropertyImmutableImpl( firDiagnostic.a, diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index 724c7a2225f..e67ca116199 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -672,6 +672,11 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val useSiteDescription: String } + abstract class InapplicableTargetOnPropertyWarning : KtFirDiagnostic() { + override val diagnosticClass get() = InapplicableTargetOnPropertyWarning::class + abstract val useSiteDescription: String + } + abstract class InapplicableTargetPropertyImmutable : KtFirDiagnostic() { override val diagnosticClass get() = InapplicableTargetPropertyImmutable::class abstract val useSiteDescription: String diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index c014aa37aee..5431dabc2e8 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -804,6 +804,12 @@ internal class InapplicableTargetOnPropertyImpl( override val token: KtLifetimeToken, ) : KtFirDiagnostic.InapplicableTargetOnProperty(), KtAbstractFirDiagnostic +internal class InapplicableTargetOnPropertyWarningImpl( + override val useSiteDescription: String, + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.InapplicableTargetOnPropertyWarning(), KtAbstractFirDiagnostic + internal class InapplicableTargetPropertyImmutableImpl( override val useSiteDescription: String, override val firDiagnostic: KtPsiDiagnostic, diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index 37b564f6fd3..8809e6347bf 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -2667,6 +2667,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/ParamAnnotations.kt"); } + @Test + @TestMetadata("prohibitUseSiteGetTargetAnnotationsOff.kt") + public void testProhibitUseSiteGetTargetAnnotationsOff() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/prohibitUseSiteGetTargetAnnotationsOff.kt"); + } + + @Test + @TestMetadata("prohibitUseSiteGetTargetAnnotationsOn.kt") + public void testProhibitUseSiteGetTargetAnnotationsOn() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/prohibitUseSiteGetTargetAnnotationsOn.kt"); + } + @Test @TestMetadata("PropertyAnnotations.kt") public void testPropertyAnnotations() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index da8fbfa3328..9435ea5623c 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -2667,6 +2667,18 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/ParamAnnotations.kt"); } + @Test + @TestMetadata("prohibitUseSiteGetTargetAnnotationsOff.kt") + public void testProhibitUseSiteGetTargetAnnotationsOff() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/prohibitUseSiteGetTargetAnnotationsOff.kt"); + } + + @Test + @TestMetadata("prohibitUseSiteGetTargetAnnotationsOn.kt") + public void testProhibitUseSiteGetTargetAnnotationsOn() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/prohibitUseSiteGetTargetAnnotationsOn.kt"); + } + @Test @TestMetadata("PropertyAnnotations.kt") public void testPropertyAnnotations() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index fad969c1d91..1f552683bdc 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -2673,6 +2673,18 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/ParamAnnotations.kt"); } + @Test + @TestMetadata("prohibitUseSiteGetTargetAnnotationsOff.kt") + public void testProhibitUseSiteGetTargetAnnotationsOff() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/prohibitUseSiteGetTargetAnnotationsOff.kt"); + } + + @Test + @TestMetadata("prohibitUseSiteGetTargetAnnotationsOn.kt") + public void testProhibitUseSiteGetTargetAnnotationsOn() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/prohibitUseSiteGetTargetAnnotationsOn.kt"); + } + @Test @TestMetadata("PropertyAnnotations.kt") public void testPropertyAnnotations() throws Exception { 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 052abc5b87e..16a41922ffc 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 @@ -292,6 +292,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val INAPPLICABLE_TARGET_ON_PROPERTY by error { parameter("useSiteDescription") } + val INAPPLICABLE_TARGET_ON_PROPERTY_WARNING by error { + parameter("useSiteDescription") + } val INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE by error { parameter("useSiteDescription") } 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 69972d4d060..0fc7265b6e5 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 @@ -252,6 +252,7 @@ object FirErrors { val WRONG_ANNOTATION_TARGET by error1() val WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET by error2() val INAPPLICABLE_TARGET_ON_PROPERTY by error1() + val INAPPLICABLE_TARGET_ON_PROPERTY_WARNING by error1() val INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE by error1() val INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE by error0() val INAPPLICABLE_TARGET_PROPERTY_HAS_NO_BACKING_FIELD by error0() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationChecker.kt index 54d857b18cb..bc43712b2e7 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationChecker.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.* import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory1 import org.jetbrains.kotlin.diagnostics.hasValOrVar import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.fir.FirAnnotationContainer @@ -29,6 +30,8 @@ import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.StandardClassIds +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract object FirAnnotationChecker : FirBasicDeclarationChecker() { private val deprecatedClassId = FqName("kotlin.Deprecated") @@ -196,6 +199,17 @@ object FirAnnotationChecker : FirBasicDeclarationChecker() { when (target) { PROPERTY, PROPERTY_GETTER -> { + checkPropertyGetter( + annotated, + annotation, + target, + context, + reporter, + when (context.session.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitUseSiteGetTargetAnnotations)) { + true -> FirErrors.INAPPLICABLE_TARGET_ON_PROPERTY + false -> FirErrors.INAPPLICABLE_TARGET_ON_PROPERTY_WARNING + } + ) } FIELD -> { if (annotated is FirProperty && annotated.delegateFieldSymbol != null && !annotated.hasBackingField) { @@ -209,9 +223,9 @@ object FirAnnotationChecker : FirBasicDeclarationChecker() { } PROPERTY_SETTER, SETTER_PARAMETER -> { - if (annotated !is FirProperty || annotated.isLocal) { - reporter.reportOn(annotation.source, FirErrors.INAPPLICABLE_TARGET_ON_PROPERTY, target.renderName, context) - } else if (!annotated.isVar) { + if (!checkPropertyGetter(annotated, annotation, target, context, reporter, FirErrors.INAPPLICABLE_TARGET_ON_PROPERTY) && + !annotated.isVar + ) { reporter.reportOn(annotation.source, FirErrors.INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE, target.renderName, context) } } @@ -244,6 +258,23 @@ object FirAnnotationChecker : FirBasicDeclarationChecker() { } } + @OptIn(ExperimentalContracts::class) + private fun checkPropertyGetter( + annotated: FirAnnotationContainer, + annotation: FirAnnotation, + target: AnnotationUseSiteTarget, + context: CheckerContext, + reporter: DiagnosticReporter, + diagnostic: KtDiagnosticFactory1 + ): Boolean { + contract { + returns(false) implies (annotated is FirProperty) + } + val isReport = annotated !is FirProperty || annotated.isLocal + if (isReport) reporter.reportOn(annotation.source, diagnostic, target.renderName, context) + return isReport + } + private fun checkDeprecatedCalls( deprecatedSinceKotlin: FirAnnotation, deprecated: FirAnnotation?, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt index 0616b706d85..258ab46f8b3 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt @@ -256,6 +256,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_LATE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_OPERATOR_MODIFIER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_PARAM_TARGET import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_TARGET_ON_PROPERTY +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_TARGET_ON_PROPERTY_WARNING import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_TARGET_PROPERTY_HAS_NO_BACKING_FIELD import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE @@ -857,6 +858,11 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { map.put(ANNOTATION_ON_SUPERCLASS, "Annotations on superclass are meaningless") map.put(WRONG_ANNOTATION_TARGET, "This annotation is not applicable to target ''{0}''", TO_STRING) map.put(INAPPLICABLE_TARGET_ON_PROPERTY, "''@{0}:'' annotations could be applied only to property declarations", TO_STRING) + map.put( + INAPPLICABLE_TARGET_ON_PROPERTY_WARNING, + "''@{0}:'' annotations could be applied only to property declarations. It will be an error in a future release. See https://youtrack.jetbrains.com/issue/KT-15470", + TO_STRING + ) map.put(INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE, "''@{0}:'' annotations could be applied only to mutable properties", TO_STRING) map.put(INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE, "'@delegate:' annotations could be applied only to delegated properties") map.put( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index cc290d3e415..606dd42b517 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -359,6 +359,7 @@ public interface Errors { DiagnosticFactory0 NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION = DiagnosticFactory0.create(ERROR); DiagnosticFactory1 INAPPLICABLE_TARGET_ON_PROPERTY = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 INAPPLICABLE_TARGET_ON_PROPERTY_WARNING = DiagnosticFactory1.create(WARNING); DiagnosticFactory1 INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE = DiagnosticFactory1.create(ERROR); DiagnosticFactory0 INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 INAPPLICABLE_TARGET_PROPERTY_HAS_NO_BACKING_FIELD = DiagnosticFactory0.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index d7d8c76c8b7..47c87785a84 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -180,6 +180,9 @@ public class DefaultErrorMessages { MAP.put(WRONG_EXTENSION_FUNCTION_TYPE_WARNING, "ExtensionFunctionType makes no sense on a non-function type. It will be an error in a future release. See https://youtrack.jetbrains.com/issue/KT-43527"); MAP.put(INAPPLICABLE_TARGET_ON_PROPERTY, "''@{0}:'' annotations could be applied only to property declarations", TO_STRING); + MAP.put(INAPPLICABLE_TARGET_ON_PROPERTY_WARNING, + "''@{0}:'' annotations could be applied only to property declarations. It will be an error in a future release. See https://youtrack.jetbrains.com/issue/KT-15470", + TO_STRING); MAP.put(INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE, "''@{0}:'' annotations could be applied only to mutable properties", TO_STRING); MAP.put(INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE, "'@delegate:' annotations could be applied only to delegated properties"); MAP.put(INAPPLICABLE_TARGET_PROPERTY_HAS_NO_BACKING_FIELD, "'@field:' annotations could be applied only to properties with backing fields"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationUseSiteTargetChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationUseSiteTargetChecker.kt index 0f1f2d95d3c..4e238ddde0f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationUseSiteTargetChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationUseSiteTargetChecker.kt @@ -5,12 +5,14 @@ package org.jetbrains.kotlin.resolve +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget +import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1 import org.jetbrains.kotlin.diagnostics.Errors.* import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnce import org.jetbrains.kotlin.psi.* @@ -23,7 +25,7 @@ object AnnotationUseSiteTargetChecker { trace: BindingTrace, languageVersionSettings: LanguageVersionSettings ) { - trace.checkDeclaration(annotated, descriptor) + trace.checkDeclaration(annotated, languageVersionSettings, descriptor) if (annotated is KtCallableDeclaration) { annotated.receiverTypeReference?.let { trace.checkTypeReference(it, languageVersionSettings, isReceiver = true) } @@ -35,7 +37,7 @@ object AnnotationUseSiteTargetChecker { if (parameter.hasValOrVar()) continue val parameterDescriptor = trace.bindingContext[BindingContext.VALUE_PARAMETER, parameter] ?: continue - trace.checkDeclaration(parameter, parameterDescriptor) + trace.checkDeclaration(parameter, languageVersionSettings, parameterDescriptor) parameter.typeReference?.let { trace.checkTypeReference(it, languageVersionSettings, isReceiver = false) } } } @@ -75,7 +77,11 @@ object AnnotationUseSiteTargetChecker { } } - private fun BindingTrace.checkDeclaration(annotated: KtAnnotated, descriptor: DeclarationDescriptor) { + private fun BindingTrace.checkDeclaration( + annotated: KtAnnotated, + languageVersionSettings: LanguageVersionSettings, + descriptor: DeclarationDescriptor + ) { for (annotation in annotated.annotationEntries) { val useSiteTarget = annotation.useSiteTarget val target = useSiteTarget?.getAnnotationUseSiteTarget() ?: continue @@ -83,8 +89,14 @@ object AnnotationUseSiteTargetChecker { when (target) { AnnotationUseSiteTarget.FIELD -> checkIfHasBackingField(annotated, descriptor, annotation) AnnotationUseSiteTarget.PROPERTY, - AnnotationUseSiteTarget.PROPERTY_GETTER -> { - } + AnnotationUseSiteTarget.PROPERTY_GETTER -> checkIfProperty( + annotated, + annotation, + when (languageVersionSettings.supportsFeature(LanguageFeature.ProhibitUseSiteGetTargetAnnotations)) { + true -> INAPPLICABLE_TARGET_ON_PROPERTY + false -> INAPPLICABLE_TARGET_ON_PROPERTY_WARNING + } + ) AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD -> checkIfDelegatedProperty(annotated, annotation) AnnotationUseSiteTarget.PROPERTY_SETTER -> checkIfMutableProperty(annotated, annotation) AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER -> { @@ -129,7 +141,7 @@ object AnnotationUseSiteTargetChecker { useSiteTarget?.getAnnotationUseSiteTarget()?.renderName ?: "unknown target" // should not happen private fun BindingTrace.checkIfMutableProperty(annotated: KtAnnotated, annotation: KtAnnotationEntry) { - if (!checkIfProperty(annotated, annotation)) return + if (!checkIfProperty(annotated, annotation, INAPPLICABLE_TARGET_ON_PROPERTY)) return val isMutable = when (annotated) { is KtProperty -> annotated.isVar @@ -142,14 +154,18 @@ object AnnotationUseSiteTargetChecker { } } - private fun BindingTrace.checkIfProperty(annotated: KtAnnotated, annotation: KtAnnotationEntry): Boolean { + private fun BindingTrace.checkIfProperty( + annotated: KtAnnotated, + annotation: KtAnnotationEntry, + diagnosticFactory: DiagnosticFactory1 + ): Boolean { val isProperty = when (annotated) { is KtProperty -> !annotated.isLocal is KtParameter -> annotated.hasValOrVar() else -> false } - if (!isProperty) report(INAPPLICABLE_TARGET_ON_PROPERTY.on(annotation, annotation.useSiteDescription())) + if (!isProperty) report(diagnosticFactory.on(annotation, annotation.useSiteDescription())) return isProperty } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/GetterAnnotations.fir.kt b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/GetterAnnotations.fir.kt index 9510423cb9e..2c9978285cd 100644 --- a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/GetterAnnotations.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/GetterAnnotations.fir.kt @@ -6,10 +6,10 @@ class CustomDelegate { operator fun getValue(thisRef: Any?, prop: KProperty<*>): String = prop.name } -@get:Ann +@get:Ann class SomeClass { - @get:Ann + @get:Ann constructor() @get:Ann @@ -28,11 +28,14 @@ class SomeClass { val propertyWithCustomGetter: Int get() = 5 - @get:Ann + val useSiteTarget: Int + @get:Ann get() = 5 + + @get:Ann fun annotationOnFunction(a: Int) = a + 5 fun anotherFun() { - @get:Ann + @get:Ann val localVariable = 5 } diff --git a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/GetterAnnotations.kt b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/GetterAnnotations.kt index 9510423cb9e..c3fcc0a322d 100644 --- a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/GetterAnnotations.kt +++ b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/GetterAnnotations.kt @@ -6,10 +6,10 @@ class CustomDelegate { operator fun getValue(thisRef: Any?, prop: KProperty<*>): String = prop.name } -@get:Ann +@get:Ann class SomeClass { - @get:Ann + @get:Ann constructor() @get:Ann @@ -28,11 +28,14 @@ class SomeClass { val propertyWithCustomGetter: Int get() = 5 - @get:Ann + val useSiteTarget: Int + @get:Ann get() = 5 + + @get:Ann fun annotationOnFunction(a: Int) = a + 5 fun anotherFun() { - @get:Ann + @get:Ann val localVariable = 5 } diff --git a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/GetterAnnotations.txt b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/GetterAnnotations.txt index 2eb9a4d16d6..ae23dfea363 100644 --- a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/GetterAnnotations.txt +++ b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/GetterAnnotations.txt @@ -22,6 +22,7 @@ public final class CustomDelegate { @get:Ann public final val propertyWithCustomGetter: kotlin.Int @get:Ann protected final val simpleProperty: kotlin.String = "text" @get:Ann protected final val simplePropertyWithAnnotationList: kotlin.String = "text" + public final val useSiteTarget: kotlin.Int public final fun annotationOnFunction(/*0*/ a: kotlin.Int): kotlin.Int public final fun anotherFun(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean diff --git a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/PropertyAnnotations.fir.kt b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/PropertyAnnotations.fir.kt index aa5989a5fda..da19600281d 100644 --- a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/PropertyAnnotations.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/PropertyAnnotations.fir.kt @@ -7,10 +7,10 @@ class CustomDelegate { operator fun getValue(thisRef: Any?, prop: KProperty<*>): String = prop.name } -@property:Ann +@property:Ann class SomeClass { - @property:Ann + @property:Ann constructor(s: String) @property:Ann @@ -30,9 +30,9 @@ class SomeClass { get() = 5 set(v) {} - @property:Ann + @property:Ann fun anotherFun() { - @property:Ann + @property:Ann val localVariable = 5 } diff --git a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/PropertyAnnotations.kt b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/PropertyAnnotations.kt index aa5989a5fda..a27df69214c 100644 --- a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/PropertyAnnotations.kt +++ b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/PropertyAnnotations.kt @@ -7,10 +7,10 @@ class CustomDelegate { operator fun getValue(thisRef: Any?, prop: KProperty<*>): String = prop.name } -@property:Ann +@property:Ann class SomeClass { - @property:Ann + @property:Ann constructor(s: String) @property:Ann @@ -30,9 +30,9 @@ class SomeClass { get() = 5 set(v) {} - @property:Ann + @property:Ann fun anotherFun() { - @property:Ann + @property:Ann val localVariable = 5 } diff --git a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/prohibitUseSiteGetTargetAnnotationsOff.kt b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/prohibitUseSiteGetTargetAnnotationsOff.kt new file mode 100644 index 00000000000..df9a709491c --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/prohibitUseSiteGetTargetAnnotationsOff.kt @@ -0,0 +1,27 @@ +// FIR_IDENTICAL +// !LANGUAGE: -ProhibitUseSiteGetTargetAnnotations +annotation class Ann + +@get:Ann +@set:Ann +@Ann +var mutableProperty: Int = 42 + @get:Ann get + @set:Ann set + +@get:Ann +@set:Ann +@Ann +var mutableProperty_AnnWithoutTarget: Int = 42 + @Ann get + @Ann set + +@get:Ann +@Ann +val immutableProperty: Int = 42 + @get:Ann get + +@get:Ann +@Ann +val immutableProperty_AnnWithoutTarget: Int = 42 + @Ann get diff --git a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/prohibitUseSiteGetTargetAnnotationsOn.kt b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/prohibitUseSiteGetTargetAnnotationsOn.kt new file mode 100644 index 00000000000..4172079dce3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/prohibitUseSiteGetTargetAnnotationsOn.kt @@ -0,0 +1,27 @@ +// FIR_IDENTICAL +// !LANGUAGE: +ProhibitUseSiteGetTargetAnnotations +annotation class Ann + +@get:Ann +@set:Ann +@Ann +var mutableProperty: Int = 42 + @get:Ann get + @set:Ann set + +@get:Ann +@set:Ann +@Ann +var mutableProperty_AnnWithoutTarget: Int = 42 + @Ann get + @Ann set + +@get:Ann +@Ann +val immutableProperty: Int = 42 + @get:Ann get + +@get:Ann +@Ann +val immutableProperty_AnnWithoutTarget: Int = 42 + @Ann get diff --git a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/repeatable.fir.kt b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/repeatable.fir.kt index 6f548b52d68..61b43ad75e9 100644 --- a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/repeatable.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/repeatable.fir.kt @@ -53,7 +53,7 @@ public class B(@param:fieldOrPro @getSetAndParamAnn @setparam:getSetAndParamAnn var w: Int - @getSetAndParamAnn @get:getSetAndParamAnn get() = 0 + @getSetAndParamAnn @get:getSetAndParamAnn get() = 0 // See KT-15470: fake INAPPLICABLE_TARGET_ON_PROPERTY @getSetAndParamAnn @set:getSetAndParamAnn set(arg) {} } diff --git a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/repeatable.kt b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/repeatable.kt index f287fc92fba..87873703ee7 100644 --- a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/repeatable.kt +++ b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/repeatable.kt @@ -53,7 +53,7 @@ public class B(@param:fieldOrPro @getSetAndParamAnn @setparam:getSetAndParamAnn var w: Int - @getSetAndParamAnn @get:getSetAndParamAnn get() = 0 + @getSetAndParamAnn @get:getSetAndParamAnn get() = 0 // See KT-15470: fake INAPPLICABLE_TARGET_ON_PROPERTY @getSetAndParamAnn @set:getSetAndParamAnn set(arg) {} } diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 5a82416ee7b..caa4b14f780 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -2673,6 +2673,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/ParamAnnotations.kt"); } + @Test + @TestMetadata("prohibitUseSiteGetTargetAnnotationsOff.kt") + public void testProhibitUseSiteGetTargetAnnotationsOff() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/prohibitUseSiteGetTargetAnnotationsOff.kt"); + } + + @Test + @TestMetadata("prohibitUseSiteGetTargetAnnotationsOn.kt") + public void testProhibitUseSiteGetTargetAnnotationsOn() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/prohibitUseSiteGetTargetAnnotationsOn.kt"); + } + @Test @TestMetadata("PropertyAnnotations.kt") public void testPropertyAnnotations() throws Exception { diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 2e5b697e8c3..d3fb18bab28 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -286,6 +286,7 @@ enum class LanguageFeature( AllowEmptyIntersectionsInResultTypeResolver(KOTLIN_2_0, kind = OTHER), // KT-51221 ProhibitSmartcastsOnPropertyFromAlienBaseClassInheritedInInvisibleClass(KOTLIN_2_0, kind = BUG_FIX), // KT-57290 ForbidInferringPostponedTypeVariableIntoDeclaredUpperBound(KOTLIN_2_0, kind = BUG_FIX), // KT-47986 + ProhibitUseSiteGetTargetAnnotations(KOTLIN_2_0, kind = BUG_FIX), // KT-15470 // End of 2.* language features --------------------------------------------------