FIR: handle 'SinceKotlin' as a special kind of deprecated
#KT-51850 Fixed
This commit is contained in:
committed by
teamcity
parent
07b5bd72ae
commit
9bd6a9c069
+6
@@ -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 {
|
||||
|
||||
+12
@@ -120,6 +120,18 @@ fun List<FirAnnotation>.getAnnotationsByClassId(classId: ClassId): List<FirAnnot
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <T> List<FirAnnotation>.mapAnnotationsWithClassIdTo(
|
||||
classId: ClassId,
|
||||
destination: MutableCollection<T>,
|
||||
func: (FirAnnotation) -> T
|
||||
) {
|
||||
for (annotation in this) {
|
||||
if (annotation.annotationTypeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.classId == classId) {
|
||||
destination.add(func(annotation))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun FirExpression.unwrapVarargValue(): List<FirExpression> {
|
||||
return when (this) {
|
||||
is FirVarargArgumentsExpression -> arguments
|
||||
|
||||
+25
-7
@@ -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<FirAnnotation>.extractDeprecationInfoPerUseSite(
|
||||
currentVersion: ApiVersion,
|
||||
fromJava: Boolean
|
||||
): List<Pair<AnnotationUseSiteTarget?, DeprecationInfo>> {
|
||||
val annotations = getAnnotationsByClassId(StandardClassIds.Annotations.Deprecated).map { it to false } +
|
||||
getAnnotationsByClassId(StandardClassIds.Annotations.Java.Deprecated).map { it to true }
|
||||
@Suppress("RemoveExplicitTypeArguments")
|
||||
val annotations = buildList<Pair<FirAnnotation, Boolean>> {
|
||||
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
|
||||
|
||||
+12
-3
@@ -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<Multimap<AnnotationFqn, FirRegularClass>, PersistentList<FirDeclaration>>(
|
||||
session, scopeSession
|
||||
) {
|
||||
companion object {
|
||||
private val REQUIRED_ANNOTATIONS: Set<ClassId> = setOf(
|
||||
Deprecated, DeprecatedSinceKotlin, WasExperimental
|
||||
)
|
||||
|
||||
private val REQUIRED_ANNOTATION_NAMES: Set<Name> = REQUIRED_ANNOTATIONS.mapTo(mutableSetOf()) { it.shortClassName }
|
||||
}
|
||||
|
||||
private val predicateBasedProvider = session.predicateBasedProvider
|
||||
|
||||
var acceptableFqNames: Set<AnnotationFqn> = 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,
|
||||
|
||||
Reference in New Issue
Block a user