[FIR] Add REPEATED_ANNOTATION, REPEATED_ANNOTATION_WARNING
This commit is contained in:
committed by
TeamCityServer
parent
fa12e72551
commit
55f33999f1
+2
-2
@@ -9,7 +9,7 @@ public @interface Ann {
|
||||
// FILE: main.kt
|
||||
|
||||
@Ann(x = 10, s = "")
|
||||
@Ann(<!ARGUMENT_TYPE_MISMATCH!>10<!>, <!ARGUMENT_TYPE_MISMATCH!>""<!>)
|
||||
@Ann(x = 10, s = "", y = 10)
|
||||
<!REPEATED_ANNOTATION!>@Ann(<!ARGUMENT_TYPE_MISMATCH!>10<!>, <!ARGUMENT_TYPE_MISMATCH!>""<!>)<!>
|
||||
<!REPEATED_ANNOTATION!>@Ann(x = 10, s = "", y = 10)<!>
|
||||
class A
|
||||
|
||||
|
||||
+2
@@ -267,6 +267,8 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<String>("useSiteDescription")
|
||||
}
|
||||
val INAPPLICABLE_FILE_TARGET by error<KtAnnotationEntry>(PositioningStrategy.ANNOTATION_USE_SITE)
|
||||
val REPEATED_ANNOTATION by error<KtAnnotationEntry>()
|
||||
val REPEATED_ANNOTATION_WARNING by warning<KtAnnotationEntry>()
|
||||
}
|
||||
|
||||
val EXPERIMENTAL by object : DiagnosticGroup("OptIn-related") {
|
||||
|
||||
+35
-41
@@ -7,14 +7,12 @@ 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.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirAnnotatedDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getAllowedAnnotationTargets
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getRetention
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
||||
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
|
||||
@@ -44,7 +42,7 @@ object FirRepeatableAnnotationChecker : FirAnnotatedDeclarationChecker() {
|
||||
private val REPEATABLE_ANNOTATION_CONTAINER_NAME = Name.identifier(JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME)
|
||||
|
||||
override fun check(declaration: FirAnnotatedDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val annotationsSet = hashSetOf<FqName>()
|
||||
val annotationsMap = hashMapOf<ConeKotlinType, MutableList<AnnotationUseSiteTarget?>>()
|
||||
|
||||
val session = context.session
|
||||
val annotations = declaration.annotations
|
||||
@@ -54,9 +52,13 @@ object FirRepeatableAnnotationChecker : FirAnnotatedDeclarationChecker() {
|
||||
if (annotationClassId.isLocal) continue
|
||||
val annotationClass = session.symbolProvider.getClassLikeSymbolByClassId(annotationClassId) ?: continue
|
||||
|
||||
// TODO: consider REPEATED_ANNOTATION ?
|
||||
if (fqName in annotationsSet &&
|
||||
annotationClass.isRepeatableAnnotation(session) &&
|
||||
val useSiteTarget = annotation.useSiteTarget
|
||||
val existingTargetsForAnnotation = annotationsMap.getOrPut(annotation.annotationTypeRef.coneType) { arrayListOf() }
|
||||
val duplicateAnnotation = useSiteTarget in existingTargetsForAnnotation ||
|
||||
existingTargetsForAnnotation.any { (it == null) != (useSiteTarget == null) }
|
||||
|
||||
if (duplicateAnnotation &&
|
||||
annotationClass.containsRepeatableAnnotation(session) &&
|
||||
annotationClass.getAnnotationRetention() != AnnotationRetention.SOURCE
|
||||
) {
|
||||
if (context.isJvm6()) {
|
||||
@@ -80,22 +82,44 @@ object FirRepeatableAnnotationChecker : FirAnnotatedDeclarationChecker() {
|
||||
}
|
||||
}
|
||||
|
||||
annotationsSet.add(fqName)
|
||||
existingTargetsForAnnotation.add(useSiteTarget)
|
||||
}
|
||||
|
||||
if (declaration is FirRegularClass) {
|
||||
val javaRepeatable = annotations.find { it.fqName(session) == JAVA_REPEATABLE_ANNOTATION }
|
||||
if (javaRepeatable != null) {
|
||||
checkJavaRepeatableAnnotationDeclaration(javaRepeatable, declaration, context, reporter)
|
||||
withSuppressedDiagnostics(javaRepeatable, context) {
|
||||
checkJavaRepeatableAnnotationDeclaration(javaRepeatable, declaration, context, reporter)
|
||||
}
|
||||
} else {
|
||||
val kotlinRepeatable = annotations.find { it.fqName(session) == StandardNames.FqNames.repeatable }
|
||||
if (kotlinRepeatable != null) {
|
||||
checkKotlinRepeatableAnnotationDeclaration(kotlinRepeatable, declaration, context, reporter)
|
||||
withSuppressedDiagnostics(kotlinRepeatable, context) {
|
||||
checkKotlinRepeatableAnnotationDeclaration(kotlinRepeatable, declaration, context, reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirClassLikeSymbol<*>.resolveContainerAnnotation(): FqName? {
|
||||
val repeatableAnnotation =
|
||||
getAnnotationByFqName(StandardNames.FqNames.repeatable) ?: getAnnotationByFqName(JAVA_REPEATABLE_ANNOTATION) ?: return null
|
||||
return repeatableAnnotation.resolveContainerAnnotation()?.asSingleFqName()
|
||||
}
|
||||
|
||||
private fun FirAnnotationCall.resolveContainerAnnotation(): ClassId? {
|
||||
val value = findArgumentByName(REPEATABLE_PARAMETER_NAME) ?: return null
|
||||
val classCallArgument = (value as? FirGetClassCall)?.argument ?: return null
|
||||
if (classCallArgument is FirResolvedQualifier) {
|
||||
return classCallArgument.classId
|
||||
} else if (classCallArgument is FirClassReferenceExpression) {
|
||||
val type = classCallArgument.classTypeRef.coneType.lowerBoundIfFlexible() as? ConeClassLikeType ?: return null
|
||||
return type.lookupTag.classId
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun checkJavaRepeatableAnnotationDeclaration(
|
||||
javaRepeatable: FirAnnotationCall,
|
||||
annotationClass: FirRegularClass,
|
||||
@@ -231,34 +255,4 @@ object FirRepeatableAnnotationChecker : FirAnnotatedDeclarationChecker() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
return getAnnotationByFqName(StandardNames.FqNames.retention)?.getRetention() ?: AnnotationRetention.RUNTIME
|
||||
}
|
||||
|
||||
private fun FirClassLikeSymbol<*>.resolveContainerAnnotation(): FqName? {
|
||||
val repeatableAnnotation =
|
||||
getAnnotationByFqName(StandardNames.FqNames.repeatable) ?: getAnnotationByFqName(JAVA_REPEATABLE_ANNOTATION) ?: return null
|
||||
return repeatableAnnotation.resolveContainerAnnotation()?.asSingleFqName()
|
||||
}
|
||||
|
||||
private fun FirAnnotationCall.resolveContainerAnnotation(): ClassId? {
|
||||
val value = findArgumentByName(REPEATABLE_PARAMETER_NAME) ?: return null
|
||||
val classCallArgument = (value as? FirGetClassCall)?.argument ?: return null
|
||||
if (classCallArgument is FirResolvedQualifier) {
|
||||
return classCallArgument.classId
|
||||
} else if (classCallArgument is FirClassReferenceExpression) {
|
||||
val type = classCallArgument.classTypeRef.coneType.lowerBoundIfFlexible() as? ConeClassLikeType ?: return null
|
||||
return type.lookupTag.classId
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -234,6 +234,8 @@ object FirErrors {
|
||||
val INAPPLICABLE_PARAM_TARGET by error0<KtAnnotationEntry>()
|
||||
val REDUNDANT_ANNOTATION_TARGET by warning1<KtAnnotationEntry, String>()
|
||||
val INAPPLICABLE_FILE_TARGET by error0<KtAnnotationEntry>(SourceElementPositioningStrategies.ANNOTATION_USE_SITE)
|
||||
val REPEATED_ANNOTATION by error0<KtAnnotationEntry>()
|
||||
val REPEATED_ANNOTATION_WARNING by warning0<KtAnnotationEntry>()
|
||||
|
||||
// OptIn-related
|
||||
val EXPERIMENTAL_API_USAGE by warning2<PsiElement, FqName, String>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
|
||||
+79
@@ -6,13 +6,24 @@
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirPrimaryConstructor
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ensureResolved
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
@@ -21,10 +32,15 @@ import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.UseSiteTargetsList
|
||||
|
||||
private val RETENTION_PARAMETER_NAME = Name.identifier("value")
|
||||
private val TARGET_PARAMETER_NAME = Name.identifier("allowedTargets")
|
||||
private val JAVA_REPEATABLE_ANNOTATION = FqName("java.lang.annotation.Repeatable")
|
||||
private val JAVA_REPEATABLE_ANNOTATION_CLASS_ID = ClassId.topLevel(JAVA_REPEATABLE_ANNOTATION)
|
||||
private val JVM_REPEATABLE_ANNOTATION_CLASS_ID = ClassId.fromString("kotlin/jvm/JvmRepeatable")
|
||||
|
||||
fun FirRegularClass.getRetention(): AnnotationRetention {
|
||||
return getRetentionAnnotation()?.getRetention() ?: AnnotationRetention.RUNTIME
|
||||
@@ -90,6 +106,69 @@ fun FirExpression.extractClassesFromArgument(): List<FirRegularClassSymbol> {
|
||||
}
|
||||
}
|
||||
|
||||
fun checkRepeatedAnnotation(
|
||||
useSiteTarget: AnnotationUseSiteTarget?,
|
||||
existingTargetsForAnnotation: MutableList<AnnotationUseSiteTarget?>,
|
||||
annotation: FirAnnotationCall,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
) {
|
||||
val duplicated = useSiteTarget in existingTargetsForAnnotation
|
||||
|| existingTargetsForAnnotation.any { (it == null) != (useSiteTarget == null) }
|
||||
if (duplicated && !annotation.isRepeatable(context.session) && annotation.source?.kind !is FirFakeSourceElementKind) {
|
||||
reporter.reportOn(annotation.source, FirErrors.REPEATED_ANNOTATION, context)
|
||||
}
|
||||
}
|
||||
|
||||
fun FirAnnotationCall.isRepeatable(session: FirSession): Boolean {
|
||||
val annotationClassId = this.toAnnotationClassId() ?: return false
|
||||
if (annotationClassId.isLocal) return false
|
||||
val annotationClass = session.symbolProvider.getClassLikeSymbolByFqName(annotationClassId) ?: return false
|
||||
|
||||
return annotationClass.containsRepeatableAnnotation(session)
|
||||
}
|
||||
|
||||
fun FirClassLikeSymbol<*>.containsRepeatableAnnotation(session: FirSession): Boolean {
|
||||
if (getAnnotationByClassId(StandardNames.FqNames.repeatableClassId) != null) return true
|
||||
if (getAnnotationByClassId(JAVA_REPEATABLE_ANNOTATION_CLASS_ID) != null ||
|
||||
getAnnotationByClassId(JVM_REPEATABLE_ANNOTATION_CLASS_ID) != null
|
||||
) {
|
||||
return session.languageVersionSettings.supportsFeature(LanguageFeature.RepeatableAnnotations) ||
|
||||
getAnnotationRetention() == AnnotationRetention.SOURCE && origin == FirDeclarationOrigin.Java
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun FirClassLikeSymbol<*>.getAnnotationRetention(): AnnotationRetention {
|
||||
return getAnnotationByFqName(StandardNames.FqNames.retention)?.getRetention() ?: AnnotationRetention.RUNTIME
|
||||
}
|
||||
|
||||
fun FirAnnotationContainer.getDefaultUseSiteTarget(
|
||||
annotation: FirAnnotationCall,
|
||||
context: CheckerContext
|
||||
): AnnotationUseSiteTarget? {
|
||||
return getImplicitUseSiteTargetList(context).firstOrNull {
|
||||
KotlinTarget.USE_SITE_MAPPING[it] in annotation.getAllowedAnnotationTargets(context.session)
|
||||
}
|
||||
}
|
||||
|
||||
fun FirAnnotationContainer.getImplicitUseSiteTargetList(context: CheckerContext): List<AnnotationUseSiteTarget> {
|
||||
return when (this) {
|
||||
is FirValueParameter -> {
|
||||
return if (context.findClosest<FirDeclaration>() is FirPrimaryConstructor)
|
||||
UseSiteTargetsList.T_CONSTRUCTOR_PARAMETER
|
||||
else
|
||||
emptyList()
|
||||
}
|
||||
is FirProperty ->
|
||||
if (!isLocal) UseSiteTargetsList.T_PROPERTY else emptyList()
|
||||
is FirPropertyAccessor ->
|
||||
if (isGetter) listOf(AnnotationUseSiteTarget.PROPERTY_GETTER) else listOf(AnnotationUseSiteTarget.PROPERTY_SETTER)
|
||||
else ->
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirExpression.unfoldArrayOrVararg(): List<FirExpression> {
|
||||
return when (this) {
|
||||
is FirVarargArgumentsExpression -> arguments
|
||||
|
||||
+13
-11
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers
|
||||
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiNameIdentifierOwner
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
@@ -74,13 +75,10 @@ open class LightTreeSourceNavigator : SourceNavigator {
|
||||
}
|
||||
|
||||
override fun FirSourceElement.getRawIdentifier(): String? {
|
||||
val tokenType = elementType
|
||||
return if (tokenType is KtNameReferenceExpressionElementType || tokenType == KtTokens.IDENTIFIER) {
|
||||
lighterASTNode.toString()
|
||||
} else if (tokenType is KtTypeProjectionElementType) {
|
||||
lighterASTNode.getChildren(treeStructure).last().toString()
|
||||
} else {
|
||||
null
|
||||
return when (elementType) {
|
||||
is KtNameReferenceExpressionElementType, KtTokens.IDENTIFIER -> lighterASTNode.toString()
|
||||
is KtTypeProjectionElementType -> lighterASTNode.getChildren(treeStructure).last().toString()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,10 +87,14 @@ open class LightTreeSourceNavigator : SourceNavigator {
|
||||
}
|
||||
|
||||
override fun FirValueParameterSymbol.isCatchElementParameter(): Boolean {
|
||||
val localSource = source ?: return false
|
||||
var parent = localSource.treeStructure.getParent(localSource.lighterASTNode)
|
||||
parent?.let { parent = localSource.treeStructure.getParent(it) }
|
||||
return parent?.tokenType == KtNodeTypes.CATCH
|
||||
return source?.getParentOfParent()?.tokenType == KtNodeTypes.CATCH
|
||||
}
|
||||
|
||||
private fun FirSourceElement?.getParentOfParent(): LighterASTNode? {
|
||||
val source = this ?: return null
|
||||
var parent = source.treeStructure.getParent(source.lighterASTNode)
|
||||
parent?.let { parent = source.treeStructure.getParent(it) }
|
||||
return parent
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+65
-9
@@ -5,28 +5,26 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getActualTargetList
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getAllowedAnnotationTargets
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.hasBackingField
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.expressions.argumentMapping
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.packageFqName
|
||||
import org.jetbrains.kotlin.fir.resolve.fqName
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.resolve.AnnotationTargetList
|
||||
import org.jetbrains.kotlin.resolve.AnnotationTargetLists
|
||||
|
||||
object FirAnnotationChecker : FirAnnotatedDeclarationChecker() {
|
||||
private val deprecatedClassId = FqName("kotlin.Deprecated")
|
||||
@@ -41,12 +39,13 @@ object FirAnnotationChecker : FirAnnotatedDeclarationChecker() {
|
||||
var deprecatedSinceKotlinCall: FirAnnotationCall? = null
|
||||
|
||||
for (annotation in declaration.annotations) {
|
||||
val fqName = annotation.fqName(context.session)
|
||||
val fqName = annotation.fqName(context.session) ?: continue
|
||||
if (fqName == deprecatedClassId) {
|
||||
deprecatedCall = annotation
|
||||
} else if (fqName == deprecatedSinceKotlinClassId) {
|
||||
deprecatedSinceKotlinCall = annotation
|
||||
}
|
||||
|
||||
withSuppressedDiagnostics(annotation, context) {
|
||||
checkAnnotationTarget(declaration, annotation, context, reporter)
|
||||
}
|
||||
@@ -56,6 +55,14 @@ object FirAnnotationChecker : FirAnnotatedDeclarationChecker() {
|
||||
checkDeprecatedCalls(deprecatedSinceKotlinCall, deprecatedCall, context, reporter)
|
||||
}
|
||||
}
|
||||
|
||||
checkRepeatedAnnotations(declaration, context, reporter)
|
||||
if (declaration is FirProperty) {
|
||||
checkRepeatedAnnotationsInProperty(declaration, context, reporter)
|
||||
} else if (declaration is FirTypeAlias) {
|
||||
checkRepeatedAnnotations(declaration.expandedTypeRef, context, reporter)
|
||||
// TODO: KT-48652, implement after KT-48651
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAnnotationTarget(
|
||||
@@ -199,5 +206,54 @@ object FirAnnotationChecker : FirAnnotatedDeclarationChecker() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkRepeatedAnnotations(
|
||||
annotationContainer: FirAnnotationContainer,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
val annotationsMap = hashMapOf<ConeKotlinType, MutableList<AnnotationUseSiteTarget?>>()
|
||||
|
||||
for (annotation in annotationContainer.annotations) {
|
||||
val useSiteTarget = annotation.useSiteTarget ?: annotationContainer.getDefaultUseSiteTarget(annotation, context)
|
||||
val existingTargetsForAnnotation = annotationsMap.getOrPut(annotation.annotationTypeRef.coneType) { arrayListOf() }
|
||||
|
||||
withSuppressedDiagnostics(annotation, context) {
|
||||
checkRepeatedAnnotation(useSiteTarget, existingTargetsForAnnotation, annotation, context, reporter)
|
||||
}
|
||||
|
||||
existingTargetsForAnnotation.add(useSiteTarget)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkRepeatedAnnotationsInProperty(
|
||||
property: FirProperty,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
fun FirAnnotationContainer?.getAnnotationTypes(): List<ConeKotlinType> {
|
||||
return this?.annotations?.map { it.annotationTypeRef.coneType } ?: listOf()
|
||||
}
|
||||
|
||||
val propertyAnnotations = mapOf(
|
||||
AnnotationUseSiteTarget.PROPERTY_GETTER to property.getter?.getAnnotationTypes(),
|
||||
AnnotationUseSiteTarget.PROPERTY_SETTER to property.setter?.getAnnotationTypes(),
|
||||
AnnotationUseSiteTarget.SETTER_PARAMETER to property.setter?.valueParameters?.single().getAnnotationTypes()
|
||||
)
|
||||
|
||||
val isError = context.session.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitRepeatedUseSiteTargetAnnotations)
|
||||
|
||||
for (annotation in property.annotations) {
|
||||
val useSiteTarget = annotation.useSiteTarget ?: property.getDefaultUseSiteTarget(annotation, context)
|
||||
val existingAnnotations = propertyAnnotations[useSiteTarget] ?: continue
|
||||
|
||||
if (annotation.annotationTypeRef.coneType in existingAnnotations && !annotation.isRepeatable(context.session)) {
|
||||
val factory = if (isError) FirErrors.REPEATED_ANNOTATION else FirErrors.REPEATED_ANNOTATION_WARNING
|
||||
if (annotation.source?.kind !is FirFakeSourceElementKind) {
|
||||
reporter.reportOn(annotation.source, factory, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
@@ -5,10 +5,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.checkRepeatedAnnotation
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getAllowedAnnotationTargets
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getDefaultUseSiteTarget
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
@@ -17,6 +20,8 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
|
||||
object FirExpressionAnnotationChecker : FirBasicExpressionChecker() {
|
||||
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
@@ -26,12 +31,22 @@ object FirExpressionAnnotationChecker : FirBasicExpressionChecker() {
|
||||
expression !is FirExpression ||
|
||||
expression is FirBlock && expression.source?.kind == FirFakeSourceElementKind.DesugaredForLoop
|
||||
) return
|
||||
|
||||
val annotationsMap = hashMapOf<ConeKotlinType, MutableList<AnnotationUseSiteTarget?>>()
|
||||
|
||||
for (annotation in expression.annotations) {
|
||||
val useSiteTarget = annotation.useSiteTarget ?: expression.getDefaultUseSiteTarget(annotation, context)
|
||||
val existingTargetsForAnnotation = annotationsMap.getOrPut(annotation.annotationTypeRef.coneType) { arrayListOf() }
|
||||
|
||||
withSuppressedDiagnostics(annotation, context) {
|
||||
if (KotlinTarget.EXPRESSION !in annotation.getAllowedAnnotationTargets(context.session)) {
|
||||
reporter.reportOn(annotation.source, FirErrors.WRONG_ANNOTATION_TARGET, "expression", context)
|
||||
}
|
||||
|
||||
checkRepeatedAnnotation(useSiteTarget, existingTargetsForAnnotation, annotation, context, reporter)
|
||||
}
|
||||
|
||||
existingTargetsForAnnotation.add(useSiteTarget)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -363,6 +363,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REIFIED_TYPE_FORB
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REIFIED_TYPE_IN_CATCH_CLAUSE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REIFIED_TYPE_PARAMETER_IN_OVERRIDE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REIFIED_TYPE_PARAMETER_NO_INLINE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REPEATED_ANNOTATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REPEATED_ANNOTATION_WARNING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REPEATED_BOUND
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REPEATED_MODIFIER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RESERVED_MEMBER_INSIDE_INLINE_CLASS
|
||||
@@ -691,6 +693,8 @@ class FirDefaultErrorMessages {
|
||||
TO_STRING,
|
||||
TO_STRING
|
||||
)
|
||||
map.put(REPEATED_ANNOTATION, "This annotation is not repeatable")
|
||||
map.put(REPEATED_ANNOTATION_WARNING, "This annotation is not repeatable")
|
||||
|
||||
// OptIn
|
||||
map.put(EXPERIMENTAL_API_USAGE, "{1}", TO_STRING, STRING)
|
||||
|
||||
@@ -88,7 +88,6 @@ private val JAVA_TARGET_CLASS_ID = ClassId.topLevel(FqName(Target::class.java.ca
|
||||
private val JAVA_RETENTION_CLASS_ID = ClassId.topLevel(FqName(Retention::class.java.canonicalName))
|
||||
private val JAVA_DEPRECATED_CLASS_ID = ClassId.topLevel(FqName(Deprecated::class.java.canonicalName))
|
||||
private val JAVA_DOCUMENTED_CLASS_ID = ClassId.topLevel(FqName(Documented::class.java.canonicalName))
|
||||
private val JAVA_REPEATABLE_CLASS_ID = ClassId.topLevel(FqName("java.lang.annotation.Repeatable")) // since Java 8
|
||||
|
||||
private val JAVA_TARGETS_TO_KOTLIN = mapOf(
|
||||
"TYPE" to EnumSet.of(AnnotationTarget.CLASS, AnnotationTarget.FILE),
|
||||
@@ -171,7 +170,6 @@ private fun JavaAnnotation.toFirAnnotationCall(
|
||||
val lookupTag = when (classId) {
|
||||
JAVA_TARGET_CLASS_ID -> ClassId.topLevel(StandardNames.FqNames.target)
|
||||
JAVA_RETENTION_CLASS_ID -> ClassId.topLevel(StandardNames.FqNames.retention)
|
||||
JAVA_REPEATABLE_CLASS_ID -> ClassId.topLevel(StandardNames.FqNames.repeatable)
|
||||
JAVA_DOCUMENTED_CLASS_ID -> ClassId.topLevel(StandardNames.FqNames.mustBeDocumented)
|
||||
JAVA_DEPRECATED_CLASS_ID -> ClassId.topLevel(StandardNames.FqNames.deprecated)
|
||||
else -> classId
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// !LANGUAGE: +RepeatableAnnotations
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
// JVM_TARGET: 1.8
|
||||
|
||||
+4
-4
@@ -5,10 +5,10 @@ annotation class A1
|
||||
@Target(AnnotationTarget.TYPE_PARAMETER)
|
||||
annotation class A2(val some: Int = 12)
|
||||
|
||||
class TopLevelClass<@A1 @A2(3) @A2 @A1(<!TOO_MANY_ARGUMENTS!>12<!>) @A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>) T> {
|
||||
class InnerClass<@A1 @A2(3) @A2 @A1(<!TOO_MANY_ARGUMENTS!>12<!>) @A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>) T> {
|
||||
class TopLevelClass<@A1 @A2(3) <!REPEATED_ANNOTATION!>@A2<!> <!REPEATED_ANNOTATION!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> {
|
||||
class InnerClass<@A1 @A2(3) <!REPEATED_ANNOTATION!>@A2<!> <!REPEATED_ANNOTATION!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> {
|
||||
fun test() {
|
||||
class InFun<@A1 @A2(3) @A2 @A1(<!TOO_MANY_ARGUMENTS!>12<!>) @A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>) T>
|
||||
class InFun<@A1 @A2(3) <!REPEATED_ANNOTATION!>@A2<!> <!REPEATED_ANNOTATION!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -8,18 +8,18 @@ annotation class TA1
|
||||
@Target(AnnotationTarget.TYPE_PARAMETER)
|
||||
annotation class TA2(val some: Int = 12)
|
||||
|
||||
class TopLevelClass<<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!WRONG_ANNOTATION_TARGET!>@A2<!> <!WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> {
|
||||
class InnerClass<<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!WRONG_ANNOTATION_TARGET!>@A2<!> <!WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> {
|
||||
class TopLevelClass<<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> {
|
||||
class InnerClass<<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> {
|
||||
fun test() {
|
||||
class InFun<<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!WRONG_ANNOTATION_TARGET!>@A2<!> <!WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T>
|
||||
class InFun<<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TTopLevelClass<<!WRONG_ANNOTATION_TARGET!>@TA1<!> @TA2(3) @TA2 <!WRONG_ANNOTATION_TARGET!>@TA1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> @TA2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>) T> {
|
||||
class TInnerClass<<!WRONG_ANNOTATION_TARGET!>@TA1<!> @TA2(3) @TA2 <!WRONG_ANNOTATION_TARGET!>@TA1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> @TA2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>) T> {
|
||||
class TTopLevelClass<<!WRONG_ANNOTATION_TARGET!>@TA1<!> @TA2(3) <!REPEATED_ANNOTATION!>@TA2<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@TA1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION!>@TA2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> {
|
||||
class TInnerClass<<!WRONG_ANNOTATION_TARGET!>@TA1<!> @TA2(3) <!REPEATED_ANNOTATION!>@TA2<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@TA1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION!>@TA2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> {
|
||||
fun test() {
|
||||
class TInFun<<!WRONG_ANNOTATION_TARGET!>@TA1<!> @TA2(3) @TA2 <!WRONG_ANNOTATION_TARGET!>@TA1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> @TA2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>) T>
|
||||
class TInFun<<!WRONG_ANNOTATION_TARGET!>@TA1<!> @TA2(3) <!REPEATED_ANNOTATION!>@TA2<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@TA1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION!>@TA2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+6
-6
@@ -9,18 +9,18 @@ annotation class TA1
|
||||
@Target(AnnotationTarget.TYPE_PARAMETER)
|
||||
annotation class TA2(val some: Int = 12)
|
||||
|
||||
class TopLevelClass<<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!WRONG_ANNOTATION_TARGET!>@A2<!> <!WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> {
|
||||
class InnerClass<<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!WRONG_ANNOTATION_TARGET!>@A2<!> <!WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> {
|
||||
class TopLevelClass<<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> {
|
||||
class InnerClass<<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> {
|
||||
fun test() {
|
||||
class InFun<<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!WRONG_ANNOTATION_TARGET!>@A2<!> <!WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T>
|
||||
class InFun<<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TTopLevelClass<<!WRONG_ANNOTATION_TARGET!>@TA1<!> @TA2(3) @TA2 <!WRONG_ANNOTATION_TARGET!>@TA1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> @TA2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>) T> {
|
||||
class TInnerClass<<!WRONG_ANNOTATION_TARGET!>@TA1<!> @TA2(3) @TA2 <!WRONG_ANNOTATION_TARGET!>@TA1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> @TA2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>) T> {
|
||||
class TTopLevelClass<<!WRONG_ANNOTATION_TARGET!>@TA1<!> @TA2(3) <!REPEATED_ANNOTATION!>@TA2<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@TA1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION!>@TA2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> {
|
||||
class TInnerClass<<!WRONG_ANNOTATION_TARGET!>@TA1<!> @TA2(3) <!REPEATED_ANNOTATION!>@TA2<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@TA1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION!>@TA2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> {
|
||||
fun test() {
|
||||
class TInFun<<!WRONG_ANNOTATION_TARGET!>@TA1<!> @TA2(3) @TA2 <!WRONG_ANNOTATION_TARGET!>@TA1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> @TA2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>) T>
|
||||
class TInFun<<!WRONG_ANNOTATION_TARGET!>@TA1<!> @TA2(3) <!REPEATED_ANNOTATION!>@TA2<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@TA1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION!>@TA2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -1,13 +1,13 @@
|
||||
annotation class A1
|
||||
annotation class A2(val some: Int = 12)
|
||||
|
||||
fun <<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!WRONG_ANNOTATION_TARGET!>@A2<!> <!WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> topFun() = 12
|
||||
fun <<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> topFun() = 12
|
||||
|
||||
class SomeClass {
|
||||
fun <<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!WRONG_ANNOTATION_TARGET!>@A2<!> <!WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> method() = 12
|
||||
fun <<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> method() = 12
|
||||
|
||||
fun foo() {
|
||||
fun <<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!WRONG_ANNOTATION_TARGET!>@A2<!> <!WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> innerFun() = 12
|
||||
fun <<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> innerFun() = 12
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,12 @@ annotation class TA
|
||||
@Target(AnnotationTarget.TYPE_PARAMETER)
|
||||
annotation class TPA(val some: Int = 12)
|
||||
|
||||
fun <<!WRONG_ANNOTATION_TARGET!>@TA<!> @TPA(3) @TPA <!WRONG_ANNOTATION_TARGET!>@TA(<!TOO_MANY_ARGUMENTS!>12<!>)<!> @TPA(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>) T> topFunTPA() = 12
|
||||
fun <<!WRONG_ANNOTATION_TARGET!>@TA<!> @TPA(3) <!REPEATED_ANNOTATION!>@TPA<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@TA(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION!>@TPA(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> topFunTPA() = 12
|
||||
|
||||
class SomeClassTPA {
|
||||
fun <<!WRONG_ANNOTATION_TARGET!>@TA<!> @TPA(3) @TPA <!WRONG_ANNOTATION_TARGET!>@TA(<!TOO_MANY_ARGUMENTS!>12<!>)<!> @TPA(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>) T> method() = 12
|
||||
fun <<!WRONG_ANNOTATION_TARGET!>@TA<!> @TPA(3) <!REPEATED_ANNOTATION!>@TPA<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@TA(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION!>@TPA(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> method() = 12
|
||||
|
||||
fun foo() {
|
||||
fun <<!WRONG_ANNOTATION_TARGET!>@TA<!> @TPA(3) @TPA <!WRONG_ANNOTATION_TARGET!>@TA(<!TOO_MANY_ARGUMENTS!>12<!>)<!> @TPA(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>) T> innerFun() = 12
|
||||
fun <<!WRONG_ANNOTATION_TARGET!>@TA<!> @TPA(3) <!REPEATED_ANNOTATION!>@TPA<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@TA(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION!>@TPA(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> innerFun() = 12
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -3,10 +3,10 @@
|
||||
annotation class A1
|
||||
annotation class A2(val some: Int = 12)
|
||||
|
||||
val <<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!WRONG_ANNOTATION_TARGET!>@A2<!> <!WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> T.topProp: Int get() = 12
|
||||
val <<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> T.topProp: Int get() = 12
|
||||
|
||||
class SomeClass {
|
||||
val <<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!WRONG_ANNOTATION_TARGET!>@A2<!> <!WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> T.field: Int get() = 12
|
||||
val <<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!REPEATED_ANNOTATION, WRONG_ANNOTATION_TARGET!>@A2(<!ARGUMENT_TYPE_MISMATCH!>"Test"<!>)<!> T> T.field: Int get() = 12
|
||||
|
||||
fun foo() {
|
||||
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS!><@A1 @A2(3) @A2 @A1(12) @A2("Test") T><!> localVal = 12
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
annotation class unrepann(val x: Int)
|
||||
|
||||
annotation class ann(val y: Int)
|
||||
|
||||
@unrepann(1) @unrepann(2) class DoubleAnnotated
|
||||
|
||||
@ann(3) @ann(7) @ann(42) class TripleAnnotated
|
||||
|
||||
@Target(AnnotationTarget.EXPRESSION)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class annexpr
|
||||
|
||||
@ann(0) @ann(1) fun foo(@ann(7) @ann(2) x: Int): Int {
|
||||
@annexpr @annexpr return x
|
||||
}
|
||||
|
||||
@unrepann(0)
|
||||
@get:unrepann(1)
|
||||
var annotated = 1 // No errors should be here
|
||||
|
||||
@unrepann(0)
|
||||
@property:unrepann(1)
|
||||
var annotated2 = 2
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
annotation class unrepann(val x: Int)
|
||||
|
||||
annotation class ann(val y: Int)
|
||||
|
||||
-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()
|
||||
<!NON_SOURCE_REPEATED_ANNOTATION!>@JR<!>
|
||||
fun jr2() {}
|
||||
|
||||
@JR
|
||||
@JR.Container(JR())
|
||||
<!NON_SOURCE_REPEATED_ANNOTATION!>@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
|
||||
// FULL_JDK
|
||||
// FILE: JR.java
|
||||
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
// !LANGUAGE: -RepeatableAnnotations
|
||||
// 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 <!NON_SOURCE_REPEATED_ANNOTATION!>@Runtime<!>
|
||||
class UseRuntime
|
||||
|
||||
@Clazz <!NON_SOURCE_REPEATED_ANNOTATION!>@Clazz<!>
|
||||
class UseClazz
|
||||
|
||||
@Source @Source
|
||||
class UseSource
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !LANGUAGE: -RepeatableAnnotations
|
||||
// FULL_JDK
|
||||
// FILE: Runtime.java
|
||||
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
// !LANGUAGE: -RepeatableAnnotations
|
||||
// FULL_JDK
|
||||
// FILE: Runtime.java
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Runtime {}
|
||||
|
||||
// FILE: Clazz.java
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
public @interface Clazz {}
|
||||
|
||||
// FILE: Source.java
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Source {}
|
||||
|
||||
// FILE: usage.kt
|
||||
|
||||
@Runtime @Runtime
|
||||
class UseRuntime
|
||||
|
||||
@Clazz @Clazz
|
||||
class UseClazz
|
||||
|
||||
@Source @Source
|
||||
class UseSource
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !LANGUAGE: -RepeatableAnnotations
|
||||
// FULL_JDK
|
||||
// FILE: Runtime.java
|
||||
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
// !LANGUAGE: +RepeatableAnnotations
|
||||
// FULL_JDK
|
||||
// FILE: Runtime.java
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Runtime {}
|
||||
|
||||
// FILE: Clazz.java
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
public @interface Clazz {}
|
||||
|
||||
// FILE: Source.java
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Source {}
|
||||
|
||||
// FILE: usage.kt
|
||||
|
||||
@Runtime @Runtime
|
||||
class UseRuntime
|
||||
|
||||
@Clazz @Clazz
|
||||
class UseClazz
|
||||
|
||||
@Source @Source
|
||||
class UseSource
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !LANGUAGE: +RepeatableAnnotations
|
||||
// FULL_JDK
|
||||
// FILE: Runtime.java
|
||||
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// !LANGUAGE: -ProhibitRepeatedUseSiteTargetAnnotations
|
||||
|
||||
// Ann is not repeatable
|
||||
annotation class Ann(val x: Int)
|
||||
|
||||
@get:Ann(10)
|
||||
val a: String
|
||||
@Ann(20) get() = "foo"
|
||||
|
||||
@set:Ann(10)
|
||||
var b: String = ""
|
||||
@Ann(20) set(value) { field = value }
|
||||
|
||||
@setparam:Ann(10)
|
||||
var c = " "
|
||||
set(@Ann(20) x) {}
|
||||
|
||||
@get:Ann(10)
|
||||
@get:Ann(20)
|
||||
val d: String
|
||||
@Ann(30) @Ann(40) get() = "foo"
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// !LANGUAGE: -ProhibitRepeatedUseSiteTargetAnnotations
|
||||
|
||||
@@ -19,4 +20,4 @@ var c = " "
|
||||
<!REPEATED_ANNOTATION_WARNING!>@get:Ann(10)<!>
|
||||
<!REPEATED_ANNOTATION, REPEATED_ANNOTATION_WARNING!>@get:Ann(20)<!>
|
||||
val d: String
|
||||
@Ann(30) <!REPEATED_ANNOTATION!>@Ann(40)<!> get() = "foo"
|
||||
@Ann(30) <!REPEATED_ANNOTATION!>@Ann(40)<!> get() = "foo"
|
||||
|
||||
+6
-6
@@ -4,19 +4,19 @@
|
||||
// Ann is not repeatable
|
||||
annotation class Ann(val x: Int)
|
||||
|
||||
@get:Ann(10)
|
||||
<!REPEATED_ANNOTATION!>@get:Ann(10)<!>
|
||||
val a: String
|
||||
@Ann(20) get() = "foo"
|
||||
|
||||
@set:Ann(10)
|
||||
<!REPEATED_ANNOTATION!>@set:Ann(10)<!>
|
||||
var b: String = ""
|
||||
@Ann(20) set(value) { field = value }
|
||||
|
||||
@setparam:Ann(10)
|
||||
<!REPEATED_ANNOTATION!>@setparam:Ann(10)<!>
|
||||
var c = " "
|
||||
set(@Ann(20) x) {}
|
||||
|
||||
@get:Ann(10)
|
||||
@get:Ann(20)
|
||||
<!REPEATED_ANNOTATION!>@get:Ann(10)<!>
|
||||
<!REPEATED_ANNOTATION, REPEATED_ANNOTATION!>@get:Ann(20)<!>
|
||||
val d: String
|
||||
@Ann(30) @Ann(40) get() = "foo"
|
||||
@Ann(30) <!REPEATED_ANNOTATION!>@Ann(40)<!> get() = "foo"
|
||||
|
||||
+7
-7
@@ -9,12 +9,12 @@ class CustomDelegate {
|
||||
operator fun getValue(thisRef: Any?, prop: KProperty<*>): String = prop.name
|
||||
}
|
||||
|
||||
public class A(@param:Ann @Ann val x: Int, @param: RepeatableAnn @Ann val y: Int) {
|
||||
public class A(@param:Ann <!REPEATED_ANNOTATION!>@Ann<!> val x: Int, @param: RepeatableAnn @Ann val y: Int) {
|
||||
|
||||
@field:Ann @property:Ann @RepeatableAnn @property:RepeatableAnn
|
||||
val a: Int = 0
|
||||
|
||||
@Ann @field:Ann @property:Ann
|
||||
@Ann @field:Ann <!REPEATED_ANNOTATION!>@property:Ann<!>
|
||||
val b: Int = 0
|
||||
|
||||
@field:RepeatableAnn @field:RepeatableAnn
|
||||
@@ -46,14 +46,14 @@ annotation class fieldOrPropAnn
|
||||
annotation class getSetAndParamAnn
|
||||
|
||||
public class B(<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@param:fieldOrPropAnn<!> @fieldOrPropAnn val x: Int,
|
||||
@property:fieldOrPropAnn @fieldOrPropAnn val y: Int) {
|
||||
@property:fieldOrPropAnn <!REPEATED_ANNOTATION, REPEATED_ANNOTATION!>@fieldOrPropAnn<!> val y: Int) {
|
||||
@fieldOrPropAnn @field:fieldOrPropAnn
|
||||
val z: Int = 42
|
||||
|
||||
<!WRONG_ANNOTATION_TARGET!>@getSetAndParamAnn<!>
|
||||
@setparam:getSetAndParamAnn
|
||||
<!REPEATED_ANNOTATION!>@setparam:getSetAndParamAnn<!>
|
||||
var w: Int
|
||||
@getSetAndParamAnn @get:getSetAndParamAnn get() = 0
|
||||
@getSetAndParamAnn <!REPEATED_ANNOTATION!>@get:getSetAndParamAnn<!> get() = 0
|
||||
// See KT-15470: fake INAPPLICABLE_TARGET_ON_PROPERTY
|
||||
@getSetAndParamAnn <!INAPPLICABLE_TARGET_ON_PROPERTY!>@set:getSetAndParamAnn<!> set(arg) {}
|
||||
}
|
||||
@getSetAndParamAnn <!INAPPLICABLE_TARGET_ON_PROPERTY, REPEATED_ANNOTATION!>@set:getSetAndParamAnn<!> set(arg) {}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
class Test {
|
||||
@`InnerAnnotation` @InnerAnnotation
|
||||
@`InnerAnnotation` <!REPEATED_ANNOTATION!>@InnerAnnotation<!>
|
||||
companion object : StaticClass(), <!MANY_CLASSES_IN_SUPERTYPE_LIST, UNRESOLVED_REFERENCE!>InnerClass<!>() {
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@ annotation class A
|
||||
annotation class B
|
||||
|
||||
typealias Test0 = @A @B Int
|
||||
typealias Test1 = @A() (@A Int)
|
||||
typealias Test1 = @A() (<!REPEATED_ANNOTATION!>@A<!> Int)
|
||||
typealias Test2 = @A() (@B Int)
|
||||
typealias Test3 = @A() (@A Int) -> Int
|
||||
typealias Test4 = @A() (@B Int)?
|
||||
@@ -13,4 +13,4 @@ typealias Test5 = @A() ( (@B Int)? )
|
||||
typealias Test6 = (@A @B Int)
|
||||
typealias Test7 = (@A @B Int)?
|
||||
typealias Test8 = (@A() (@B Int)? )
|
||||
typealias Test9 = (@A() (@B Int) )?
|
||||
typealias Test9 = (@A() (@B Int) )?
|
||||
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class A
|
||||
|
||||
typealias Test1 = @A @A Int
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class A
|
||||
|
||||
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
// !DIAGNOSTICS: -JAVA_LANG_CLASS_PARAMETER_IN_ANNOTATION
|
||||
package a.b.c
|
||||
|
||||
@kotlin.Deprecated("aaa")
|
||||
@ann1(kotlin.Deprecated("aaa"))
|
||||
|
||||
@a.b.c.ann1()
|
||||
@ann2(a.b.c.ann1())
|
||||
|
||||
@A.IAnn()
|
||||
@ann3(A.IAnn())
|
||||
|
||||
@a.b.c.A.IAnn()
|
||||
@ann3(a.b.c.A.IAnn())
|
||||
|
||||
@annArray(kotlin.arrayOf("a"))
|
||||
fun test() = 1
|
||||
|
||||
annotation class ann1(val p: Deprecated = kotlin.Deprecated("aaa"))
|
||||
annotation class ann2(val p: ann1 = a.b.c.ann1())
|
||||
annotation class ann3(val p: A.IAnn = A.IAnn(), val p2: A.IAnn = a.b.c.A.IAnn())
|
||||
|
||||
annotation class annArray(val p: Array<String> = kotlin.arrayOf("a"))
|
||||
|
||||
class A {
|
||||
annotation class IAnn
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -JAVA_LANG_CLASS_PARAMETER_IN_ANNOTATION
|
||||
package a.b.c
|
||||
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// FIR_IDE_IGNORE
|
||||
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn api.ExperimentalAPI
|
||||
// MODULE: api
|
||||
// FILE: api.kt
|
||||
|
||||
+12
@@ -859,6 +859,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.REPEATED_ANNOTATION) { firDiagnostic ->
|
||||
RepeatedAnnotationImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.REPEATED_ANNOTATION_WARNING) { firDiagnostic ->
|
||||
RepeatedAnnotationWarningImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.EXPERIMENTAL_API_USAGE) { firDiagnostic ->
|
||||
ExperimentalApiUsageImpl(
|
||||
firDiagnostic.a,
|
||||
|
||||
+8
@@ -618,6 +618,14 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = InapplicableFileTarget::class
|
||||
}
|
||||
|
||||
abstract class RepeatedAnnotation : KtFirDiagnostic<KtAnnotationEntry>() {
|
||||
override val diagnosticClass get() = RepeatedAnnotation::class
|
||||
}
|
||||
|
||||
abstract class RepeatedAnnotationWarning : KtFirDiagnostic<KtAnnotationEntry>() {
|
||||
override val diagnosticClass get() = RepeatedAnnotationWarning::class
|
||||
}
|
||||
|
||||
abstract class ExperimentalApiUsage : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = ExperimentalApiUsage::class
|
||||
abstract val optInMarkerFqName: FqName
|
||||
|
||||
+14
@@ -991,6 +991,20 @@ internal class InapplicableFileTargetImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class RepeatedAnnotationImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.RepeatedAnnotation(), KtAbstractFirDiagnostic<KtAnnotationEntry> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class RepeatedAnnotationWarningImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.RepeatedAnnotationWarning(), KtAbstractFirDiagnostic<KtAnnotationEntry> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ExperimentalApiUsageImpl(
|
||||
override val optInMarkerFqName: FqName,
|
||||
override val message: String,
|
||||
|
||||
Reference in New Issue
Block a user