Use AnnotationDescriptor.fqName instead of type

Also use the annotationClass extension property instead of
TypeUtils.getClassDescriptor(annotation.type)
This commit is contained in:
Alexander Udalov
2017-07-04 18:38:36 +03:00
parent 541b9dab52
commit def3f73fdd
16 changed files with 48 additions and 100 deletions
@@ -21,28 +21,29 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtAnnotationEntry import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.resolve.AdditionalAnnotationChecker import org.jetbrains.kotlin.resolve.AdditionalAnnotationChecker
import org.jetbrains.kotlin.resolve.AnnotationChecker import org.jetbrains.kotlin.resolve.AnnotationChecker
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace 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.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention
import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
object RepeatableAnnotationChecker: AdditionalAnnotationChecker { object RepeatableAnnotationChecker: AdditionalAnnotationChecker {
override fun checkEntries(entries: List<KtAnnotationEntry>, actualTargets: List<KotlinTarget>, trace: BindingTrace) { 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) { for (entry in entries) {
val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue 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 useSiteTarget = entry.useSiteTarget?.getAnnotationUseSiteTarget()
val existingTargetsForAnnotation = entryTypesWithAnnotations.getOrPut(descriptor.type) { arrayListOf() } val existingTargetsForAnnotation = entryTypesWithAnnotations.getOrPut(fqName) { arrayListOf() }
val duplicateAnnotation = useSiteTarget in existingTargetsForAnnotation val duplicateAnnotation = useSiteTarget in existingTargetsForAnnotation
|| (existingTargetsForAnnotation.any { (it == null) != (useSiteTarget == null) }) || (existingTargetsForAnnotation.any { (it == null) != (useSiteTarget == null) })
@@ -66,7 +67,7 @@ object FileClassAnnotationsChecker: AdditionalAnnotationChecker {
for (entry in entries) { for (entry in entries) {
if (entry.useSiteTarget?.getAnnotationUseSiteTarget() != AnnotationUseSiteTarget.FILE) continue if (entry.useSiteTarget?.getAnnotationUseSiteTarget() != AnnotationUseSiteTarget.FILE) continue
val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: 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. // This check matters for the applicable annotations only.
val applicableTargets = AnnotationChecker.applicableTargetSet(classDescriptor) val applicableTargets = AnnotationChecker.applicableTargetSet(classDescriptor)
if (applicableTargets == null || !applicableTargets.contains(KotlinTarget.FILE)) continue 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.descriptorUtil.isRepeatableAnnotation
import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
import org.jetbrains.kotlin.types.isError import org.jetbrains.kotlin.types.isError
@@ -107,7 +106,7 @@ class AnnotationChecker(private val additionalCheckers: Iterable<AdditionalAnnot
for (entry in entries) { for (entry in entries) {
checkAnnotationEntry(entry, actualTargets, trace) checkAnnotationEntry(entry, actualTargets, trace)
val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue 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 useSiteTarget = entry.useSiteTarget?.getAnnotationUseSiteTarget() ?: annotated.getDefaultUseSiteTarget(descriptor)
val existingTargetsForAnnotation = entryTypesWithAnnotations.getOrPut(descriptor.type) { arrayListOf() } 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 val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: return KotlinTarget.DEFAULT_TARGET_SET
// For descriptor with error type, all targets are considered as possible // For descriptor with error type, all targets are considered as possible
if (descriptor.type.isError) return KotlinTarget.ALL_TARGET_SET if (descriptor.type.isError) return KotlinTarget.ALL_TARGET_SET
val classDescriptor = TypeUtils.getClassDescriptor(descriptor.type) ?: return KotlinTarget.DEFAULT_TARGET_SET return descriptor.annotationClass?.let(this::applicableTargetSet) ?: KotlinTarget.DEFAULT_TARGET_SET
return applicableTargetSet(classDescriptor) ?: KotlinTarget.DEFAULT_TARGET_SET
} }
@JvmStatic fun applicableTargetSet(descriptor: AnnotationDescriptor): Set<KotlinTarget> { @JvmStatic fun applicableTargetSet(descriptor: AnnotationDescriptor): Set<KotlinTarget> {
@@ -142,10 +142,10 @@ class TypeAliasExpander(
} }
private fun checkRepeatedAnnotations(existingAnnotations: Annotations, newAnnotations: Annotations) { 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) { for (annotation in newAnnotations) {
if (annotation.type in existingAnnotationTypes) { if (annotation.fqName in existingAnnotationFqNames) {
reportStrategy.repeatedAnnotation(annotation) reportStrategy.repeatedAnnotation(annotation)
} }
} }
@@ -25,27 +25,22 @@ import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace 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 { object PublishedApiUsageChecker {
fun check( fun check(
declaration: KtDeclaration, declaration: KtDeclaration,
descriptor: DeclarationDescriptor, descriptor: DeclarationDescriptor,
trace: BindingTrace trace: BindingTrace
) { ) {
if (descriptor !is DeclarationDescriptorWithVisibility || descriptor.visibility == Visibilities.INTERNAL) return 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 if (descriptor is PropertyAccessorDescriptor) return
for (entry in declaration.annotationEntries) { for (entry in declaration.annotationEntries) {
val annotationDescriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue val annotationDescriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue
val classDescriptor = TypeUtils.getClassDescriptor(annotationDescriptor.type) ?: continue if (annotationDescriptor.fqName == KotlinBuiltIns.FQ_NAMES.publishedApi) {
if (classDescriptor.fqNameSafe == KotlinBuiltIns.FQ_NAMES.publishedApi) {
trace.report(Errors.NON_INTERNAL_PUBLISHED_API.on(entry)) trace.report(Errors.NON_INTERNAL_PUBLISHED_API.on(entry))
} }
} }
} }
} }
@@ -171,7 +171,7 @@ abstract class KotlinSuppressCache {
builder.addAll(suppressStringProvider[annotationDescriptor]) 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 // We only add strings and skip other values to facilitate recovery in presence of erroneous code
for (arrayValue in annotationDescriptor.allValueArguments.values) { for (arrayValue in annotationDescriptor.allValueArguments.values) {
@@ -16,17 +16,12 @@
package org.jetbrains.kotlin.resolve.diagnostics package org.jetbrains.kotlin.resolve.diagnostics
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.*
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFunction 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.psi.KtProperty
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
val FUNCTION_NO_BODY_ERRORS: List<DiagnosticFactory1<KtFunction, SimpleFunctionDescriptor>> = val FUNCTION_NO_BODY_ERRORS: List<DiagnosticFactory1<KtFunction, SimpleFunctionDescriptor>> =
listOf(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, Errors.NON_MEMBER_FUNCTION_NO_BODY) 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( abstract class SuppressDiagnosticsByAnnotations(
diagnosticsToSuppress: List<DiagnosticFactory<out Diagnostic>>, diagnosticsToSuppress: List<DiagnosticFactory<out Diagnostic>>,
vararg annotationsFqName: FqName vararg annotationFqNames: FqName
) : SuppressStringProvider { ) : SuppressStringProvider {
private val stringsToSuppress = diagnosticsToSuppress.map { it.name.toLowerCase() } 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> { override fun get(annotationDescriptor: AnnotationDescriptor): List<String> {
val descriptor = DescriptorUtils.getClassDescriptorForType(annotationDescriptor.type) return if (annotationDescriptor.fqName in expectedFqNames) stringsToSuppress else emptyList()
val actualFqName = DescriptorUtils.getFqName(descriptor).asString()
if (expectedFqNames.any { it == actualFqName }) return stringsToSuppress
return listOf()
} }
} }
@@ -23,7 +23,10 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtAnnotationEntry 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.constants.ConstantValue
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
import org.jetbrains.kotlin.resolve.lazy.LazyEntity 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.resolve.source.toSourceElement
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.types.isError
abstract class LazyAnnotationsContext( abstract class LazyAnnotationsContext(
val annotationResolver: AnnotationResolver, val annotationResolver: AnnotationResolver,
@@ -62,22 +64,7 @@ class LazyAnnotations(
AnnotationWithTarget(descriptor, target) AnnotationWithTarget(descriptor, target)
} }
override fun findAnnotation(fqName: FqName): AnnotationDescriptor? { override fun findAnnotation(fqName: FqName): AnnotationDescriptor? = firstOrNull { it.fqName == fqName }
// 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 getUseSiteTargetedAnnotations(): List<AnnotationWithTarget> { override fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget> {
return annotationEntries 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.load.java.lazy.descriptors.LazyJavaPackageFragment
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil
import org.jetbrains.kotlin.test.ConfigurationKind import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.KotlinTestUtils
@@ -75,9 +74,7 @@ class LoadJavaPackageAnnotationsTest : KtUsefulTestCase() {
val singleAnnotation = packageFragmentDescriptor.annotations.singleOrNull() val singleAnnotation = packageFragmentDescriptor.annotations.singleOrNull()
assertNotNull(singleAnnotation) assertNotNull(singleAnnotation)
val annotationFqName = singleAnnotation!!.type.constructor.declarationDescriptor?.fqNameSafe assertEquals(FqName("test.Ann"), singleAnnotation!!.fqName)
assertEquals(FqName("test.Ann"), annotationFqName)
} }
fun testAnnotationFromSource() { fun testAnnotationFromSource() {
@@ -24,7 +24,10 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.functions.BuiltInFictitiousFunctionClassFactory; import org.jetbrains.kotlin.builtins.functions.BuiltInFictitiousFunctionClassFactory;
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor; import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.*; import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention;
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget;
import org.jetbrains.kotlin.descriptors.deserialization.AdditionalClassPartsProvider; import org.jetbrains.kotlin.descriptors.deserialization.AdditionalClassPartsProvider;
import org.jetbrains.kotlin.descriptors.deserialization.ClassDescriptorFactory; import org.jetbrains.kotlin.descriptors.deserialization.ClassDescriptorFactory;
import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentDeclarationFilter; import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentDeclarationFilter;
@@ -254,7 +257,7 @@ public abstract class KotlinBuiltIns {
public final FqNameUnsafe any = fqNameUnsafe("Any"); public final FqNameUnsafe any = fqNameUnsafe("Any");
public final FqNameUnsafe nothing = fqNameUnsafe("Nothing"); public final FqNameUnsafe nothing = fqNameUnsafe("Nothing");
public final FqNameUnsafe cloneable = fqNameUnsafe("Cloneable"); public final FqNameUnsafe cloneable = fqNameUnsafe("Cloneable");
public final FqNameUnsafe suppress = fqNameUnsafe("Suppress"); public final FqName suppress = fqName("Suppress");
public final FqNameUnsafe unit = fqNameUnsafe("Unit"); public final FqNameUnsafe unit = fqNameUnsafe("Unit");
public final FqNameUnsafe charSequence = fqNameUnsafe("CharSequence"); public final FqNameUnsafe charSequence = fqNameUnsafe("CharSequence");
public final FqNameUnsafe string = fqNameUnsafe("String"); public final FqNameUnsafe string = fqNameUnsafe("String");
@@ -1095,10 +1098,6 @@ public abstract class KotlinBuiltIns {
return BUILT_INS_PACKAGE_FQ_NAME.child(primitiveType.getTypeName()); return BUILT_INS_PACKAGE_FQ_NAME.child(primitiveType.getTypeName());
} }
public static boolean isSuppressAnnotation(@NotNull AnnotationDescriptor annotationDescriptor) {
return isConstructedFromGivenClass(annotationDescriptor.getType(), FQ_NAMES.suppress);
}
private static boolean containsAnnotation(DeclarationDescriptor descriptor, FqName annotationClassFqName) { private static boolean containsAnnotation(DeclarationDescriptor descriptor, FqName annotationClassFqName) {
DeclarationDescriptor original = descriptor.getOriginal(); DeclarationDescriptor original = descriptor.getOriginal();
Annotations annotations = original.getAnnotations(); Annotations annotations = original.getAnnotations();
@@ -16,21 +16,21 @@
package org.jetbrains.kotlin.descriptors.annotations package org.jetbrains.kotlin.descriptors.annotations
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
interface AnnotationDescriptor { interface AnnotationDescriptor {
val type: KotlinType val type: KotlinType
val fqName: FqName? get() = val fqName: FqName?
(type.constructor.declarationDescriptor as? ClassDescriptor)?.fqNameUnsafe?.takeIf(FqNameUnsafe::isSafe)?.toSafe() get() = annotationClass?.takeUnless(ErrorUtils::isError)?.fqNameUnsafe?.takeIf(FqNameUnsafe::isSafe)?.toSafe()
val allValueArguments: Map<Name, ConstantValue<*>> val allValueArguments: Map<Name, ConstantValue<*>>
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.resolve.constants.AnnotationValue
import org.jetbrains.kotlin.resolve.constants.ArrayValue import org.jetbrains.kotlin.resolve.constants.ArrayValue
import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.KClassValue import org.jetbrains.kotlin.resolve.constants.KClassValue
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.ErrorUtils.UninferredParameterTypeConstructor import org.jetbrains.kotlin.types.ErrorUtils.UninferredParameterTypeConstructor
@@ -428,7 +429,7 @@ internal class DescriptorRendererImpl(
private fun renderAndSortAnnotationArguments(descriptor: AnnotationDescriptor): List<String> { private fun renderAndSortAnnotationArguments(descriptor: AnnotationDescriptor): List<String> {
val allValueArguments = descriptor.allValueArguments val allValueArguments = descriptor.allValueArguments
val classDescriptor = if (renderDefaultAnnotationArguments) TypeUtils.getClassDescriptor(descriptor.type) else null val classDescriptor = if (renderDefaultAnnotationArguments) descriptor.annotationClass else null
val parameterDescriptorsWithDefaultValue = classDescriptor?.unsubstitutedPrimaryConstructor?.valueParameters val parameterDescriptorsWithDefaultValue = classDescriptor?.unsubstitutedPrimaryConstructor?.valueParameters
?.filter { it.declaresDefaultValue() } ?.filter { it.declaresDefaultValue() }
?.map { it.name } ?.map { it.name }
@@ -53,7 +53,7 @@ class KotlinSuppressIntentionAction private constructor(
val id = "\"$suppressKey\"" val id = "\"$suppressKey\""
when (suppressAt) { when (suppressAt) {
is KtModifierListOwner -> is KtModifierListOwner ->
suppressAt.addAnnotation(KotlinBuiltIns.FQ_NAMES.suppress.toSafe(), suppressAt.addAnnotation(KotlinBuiltIns.FQ_NAMES.suppress,
id, id,
whiteSpaceText = if (kind.newLineNeeded) "\n" else " ", whiteSpaceText = if (kind.newLineNeeded) "\n" else " ",
addToExistingAnnotation = { entry -> addToExistingAnnotation = { entry ->
@@ -151,13 +151,9 @@ class KotlinSuppressIntentionAction private constructor(
} }
private fun findSuppressAnnotation(context: BindingContext, annotationEntries: List<KtAnnotationEntry>): KtAnnotationEntry? { private fun findSuppressAnnotation(context: BindingContext, annotationEntries: List<KtAnnotationEntry>): KtAnnotationEntry? {
for (entry in annotationEntries) { return annotationEntries.firstOrNull { entry ->
val annotationDescriptor = context.get(BindingContext.ANNOTATION, entry) context.get(BindingContext.ANNOTATION, entry)?.fqName == KotlinBuiltIns.FQ_NAMES.suppress
if (annotationDescriptor != null && KotlinBuiltIns.isSuppressAnnotation(annotationDescriptor)) {
return entry
}
} }
return null
} }
} }
@@ -18,13 +18,11 @@ package org.jetbrains.kotlin.idea.util
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
fun KtModifierListOwner.addAnnotation( fun KtModifierListOwner.addAnnotation(
annotationFqName: FqName, annotationFqName: FqName,
annotationInnerText: String? = null, annotationInnerText: String? = null,
@@ -75,16 +73,5 @@ fun KtAnnotated.findAnnotation(annotationFqName: FqName): KtAnnotationEntry? {
val context = analyze(bodyResolveMode = BodyResolveMode.PARTIAL) val context = analyze(bodyResolveMode = BodyResolveMode.PARTIAL)
for (entry in annotationEntries) { return annotationEntries.firstOrNull { entry -> context.get(BindingContext.ANNOTATION, entry)?.fqName == annotationFqName }
val annotationDescriptor = context.get(BindingContext.ANNOTATION, entry)
if (annotationDescriptor != null) {
val fqName = annotationDescriptor.type.getJetTypeFqName(false)
if (fqName == annotationFqName.asString()) {
return entry
}
}
}
return null
} }
@@ -118,10 +118,9 @@ class KtParameterPattern : PsiElementPattern<KtParameter, KtParameterPattern>(Kt
return withPatternCondition("KtParameterPattern-withAnnotation") { ktParameter, _ -> return withPatternCondition("KtParameterPattern-withAnnotation") { ktParameter, _ ->
if (ktParameter.annotationEntries.isEmpty()) return@withPatternCondition false if (ktParameter.annotationEntries.isEmpty()) return@withPatternCondition false
val parameterDescriptor = ktParameter.resolveToDescriptorIfAny() as? ValueParameterDescriptor ?: return@withPatternCondition false val parameterDescriptor = ktParameter.resolveToDescriptorIfAny()
parameterDescriptor is ValueParameterDescriptor && parameterDescriptor.annotations.any { annotation ->
parameterDescriptor.annotations.any { annotation -> annotation.fqName?.asString() == fqName
DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(annotation.type) == fqName
} }
} }
} }
@@ -204,7 +204,7 @@ class MigrateExternalExtensionFix(declaration: KtNamedDeclaration)
} }
if (declaration is KtFunction) { if (declaration is KtFunction) {
declaration.addAnnotation(KotlinBuiltIns.FQ_NAMES.suppress.toSafe(), "\"NOTHING_TO_INLINE\"") declaration.addAnnotation(KotlinBuiltIns.FQ_NAMES.suppress, "\"NOTHING_TO_INLINE\"")
} }
convertNativeAnnotationToJsName(declaration, annotations) convertNativeAnnotationToJsName(declaration, annotations)
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
object JsExternalFileChecker : SimpleDeclarationChecker { object JsExternalFileChecker : SimpleDeclarationChecker {
private val annotationFqNames = setOf(AnnotationsUtils.JS_MODULE_ANNOTATION, AnnotationsUtils.JS_QUALIFIER_ANNOTATION) private val annotationFqNames = setOf(AnnotationsUtils.JS_MODULE_ANNOTATION, AnnotationsUtils.JS_QUALIFIER_ANNOTATION)
@@ -36,11 +35,10 @@ object JsExternalFileChecker : SimpleDeclarationChecker {
) { ) {
if (!AnnotationsUtils.isNativeObject(descriptor) && DescriptorUtils.isTopLevelDeclaration(descriptor)) { if (!AnnotationsUtils.isNativeObject(descriptor) && DescriptorUtils.isTopLevelDeclaration(descriptor)) {
AnnotationsUtils.getContainingFileAnnotations(bindingContext, descriptor).asSequence() AnnotationsUtils.getContainingFileAnnotations(bindingContext, descriptor).asSequence()
.map { it.type } .firstOrNull { it.fqName in annotationFqNames }
.firstOrNull { it.constructor.declarationDescriptor?.fqNameSafe in annotationFqNames }
?.let { ?.let {
diagnosticHolder.report(ErrorsJs.NON_EXTERNAL_DECLARATION_IN_INAPPROPRIATE_FILE.on(declaration, it)) diagnosticHolder.report(ErrorsJs.NON_EXTERNAL_DECLARATION_IN_INAPPROPRIATE_FILE.on(declaration, it.type))
} }
} }
} }
} }