Check deprecated annotations with use site targets
This commit is contained in:
+34
-7
@@ -22,6 +22,7 @@ import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
@@ -29,6 +30,9 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.annotations.argumentValue
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.PROPERTY_GETTER
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.PROPERTY_SETTER
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
|
||||
public class DeprecatedSymbolValidator : SymbolUsageValidator {
|
||||
private val JAVA_DEPRECATED = FqName(javaClass<Deprecated>().getName())
|
||||
@@ -63,9 +67,10 @@ public class DeprecatedSymbolValidator : SymbolUsageValidator {
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.getDeprecatedAnnotation(): Pair<AnnotationDescriptor, DeclarationDescriptor>? {
|
||||
val ownAnnotation = getDeclaredDeprecatedAnnotation()
|
||||
val ownAnnotation = getDeclaredDeprecatedAnnotation(AnnotationUseSiteTarget.getAssociatedUseSiteTarget(this))
|
||||
if (ownAnnotation != null)
|
||||
return ownAnnotation to this
|
||||
|
||||
when (this) {
|
||||
is ConstructorDescriptor -> {
|
||||
val classDescriptor = getContainingDeclaration()
|
||||
@@ -74,17 +79,39 @@ public class DeprecatedSymbolValidator : SymbolUsageValidator {
|
||||
return classAnnotation to classDescriptor
|
||||
}
|
||||
is PropertyAccessorDescriptor -> {
|
||||
val propertyDescriptor = getContainingDeclaration()
|
||||
val propertyAnnotation = propertyDescriptor.getDeclaredDeprecatedAnnotation()
|
||||
if (propertyAnnotation != null)
|
||||
return propertyAnnotation to propertyDescriptor
|
||||
val propertyDescriptor = correspondingProperty
|
||||
|
||||
val target = if (this is PropertyGetterDescriptor) PROPERTY_GETTER else PROPERTY_SETTER
|
||||
val accessorAnnotation = propertyDescriptor.getDeclaredDeprecatedAnnotation(target, false)
|
||||
if (accessorAnnotation != null)
|
||||
return accessorAnnotation to this
|
||||
|
||||
val classDescriptor = containingDeclaration as? ClassDescriptor
|
||||
if (classDescriptor != null && classDescriptor.isCompanionObject) {
|
||||
val classAnnotation = classDescriptor.getDeclaredDeprecatedAnnotation()
|
||||
if (classAnnotation != null)
|
||||
return classAnnotation to classDescriptor
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.getDeclaredDeprecatedAnnotation(): AnnotationDescriptor? {
|
||||
return getAnnotations().findAnnotation(KotlinBuiltIns.FQ_NAMES.deprecated) ?: getAnnotations().findAnnotation(JAVA_DEPRECATED)
|
||||
private fun DeclarationDescriptor.getDeclaredDeprecatedAnnotation(
|
||||
target: AnnotationUseSiteTarget? = null,
|
||||
findAnnotationsWithoutTarget: Boolean = true
|
||||
): AnnotationDescriptor? {
|
||||
if (findAnnotationsWithoutTarget) {
|
||||
val annotations = annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.deprecated) ?: annotations.findAnnotation(JAVA_DEPRECATED)
|
||||
if (annotations != null) return annotations
|
||||
}
|
||||
|
||||
if (target != null) {
|
||||
return Annotations.Companion.findUseSiteTargetedAnnotation(annotations, target, KotlinBuiltIns.FQ_NAMES.deprecated)
|
||||
?: Annotations.Companion.findUseSiteTargetedAnnotation(annotations, target, JAVA_DEPRECATED)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun createDeprecationDiagnostic(element: PsiElement, descriptor: DeclarationDescriptor, deprecated: AnnotationDescriptor): Diagnostic {
|
||||
|
||||
@@ -11,6 +11,6 @@ public class A {
|
||||
|
||||
// FILE: B.kt
|
||||
|
||||
class B(private @deprecated val foo: String) : <!DEPRECATED_SYMBOL_WITH_MESSAGE!>A<!>() {
|
||||
class B(private @property:deprecated val foo: String) : <!DEPRECATED_SYMBOL_WITH_MESSAGE!>A<!>() {
|
||||
override fun getFoo(text: String): String = super.<!DEPRECATED_SYMBOL_WITH_MESSAGE!>getFoo<!>(text + <!DEPRECATED_SYMBOL!>foo<!>)
|
||||
}
|
||||
@@ -9,7 +9,7 @@ kotlin.deprecated(value = "Deprecated in Java") public open class A {
|
||||
}
|
||||
|
||||
internal final class B : A {
|
||||
public constructor B(/*0*/ kotlin.deprecated() foo: kotlin.String)
|
||||
public constructor B(/*0*/ foo: kotlin.String)
|
||||
kotlin.deprecated() private final val foo: kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ fun getFoo(/*0*/ text: kotlin.String): kotlin.String
|
||||
|
||||
@@ -1026,7 +1026,19 @@ public class KotlinBuiltIns {
|
||||
}
|
||||
|
||||
private static boolean containsAnnotation(DeclarationDescriptor descriptor, FqName annotationClassFqName) {
|
||||
return descriptor.getOriginal().getAnnotations().findAnnotation(annotationClassFqName) != null;
|
||||
DeclarationDescriptor original = descriptor.getOriginal();
|
||||
Annotations annotations = original.getAnnotations();
|
||||
|
||||
if (annotations.findAnnotation(annotationClassFqName) != null) return true;
|
||||
|
||||
AnnotationUseSiteTarget associatedUseSiteTarget = AnnotationUseSiteTarget.Companion.getAssociatedUseSiteTarget(descriptor);
|
||||
if (associatedUseSiteTarget != null) {
|
||||
if (annotations.findUseSiteTargetedAnnotation(associatedUseSiteTarget, annotationClassFqName) != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+12
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.annotations
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
|
||||
public enum class AnnotationUseSiteTarget(renderName: String? = null) {
|
||||
FIELD(),
|
||||
FILE(),
|
||||
@@ -27,4 +29,14 @@ public enum class AnnotationUseSiteTarget(renderName: String? = null) {
|
||||
SETTER_PARAMETER("sparam");
|
||||
|
||||
public val renderName: String = renderName ?: name().toLowerCase()
|
||||
|
||||
public companion object {
|
||||
public fun getAssociatedUseSiteTarget(descriptor: DeclarationDescriptor): AnnotationUseSiteTarget? = when (descriptor) {
|
||||
is PropertyDescriptor -> PROPERTY
|
||||
is ValueParameterDescriptor -> CONSTRUCTOR_PARAMETER
|
||||
is PropertyGetterDescriptor -> PROPERTY_GETTER
|
||||
is PropertySetterDescriptor -> PROPERTY_SETTER
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.annotations
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
|
||||
@@ -38,6 +39,13 @@ public interface Annotations : Iterable<AnnotationDescriptor> {
|
||||
}
|
||||
}
|
||||
|
||||
public fun findUseSiteTargetedAnnotation(target: AnnotationUseSiteTarget, fqName: FqName): AnnotationDescriptor? {
|
||||
return getUseSiteTargetedAnnotations(target).firstOrNull {
|
||||
val descriptor = it.type.constructor.declarationDescriptor
|
||||
descriptor is ClassDescriptor && fqName.toUnsafe() == DescriptorUtils.getFqName(descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns both targeted and annotations without target. Annotation order is preserved.
|
||||
public fun getAllAnnotations(): List<AnnotationWithTarget>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user