From 6393ac5871491436412567b37242be02f7c9378b Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 14 Dec 2016 16:46:49 +0300 Subject: [PATCH] Check language version for deprecation via SinceKotlinInfo --- .../org/jetbrains/kotlin/codegen/AsmUtil.java | 9 ++++-- .../calls/checkers/DeprecatedCallChecker.kt | 4 +-- .../DeprecatedClassifierUsageChecker.kt | 3 +- .../kotlin/resolve/deprecationUtil.kt | 29 ++++++++++++------- .../idea/KotlinQuickDocumentationProvider.kt | 22 ++++++++++---- .../OverridingDeprecatedMemberInspection.kt | 5 +++- 6 files changed, 48 insertions(+), 24 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java index 950974d7af4..609c105410c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods; import org.jetbrains.kotlin.codegen.serialization.JvmStringTable; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; +import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.load.java.JavaVisibilities; @@ -236,9 +237,13 @@ public class AsmUtil { int flags = getVisibilityAccessFlag(functionDescriptor); flags |= getVarargsFlag(functionDescriptor); flags |= getDeprecatedAccessFlag(functionDescriptor); - if (DeprecationUtilKt.isDeprecatedHidden(functionDescriptor) + if (DeprecationUtilKt.isDeprecatedHidden(functionDescriptor, LanguageVersionSettingsImpl.DEFAULT) || functionDescriptor instanceof PropertyAccessorDescriptor - && DeprecationUtilKt.isDeprecatedHidden(((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty())) { + && DeprecationUtilKt.isDeprecatedHidden( + ((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty(), + LanguageVersionSettingsImpl.DEFAULT + ) + ) { flags |= ACC_SYNTHETIC; } return flags; diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/DeprecatedCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/DeprecatedCallChecker.kt index 0195a68a128..2fd5adb5055 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/DeprecatedCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/DeprecatedCallChecker.kt @@ -45,11 +45,11 @@ object DeprecatedCallChecker : CallChecker { // Objects will be checked by DeprecatedClassifierUsageChecker if (targetDescriptor is FakeCallableDescriptorForObject) return - val deprecations = targetDescriptor.getDeprecations().toMutableList() + val deprecations = targetDescriptor.getDeprecations(languageVersionSettings).toMutableList() // avoid duplicating diagnostic when deprecation for property effectively deprecates setter if (targetDescriptor is PropertySetterDescriptor) { - deprecations -= targetDescriptor.correspondingProperty.getDeprecations() + deprecations -= targetDescriptor.correspondingProperty.getDeprecations(languageVersionSettings) } if (deprecations.isNotEmpty()) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/DeprecatedClassifierUsageChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/DeprecatedClassifierUsageChecker.kt index 9055584b59b..bd697c264d8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/DeprecatedClassifierUsageChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/DeprecatedClassifierUsageChecker.kt @@ -30,8 +30,7 @@ class DeprecatedClassifierUsageChecker : ClassifierUsageChecker { element: PsiElement, languageVersionSettings: LanguageVersionSettings ) { - val deprecations = targetDescriptor.getDeprecations() - for (deprecation in deprecations) { + for (deprecation in targetDescriptor.getDeprecations(languageVersionSettings)) { trace.report(createDeprecationDiagnostic(element, deprecation, languageVersionSettings)) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt index fee67f3baa7..52e3fbd674f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve import com.intellij.psi.PsiElement import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor @@ -125,20 +126,20 @@ private data class DeprecatedBySinceKotlinInfo( get() = sinceKotlinInfo.version.asString() } -fun DeclarationDescriptor.getDeprecations(): List { - val deprecations = this.getOwnDeprecations() +fun DeclarationDescriptor.getDeprecations(languageVersionSettings: LanguageVersionSettings): List { + val deprecations = this.getOwnDeprecations(languageVersionSettings) if (deprecations.isNotEmpty()) { return deprecations } if (this is CallableMemberDescriptor) { - return listOfNotNull(deprecationByOverridden(this)) + return listOfNotNull(deprecationByOverridden(this, languageVersionSettings)) } return emptyList() } -private fun deprecationByOverridden(root: CallableMemberDescriptor): Deprecation? { +private fun deprecationByOverridden(root: CallableMemberDescriptor, languageVersionSettings: LanguageVersionSettings): Deprecation? { val visited = HashSet() val deprecations = LinkedHashSet() var hasUndeprecatedOverridden = false @@ -148,7 +149,7 @@ private fun deprecationByOverridden(root: CallableMemberDescriptor): Deprecation visited.add(node) - val deprecationsByAnnotation = node.getOwnDeprecations() + val deprecationsByAnnotation = node.getOwnDeprecations(languageVersionSettings) val overriddenDescriptors = node.original.overriddenDescriptors when { deprecationsByAnnotation.isNotEmpty() -> { @@ -171,11 +172,12 @@ private fun deprecationByOverridden(root: CallableMemberDescriptor): Deprecation return DeprecatedByOverridden(deprecations) } -private fun DeclarationDescriptor.getOwnDeprecations(): List { +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() + typeAliasDescriptor.getOwnDeprecations() + return underlyingConstructorDescriptor.getOwnDeprecations(languageVersionSettings) + + typeAliasDescriptor.getOwnDeprecations(languageVersionSettings) } val result = SmartList() @@ -190,7 +192,12 @@ private fun DeclarationDescriptor.getOwnDeprecations(): List { if (target is DeserializedMemberDescriptor) { val sinceKotlinInfo = target.sinceKotlinInfo if (sinceKotlinInfo != null) { - result.add(DeprecatedBySinceKotlinInfo(sinceKotlinInfo, target)) + // We're using ApiVersion because it's convenient to compare versions, "-api-version" is not involved in any way + // TODO: usage of ApiVersion is confusing here, refactor + if (ApiVersion.createBySinceKotlinInfo(sinceKotlinInfo) > + ApiVersion.createByLanguageVersion(languageVersionSettings.languageVersion)) { + result.add(DeprecatedBySinceKotlinInfo(sinceKotlinInfo, target)) + } } } } @@ -250,8 +257,8 @@ enum class DeprecationLevelValue { WARNING, ERROR, HIDDEN } -fun DeclarationDescriptor.isDeprecatedHidden(): Boolean = - getDeprecations().any { it.deprecationLevel == HIDDEN } +fun DeclarationDescriptor.isDeprecatedHidden(languageVersionSettings: LanguageVersionSettings): Boolean = + getDeprecations(languageVersionSettings).any { it.deprecationLevel == HIDDEN } @JvmOverloads fun DeclarationDescriptor.isHiddenInResolution(languageVersionSettings: LanguageVersionSettings, isSuperCall: Boolean = false): Boolean { @@ -262,5 +269,5 @@ fun DeclarationDescriptor.isHiddenInResolution(languageVersionSettings: Language if (!checkSinceKotlinVersionAccessibility(languageVersionSettings)) return true - return isDeprecatedHidden() + return isDeprecatedHidden(languageVersionSettings) } diff --git a/idea/src/org/jetbrains/kotlin/idea/KotlinQuickDocumentationProvider.kt b/idea/src/org/jetbrains/kotlin/idea/KotlinQuickDocumentationProvider.kt index e12770d94a3..2802136343e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/KotlinQuickDocumentationProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/KotlinQuickDocumentationProvider.kt @@ -26,6 +26,7 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiManager import org.jetbrains.kotlin.asJava.LightClassUtil import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor @@ -38,6 +39,7 @@ import org.jetbrains.kotlin.idea.kdoc.KDocRenderer import org.jetbrains.kotlin.idea.kdoc.findKDoc import org.jetbrains.kotlin.idea.kdoc.isBoringBuiltinClass import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink +import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.psi.* @@ -137,16 +139,21 @@ class KotlinQuickDocumentationProvider : AbstractDocumentationProvider() { return "No documentation available" } - return renderKotlin(context, declarationDescriptor, quickNavigation) + return renderKotlin(context, declarationDescriptor, quickNavigation, declaration.languageVersionSettings) } private fun renderKotlinImplicitLambdaParameter(element: KtReferenceExpression, quickNavigation: Boolean): String? { val context = element.analyze(BodyResolveMode.PARTIAL) val target = element.mainReference.resolveToDescriptors(context).singleOrNull() as? ValueParameterDescriptor? ?: return null - return renderKotlin(context, target, quickNavigation) + return renderKotlin(context, target, quickNavigation, element.languageVersionSettings) } - private fun renderKotlin(context: BindingContext, declarationDescriptor: DeclarationDescriptor, quickNavigation: Boolean): String { + private fun renderKotlin( + context: BindingContext, + declarationDescriptor: DeclarationDescriptor, + quickNavigation: Boolean, + languageVersionSettings: LanguageVersionSettings + ): String { @Suppress("NAME_SHADOWING") var declarationDescriptor = declarationDescriptor if (declarationDescriptor is ValueParameterDescriptor) { @@ -162,7 +169,7 @@ class KotlinQuickDocumentationProvider : AbstractDocumentationProvider() { renderedDecl = "
$renderedDecl
" } - renderedDecl += renderDeprecationInfo(declarationDescriptor) + renderedDecl += renderDeprecationInfo(declarationDescriptor, languageVersionSettings) if (!quickNavigation) { val comment = declarationDescriptor.findKDoc() @@ -192,8 +199,11 @@ class KotlinQuickDocumentationProvider : AbstractDocumentationProvider() { return renderedDecl } - private fun renderDeprecationInfo(declarationDescriptor: DeclarationDescriptor): String { - val deprecation = declarationDescriptor.getDeprecations().firstOrNull() ?: return "" + private fun renderDeprecationInfo( + declarationDescriptor: DeclarationDescriptor, + languageVersionSettings: LanguageVersionSettings + ): String { + val deprecation = declarationDescriptor.getDeprecations(languageVersionSettings).firstOrNull() ?: return "" return buildString { wrapTag("DL") { diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/OverridingDeprecatedMemberInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/OverridingDeprecatedMemberInspection.kt index 007dbbe73a7..01c41838909 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/OverridingDeprecatedMemberInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/OverridingDeprecatedMemberInspection.kt @@ -22,6 +22,7 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiElementVisitor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor +import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.deprecatedByOverriddenMessage import org.jetbrains.kotlin.resolve.getDeprecations @@ -41,7 +42,9 @@ class OverridingDeprecatedMemberInspection : AbstractKotlinInspection() { if (declaration is KtDestructuringDeclarationEntry) return val accessorDescriptor = declaration.resolveToDescriptor() as? CallableMemberDescriptor ?: return - val message = accessorDescriptor.getDeprecations().firstOrNull()?.deprecatedByOverriddenMessage() ?: return + val message = accessorDescriptor.getDeprecations(declaration.languageVersionSettings) + .firstOrNull() + ?.deprecatedByOverriddenMessage() ?: return val problem = holder.manager.createProblemDescriptor( targetForProblem, message,