K1: Report deprecation on synthetic properties for NOT_CONSIDERED JDK members

Currently, for other synthetic properties, deprecation from the original
method is already being propagated to the relevant new synthetic
property accessor.

But what we need is also reporting warnings on synthetic properties
accessors call-sites if original methods are considered deprecated
as a result of deprecation propagation.

KT-60659 Fixed
^KT-60769 Fixed
This commit is contained in:
Denis.Zharkov
2023-07-28 19:56:10 +02:00
committed by Space Team
parent eae97e4f76
commit 0694ee50a3
11 changed files with 252 additions and 27 deletions
@@ -20745,6 +20745,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/j+k/deprecations"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform");
}
@Test
@TestMetadata("doNotMarkWriteIfGetterDeprecated.kt")
public void testDoNotMarkWriteIfGetterDeprecated() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/deprecations/doNotMarkWriteIfGetterDeprecated.kt");
}
@Test
@TestMetadata("forFakeOverrides.kt")
public void testForFakeOverrides() throws Exception {
@@ -20762,6 +20768,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
public void testForOverrides() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/deprecations/forOverrides.kt");
}
@Test
@TestMetadata("forSyntheticPropertyOverrides.kt")
public void testForSyntheticPropertyOverrides() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/deprecations/forSyntheticPropertyOverrides.kt");
}
}
@Nested
@@ -20745,6 +20745,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/j+k/deprecations"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform");
}
@Test
@TestMetadata("doNotMarkWriteIfGetterDeprecated.kt")
public void testDoNotMarkWriteIfGetterDeprecated() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/deprecations/doNotMarkWriteIfGetterDeprecated.kt");
}
@Test
@TestMetadata("forFakeOverrides.kt")
public void testForFakeOverrides() throws Exception {
@@ -20762,6 +20768,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
public void testForOverrides() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/deprecations/forOverrides.kt");
}
@Test
@TestMetadata("forSyntheticPropertyOverrides.kt")
public void testForSyntheticPropertyOverrides() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/deprecations/forSyntheticPropertyOverrides.kt");
}
}
@Nested
@@ -20745,6 +20745,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/j+k/deprecations"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform");
}
@Test
@TestMetadata("doNotMarkWriteIfGetterDeprecated.kt")
public void testDoNotMarkWriteIfGetterDeprecated() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/deprecations/doNotMarkWriteIfGetterDeprecated.kt");
}
@Test
@TestMetadata("forFakeOverrides.kt")
public void testForFakeOverrides() throws Exception {
@@ -20762,6 +20768,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
public void testForOverrides() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/deprecations/forOverrides.kt");
}
@Test
@TestMetadata("forSyntheticPropertyOverrides.kt")
public void testForSyntheticPropertyOverrides() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/deprecations/forSyntheticPropertyOverrides.kt");
}
}
@Nested
@@ -20751,6 +20751,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/j+k/deprecations"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform");
}
@Test
@TestMetadata("doNotMarkWriteIfGetterDeprecated.kt")
public void testDoNotMarkWriteIfGetterDeprecated() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/deprecations/doNotMarkWriteIfGetterDeprecated.kt");
}
@Test
@TestMetadata("forFakeOverrides.kt")
public void testForFakeOverrides() throws Exception {
@@ -20768,6 +20774,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
public void testForOverrides() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/deprecations/forOverrides.kt");
}
@Test
@TestMetadata("forSyntheticPropertyOverrides.kt")
public void testForSyntheticPropertyOverrides() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/deprecations/forSyntheticPropertyOverrides.kt");
}
}
@Nested
@@ -39,27 +39,50 @@ class DeprecationResolver(
) {
private val deprecations: MemoizedFunctionToNotNull<DeclarationDescriptor, DeprecationInfo> =
storageManager.createMemoizedFunction { descriptor ->
val deprecations = descriptor.getOwnDeprecations()
when {
deprecations.isNotEmpty() -> DeprecationInfo(deprecations, hasInheritedDeprecations = false)
descriptor is CallableMemberDescriptor -> {
val inheritedDeprecations = listOfNotNull(deprecationByOverridden(descriptor))
when (inheritedDeprecations.isNotEmpty()) {
true -> when (languageVersionSettings.supportsFeature(LanguageFeature.StopPropagatingDeprecationThroughOverrides)) {
true -> DeprecationInfo(
inheritedDeprecations.filter { it.forcePropagationToOverrides },
hasInheritedDeprecations = true,
inheritedDeprecations
)
false -> DeprecationInfo(inheritedDeprecations, hasInheritedDeprecations = true)
}
false -> DeprecationInfo.EMPTY
}
}
else -> DeprecationInfo.EMPTY
}
computeDeprecation(descriptor)
}
private fun computeDeprecation(descriptor: DeclarationDescriptor): DeprecationInfo {
val deprecations = descriptor.getOwnDeprecations()
return when {
deprecations.isNotEmpty() -> DeprecationInfo(deprecations, hasInheritedDeprecations = false)
descriptor is PropertyAccessorDescriptor && descriptor.correspondingProperty is SyntheticPropertyDescriptor -> {
val syntheticProperty = descriptor.correspondingProperty as SyntheticPropertyDescriptor
val originalMethod =
if (descriptor is PropertyGetterDescriptor) syntheticProperty.getMethod else syntheticProperty.setMethod
@Suppress("FoldInitializerAndIfToElvis") // Wait until KTIJ-26450 is fixed
if (originalMethod == null) return DeprecationInfo.EMPTY
val originalMethodDeprecationInfo = deprecations(originalMethod)
// Limiting these new (they didn't exist before 1.9.10) deprecations only to WARNING and forcePropagationToOverrides
// (i.e., for overrides of NOT_CONSIDERED JDK members)
// is deliberate once we would like to reduce the scope of affected usages because otherwise
// it might be a big unexpected breaking change for users who are enabled -Werror flag.
val filteredDeprecations =
originalMethodDeprecationInfo.deprecations.filter {
it.deprecationLevel == DeprecationLevelValue.WARNING && it.forcePropagationToOverrides
}
return originalMethodDeprecationInfo.copy(deprecations = filteredDeprecations)
}
descriptor is CallableMemberDescriptor -> {
val inheritedDeprecations = listOfNotNull(deprecationByOverridden(descriptor))
when (inheritedDeprecations.isNotEmpty()) {
true -> when (languageVersionSettings.supportsFeature(LanguageFeature.StopPropagatingDeprecationThroughOverrides)) {
true -> DeprecationInfo(
inheritedDeprecations.filter { it.forcePropagationToOverrides },
hasInheritedDeprecations = true,
inheritedDeprecations
)
false -> DeprecationInfo(inheritedDeprecations, hasInheritedDeprecations = true)
}
false -> DeprecationInfo.EMPTY
}
}
else -> DeprecationInfo.EMPTY
}
}
private data class DeprecationInfo(
val deprecations: List<DescriptorBasedDeprecationInfo>,
val hasInheritedDeprecations: Boolean,
@@ -0,0 +1,51 @@
// LANGUAGE: -StopPropagatingDeprecationThroughOverrides
// FILE: JavaClass.java
public class JavaClass {
@Deprecated
public String getFoo() { return ""; }
public void setFoo(String x) {}
}
// FILE: main.kt
open class KotlinClass : JavaClass() {
@Deprecated("")
override fun getFoo(): String {
return super.<!DEPRECATION!>getFoo<!>()
}
override fun setFoo(x: String?) {
super.setFoo(x)
}
}
class KotlinSubClass : KotlinClass() {
override fun <!OVERRIDE_DEPRECATION!>getFoo<!>(): String {
return super.<!DEPRECATION!>getFoo<!>()
}
override fun setFoo(x: String?) {
super.setFoo(x)
}
}
fun main(j: JavaClass, k: KotlinClass, ks: KotlinSubClass) {
j.<!DEPRECATION!>getFoo<!>()
j.setFoo("")
j.<!DEPRECATION!>foo<!>
j.foo = ""
k.<!DEPRECATION!>getFoo<!>()
k.setFoo("")
k.<!DEPRECATION!>foo<!>
k.foo = ""
ks.getFoo()
ks.setFoo("")
ks.foo
ks.foo = ""
}
@@ -0,0 +1,51 @@
// LANGUAGE: -StopPropagatingDeprecationThroughOverrides
// FILE: JavaClass.java
public class JavaClass {
@Deprecated
public String getFoo() { return ""; }
public void setFoo(String x) {}
}
// FILE: main.kt
open class KotlinClass : JavaClass() {
@Deprecated("")
override fun getFoo(): String {
return super.<!DEPRECATION!>getFoo<!>()
}
override fun setFoo(x: String?) {
super.setFoo(x)
}
}
class KotlinSubClass : KotlinClass() {
override fun <!OVERRIDE_DEPRECATION!>getFoo<!>(): String {
return super.<!DEPRECATION!>getFoo<!>()
}
override fun setFoo(x: String?) {
super.setFoo(x)
}
}
fun main(j: JavaClass, k: KotlinClass, ks: KotlinSubClass) {
j.<!DEPRECATION!>getFoo<!>()
j.setFoo("")
j.<!DEPRECATION!>foo<!>
j.foo = ""
k.<!DEPRECATION!>getFoo<!>()
k.setFoo("")
k.<!DEPRECATION!>foo<!>
k.foo = ""
ks.<!DEPRECATION!>getFoo<!>()
ks.setFoo("")
ks.foo
ks.foo = ""
}
@@ -0,0 +1,40 @@
// FIR_IDENTICAL
// LANGUAGE: -StopPropagatingDeprecationThroughOverrides
// FILE: JavaClass.java
public class JavaClass {
public String getFoo() { return ""; }
public String getBar() { return ""; }
}
// FILE: main.kt
open class KotlinClass : JavaClass() {
@Deprecated("sdas")
override fun getFoo(): String {
return super.getFoo()
}
@Deprecated("dasd", level = DeprecationLevel.ERROR)
override fun getBar(): String {
return super.getBar()
}
}
class KotlinSubClass : KotlinClass() {
override fun <!OVERRIDE_DEPRECATION!>getFoo<!>(): String {
return super.<!DEPRECATION!>getFoo<!>()
}
override fun <!OVERRIDE_DEPRECATION!>getBar<!>(): String {
return super.<!DEPRECATION_ERROR!>getBar<!>()
}
}
fun main(kotlinClass: KotlinClass, kotlinSubClass: KotlinSubClass) {
kotlinClass.<!DEPRECATION!>foo<!>
kotlinClass.<!DEPRECATION_ERROR!>bar<!>
kotlinSubClass.foo
kotlinSubClass.bar
}
@@ -4,10 +4,10 @@ fun foo(ll: java.util.LinkedList<String>, al: ArrayList<String>, ad: ArrayDeque<
ll.addFirst("")
ll.addLast("")
ll.<!DEPRECATION!>getFirst<!>()
ll.first // synthetic property for getFirst()
ll.<!DEPRECATION!>first<!> // synthetic property for getFirst()
ll.first() // stdlib extension on List
ll.<!DEPRECATION!>getLast<!>()
ll.last
ll.<!DEPRECATION!>last<!>
ll.last()
ll.<!DEBUG_INFO_CALL("fqName: java.util.LinkedList.removeFirst; typeCall: function")!>removeFirst()<!>
ll.<!DEBUG_INFO_CALL("fqName: java.util.LinkedList.removeLast; typeCall: function")!>removeLast()<!>
@@ -16,10 +16,10 @@ fun foo(ll: java.util.LinkedList<String>, al: ArrayList<String>, ad: ArrayDeque<
al.addFirst("")
al.addLast("")
al.<!DEPRECATION!>getFirst<!>()
al.first
al.<!DEPRECATION!>first<!>
al.first()
al.<!DEPRECATION!>getLast<!>()
al.last
al.<!DEPRECATION!>last<!>
al.last()
al.<!DEBUG_INFO_CALL("fqName: java.util.ArrayList.removeFirst; typeCall: function")!>removeFirst()<!>
al.<!DEBUG_INFO_CALL("fqName: java.util.ArrayList.removeLast; typeCall: function")!>removeLast()<!>
@@ -35,10 +35,10 @@ fun foo(x: MutableList<String>, y: ArrayList<String>, z: A<String>) {
y.addFirst("")
y.addLast("")
y.<!DEPRECATION!>getFirst<!>()
y.first
y.<!DEPRECATION!>first<!>
y.first()
y.<!DEPRECATION!>getLast<!>()
y.last
y.<!DEPRECATION!>last<!>
y.last()
y.<!DEBUG_INFO_CALL("fqName: java.util.ArrayList.removeFirst; typeCall: function")!>removeFirst()<!>
y.<!DEBUG_INFO_CALL("fqName: java.util.ArrayList.removeLast; typeCall: function")!>removeLast()<!>
@@ -47,10 +47,10 @@ fun foo(x: MutableList<String>, y: ArrayList<String>, z: A<String>) {
z.addFirst("")
z.addLast("")
z.<!DEPRECATION!>getFirst<!>()
z.first
z.<!DEPRECATION!>first<!>
z.first()
z.<!DEPRECATION!>getLast<!>()
z.last
z.<!DEPRECATION!>last<!>
z.last()
z.<!DEBUG_INFO_CALL("fqName: A.removeFirst; typeCall: function")!>removeFirst()<!>
z.<!DEBUG_INFO_CALL("fqName: A.removeLast; typeCall: function")!>removeLast()<!>
@@ -20751,6 +20751,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/j+k/deprecations"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true);
}
@Test
@TestMetadata("doNotMarkWriteIfGetterDeprecated.kt")
public void testDoNotMarkWriteIfGetterDeprecated() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/deprecations/doNotMarkWriteIfGetterDeprecated.kt");
}
@Test
@TestMetadata("forFakeOverrides.kt")
public void testForFakeOverrides() throws Exception {
@@ -20768,6 +20774,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
public void testForOverrides() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/deprecations/forOverrides.kt");
}
@Test
@TestMetadata("forSyntheticPropertyOverrides.kt")
public void testForSyntheticPropertyOverrides() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/deprecations/forSyntheticPropertyOverrides.kt");
}
}
@Nested