K1: Force propagating deprecation on NOT_CONSIDERED JDK members to overrides

^KT-60858 Related
KT-60659 In Progress
^KT-60769 In Progress
This commit is contained in:
Denis.Zharkov
2023-07-28 19:59:25 +02:00
committed by Space Team
parent 1e86a82ee1
commit eae97e4f76
9 changed files with 74 additions and 22 deletions
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.BuiltInAnnotationDescriptor
import org.jetbrains.kotlin.metadata.deserialization.VersionRequirement
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.annotations.argumentValue
@@ -23,8 +24,16 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
internal sealed class DeprecatedByAnnotation(
val annotation: AnnotationDescriptor,
override val target: DeclarationDescriptor,
override val propagatesToOverrides: Boolean
final override val propagatesToOverrides: Boolean,
final override val forcePropagationToOverrides: Boolean = false,
) : DescriptorBasedDeprecationInfo() {
init {
require(!forcePropagationToOverrides || propagatesToOverrides) {
"if something is `forcePropagationToOverrides`, it's expected that `propagatesToOverrides` == true, too"
}
}
override val message: String?
get() = (annotation.argumentValue("message") as? StringValue)?.value
@@ -37,8 +46,9 @@ internal sealed class DeprecatedByAnnotation(
class StandardDeprecated(
annotation: AnnotationDescriptor,
target: DeclarationDescriptor,
propagatesToOverrides: Boolean
) : DeprecatedByAnnotation(annotation, target, propagatesToOverrides) {
propagatesToOverrides: Boolean,
forcePropagationToOverrides: Boolean = false,
) : DeprecatedByAnnotation(annotation, target, propagatesToOverrides, forcePropagationToOverrides) {
override val deprecationLevel: DeprecationLevelValue
get() = when ((annotation.argumentValue("level") as? EnumValue)?.enumEntryName?.asString()) {
"WARNING" -> WARNING
@@ -105,7 +115,14 @@ internal sealed class DeprecatedByAnnotation(
val level = computeLevelForDeprecatedSinceKotlin(deprecatedSinceKotlinAnnotation, apiVersion) ?: return null
return DeprecatedSince(deprecatedAnnotation, target, propagatesToOverrides, level)
}
return StandardDeprecated(deprecatedAnnotation, target, propagatesToOverrides)
val forcePropagationToOverrides =
(deprecatedAnnotation as? BuiltInAnnotationDescriptor)?.forcePropagationDeprecationToOverrides == true
return StandardDeprecated(
deprecatedAnnotation,
target,
propagatesToOverrides || forcePropagationToOverrides,
forcePropagationToOverrides = forcePropagationToOverrides
)
}
}
}
@@ -116,6 +133,8 @@ internal data class DeprecatedByOverridden(private val deprecations: Collection<
assert(deprecations.none { it is DeprecatedByOverridden })
}
override val forcePropagationToOverrides: Boolean = deprecations.any { it.forcePropagationToOverrides }
override val deprecationLevel: DeprecationLevelValue = deprecations.map(DescriptorBasedDeprecationInfo::deprecationLevel).minOrNull()!!
override val target: DeclarationDescriptor
@@ -46,7 +46,11 @@ class DeprecationResolver(
val inheritedDeprecations = listOfNotNull(deprecationByOverridden(descriptor))
when (inheritedDeprecations.isNotEmpty()) {
true -> when (languageVersionSettings.supportsFeature(LanguageFeature.StopPropagatingDeprecationThroughOverrides)) {
true -> DeprecationInfo(emptyList(), hasInheritedDeprecations = true, inheritedDeprecations)
true -> DeprecationInfo(
inheritedDeprecations.filter { it.forcePropagationToOverrides },
hasInheritedDeprecations = true,
inheritedDeprecations
)
false -> DeprecationInfo(inheritedDeprecations, hasInheritedDeprecations = true)
}
false -> DeprecationInfo.EMPTY
@@ -167,7 +171,8 @@ class DeprecationResolver(
traverse(root)
if (hasUndeprecatedOverridden || deprecations.isEmpty()) return null
if (deprecations.isEmpty()) return null
if (hasUndeprecatedOverridden && deprecations.none { it.forcePropagationToOverrides }) return null
// We might've filtered out not-propagating deprecations already in the initializer of `deprecationsByAnnotation` in the code above.
// But it would lead to treating Java overridden as not-deprecated at all that works controversially in case of mixed J/K override:
@@ -9,5 +9,5 @@ interface A : MutableCollection<String> {
fun foo(x: MutableCollection<Int>, y: Collection<String>, z: A) {
x.<!DEPRECATION!>nonExistingMethod<!>(1).checkType { _<String>() }
y.<!DEPRECATION!>nonExistingMethod<!>("")
z.nonExistingMethod("")
z.<!DEPRECATION!>nonExistingMethod<!>("")
}
@@ -3,10 +3,10 @@
fun foo(ll: java.util.LinkedList<String>, al: ArrayList<String>, ad: ArrayDeque<String>, jad: java.util.ArrayDeque<String>) {
ll.addFirst("")
ll.addLast("")
ll.getFirst()
ll.<!DEPRECATION!>getFirst<!>()
ll.first // synthetic property for getFirst()
ll.first() // stdlib extension on List
ll.getLast()
ll.<!DEPRECATION!>getLast<!>()
ll.last
ll.last()
ll.<!DEBUG_INFO_CALL("fqName: java.util.LinkedList.removeFirst; typeCall: function")!>removeFirst()<!>
@@ -15,10 +15,10 @@ fun foo(ll: java.util.LinkedList<String>, al: ArrayList<String>, ad: ArrayDeque<
al.addFirst("")
al.addLast("")
al.getFirst()
al.<!DEPRECATION!>getFirst<!>()
al.first
al.first()
al.getLast()
al.<!DEPRECATION!>getLast<!>()
al.last
al.last()
al.<!DEBUG_INFO_CALL("fqName: java.util.ArrayList.removeFirst; typeCall: function")!>removeFirst()<!>
@@ -10,8 +10,8 @@ class A<T> : ArrayList<T>() {
super.addLast(t)
}
override fun <!OVERRIDE_DEPRECATION!>getFirst<!>(): T = super.getFirst()
override fun <!OVERRIDE_DEPRECATION!>getLast<!>(): T = super.getLast()
override fun <!OVERRIDE_DEPRECATION!>getFirst<!>(): T = super.<!DEPRECATION!>getFirst<!>()
override fun <!OVERRIDE_DEPRECATION!>getLast<!>(): T = super.<!DEPRECATION!>getLast<!>()
override fun removeFirst(): T = super.removeFirst()
override fun removeLast(): T = super.removeLast()
@@ -34,10 +34,10 @@ fun foo(x: MutableList<String>, y: ArrayList<String>, z: A<String>) {
y.addFirst("")
y.addLast("")
y.getFirst()
y.<!DEPRECATION!>getFirst<!>()
y.first
y.first()
y.getLast()
y.<!DEPRECATION!>getLast<!>()
y.last
y.last()
y.<!DEBUG_INFO_CALL("fqName: java.util.ArrayList.removeFirst; typeCall: function")!>removeFirst()<!>
@@ -46,10 +46,10 @@ fun foo(x: MutableList<String>, y: ArrayList<String>, z: A<String>) {
z.addFirst("")
z.addLast("")
z.getFirst()
z.<!DEPRECATION!>getFirst<!>()
z.first
z.first()
z.getLast()
z.<!DEPRECATION!>getLast<!>()
z.last
z.last()
z.<!DEBUG_INFO_CALL("fqName: A.removeFirst; typeCall: function")!>removeFirst()<!>