Check language version for deprecation via SinceKotlinInfo

This commit is contained in:
Alexander Udalov
2016-12-14 16:46:49 +03:00
parent 5c1adb1258
commit 6393ac5871
6 changed files with 48 additions and 24 deletions
@@ -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;
@@ -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()) {
@@ -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))
}
}
@@ -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<Deprecation> {
val deprecations = this.getOwnDeprecations()
fun DeclarationDescriptor.getDeprecations(languageVersionSettings: LanguageVersionSettings): List<Deprecation> {
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<CallableMemberDescriptor>()
val deprecations = LinkedHashSet<Deprecation>()
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<Deprecation> {
private fun DeclarationDescriptor.getOwnDeprecations(languageVersionSettings: LanguageVersionSettings): List<Deprecation> {
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<Deprecation>()
@@ -190,7 +192,12 @@ private fun DeclarationDescriptor.getOwnDeprecations(): List<Deprecation> {
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)
}
@@ -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 = "<pre>$renderedDecl</pre>"
}
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") {
@@ -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,