Use AnnotationDescriptor.fqName instead of type
Also use the annotationClass extension property instead of TypeUtils.getClassDescriptor(annotation.type)
This commit is contained in:
+7
-6
@@ -21,28 +21,29 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||
import org.jetbrains.kotlin.resolve.AdditionalAnnotationChecker
|
||||
import org.jetbrains.kotlin.resolve.AnnotationChecker
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
|
||||
object RepeatableAnnotationChecker: AdditionalAnnotationChecker {
|
||||
override fun checkEntries(entries: List<KtAnnotationEntry>, actualTargets: List<KotlinTarget>, trace: BindingTrace) {
|
||||
val entryTypesWithAnnotations = hashMapOf<KotlinType, MutableList<AnnotationUseSiteTarget?>>()
|
||||
val entryTypesWithAnnotations = hashMapOf<FqName, MutableList<AnnotationUseSiteTarget?>>()
|
||||
|
||||
for (entry in entries) {
|
||||
val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue
|
||||
val classDescriptor = TypeUtils.getClassDescriptor(descriptor.type) ?: continue
|
||||
val fqName = descriptor.fqName ?: continue
|
||||
val classDescriptor = descriptor.annotationClass ?: continue
|
||||
|
||||
val useSiteTarget = entry.useSiteTarget?.getAnnotationUseSiteTarget()
|
||||
val existingTargetsForAnnotation = entryTypesWithAnnotations.getOrPut(descriptor.type) { arrayListOf() }
|
||||
val existingTargetsForAnnotation = entryTypesWithAnnotations.getOrPut(fqName) { arrayListOf() }
|
||||
val duplicateAnnotation = useSiteTarget in existingTargetsForAnnotation
|
||||
|| (existingTargetsForAnnotation.any { (it == null) != (useSiteTarget == null) })
|
||||
|
||||
@@ -66,7 +67,7 @@ object FileClassAnnotationsChecker: AdditionalAnnotationChecker {
|
||||
for (entry in entries) {
|
||||
if (entry.useSiteTarget?.getAnnotationUseSiteTarget() != AnnotationUseSiteTarget.FILE) continue
|
||||
val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue
|
||||
val classDescriptor = TypeUtils.getClassDescriptor(descriptor.type) ?: continue
|
||||
val classDescriptor = descriptor.annotationClass ?: continue
|
||||
// This check matters for the applicable annotations only.
|
||||
val applicableTargets = AnnotationChecker.applicableTargetSet(classDescriptor)
|
||||
if (applicableTargets == null || !applicableTargets.contains(KotlinTarget.FILE)) continue
|
||||
|
||||
@@ -35,7 +35,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||
import org.jetbrains.kotlin.types.isError
|
||||
|
||||
@@ -107,7 +106,7 @@ class AnnotationChecker(private val additionalCheckers: Iterable<AdditionalAnnot
|
||||
for (entry in entries) {
|
||||
checkAnnotationEntry(entry, actualTargets, trace)
|
||||
val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue
|
||||
val classDescriptor = TypeUtils.getClassDescriptor(descriptor.type) ?: continue
|
||||
val classDescriptor = descriptor.annotationClass ?: continue
|
||||
|
||||
val useSiteTarget = entry.useSiteTarget?.getAnnotationUseSiteTarget() ?: annotated.getDefaultUseSiteTarget(descriptor)
|
||||
val existingTargetsForAnnotation = entryTypesWithAnnotations.getOrPut(descriptor.type) { arrayListOf() }
|
||||
@@ -169,8 +168,7 @@ class AnnotationChecker(private val additionalCheckers: Iterable<AdditionalAnnot
|
||||
val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: return KotlinTarget.DEFAULT_TARGET_SET
|
||||
// For descriptor with error type, all targets are considered as possible
|
||||
if (descriptor.type.isError) return KotlinTarget.ALL_TARGET_SET
|
||||
val classDescriptor = TypeUtils.getClassDescriptor(descriptor.type) ?: return KotlinTarget.DEFAULT_TARGET_SET
|
||||
return applicableTargetSet(classDescriptor) ?: KotlinTarget.DEFAULT_TARGET_SET
|
||||
return descriptor.annotationClass?.let(this::applicableTargetSet) ?: KotlinTarget.DEFAULT_TARGET_SET
|
||||
}
|
||||
|
||||
@JvmStatic fun applicableTargetSet(descriptor: AnnotationDescriptor): Set<KotlinTarget> {
|
||||
|
||||
@@ -142,10 +142,10 @@ class TypeAliasExpander(
|
||||
}
|
||||
|
||||
private fun checkRepeatedAnnotations(existingAnnotations: Annotations, newAnnotations: Annotations) {
|
||||
val existingAnnotationTypes = existingAnnotations.mapTo(hashSetOf()) { it.type }
|
||||
val existingAnnotationFqNames = existingAnnotations.mapTo(hashSetOf()) { it.fqName }
|
||||
|
||||
for (annotation in newAnnotations) {
|
||||
if (annotation.type in existingAnnotationTypes) {
|
||||
if (annotation.fqName in existingAnnotationFqNames) {
|
||||
reportStrategy.repeatedAnnotation(annotation)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-8
@@ -25,27 +25,22 @@ import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
|
||||
object PublishedApiUsageChecker {
|
||||
|
||||
fun check(
|
||||
declaration: KtDeclaration,
|
||||
descriptor: DeclarationDescriptor,
|
||||
trace: BindingTrace
|
||||
) {
|
||||
if (descriptor !is DeclarationDescriptorWithVisibility || descriptor.visibility == Visibilities.INTERNAL) return
|
||||
/*Don't report diagnostic twise*/
|
||||
// Don't report the diagnostic twice
|
||||
if (descriptor is PropertyAccessorDescriptor) return
|
||||
|
||||
for (entry in declaration.annotationEntries) {
|
||||
val annotationDescriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue
|
||||
val classDescriptor = TypeUtils.getClassDescriptor(annotationDescriptor.type) ?: continue
|
||||
if (classDescriptor.fqNameSafe == KotlinBuiltIns.FQ_NAMES.publishedApi) {
|
||||
if (annotationDescriptor.fqName == KotlinBuiltIns.FQ_NAMES.publishedApi) {
|
||||
trace.report(Errors.NON_INTERNAL_PUBLISHED_API.on(entry))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -171,7 +171,7 @@ abstract class KotlinSuppressCache {
|
||||
builder.addAll(suppressStringProvider[annotationDescriptor])
|
||||
}
|
||||
|
||||
if (!KotlinBuiltIns.isSuppressAnnotation(annotationDescriptor)) return
|
||||
if (annotationDescriptor.fqName != KotlinBuiltIns.FQ_NAMES.suppress) return
|
||||
|
||||
// We only add strings and skip other values to facilitate recovery in presence of erroneous code
|
||||
for (arrayValue in annotationDescriptor.allValueArguments.values) {
|
||||
|
||||
+5
-15
@@ -16,17 +16,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||
import org.jetbrains.kotlin.diagnostics.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
|
||||
|
||||
val FUNCTION_NO_BODY_ERRORS: List<DiagnosticFactory1<KtFunction, SimpleFunctionDescriptor>> =
|
||||
listOf(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, Errors.NON_MEMBER_FUNCTION_NO_BODY)
|
||||
@@ -36,18 +31,13 @@ val PROPERTY_NOT_INITIALIZED_ERRORS: List<DiagnosticFactory0<KtProperty>> =
|
||||
|
||||
abstract class SuppressDiagnosticsByAnnotations(
|
||||
diagnosticsToSuppress: List<DiagnosticFactory<out Diagnostic>>,
|
||||
vararg annotationsFqName: FqName
|
||||
vararg annotationFqNames: FqName
|
||||
) : SuppressStringProvider {
|
||||
|
||||
private val stringsToSuppress = diagnosticsToSuppress.map { it.name.toLowerCase() }
|
||||
private val expectedFqNames = annotationsFqName.map(FqName::toString)
|
||||
private val expectedFqNames = annotationFqNames.toSet()
|
||||
|
||||
override fun get(annotationDescriptor: AnnotationDescriptor): List<String> {
|
||||
val descriptor = DescriptorUtils.getClassDescriptorForType(annotationDescriptor.type)
|
||||
val actualFqName = DescriptorUtils.getFqName(descriptor).asString()
|
||||
|
||||
if (expectedFqNames.any { it == actualFqName }) return stringsToSuppress
|
||||
|
||||
return listOf()
|
||||
return if (annotationDescriptor.fqName in expectedFqNames) stringsToSuppress else emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
+5
-18
@@ -23,7 +23,10 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.AnnotationResolver
|
||||
import org.jetbrains.kotlin.resolve.AnnotationResolverImpl
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
|
||||
import org.jetbrains.kotlin.resolve.lazy.LazyEntity
|
||||
@@ -31,7 +34,6 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.storage.getValue
|
||||
import org.jetbrains.kotlin.types.isError
|
||||
|
||||
abstract class LazyAnnotationsContext(
|
||||
val annotationResolver: AnnotationResolver,
|
||||
@@ -62,22 +64,7 @@ class LazyAnnotations(
|
||||
AnnotationWithTarget(descriptor, target)
|
||||
}
|
||||
|
||||
override fun findAnnotation(fqName: FqName): AnnotationDescriptor? {
|
||||
// We can not efficiently check short names here:
|
||||
// an annotation class may be renamed on import
|
||||
for (annotationDescriptor in iterator()) {
|
||||
val annotationType = annotationDescriptor.type
|
||||
if (annotationType.isError) continue
|
||||
|
||||
val descriptor = annotationType.constructor.declarationDescriptor ?: continue
|
||||
|
||||
if (DescriptorUtils.getFqNameSafe(descriptor) == fqName) {
|
||||
return annotationDescriptor
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
override fun findAnnotation(fqName: FqName): AnnotationDescriptor? = firstOrNull { it.fqName == fqName }
|
||||
|
||||
override fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget> {
|
||||
return annotationEntries
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil
|
||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
@@ -75,9 +74,7 @@ class LoadJavaPackageAnnotationsTest : KtUsefulTestCase() {
|
||||
val singleAnnotation = packageFragmentDescriptor.annotations.singleOrNull()
|
||||
assertNotNull(singleAnnotation)
|
||||
|
||||
val annotationFqName = singleAnnotation!!.type.constructor.declarationDescriptor?.fqNameSafe
|
||||
|
||||
assertEquals(FqName("test.Ann"), annotationFqName)
|
||||
assertEquals(FqName("test.Ann"), singleAnnotation!!.fqName)
|
||||
}
|
||||
|
||||
fun testAnnotationFromSource() {
|
||||
|
||||
Reference in New Issue
Block a user