diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirModifierChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirModifierChecker.kt index 38ebcf55443..c72d8104d64 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirModifierChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirModifierChecker.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget -import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.* import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.Companion.classActualTargets import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.FirSourceElement @@ -53,9 +52,12 @@ object FirModifierChecker : FirBasicDeclarationChecker() { context: CheckerContext, reporter: DiagnosticReporter ) { + if (list.modifiers.isEmpty()) return + // general strategy: report no more than one error and any number of warnings // therefore, a track of nodes with already reported errors should be kept val reportedNodes = hashSetOf>() + val actualTargets = getActualTargetList(owner).defaultTargets val parent = context.findClosest { @@ -65,17 +67,17 @@ object FirModifierChecker : FirBasicDeclarationChecker() { } val actualParents = when (parent) { - is FirAnonymousObject -> listOf(LOCAL_CLASS, CLASS) + is FirAnonymousObject -> KotlinTarget.LOCAL_CLASS_LIST is FirClass -> classActualTargets( parent.classKind, isInnerClass = (parent as? FirMemberDeclaration)?.isInner ?: false, isCompanionObject = (parent as? FirRegularClass)?.isCompanion ?: false, isLocalClass = parent.isLocal ) - is FirPropertyAccessor -> listOf(if (parent.isSetter) PROPERTY_SETTER else PROPERTY_GETTER) - is FirFunction -> listOf(FUNCTION) - is FirEnumEntry -> listOf(ENUM_ENTRY, PROPERTY, FIELD) - else -> listOf(FILE) + is FirPropertyAccessor -> if (parent.isSetter) KotlinTarget.PROPERTY_SETTER_LIST else KotlinTarget.PROPERTY_GETTER_LIST + is FirFunction -> KotlinTarget.FUNCTION_LIST + is FirEnumEntry -> KotlinTarget.ENUM_ENTRY_LIST + else -> KotlinTarget.FILE_LIST } val modifiers = list.modifiers diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.kt index 21775ab8fee..d7c42e29f6f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.kt @@ -12,7 +12,6 @@ import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget -import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.* import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.lexer.KtKeywordToken import org.jetbrains.kotlin.lexer.KtModifierKeywordToken @@ -206,10 +205,10 @@ object ModifierCheckerCore { isCompanionObject = parentDescriptor.isCompanionObject, isLocalClass = DescriptorUtils.isLocal(parentDescriptor) ) - is PropertySetterDescriptor -> listOf(PROPERTY_SETTER) - is PropertyGetterDescriptor -> listOf(PROPERTY_GETTER) - is FunctionDescriptor -> listOf(FUNCTION) - else -> listOf(FILE) + is PropertySetterDescriptor -> KotlinTarget.PROPERTY_SETTER_LIST + is PropertyGetterDescriptor -> KotlinTarget.PROPERTY_GETTER_LIST + is FunctionDescriptor -> KotlinTarget.FUNCTION_LIST + else -> KotlinTarget.FILE_LIST } val deprecatedParents = deprecatedParentTargetMap[modifierType] if (deprecatedParents != null && actualParents.any { it in deprecatedParents }) { diff --git a/core/compiler.common/src/org/jetbrains/kotlin/descriptors/annotations/KotlinTarget.kt b/core/compiler.common/src/org/jetbrains/kotlin/descriptors/annotations/KotlinTarget.kt index 3d7144c4f97..ed0d20ea818 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/descriptors/annotations/KotlinTarget.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/descriptors/annotations/KotlinTarget.kt @@ -76,37 +76,49 @@ enum class KotlinTarget(val description: String, val isDefault: Boolean = true) fun valueOrNull(name: String): KotlinTarget? = map[name] val DEFAULT_TARGET_SET: Set = values().filter { it.isDefault }.toSet() - val ALL_TARGET_SET: Set = values().toSet() + val ANNOTATION_CLASS_LIST = listOf(ANNOTATION_CLASS, CLASS) + val LOCAL_CLASS_LIST = listOf(LOCAL_CLASS, CLASS) + val CLASS_LIST = listOf(CLASS_ONLY, CLASS) + val COMPANION_OBJECT_LIST = listOf(COMPANION_OBJECT, OBJECT, CLASS) + val OBJECT_LIST = listOf(OBJECT, CLASS) + val INTERFACE_LIST = listOf(INTERFACE, CLASS) + val ENUM_LIST = listOf(ENUM_CLASS, CLASS) + val ENUM_ENTRY_LIST = listOf(ENUM_ENTRY, PROPERTY, FIELD) + val PROPERTY_SETTER_LIST = listOf(PROPERTY_SETTER) + val PROPERTY_GETTER_LIST = listOf(PROPERTY_GETTER) + val FUNCTION_LIST = listOf(FUNCTION) + val FILE_LIST = listOf(FILE) + fun classActualTargets( kind: ClassKind, isInnerClass: Boolean, isCompanionObject: Boolean, isLocalClass: Boolean ): List = when (kind) { - ClassKind.ANNOTATION_CLASS -> listOf(ANNOTATION_CLASS, CLASS) + ClassKind.ANNOTATION_CLASS -> ANNOTATION_CLASS_LIST ClassKind.CLASS -> // inner local classes should be CLASS_ONLY, not LOCAL_CLASS if (!isInnerClass && isLocalClass) { - listOf(LOCAL_CLASS, CLASS) + LOCAL_CLASS_LIST } else { - listOf(CLASS_ONLY, CLASS) + CLASS_LIST } ClassKind.OBJECT -> if (isCompanionObject) { - listOf(COMPANION_OBJECT, OBJECT, CLASS) + COMPANION_OBJECT_LIST } else { - listOf(OBJECT, CLASS) + OBJECT_LIST } - ClassKind.INTERFACE -> listOf(INTERFACE, CLASS) + ClassKind.INTERFACE -> INTERFACE_LIST ClassKind.ENUM_CLASS -> if (isLocalClass) { - listOf(LOCAL_CLASS, CLASS) + LOCAL_CLASS_LIST } else { - listOf(ENUM_CLASS, CLASS) + ENUM_LIST } - ClassKind.ENUM_ENTRY -> listOf(ENUM_ENTRY, PROPERTY, FIELD) + ClassKind.ENUM_ENTRY -> ENUM_ENTRY_LIST } val USE_SITE_MAPPING: Map = mapOf(