Report error on class named Container inside repeatable annotation
#KT-12794 #KT-47971
This commit is contained in:
+43
-8
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.resolve.jvm.checkers
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
@@ -16,7 +17,9 @@ 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.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -63,19 +66,51 @@ class RepeatableAnnotationChecker(
|
||||
|
||||
if (annotated is KtClassOrObject && annotated.hasModifier(KtTokens.ANNOTATION_KEYWORD)) {
|
||||
val annotationClass = trace.get(BindingContext.CLASS, annotated)
|
||||
val repeatable = annotations.find { it.descriptor.fqName == JvmAnnotationNames.REPEATABLE_ANNOTATION }
|
||||
if (annotationClass != null && repeatable != null) {
|
||||
val containerKClassValue = repeatable.descriptor.allValueArguments[Name.identifier("value")]
|
||||
if (containerKClassValue is KClassValue) {
|
||||
val containerClass = TypeUtils.getClassDescriptor(containerKClassValue.getArgumentType(module))
|
||||
if (containerClass != null) {
|
||||
checkRepeatableAnnotationContainer(annotationClass, containerClass, trace, repeatable.entry)
|
||||
}
|
||||
if (annotationClass != null) {
|
||||
val javaRepeatable = annotations.find { it.descriptor.fqName == JvmAnnotationNames.REPEATABLE_ANNOTATION }
|
||||
val kotlinRepeatable = annotations.find { it.descriptor.fqName == StandardNames.FqNames.repeatable }
|
||||
when {
|
||||
javaRepeatable != null -> checkJavaRepeatableAnnotationDeclaration(javaRepeatable, annotationClass, trace)
|
||||
kotlinRepeatable != null -> checkKotlinRepeatableAnnotationDeclaration(kotlinRepeatable, annotationClass, trace)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkJavaRepeatableAnnotationDeclaration(
|
||||
javaRepeatable: ResolvedAnnotation,
|
||||
annotationClass: ClassDescriptor,
|
||||
trace: BindingTrace,
|
||||
) {
|
||||
val containerKClassValue = javaRepeatable.descriptor.allValueArguments[Name.identifier("value")]
|
||||
if (containerKClassValue is KClassValue) {
|
||||
val containerClass = TypeUtils.getClassDescriptor(containerKClassValue.getArgumentType(module))
|
||||
if (containerClass != null) {
|
||||
checkRepeatableAnnotationContainer(annotationClass, containerClass, trace, javaRepeatable.entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkKotlinRepeatableAnnotationDeclaration(
|
||||
kotlinRepeatable: ResolvedAnnotation,
|
||||
annotationClass: ClassDescriptor,
|
||||
trace: BindingTrace,
|
||||
) {
|
||||
val nestedClassNamedContainer =
|
||||
annotationClass.unsubstitutedInnerClassesScope.getContributedClassifier(
|
||||
Name.identifier(JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME),
|
||||
NoLookupLocation.FOR_ALREADY_TRACKED
|
||||
)
|
||||
if (nestedClassNamedContainer != null) {
|
||||
trace.report(
|
||||
select(
|
||||
ErrorsJvm.REPEATABLE_ANNOTATION_HAS_NESTED_CLASS_NAMED_CONTAINER,
|
||||
ErrorsJvm.REPEATABLE_ANNOTATION_HAS_NESTED_CLASS_NAMED_CONTAINER_ERROR
|
||||
).on(kotlinRepeatable.entry)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkRepeatedEntries(annotations: List<ResolvedAnnotation>, trace: BindingTrace) {
|
||||
val entryTypesWithAnnotations = hashMapOf<FqName, MutableList<AnnotationUseSiteTarget?>>()
|
||||
|
||||
|
||||
+2
@@ -83,6 +83,8 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
MAP.put(REPEATABLE_CONTAINER_HAS_SHORTER_RETENTION_ERROR, "Container annotation ''{0}'' has shorter retention (''{1}'') than the repeatable annotation ''{2}'' (''{3}'')", TO_STRING, TO_STRING, TO_STRING, TO_STRING);
|
||||
MAP.put(REPEATABLE_CONTAINER_TARGET_SET_NOT_A_SUBSET, "Target set of container annotation ''{0}'' must be a subset of the target set of contained annotation ''{1}''. This code will be prohibited in Kotlin 1.6", TO_STRING, TO_STRING);
|
||||
MAP.put(REPEATABLE_CONTAINER_TARGET_SET_NOT_A_SUBSET_ERROR, "Target set of container annotation ''{0}'' must be a subset of the target set of contained annotation ''{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(REPEATABLE_ANNOTATION_HAS_NESTED_CLASS_NAMED_CONTAINER, "Repeatable annotation cannot have a nested class named 'Container'. This name is reserved for auto-generated container class");
|
||||
MAP.put(REPEATABLE_ANNOTATION_HAS_NESTED_CLASS_NAMED_CONTAINER_ERROR, "Repeatable annotation cannot have a nested class named 'Container'. This name is reserved for auto-generated container class");
|
||||
|
||||
MAP.put(JVM_PACKAGE_NAME_CANNOT_BE_EMPTY, "''@JvmPackageName'' annotation value cannot be empty");
|
||||
MAP.put(JVM_PACKAGE_NAME_MUST_BE_VALID_NAME, "''@JvmPackageName'' annotation value must be a valid dot-qualified name of a package");
|
||||
|
||||
@@ -83,6 +83,8 @@ public interface ErrorsJvm {
|
||||
DiagnosticFactory4<KtAnnotationEntry, FqName, String, FqName, String> REPEATABLE_CONTAINER_HAS_SHORTER_RETENTION_ERROR = DiagnosticFactory4.create(ERROR);
|
||||
DiagnosticFactory2<KtAnnotationEntry, FqName, FqName> REPEATABLE_CONTAINER_TARGET_SET_NOT_A_SUBSET = DiagnosticFactory2.create(WARNING);
|
||||
DiagnosticFactory2<KtAnnotationEntry, FqName, FqName> REPEATABLE_CONTAINER_TARGET_SET_NOT_A_SUBSET_ERROR = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory0<KtAnnotationEntry> REPEATABLE_ANNOTATION_HAS_NESTED_CLASS_NAMED_CONTAINER = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<KtAnnotationEntry> REPEATABLE_ANNOTATION_HAS_NESTED_CLASS_NAMED_CONTAINER_ERROR = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
DiagnosticFactory1<KtAnnotationEntry, FqName> ANNOTATION_IS_NOT_APPLICABLE_TO_MULTIFILE_CLASSES = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user