Report errors for annotations with BINARY or RUNTIME retention on file classes.
This commit is contained in:
+1
@@ -61,6 +61,7 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
MAP.put(ErrorsJvm.DEPRECATED_ANNOTATION_METHOD_CALL, "Annotation methods are deprecated. Use property instead");
|
||||
MAP.put(ErrorsJvm.DEPRECATED_JAVA_ANNOTATION, "This annotation is deprecated in Kotlin. Use ''{0}'' instead", Renderers.TO_STRING);
|
||||
MAP.put(ErrorsJvm.NON_SOURCE_REPEATED_ANNOTATION, "Only annotations with SOURCE retention can be repeated on JVM version before 1.8");
|
||||
MAP.put(ErrorsJvm.ANNOTATION_IS_NOT_APPLICABLE_TO_MULTIFILE_CLASSES, "Annotation {0} is not applicable to the multi-file classes", Renderers.TO_STRING);
|
||||
|
||||
MAP.put(ErrorsJvm.NO_REFLECTION_IN_CLASS_PATH, "Call uses reflection API which is not found in compilation classpath. " +
|
||||
"Make sure you have kotlin-reflect.jar in the classpath");
|
||||
|
||||
+4
-3
@@ -55,10 +55,11 @@ public interface ErrorsJvm {
|
||||
DiagnosticFactory0<JetDeclaration> EXTERNAL_DECLARATION_IN_TRAIT = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<JetDeclaration> EXTERNAL_DECLARATION_CANNOT_BE_INLINED = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
|
||||
DiagnosticFactory0<JetExpression> POSITIONED_VALUE_ARGUMENT_FOR_JAVA_ANNOTATION = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<JetElement> DEPRECATED_ANNOTATION_METHOD_CALL = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<JetExpression> POSITIONED_VALUE_ARGUMENT_FOR_JAVA_ANNOTATION = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<JetElement> DEPRECATED_ANNOTATION_METHOD_CALL = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory1<JetAnnotationEntry, FqName> DEPRECATED_JAVA_ANNOTATION = DiagnosticFactory1.create(WARNING);
|
||||
DiagnosticFactory0<JetAnnotationEntry> NON_SOURCE_REPEATED_ANNOTATION = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<JetAnnotationEntry> NON_SOURCE_REPEATED_ANNOTATION = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<JetAnnotationEntry, FqName> ANNOTATION_IS_NOT_APPLICABLE_TO_MULTIFILE_CLASSES = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<JetElement> TRAIT_CANT_CALL_DEFAULT_METHOD_VIA_SUPER = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
|
||||
+34
-1
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.jvm.RuntimeAssertionsTypeChecker
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.load.java.lazy.types.isMarkedNotNull
|
||||
@@ -49,6 +50,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability
|
||||
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.annotations.hasJvmOverloadsAnnotation
|
||||
@@ -92,7 +94,10 @@ public object JvmPlatformConfigurator : PlatformConfigurator(
|
||||
|
||||
additionalSymbolUsageValidators = listOf(),
|
||||
|
||||
additionalAnnotationCheckers = listOf(RepeatableAnnotationChecker)
|
||||
additionalAnnotationCheckers = listOf(
|
||||
RepeatableAnnotationChecker,
|
||||
FileClassAnnotationsChecker
|
||||
)
|
||||
) {
|
||||
|
||||
override fun configure(container: StorageComponentContainer) {
|
||||
@@ -126,6 +131,34 @@ public object RepeatableAnnotationChecker: AdditionalAnnotationChecker {
|
||||
}
|
||||
}
|
||||
|
||||
public object FileClassAnnotationsChecker: AdditionalAnnotationChecker {
|
||||
// JvmName & JvmMultifileClass annotations are applicable to multi-file class parts regardless of their retention.
|
||||
private val ALWAYS_APPLICABLE = hashSetOf(JvmFileClassUtil.JVM_NAME, JvmFileClassUtil.JVM_MULTIFILE_CLASS)
|
||||
|
||||
override fun checkEntries(entries: List<JetAnnotationEntry>, actualTargets: List<KotlinTarget>, trace: BindingTrace) {
|
||||
val fileAnnotationsToCheck = arrayListOf<Pair<JetAnnotationEntry, ClassDescriptor>>()
|
||||
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
|
||||
// This check matters for the applicable annotations only.
|
||||
val applicableTargets = AnnotationChecker.applicableTargetSet(classDescriptor)
|
||||
if (applicableTargets == null || !applicableTargets.contains(KotlinTarget.FILE)) continue
|
||||
fileAnnotationsToCheck.add(Pair(entry, classDescriptor))
|
||||
}
|
||||
|
||||
if (!fileAnnotationsToCheck.any { it.second.classId.asSingleFqName() == JvmFileClassUtil.JVM_MULTIFILE_CLASS }) return
|
||||
|
||||
for ((entry, classDescriptor) in fileAnnotationsToCheck) {
|
||||
val classFqName = classDescriptor.classId.asSingleFqName()
|
||||
if (ALWAYS_APPLICABLE.contains(classFqName)) continue
|
||||
if (classDescriptor.getAnnotationRetention() != KotlinRetention.SOURCE) {
|
||||
trace.report(ErrorsJvm.ANNOTATION_IS_NOT_APPLICABLE_TO_MULTIFILE_CLASSES.on(entry, classFqName))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class LocalFunInlineChecker : DeclarationChecker {
|
||||
|
||||
override fun check(
|
||||
|
||||
Reference in New Issue
Block a user