From c1ef0bfcdba1d803ffb95dbbe4bcaa688ce853cd Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Wed, 17 May 2017 16:04:29 +0300 Subject: [PATCH] Report deprecation on usage of type alias expanded to a deprecated class #KT-15243 Fixed --- .../kotlin/resolve/deprecationUtil.kt | 25 +++++++++++++------ .../tests/deprecated/typealiasConstructor.kt | 5 +++- .../tests/deprecated/typealiasConstructor.txt | 3 +++ .../deprecated/typealiasForDeprecatedClass.kt | 10 ++++++++ .../typealiasForDeprecatedClass.txt | 15 +++++++++++ .../checkers/DiagnosticsTestGenerated.java | 6 +++++ 6 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/deprecated/typealiasForDeprecatedClass.kt create mode 100644 compiler/testData/diagnostics/tests/deprecated/typealiasForDeprecatedClass.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt index 952907185a3..e803a77fec4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt @@ -37,6 +37,8 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.SinceKotlinInfo +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.utils.SmartList private val JAVA_DEPRECATED = FqName("java.lang.Deprecated") @@ -143,6 +145,16 @@ fun DeclarationDescriptor.getDeprecations(languageVersionSettings: LanguageVersi return emptyList() } +private fun KotlinType.deprecationsByConstituentTypes(languageVersionSettings: LanguageVersionSettings): List = + SmartList().also { deprecations -> + TypeUtils.contains(this) { type -> + type.constructor.declarationDescriptor?.run { + deprecations.addAll(getDeprecations(languageVersionSettings)) + } + false + } + } + private fun deprecationByOverridden(root: CallableMemberDescriptor, languageVersionSettings: LanguageVersionSettings): Deprecation? { val visited = HashSet() val deprecations = LinkedHashSet() @@ -177,13 +189,6 @@ private fun deprecationByOverridden(root: CallableMemberDescriptor, languageVers } private fun DeclarationDescriptor.getOwnDeprecations(languageVersionSettings: LanguageVersionSettings): List { - if (this is TypeAliasConstructorDescriptor) { - // Constructor of type alias has no annotations by itself, all its annotations come from the aliased constructor - // and from the typealias declaration - return underlyingConstructorDescriptor.getOwnDeprecations(languageVersionSettings) + - typeAliasDescriptor.getOwnDeprecations(languageVersionSettings) - } - // The problem is that declaration `mod` in built-ins has @Deprecated annotation but actually it was deprecated only in version 1.1 if (this is FunctionDescriptor && this.isOperatorMod() && this.hasSubpackageOfKotlin()) { if (!shouldWarnAboutDeprecatedModFromBuiltIns(languageVersionSettings)) { @@ -227,6 +232,12 @@ private fun DeclarationDescriptor.getOwnDeprecations(languageVersionSettings: La addUseSiteTargetedDeprecationIfPresent(this, AnnotationUseSiteTarget.getAssociatedUseSiteTarget(this)) when (this) { + is TypeAliasDescriptor -> { + result.addAll(expandedType.deprecationsByConstituentTypes(languageVersionSettings)) + } + is TypeAliasConstructorDescriptor -> { + result.addAll(typeAliasDescriptor.getOwnDeprecations(languageVersionSettings)) + } is ConstructorDescriptor -> { addDeprecationIfPresent(containingDeclaration) } diff --git a/compiler/testData/diagnostics/tests/deprecated/typealiasConstructor.kt b/compiler/testData/diagnostics/tests/deprecated/typealiasConstructor.kt index a3735aa78c3..b47cd33d008 100644 --- a/compiler/testData/diagnostics/tests/deprecated/typealiasConstructor.kt +++ b/compiler/testData/diagnostics/tests/deprecated/typealiasConstructor.kt @@ -8,7 +8,10 @@ open class WithDeprecatedCtor(val x: Int) { typealias DeprecatedClassAlias = DeprecatedClass typealias WithDeprecatedCtorAlias = WithDeprecatedCtor +typealias ArrayListOfDeprecatedClass = ArrayList<DeprecatedClass> class Test1 : DeprecatedClassAlias() -class Test2 : WithDeprecatedCtorAlias() \ No newline at end of file +class Test2 : WithDeprecatedCtorAlias() + +val test3 = ArrayListOfDeprecatedClass() \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/deprecated/typealiasConstructor.txt b/compiler/testData/diagnostics/tests/deprecated/typealiasConstructor.txt index f48baacaea2..2737eabbc19 100644 --- a/compiler/testData/diagnostics/tests/deprecated/typealiasConstructor.txt +++ b/compiler/testData/diagnostics/tests/deprecated/typealiasConstructor.txt @@ -1,5 +1,7 @@ package +public val test3: ArrayListOfDeprecatedClass /* = java.util.ArrayList */ + @kotlin.Deprecated(message = "Deprecated class") public open class DeprecatedClass { public constructor DeprecatedClass() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean @@ -30,5 +32,6 @@ public open class WithDeprecatedCtor { public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } +public typealias ArrayListOfDeprecatedClass = kotlin.collections.ArrayList public typealias DeprecatedClassAlias = DeprecatedClass public typealias WithDeprecatedCtorAlias = WithDeprecatedCtor diff --git a/compiler/testData/diagnostics/tests/deprecated/typealiasForDeprecatedClass.kt b/compiler/testData/diagnostics/tests/deprecated/typealiasForDeprecatedClass.kt new file mode 100644 index 00000000000..419fb163c61 --- /dev/null +++ b/compiler/testData/diagnostics/tests/deprecated/typealiasForDeprecatedClass.kt @@ -0,0 +1,10 @@ +@Deprecated("") +class Foo + +typealias Test1 = Foo +typealias Test2 = List<Foo> +typealias Test3 = List<Test2> + +fun use1(b: Test1) = b +fun use2(b: Test2) = b +fun use3(b: Test3) = b \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/deprecated/typealiasForDeprecatedClass.txt b/compiler/testData/diagnostics/tests/deprecated/typealiasForDeprecatedClass.txt new file mode 100644 index 00000000000..18b49254397 --- /dev/null +++ b/compiler/testData/diagnostics/tests/deprecated/typealiasForDeprecatedClass.txt @@ -0,0 +1,15 @@ +package + +public fun use1(/*0*/ b: Test1 /* = Foo */): Test1 /* = Foo */ +public fun use2(/*0*/ b: Test2 /* = kotlin.collections.List */): Test2 /* = kotlin.collections.List */ +public fun use3(/*0*/ b: Test3 /* = kotlin.collections.List */> */): Test3 /* = kotlin.collections.List */> */ + +@kotlin.Deprecated(message = "") public final class Foo { + public constructor Foo() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} +public typealias Test1 = Foo +public typealias Test2 = kotlin.collections.List +public typealias Test3 = kotlin.collections.List diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 8980b4c04c7..e79c1f77214 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -6607,6 +6607,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("typealiasForDeprecatedClass.kt") + public void testTypealiasForDeprecatedClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/deprecated/typealiasForDeprecatedClass.kt"); + doTest(fileName); + } + @TestMetadata("typealiasUsage.kt") public void testTypealiasUsage() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/deprecated/typealiasUsage.kt");