[FIR] Add REPEATED_ANNOTATION_WITH_CONTAINER, NON_SOURCE_REPEATED_ANNOTATION
REPEATED_ANNOTATION_TARGET6
This commit is contained in:
committed by
TeamCityServer
parent
2baed77598
commit
97bc079634
+13
-3
@@ -7,15 +7,16 @@ package org.jetbrains.kotlin.fir.checkers.generator.diagnostics
|
|||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
|
import org.jetbrains.kotlin.descriptors.Named
|
||||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticList
|
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
|
||||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.*
|
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.*
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
|
||||||
@Suppress("UNUSED_VARIABLE", "LocalVariableName", "ClassName", "unused")
|
@Suppress("UNUSED_VARIABLE", "LocalVariableName", "ClassName", "unused")
|
||||||
@OptIn(PrivateForInline::class)
|
@OptIn(PrivateForInline::class)
|
||||||
@@ -111,6 +112,15 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") {
|
|||||||
val EXTERNAL_DECLARATION_CANNOT_BE_INLINED by error<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
|
val EXTERNAL_DECLARATION_CANNOT_BE_INLINED by error<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val REPEATABLE by object : DiagnosticGroup("Repeatable Annotations") {
|
||||||
|
val NON_SOURCE_REPEATED_ANNOTATION by error<KtAnnotationEntry>()
|
||||||
|
val REPEATED_ANNOTATION_TARGET6 by error<KtAnnotationEntry>()
|
||||||
|
val REPEATED_ANNOTATION_WITH_CONTAINER by error<KtAnnotationEntry> {
|
||||||
|
parameter<FqName>("name")
|
||||||
|
parameter<FqName>("explicitContainerName")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val MISC by object : DiagnosticGroup("Misc") {
|
val MISC by object : DiagnosticGroup("Misc") {
|
||||||
val INAPPLICABLE_JVM_FIELD by error<KtAnnotationEntry> {
|
val INAPPLICABLE_JVM_FIELD by error<KtAnnotationEntry> {
|
||||||
parameter<String>("message")
|
parameter<String>("message")
|
||||||
|
|||||||
+5
@@ -89,6 +89,11 @@ object FirJvmErrors {
|
|||||||
val EXTERNAL_DECLARATION_IN_INTERFACE by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
val EXTERNAL_DECLARATION_IN_INTERFACE by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||||
val EXTERNAL_DECLARATION_CANNOT_BE_INLINED by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
val EXTERNAL_DECLARATION_CANNOT_BE_INLINED by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||||
|
|
||||||
|
// Repeatable Annotations
|
||||||
|
val NON_SOURCE_REPEATED_ANNOTATION by error0<KtAnnotationEntry>()
|
||||||
|
val REPEATED_ANNOTATION_TARGET6 by error0<KtAnnotationEntry>()
|
||||||
|
val REPEATED_ANNOTATION_WITH_CONTAINER by error2<KtAnnotationEntry, FqName, FqName>()
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
val INAPPLICABLE_JVM_FIELD by error1<KtAnnotationEntry, String>()
|
val INAPPLICABLE_JVM_FIELD by error1<KtAnnotationEntry, String>()
|
||||||
val INAPPLICABLE_JVM_FIELD_WARNING by warning1<KtAnnotationEntry, String>()
|
val INAPPLICABLE_JVM_FIELD_WARNING by warning1<KtAnnotationEntry, String>()
|
||||||
|
|||||||
+1
@@ -19,6 +19,7 @@ object JvmDeclarationCheckers : DeclarationCheckers() {
|
|||||||
override val annotatedDeclarationCheckers: Set<FirAnnotatedDeclarationChecker>
|
override val annotatedDeclarationCheckers: Set<FirAnnotatedDeclarationChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirJvmStaticChecker,
|
FirJvmStaticChecker,
|
||||||
|
FirRepeatableAnnotationChecker
|
||||||
)
|
)
|
||||||
|
|
||||||
override val classCheckers: Set<FirClassChecker>
|
override val classCheckers: Set<FirClassChecker>
|
||||||
|
|||||||
+106
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.analysis.jvm.checkers.declaration
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.StandardNames
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirAnnotatedDeclarationChecker
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||||
|
import org.jetbrains.kotlin.fir.moduleData
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.fqName
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirEnumEntrySymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
|
import org.jetbrains.kotlin.fir.types.lowerBoundIfFlexible
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
object FirRepeatableAnnotationChecker : FirAnnotatedDeclarationChecker() {
|
||||||
|
private val RETENTION_PARAMETER_NAME = Name.identifier("value")
|
||||||
|
private val REPEATABLE_PARAMETER_NAME = Name.identifier("value")
|
||||||
|
private val JAVA_REPEATABLE_ANNOTATION = FqName("java.lang.annotation.Repeatable")
|
||||||
|
|
||||||
|
override fun check(declaration: FirAnnotatedDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
val annotationsSet = hashSetOf<FqName>()
|
||||||
|
|
||||||
|
val session = context.session
|
||||||
|
val annotations = declaration.annotations
|
||||||
|
for (annotation in annotations) {
|
||||||
|
val classId = annotation.classId ?: continue
|
||||||
|
val annotationClassId = annotation.toAnnotationClassId() ?: continue
|
||||||
|
if (annotationClassId.isLocal) continue
|
||||||
|
val annotationClass = session.symbolProvider.getClassLikeSymbolByFqName(annotationClassId) ?: continue
|
||||||
|
|
||||||
|
// TODO: consider REPEATED_ANNOTATION ?
|
||||||
|
if (fqName in annotationsSet &&
|
||||||
|
annotationClass.isRepeatableAnnotation(session) &&
|
||||||
|
annotationClass.getAnnotationRetention() != AnnotationRetention.SOURCE
|
||||||
|
) {
|
||||||
|
if (session.moduleData.platform.componentPlatforms.any { it.targetName == "1.6" }) {
|
||||||
|
reporter.reportOn(annotation.source, FirJvmErrors.REPEATED_ANNOTATION_TARGET6, context)
|
||||||
|
} else if (session.languageVersionSettings.supportsFeature(LanguageFeature.RepeatableAnnotations)) {
|
||||||
|
// It's not allowed to have both a repeated annotation (applied more than once) and its container
|
||||||
|
// on the same element.
|
||||||
|
// See https://docs.oracle.com/javase/specs/jls/se16/html/jls-9.html#jls-9.7.5.
|
||||||
|
val explicitContainer = annotationClass.resolveContainerAnnotation()
|
||||||
|
if (explicitContainer != null && annotations.any { it.fqName(session) == explicitContainer }) {
|
||||||
|
reporter.reportOn(
|
||||||
|
annotation.source,
|
||||||
|
FirJvmErrors.REPEATED_ANNOTATION_WITH_CONTAINER,
|
||||||
|
fqName,
|
||||||
|
explicitContainer,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reporter.reportOn(annotation.source, FirJvmErrors.NON_SOURCE_REPEATED_ANNOTATION, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
annotationsSet.add(fqName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirClassLikeSymbol<*>.isRepeatableAnnotation(session: FirSession): Boolean {
|
||||||
|
if (getAnnotationByFqName(StandardNames.FqNames.repeatable) != null) return true
|
||||||
|
if (getAnnotationByFqName(JAVA_REPEATABLE_ANNOTATION) == null) return false
|
||||||
|
|
||||||
|
return session.languageVersionSettings.supportsFeature(LanguageFeature.RepeatableAnnotations) ||
|
||||||
|
getAnnotationRetention() == AnnotationRetention.SOURCE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirClassLikeSymbol<*>.getAnnotationRetention(): AnnotationRetention? {
|
||||||
|
val repeatableAnnotation = getAnnotationByFqName(StandardNames.FqNames.retention) ?: return null
|
||||||
|
val retentionValue = repeatableAnnotation.findArgumentByName(RETENTION_PARAMETER_NAME) ?: return null
|
||||||
|
val resolvedSymbol = retentionValue.toResolvedCallableSymbol() as? FirEnumEntrySymbol ?: return null
|
||||||
|
val name = resolvedSymbol.name.asString()
|
||||||
|
|
||||||
|
return AnnotationRetention.values().firstOrNull { it.name == name }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirClassLikeSymbol<*>.resolveContainerAnnotation(): FqName? {
|
||||||
|
val repeatableAnnotation =
|
||||||
|
getAnnotationByFqName(StandardNames.FqNames.repeatable) ?: getAnnotationByFqName(JAVA_REPEATABLE_ANNOTATION) ?: return null
|
||||||
|
val value = repeatableAnnotation.findArgumentByName(REPEATABLE_PARAMETER_NAME) ?: return null
|
||||||
|
val classCallArgument = (value as? FirGetClassCall)?.argument ?: return null
|
||||||
|
if (classCallArgument is FirResolvedQualifier) {
|
||||||
|
return classCallArgument.relativeClassFqName
|
||||||
|
} else if (classCallArgument is FirClassReferenceExpression) {
|
||||||
|
val type = classCallArgument.classTypeRef.coneType.lowerBoundIfFlexible() as? ConeClassLikeType ?: return null
|
||||||
|
return type.lookupTag.classId.asSingleFqName()
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
+32
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.jvm.diagnostics
|
package org.jetbrains.kotlin.fir.analysis.jvm.diagnostics
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.diagnostics.rendering.Renderers.NAME
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING
|
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDefaultErrorMessages
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDefaultErrorMessages
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_TYPE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_TYPE
|
||||||
@@ -47,6 +48,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.LOCAL_JVM_
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.NON_DATA_CLASS_JVM_RECORD
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.NON_DATA_CLASS_JVM_RECORD
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.NON_FINAL_JVM_RECORD
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.NON_FINAL_JVM_RECORD
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.NON_SOURCE_REPEATED_ANNOTATION
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_ABSTRACT
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_ABSTRACT
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_INTERFACE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_INTERFACE
|
||||||
@@ -54,6 +56,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_PRIVATE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_PRIVATE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERRIDE_CANNOT_BE_STATIC
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERRIDE_CANNOT_BE_STATIC
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.REPEATED_ANNOTATION_TARGET6
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.REPEATED_ANNOTATION_WITH_CONTAINER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.STRICTFP_ON_CLASS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.STRICTFP_ON_CLASS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SUPER_CALL_WITH_DEFAULT_PARAMETERS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SUPER_CALL_WITH_DEFAULT_PARAMETERS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZED_IN_INTERFACE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZED_IN_INTERFACE
|
||||||
@@ -172,6 +176,34 @@ object FirJvmDefaultErrorMessages {
|
|||||||
map.put(INAPPLICABLE_JVM_FIELD_WARNING, "{0}. This warning will become an error in further releases", STRING)
|
map.put(INAPPLICABLE_JVM_FIELD_WARNING, "{0}. This warning will become an error in further releases", STRING)
|
||||||
|
|
||||||
map.put(JVM_SYNTHETIC_ON_DELEGATE, "'@JvmSynthetic' annotation cannot be used on delegated properties")
|
map.put(JVM_SYNTHETIC_ON_DELEGATE, "'@JvmSynthetic' annotation cannot be used on delegated properties")
|
||||||
|
|
||||||
|
map.put(
|
||||||
|
NON_SOURCE_REPEATED_ANNOTATION,
|
||||||
|
"Repeatable annotations with non-SOURCE retention are only supported starting from Kotlin 1.6"
|
||||||
|
)
|
||||||
|
map.put(
|
||||||
|
REPEATED_ANNOTATION_TARGET6,
|
||||||
|
"Repeatable annotations with non-SOURCE retention are not supported with JVM target 1.6. Use -jvm-target 1.8"
|
||||||
|
)
|
||||||
|
map.put(
|
||||||
|
REPEATED_ANNOTATION_WITH_CONTAINER,
|
||||||
|
"Repeated annotation ''@{0}'' cannot be used on a declaration which is annotated with its container annotation ''@{1}''",
|
||||||
|
TO_STRING,
|
||||||
|
TO_STRING
|
||||||
|
)
|
||||||
|
|
||||||
|
map.put(
|
||||||
|
DEFAULT_METHOD_CALL_FROM_JAVA6_TARGET,
|
||||||
|
"Super calls to Java default methods are prohibited in JVM target 1.6. Recompile with '-jvm-target 1.8'"
|
||||||
|
)
|
||||||
|
map.put(
|
||||||
|
INTERFACE_STATIC_METHOD_CALL_FROM_JAVA6_TARGET,
|
||||||
|
"Calls to static methods in Java interfaces are prohibited in JVM target 1.6. Recompile with '-jvm-target 1.8'"
|
||||||
|
)
|
||||||
|
map.put(
|
||||||
|
INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER,
|
||||||
|
"Interfaces can call default methods via super only within @JvmDefault members. Please annotate the containing interface member with @JvmDefault"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -50,12 +50,12 @@ fun jr1() {}
|
|||||||
|
|
||||||
@JR
|
@JR
|
||||||
@JR.Container()
|
@JR.Container()
|
||||||
@JR
|
<!NON_SOURCE_REPEATED_ANNOTATION!>@JR<!>
|
||||||
fun jr2() {}
|
fun jr2() {}
|
||||||
|
|
||||||
@JR
|
@JR
|
||||||
@JR.Container(JR())
|
@JR.Container(JR())
|
||||||
@JR
|
<!NON_SOURCE_REPEATED_ANNOTATION!>@JR<!>
|
||||||
fun jr3() {}
|
fun jr3() {}
|
||||||
|
|
||||||
@JR
|
@JR
|
||||||
|
|||||||
-142
@@ -1,142 +0,0 @@
|
|||||||
// !LANGUAGE: +RepeatableAnnotations
|
|
||||||
// FULL_JDK
|
|
||||||
// FILE: JR.java
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
|
|
||||||
@Repeatable(JR.Container.class)
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
public @interface JR {
|
|
||||||
public @interface Container {
|
|
||||||
JR[] value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: JS.java
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
|
|
||||||
@Repeatable(JS.Container.class)
|
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
|
||||||
public @interface JS {
|
|
||||||
public @interface Container {
|
|
||||||
JS[] value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: KR.kt
|
|
||||||
|
|
||||||
@java.lang.annotation.Repeatable(KR.Container::class)
|
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
annotation class KR {
|
|
||||||
annotation class Container(val value: Array<KR>)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: KS.kt
|
|
||||||
|
|
||||||
@java.lang.annotation.Repeatable(KS.Container::class)
|
|
||||||
@Retention(AnnotationRetention.SOURCE)
|
|
||||||
annotation class KS {
|
|
||||||
annotation class Container(val value: Array<KS>)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: test.kt
|
|
||||||
|
|
||||||
// Java runtime-retained annotation
|
|
||||||
|
|
||||||
@JR
|
|
||||||
@JR.Container()
|
|
||||||
fun jr1() {}
|
|
||||||
|
|
||||||
@JR
|
|
||||||
@JR.Container()
|
|
||||||
@JR
|
|
||||||
fun jr2() {}
|
|
||||||
|
|
||||||
@JR
|
|
||||||
@JR.Container(JR())
|
|
||||||
@JR
|
|
||||||
fun jr3() {}
|
|
||||||
|
|
||||||
@JR
|
|
||||||
@JR.Container(JR())
|
|
||||||
fun jr4() {}
|
|
||||||
|
|
||||||
@JR
|
|
||||||
@JR.Container(JR(), JR())
|
|
||||||
fun jr5() {}
|
|
||||||
|
|
||||||
|
|
||||||
// Java source-retained annotation
|
|
||||||
|
|
||||||
@JS
|
|
||||||
@JS.Container()
|
|
||||||
fun js1() {}
|
|
||||||
|
|
||||||
@JS
|
|
||||||
@JS.Container()
|
|
||||||
@JS
|
|
||||||
fun js2() {}
|
|
||||||
|
|
||||||
@JS
|
|
||||||
@JS.Container(JS())
|
|
||||||
@JS
|
|
||||||
fun js3() {}
|
|
||||||
|
|
||||||
@JS
|
|
||||||
@JS.Container(JS())
|
|
||||||
fun js4() {}
|
|
||||||
|
|
||||||
@JS
|
|
||||||
@JS.Container(JS(), JS())
|
|
||||||
fun js5() {}
|
|
||||||
|
|
||||||
|
|
||||||
// Kotlin runtime-retained annotation
|
|
||||||
|
|
||||||
@KR.Container([])
|
|
||||||
@KR
|
|
||||||
fun kr1() {}
|
|
||||||
|
|
||||||
@KR.Container([])
|
|
||||||
@KR
|
|
||||||
@KR
|
|
||||||
fun kr2() {}
|
|
||||||
|
|
||||||
@KR
|
|
||||||
@KR
|
|
||||||
@KR.Container([KR()])
|
|
||||||
fun kr3() {}
|
|
||||||
|
|
||||||
@KR.Container([KR()])
|
|
||||||
@KR
|
|
||||||
fun kr4() {}
|
|
||||||
|
|
||||||
@KR
|
|
||||||
@KR.Container([KR(), KR()])
|
|
||||||
fun kr5() {}
|
|
||||||
|
|
||||||
|
|
||||||
// Kotlin source-retained annotation
|
|
||||||
|
|
||||||
@KS.Container([])
|
|
||||||
@KS
|
|
||||||
fun ks1() {}
|
|
||||||
|
|
||||||
@KS.Container([])
|
|
||||||
@KS
|
|
||||||
@KS
|
|
||||||
fun ks2() {}
|
|
||||||
|
|
||||||
@KS
|
|
||||||
@KS
|
|
||||||
@KS.Container([KS()])
|
|
||||||
fun ks3() {}
|
|
||||||
|
|
||||||
@KS.Container([KS()])
|
|
||||||
@KS
|
|
||||||
fun ks4() {}
|
|
||||||
|
|
||||||
@KS
|
|
||||||
@KS.Container([KS(), KS()])
|
|
||||||
fun ks5() {}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !LANGUAGE: +RepeatableAnnotations
|
// !LANGUAGE: +RepeatableAnnotations
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
// FILE: JR.java
|
// FILE: JR.java
|
||||||
|
|||||||
-49
@@ -1,49 +0,0 @@
|
|||||||
// !LANGUAGE: +RepeatableAnnotations
|
|
||||||
// !JVM_TARGET: 1.6
|
|
||||||
// FULL_JDK
|
|
||||||
// FILE: Runtime.java
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
|
|
||||||
@Repeatable(Runtime.Container.class)
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
public @interface Runtime {
|
|
||||||
public @interface Container {
|
|
||||||
Runtime[] value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: Clazz.java
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
|
|
||||||
@Repeatable(Clazz.Container.class)
|
|
||||||
@Retention(RetentionPolicy.CLASS)
|
|
||||||
public @interface Clazz {
|
|
||||||
public @interface Container {
|
|
||||||
Clazz[] value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: Source.java
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
|
|
||||||
@Repeatable(Source.Container.class)
|
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
|
||||||
public @interface Source {
|
|
||||||
public @interface Container {
|
|
||||||
Source[] value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: usage.kt
|
|
||||||
|
|
||||||
@Runtime @Runtime
|
|
||||||
class UseRuntime
|
|
||||||
|
|
||||||
@Clazz @Clazz
|
|
||||||
class UseClazz
|
|
||||||
|
|
||||||
@Source @Source
|
|
||||||
class UseSource
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !LANGUAGE: +RepeatableAnnotations
|
// !LANGUAGE: +RepeatableAnnotations
|
||||||
// !JVM_TARGET: 1.6
|
// !JVM_TARGET: 1.6
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
|
|||||||
+2
-2
@@ -38,10 +38,10 @@ public @interface Source {
|
|||||||
|
|
||||||
// FILE: usage.kt
|
// FILE: usage.kt
|
||||||
|
|
||||||
@Runtime @Runtime
|
@Runtime <!NON_SOURCE_REPEATED_ANNOTATION!>@Runtime<!>
|
||||||
class UseRuntime
|
class UseRuntime
|
||||||
|
|
||||||
@Clazz @Clazz
|
@Clazz <!NON_SOURCE_REPEATED_ANNOTATION!>@Clazz<!>
|
||||||
class UseClazz
|
class UseClazz
|
||||||
|
|
||||||
@Source @Source
|
@Source @Source
|
||||||
|
|||||||
-33
@@ -1,33 +0,0 @@
|
|||||||
// !LANGUAGE: -RepeatableAnnotations
|
|
||||||
|
|
||||||
@Repeatable
|
|
||||||
annotation class repann
|
|
||||||
|
|
||||||
@Retention(AnnotationRetention.SOURCE)
|
|
||||||
@Repeatable
|
|
||||||
annotation class repann1(val x: Int)
|
|
||||||
|
|
||||||
@Retention(AnnotationRetention.SOURCE)
|
|
||||||
@Repeatable
|
|
||||||
annotation class repann2(val f: Boolean)
|
|
||||||
|
|
||||||
@Retention(AnnotationRetention.BINARY)
|
|
||||||
@Repeatable
|
|
||||||
annotation class binrepann
|
|
||||||
|
|
||||||
@Target(AnnotationTarget.EXPRESSION)
|
|
||||||
@Retention(AnnotationRetention.SOURCE)
|
|
||||||
@Repeatable
|
|
||||||
annotation class repexpr
|
|
||||||
|
|
||||||
@repann @repann class DoubleAnnotated
|
|
||||||
|
|
||||||
@repann1(1) @repann1(2) @repann1(3) class TripleAnnotated
|
|
||||||
|
|
||||||
@repann2(true) @repann2(false) @repann2(false) @repann2(true) class FourTimesAnnotated
|
|
||||||
|
|
||||||
@binrepann @binrepann class BinaryAnnotated
|
|
||||||
|
|
||||||
@repann @repann fun foo(@repann @repann x: Int): Int {
|
|
||||||
@repexpr @repexpr return x
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !LANGUAGE: -RepeatableAnnotations
|
// !LANGUAGE: -RepeatableAnnotations
|
||||||
|
|
||||||
@Repeatable
|
@Repeatable
|
||||||
|
|||||||
+20
@@ -3780,6 +3780,26 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirJvmErrors.NON_SOURCE_REPEATED_ANNOTATION) { firDiagnostic ->
|
||||||
|
NonSourceRepeatedAnnotationImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirJvmErrors.REPEATED_ANNOTATION_TARGET6) { firDiagnostic ->
|
||||||
|
RepeatedAnnotationTarget6Impl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirJvmErrors.REPEATED_ANNOTATION_WITH_CONTAINER) { firDiagnostic ->
|
||||||
|
RepeatedAnnotationWithContainerImpl(
|
||||||
|
firDiagnostic.a,
|
||||||
|
firDiagnostic.b,
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirJvmErrors.INAPPLICABLE_JVM_FIELD) { firDiagnostic ->
|
add(FirJvmErrors.INAPPLICABLE_JVM_FIELD) { firDiagnostic ->
|
||||||
InapplicableJvmFieldImpl(
|
InapplicableJvmFieldImpl(
|
||||||
firDiagnostic.a,
|
firDiagnostic.a,
|
||||||
|
|||||||
+14
@@ -2628,6 +2628,20 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = ExternalDeclarationCannotBeInlined::class
|
override val diagnosticClass get() = ExternalDeclarationCannotBeInlined::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class NonSourceRepeatedAnnotation : KtFirDiagnostic<KtAnnotationEntry>() {
|
||||||
|
override val diagnosticClass get() = NonSourceRepeatedAnnotation::class
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class RepeatedAnnotationTarget6 : KtFirDiagnostic<KtAnnotationEntry>() {
|
||||||
|
override val diagnosticClass get() = RepeatedAnnotationTarget6::class
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class RepeatedAnnotationWithContainer : KtFirDiagnostic<KtAnnotationEntry>() {
|
||||||
|
override val diagnosticClass get() = RepeatedAnnotationWithContainer::class
|
||||||
|
abstract val name: FqName
|
||||||
|
abstract val explicitContainerName: FqName
|
||||||
|
}
|
||||||
|
|
||||||
abstract class InapplicableJvmField : KtFirDiagnostic<KtAnnotationEntry>() {
|
abstract class InapplicableJvmField : KtFirDiagnostic<KtAnnotationEntry>() {
|
||||||
override val diagnosticClass get() = InapplicableJvmField::class
|
override val diagnosticClass get() = InapplicableJvmField::class
|
||||||
abstract val message: String
|
abstract val message: String
|
||||||
|
|||||||
+23
@@ -4273,6 +4273,29 @@ internal class ExternalDeclarationCannotBeInlinedImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class NonSourceRepeatedAnnotationImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.NonSourceRepeatedAnnotation(), KtAbstractFirDiagnostic<KtAnnotationEntry> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class RepeatedAnnotationTarget6Impl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.RepeatedAnnotationTarget6(), KtAbstractFirDiagnostic<KtAnnotationEntry> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class RepeatedAnnotationWithContainerImpl(
|
||||||
|
override val name: FqName,
|
||||||
|
override val explicitContainerName: FqName,
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.RepeatedAnnotationWithContainer(), KtAbstractFirDiagnostic<KtAnnotationEntry> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
internal class InapplicableJvmFieldImpl(
|
internal class InapplicableJvmFieldImpl(
|
||||||
override val message: String,
|
override val message: String,
|
||||||
firDiagnostic: FirPsiDiagnostic,
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
|||||||
Reference in New Issue
Block a user