diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 65139905db3..d24b1a3584e 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -17255,6 +17255,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/fir/CustomThrowableMessage.kt"); } + @Test + @TestMetadata("differentSinceKotlin.kt") + public void testDifferentSinceKotlin() throws Exception { + runTest("compiler/testData/codegen/box/fir/differentSinceKotlin.kt"); + } + @Test @TestMetadata("ExtensionAlias.kt") public void testExtensionAlias() throws Exception { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt index 1d957be9005..51cbc1a2784 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt @@ -120,6 +120,18 @@ fun List.getAnnotationsByClassId(classId: ClassId): List List.mapAnnotationsWithClassIdTo( + classId: ClassId, + destination: MutableCollection, + func: (FirAnnotation) -> T +) { + for (annotation in this) { + if (annotation.annotationTypeRef.coneTypeSafe()?.lookupTag?.classId == classId) { + destination.add(func(annotation)) + } + } +} + fun FirExpression.unwrapVarargValue(): List { return when (this) { is FirVarargArgumentsExpression -> arguments diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/deprecationUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/deprecationUtils.kt index bbb6f47cca1..602e43dd1c9 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/deprecationUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/deprecationUtils.kt @@ -25,7 +25,7 @@ import org.jetbrains.kotlin.name.StandardClassIds.Annotations.ParameterNames.dep import org.jetbrains.kotlin.resolve.deprecation.DeprecationInfo import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue import org.jetbrains.kotlin.resolve.deprecation.SimpleDeprecationInfo -import org.jetbrains.kotlin.utils.addToStdlib.safeAs +import org.jetbrains.kotlin.utils.addToStdlib.runUnless fun FirBasedSymbol<*>.getDeprecation(callSite: FirElement?): DeprecationInfo? { return when (this) { @@ -111,20 +111,38 @@ private fun List.extractDeprecationInfoPerUseSite( currentVersion: ApiVersion, fromJava: Boolean ): List> { - val annotations = getAnnotationsByClassId(StandardClassIds.Annotations.Deprecated).map { it to false } + - getAnnotationsByClassId(StandardClassIds.Annotations.Java.Deprecated).map { it to true } + @Suppress("RemoveExplicitTypeArguments") + val annotations = buildList> { + mapAnnotationsWithClassIdTo(StandardClassIds.Annotations.Deprecated, this) { it to false } + mapAnnotationsWithClassIdTo(StandardClassIds.Annotations.Java.Deprecated, this) { it to true } + mapAnnotationsWithClassIdTo(StandardClassIds.Annotations.SinceKotlin, this) { it to false } + } return annotations.mapNotNull { (deprecated, fromJavaAnnotation) -> + if (deprecated.classId == StandardClassIds.Annotations.SinceKotlin) { + val sinceKotlinSingleArgument = deprecated.findArgumentByName(ParameterNames.sinceKotlinVersion) + val apiVersion = ((sinceKotlinSingleArgument as? FirConstExpression<*>)?.value as? String) + ?.let(ApiVersion.Companion::parse) ?: return@mapNotNull null + if (apiVersion <= currentVersion) return@mapNotNull null + val wasExperimental = this.any { it.classId == StandardClassIds.Annotations.WasExperimental } + return@mapNotNull runUnless(wasExperimental) { + deprecated.useSiteTarget to SimpleDeprecationInfo( + deprecationLevel = DeprecationLevelValue.HIDDEN, + propagatesToOverrides = true, + message = null + ) + } + } val deprecationLevel = deprecated.getDeprecationLevel() ?: DeprecationLevelValue.WARNING val deprecatedSinceKotlin = getAnnotationsByClassId(StandardClassIds.Annotations.DeprecatedSinceKotlin).firstOrNull() - fun levelApplied(name: Name, level: DeprecationLevelValue): DeprecationLevelValue? { + fun deprecatedLevelApplied(name: Name, level: DeprecationLevelValue): DeprecationLevelValue? { deprecatedSinceKotlin?.getVersionFromArgument(name)?.takeIf { it <= currentVersion }?.let { return level } return level.takeIf { deprecatedSinceKotlin == null && level == deprecationLevel } } - val appliedLevel = (levelApplied(deprecatedSinceKotlinHiddenSince, DeprecationLevelValue.HIDDEN) - ?: levelApplied(deprecatedSinceKotlinErrorSince, DeprecationLevelValue.ERROR) - ?: levelApplied(deprecatedSinceKotlinWarningSince, DeprecationLevelValue.WARNING)) + val appliedLevel = (deprecatedLevelApplied(deprecatedSinceKotlinHiddenSince, DeprecationLevelValue.HIDDEN) + ?: deprecatedLevelApplied(deprecatedSinceKotlinErrorSince, DeprecationLevelValue.ERROR) + ?: deprecatedLevelApplied(deprecatedSinceKotlinWarningSince, DeprecationLevelValue.WARNING)) appliedLevel?.let { val inheritable = !fromJavaAnnotation && !fromJava diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt index 9e9f12840a9..2ca97a145f8 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt @@ -27,9 +27,12 @@ import org.jetbrains.kotlin.fir.resolve.transformers.* import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.FirUserTypeRef import org.jetbrains.kotlin.fir.types.coneTypeSafe +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.StandardClassIds.Annotations.Deprecated import org.jetbrains.kotlin.name.StandardClassIds.Annotations.DeprecatedSinceKotlin +import org.jetbrains.kotlin.name.StandardClassIds.Annotations.WasExperimental class FirCompilerRequiredAnnotationsResolveProcessor( session: FirSession, @@ -120,6 +123,14 @@ private class FirAnnotationResolveTransformer( ) : FirAbstractAnnotationResolveTransformer, PersistentList>( session, scopeSession ) { + companion object { + private val REQUIRED_ANNOTATIONS: Set = setOf( + Deprecated, DeprecatedSinceKotlin, WasExperimental + ) + + private val REQUIRED_ANNOTATION_NAMES: Set = REQUIRED_ANNOTATIONS.mapTo(mutableSetOf()) { it.shortClassName } + } + private val predicateBasedProvider = session.predicateBasedProvider var acceptableFqNames: Set = emptySet() @@ -156,9 +167,7 @@ private class FirAnnotationResolveTransformer( val annotationTypeRef = annotation.annotationTypeRef if (annotationTypeRef !is FirUserTypeRef) return annotation val name = annotationTypeRef.qualifier.last().name - if (name != Deprecated.shortClassName && name != DeprecatedSinceKotlin.shortClassName && - acceptableFqNames.none { it.shortName() == name } - ) return annotation + if (name !in REQUIRED_ANNOTATION_NAMES && acceptableFqNames.none { it.shortName() == name }) return annotation val transformedAnnotation = annotation.transformAnnotationTypeRef( typeResolverTransformer, diff --git a/compiler/testData/codegen/box/fir/differentSinceKotlin.kt b/compiler/testData/codegen/box/fir/differentSinceKotlin.kt new file mode 100644 index 00000000000..bcdd37edb55 --- /dev/null +++ b/compiler/testData/codegen/box/fir/differentSinceKotlin.kt @@ -0,0 +1,27 @@ +// TARGET_BACKEND: JVM +// !API_VERSION: 1.4 +// WITH_STDLIB +// MODULE: m1 +// FILE: m1.kt + +package kotlin + +@SinceKotlin("1.7") +@kotlin.jvm.JvmName("bar") +@Suppress("CONFLICTING_OVERLOADS") +fun List.foo(): T = this[1] + +// MODULE: m2 +// FILE: m2.kt + +package kotlin + +@Deprecated("") +@DeprecatedSinceKotlin(warningSince = "1.4", errorSince = "1.5", hiddenSince = "1.6") +@Suppress("CONFLICTING_OVERLOADS") +fun List.foo(): T? = getOrNull(0) + +// MODULE: m3(m1, m2) +// FILE: test.kt + +fun box(): String = listOf("OK", "FAIL").foo()!! diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.fir.kt b/compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.fir.kt deleted file mode 100644 index 073ed8d2ca2..00000000000 --- a/compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.fir.kt +++ /dev/null @@ -1,34 +0,0 @@ -// !API_VERSION: 1.0 -// MODULE: m1 -// FILE: a.kt - -package p1 - -@SinceKotlin("1.1") -fun foo(s: Int): String = s.toString() - -// MODULE: m2 -// FILE: b.kt - -package p2 - -fun foo(s: Int): Int = s - -// MODULE: m3(m1, m2) -// FILE: severalStarImports.kt -import p1.* -import p2.* - -fun test1(): Int { - val r = foo(42) - return r -} - -// FILE: explicitlyImportP1.kt -import p1.foo // TODO: consider reporting API_NOT_AVAILABLE here -import p2.* - -fun test2(): Int { - val r = foo(42) - return r -} diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.kt b/compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.kt index 87c398e27f8..7ec9761f48b 100644 --- a/compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.kt +++ b/compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !API_VERSION: 1.0 // MODULE: m1 // FILE: a.kt diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/annotations.fir.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/annotations.fir.kt index a5c28aa873c..2f81f5e6484 100644 --- a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/annotations.fir.kt +++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/annotations.fir.kt @@ -7,5 +7,5 @@ annotation class Anno2 @SinceKotlin("1.1") constructor() @Anno1("") -@Anno2 +@Anno2 fun t1() {} diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/classesAndConstructors.fir.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/classesAndConstructors.fir.kt index 64b5a3678bb..35991b09006 100644 --- a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/classesAndConstructors.fir.kt +++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/classesAndConstructors.fir.kt @@ -16,8 +16,8 @@ fun t1(): Foo = Foo() // TODO: do not report API_NOT_AVAILABLE twice fun t2() = object : Foo() {} -fun t3(): Bar? = Bar() +fun t3(): Bar? = Bar() -fun t4(): Baz = Baz() +fun t4(): Baz = Baz() fun t5(): Quux = Quux() diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/overriddenMembers.fir.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/overriddenMembers.fir.kt index a7a245388c3..c0fac4b7f43 100644 --- a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/overriddenMembers.fir.kt +++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/overriddenMembers.fir.kt @@ -18,14 +18,14 @@ interface I11 { } fun f1(x: I10) = x.foo() -fun f2(x: I11) = x.foo() +fun f2(x: I11) = x.foo() fun f3(x: J) = x.foo() interface BothI1 : I10, I11 fun f4(x: BothI1) = x.foo() interface BothI2 : I11, I10 -fun f5(x: BothI2) = x.foo() +fun f5(x: BothI2) = x.foo() interface JAndI10 : J, I10 fun f6(x: JAndI10) = x.foo() diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/propertyAccessors.fir.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/propertyAccessors.fir.kt index fa394d768ed..b653b0d5bc4 100644 --- a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/propertyAccessors.fir.kt +++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/propertyAccessors.fir.kt @@ -34,15 +34,15 @@ val v7: String get() = "" fun test() { - v1 - v2 - v3 + v1 + v2 + v3 v3 = "" v4 - v4 = "" - v5 - v5 = "" - v6 - v6 = "" - v7 + v4 = "" + v5 + v5 = "" + v6 + v6 = "" + v7 } diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/simpleMembers.fir.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/simpleMembers.fir.kt deleted file mode 100644 index 69a4086b5a8..00000000000 --- a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/simpleMembers.fir.kt +++ /dev/null @@ -1,19 +0,0 @@ -// !API_VERSION: 1.0 - -@SinceKotlin("1.1") -fun f() {} - -@SinceKotlin("1.1") -var p = Unit - -@SinceKotlin("1.1.2") -fun z() {} - - -fun t1() = f() - -fun t2() = p - -fun t3() { p = Unit } - -fun t4() { z() } diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/simpleMembers.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/simpleMembers.kt index 2fb3a53d971..83d0d32472c 100644 --- a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/simpleMembers.kt +++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/simpleMembers.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !API_VERSION: 1.0 @SinceKotlin("1.1") diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/typealiasesAsConstructors.fir.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/typealiasesAsConstructors.fir.kt index 9eb127a0378..7956fb3a45a 100644 --- a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/typealiasesAsConstructors.fir.kt +++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/typealiasesAsConstructors.fir.kt @@ -13,8 +13,8 @@ open class C2(val x: Int) { typealias C2_Alias = C2 val test1 = C1_Alias() -val test2 = C2_Alias() +val test2 = C2_Alias() class Test3 : C1_Alias() -class Test4 : C2_Alias() \ No newline at end of file +class Test4 : C2_Alias() diff --git a/compiler/testData/diagnostics/testsWithStdLib/experimental/wasExperimental.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/experimental/wasExperimental.fir.kt index 4f25d868e43..005f1a1e622 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/experimental/wasExperimental.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/experimental/wasExperimental.fir.kt @@ -31,7 +31,7 @@ fun use1( c1: NewClassExperimentalInThePast, t1: TypeAliasToNewClass ) { - newPublishedFun() + newPublishedFun() newFunExperimentalInThePast() newValExperimentalInThePast NewClassExperimentalInThePast() @@ -42,7 +42,7 @@ fun use2( c2: NewClassExperimentalInThePast, t2: TypeAliasToNewClass ) { - newPublishedFun() + newPublishedFun() newFunExperimentalInThePast() newValExperimentalInThePast NewClassExperimentalInThePast() @@ -53,7 +53,7 @@ fun use3( c3: NewClassExperimentalInThePast, t3: TypeAliasToNewClass ) { - newPublishedFun() + newPublishedFun() newFunExperimentalInThePast() newValExperimentalInThePast NewClassExperimentalInThePast() diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index b9337bea993..7fb0fb73bb0 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -16871,6 +16871,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/fir/ConstValAccess.kt"); } + @Test + @TestMetadata("differentSinceKotlin.kt") + public void testDifferentSinceKotlin() throws Exception { + runTest("compiler/testData/codegen/box/fir/differentSinceKotlin.kt"); + } + @Test @TestMetadata("ExtensionAlias.kt") public void testExtensionAlias() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index c68f6983a6b..d99732be603 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -17255,6 +17255,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/fir/CustomThrowableMessage.kt"); } + @Test + @TestMetadata("differentSinceKotlin.kt") + public void testDifferentSinceKotlin() throws Exception { + runTest("compiler/testData/codegen/box/fir/differentSinceKotlin.kt"); + } + @Test @TestMetadata("ExtensionAlias.kt") public void testExtensionAlias() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index d96c53e302a..e0fa036ed0d 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -13969,6 +13969,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/fir/ConstValAccess.kt"); } + @TestMetadata("differentSinceKotlin.kt") + public void testDifferentSinceKotlin() throws Exception { + runTest("compiler/testData/codegen/box/fir/differentSinceKotlin.kt"); + } + @TestMetadata("ExtensionAlias.kt") public void testExtensionAlias() throws Exception { runTest("compiler/testData/codegen/box/fir/ExtensionAlias.kt"); 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 ebbd78c0806..a1f11c0255b 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt @@ -161,6 +161,8 @@ object StandardClassIds { val RestrictsSuspension = "RestrictsSuspension".coroutinesId() + val WasExperimental = "WasExperimental".baseId() + object Java { val Deprecated = "Deprecated".javaLangId() val Repeatable = "Repeatable".javaAnnotationId()