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(
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package test
|
||||
|
||||
@kotlin.jvm.JvmName(name = "bar") public fun foo(): kotlin.Unit
|
||||
public fun foo(): kotlin.Unit
|
||||
|
||||
public open class PlatformName {
|
||||
public constructor PlatformName()
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// FILE: annotations.kt
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
public annotation class ClassAnn
|
||||
|
||||
@Target(AnnotationTarget.FILE)
|
||||
public annotation class FileAnn
|
||||
|
||||
// FILE: 1.kt
|
||||
<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@file:ClassAnn<!>
|
||||
|
||||
// FILE: 2.kr
|
||||
@file:FileAnn
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
@file:JvmName("MultifileClass")
|
||||
@file:JvmMultifileClass
|
||||
<!ANNOTATION_IS_NOT_APPLICABLE_TO_MULTIFILE_CLASSES!>@file:FileAnn<!>
|
||||
<!ANNOTATION_IS_NOT_APPLICABLE_TO_MULTIFILE_CLASSES!>@file:FileBinaryAnn<!>
|
||||
@file:FileSourceAnn
|
||||
|
||||
@Target(AnnotationTarget.FILE)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
public annotation class FileAnn
|
||||
|
||||
@Target(AnnotationTarget.FILE)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
public annotation class FileBinaryAnn
|
||||
|
||||
@Target(AnnotationTarget.FILE)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
public annotation class FileSourceAnn
|
||||
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
// FILE: test.kt
|
||||
@file:JvmName("MultifileClass")
|
||||
@file:JvmMultifileClass
|
||||
<!ANNOTATION_IS_NOT_APPLICABLE_TO_MULTIFILE_CLASSES!>@file:JavaAnn<!>
|
||||
<!ANNOTATION_IS_NOT_APPLICABLE_TO_MULTIFILE_CLASSES!>@file:JavaClassAnn<!>
|
||||
@file:JavaSourceAnn
|
||||
|
||||
// FILE: JavaAnn.java
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface JavaAnn {
|
||||
}
|
||||
|
||||
// FILE: JavaClassAnn.java
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
public @interface JavaClassAnn {
|
||||
}
|
||||
|
||||
// FILE: JavaSourceAnn.java
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface JavaSourceAnn {
|
||||
}
|
||||
|
||||
@@ -1232,6 +1232,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("FileAnnotations.kt")
|
||||
public void testFileAnnotations() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/FileAnnotations.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("GetterAnnotations.kt")
|
||||
public void testGetterAnnotations() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/GetterAnnotations.kt");
|
||||
|
||||
+12
@@ -128,6 +128,18 @@ public class JetDiagnosticsTestWithStdLibGenerated extends AbstractJetDiagnostic
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/jvmName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multifileClassPart.kt")
|
||||
public void testMultifileClassPart() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/multifileClassPart.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multifileClassPartWithJavaAnnotation.kt")
|
||||
public void testMultifileClassPartWithJavaAnnotation() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/multifileClassPartWithJavaAnnotation.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant")
|
||||
|
||||
Reference in New Issue
Block a user