diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java index 73c780c7c9e..1d8d86245df 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java @@ -379,6 +379,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract runTest("compiler/fir/analysis-tests/testData/resolve/statusResolveForTypealiasAsSuperClass.kt"); } + @TestMetadata("supertypesForAnnotationClass.kt") + public void testSupertypesForAnnotationClass() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/supertypesForAnnotationClass.kt"); + } + @TestMetadata("syntheticsVsNormalProperties.kt") public void testSyntheticsVsNormalProperties() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/syntheticsVsNormalProperties.kt"); diff --git a/compiler/fir/analysis-tests/testData/resolve/supertypesForAnnotationClass.fir.txt b/compiler/fir/analysis-tests/testData/resolve/supertypesForAnnotationClass.fir.txt new file mode 100644 index 00000000000..849d6d8ea0c --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/supertypesForAnnotationClass.fir.txt @@ -0,0 +1,33 @@ +FILE: supertypesForAnnotationClass.kt + public abstract interface SomeInterface : R|kotlin/Any| { + } + public abstract class SomeClass : R|kotlin/Any| { + public constructor(): R|SomeClass| { + super() + } + + } + public final annotation class Ann : R|SomeInterface|, R|SomeClass|, R|kotlin/Annotation| { + public constructor(): R|Ann| { + super() + } + + } + public final annotation class Ann2 : R|kotlin/Annotation| { + public constructor(): R|Ann2| { + super() + } + + } + public final annotation class Ann3 : R|kotlin/Annotation|, R|kotlin/Annotation| { + public constructor(): R|Ann3| { + super() + } + + } + public final class MyClass : R|SomeInterface|, R|SomeClass| { + public constructor(): R|MyClass| { + super() + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/supertypesForAnnotationClass.kt b/compiler/fir/analysis-tests/testData/resolve/supertypesForAnnotationClass.kt new file mode 100644 index 00000000000..1bdcbcc8d89 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/supertypesForAnnotationClass.kt @@ -0,0 +1,11 @@ +interface SomeInterface + +abstract class SomeClass + +annotation class Ann : SomeInterface, SomeClass() + +annotation class Ann2 + +annotation class Ann3 : Annotation + +class MyClass : SomeInterface, SomeClass() diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java index 1110c8752b2..a54b4c15fc8 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java @@ -446,6 +446,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { runTest("compiler/fir/analysis-tests/testData/resolve/statusResolveForTypealiasAsSuperClass.kt"); } + @Test + @TestMetadata("supertypesForAnnotationClass.kt") + public void testSupertypesForAnnotationClass() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/supertypesForAnnotationClass.kt"); + } + @Test @TestMetadata("syntheticsVsNormalProperties.kt") public void testSyntheticsVsNormalProperties() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java index 3e14207f9f6..25955a71cb3 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java @@ -449,6 +449,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/statusResolveForTypealiasAsSuperClass.kt"); } + @Test + @TestMetadata("supertypesForAnnotationClass.kt") + public void testSupertypesForAnnotationClass() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/supertypesForAnnotationClass.kt"); + } + @Test @TestMetadata("syntheticsVsNormalProperties.kt") public void testSyntheticsVsNormalProperties() throws Exception { diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt index 58797850a92..1f4b7a36a20 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt @@ -53,6 +53,7 @@ enum class PositioningStrategy(private val strategy: String? = null) { ARRAY_ACCESS, NAME_OF_NAMED_ARGUMENT, VALUE_ARGUMENTS, + SUPERTYPES_LIST, ; val expressionToCreate get() = "SourceElementPositioningStrategies.${strategy ?: name}" diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 88b53f681a5..24b8d907763 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -146,6 +146,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() { } val NULLABLE_TYPE_OF_ANNOTATION_MEMBER by error() val VAR_ANNOTATION_PARAMETER by error(PositioningStrategy.VAL_OR_VAR_NODE) + val SUPERTYPES_FOR_ANNOTATION_CLASS by error(PositioningStrategy.SUPERTYPES_LIST) } val EXPOSED_VISIBILITY by object : DiagnosticGroup("Exposed visibility") { diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 21156a72555..7ebcc957c29 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtArrayAccessExpression +import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDestructuringDeclaration @@ -139,6 +140,7 @@ object FirErrors { val NOT_AN_ANNOTATION_CLASS by error1() val NULLABLE_TYPE_OF_ANNOTATION_MEMBER by error0() val VAR_ANNOTATION_PARAMETER by error0(SourceElementPositioningStrategies.VAL_OR_VAR_NODE) + val SUPERTYPES_FOR_ANNOTATION_CLASS by error0(SourceElementPositioningStrategies.SUPERTYPES_LIST) // Exposed visibility val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3(SourceElementPositioningStrategies.DECLARATION_NAME) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt index 62d53ae7478..6aebccb4724 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt @@ -26,6 +26,10 @@ object FirAnnotationClassDeclarationChecker : FirRegularClassChecker() { if (declaration.classKind != ANNOTATION_CLASS) return if (declaration.isLocal) reporter.reportOn(declaration.source, FirErrors.LOCAL_ANNOTATION_CLASS_ERROR, context) + if (declaration.superTypeRefs.size != 1) { + reporter.reportOn(declaration.source, FirErrors.SUPERTYPES_FOR_ANNOTATION_CLASS, context) + } + for (it in declaration.declarations) { when { it is FirConstructor && it.isPrimary -> { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index 1f0c4e2125c..89df27ed401 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -191,6 +191,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_SUPERTYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_SUPERTYPE_IN_LOCAL_CLASS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_INLINE_CLASS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPES_FOR_ANNOTATION_CLASS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_INITIALIZED_IN_INTERFACE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_NOT_A_CLASS_OR_INTERFACE @@ -345,6 +346,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { map.put(INVALID_TYPE_OF_ANNOTATION_MEMBER, "Invalid type of annotation member") map.put(VAR_ANNOTATION_PARAMETER, "An annotation parameter cannot be 'var'") map.put(NOT_AN_ANNOTATION_CLASS, "Illegal annotation class: {0}", NULLABLE_STRING) + map.put(SUPERTYPES_FOR_ANNOTATION_CLASS, "Annotation class cannot have supertypes") // Exposed visibility group // # map.put( diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt index 329f5e64892..2153c06dc88 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt @@ -44,6 +44,18 @@ object LightTreePositioningStrategies { } } + val SUPERTYPES_LIST = object : LightTreePositioningStrategy() { + override fun mark( + node: LighterASTNode, + startOffset: Int, + endOffset: Int, + tree: FlyweightCapableTreeStructure + ): List { + val target = tree.supertypesList(node) ?: node + return markElement(target, startOffset, endOffset, tree, node) + } + } + val VAL_OR_VAR_NODE: LightTreePositioningStrategy = object : LightTreePositioningStrategy() { override fun mark( node: LighterASTNode, @@ -566,6 +578,9 @@ internal fun FlyweightCapableTreeStructure.modalityModifier(decl internal fun FlyweightCapableTreeStructure.overrideModifier(declaration: LighterASTNode): LighterASTNode? = modifierList(declaration)?.let { findChildByType(it, KtTokens.OVERRIDE_KEYWORD) } +private fun FlyweightCapableTreeStructure.supertypesList(node: LighterASTNode): LighterASTNode? = + findChildByType(node, KtNodeTypes.SUPER_TYPE_LIST) + private fun FlyweightCapableTreeStructure.accessorNamePlaceholder(node: LighterASTNode): LighterASTNode = findChildByType(node, KtTokens.GET_KEYWORD) ?: findChildByType(node, KtTokens.SET_KEYWORD)!! diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt index 45aa0814db4..055122cbebe 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt @@ -128,6 +128,11 @@ object SourceElementPositioningStrategies { PositioningStrategies.VALUE_ARGUMENTS ) + val SUPERTYPES_LIST = SourceElementPositioningStrategy( + LightTreePositioningStrategies.SUPERTYPES_LIST, + PositioningStrategies.SUPERTYPES_LIST + ) + val DOT_BY_QUALIFIED = SourceElementPositioningStrategy( LightTreePositioningStrategies.DOT_BY_QUALIFIED, PositioningStrategies.DOT_BY_QUALIFIED diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index 3dbb8d075e7..59a0eeff0d2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -67,6 +67,20 @@ object PositioningStrategies { } } + @JvmField + val SUPERTYPES_LIST: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: PsiElement): List { + val supertypes = (( + element as? KtClass + ) ?: return markElement(element) + ).superTypeListEntries + return if (supertypes.isEmpty()) + markElement(element) + else + markRange(supertypes[0], supertypes.last()) + } + } + @JvmField val DECLARATION_RETURN_TYPE: PositioningStrategy = object : PositioningStrategy() { override fun mark(element: KtDeclaration): List { diff --git a/compiler/testData/diagnostics/tests/annotations/annotationInheritance.fir.kt b/compiler/testData/diagnostics/tests/annotations/annotationInheritance.fir.kt index 933f1b7a760..56833c94cb0 100644 --- a/compiler/testData/diagnostics/tests/annotations/annotationInheritance.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/annotationInheritance.fir.kt @@ -2,7 +2,7 @@ val a = object: T {} open class C interface T -annotation class Ann: C() -annotation class Ann2: T -annotation class Ann3: T by a -annotation class Ann4: C(), T \ No newline at end of file +annotation class Ann: C() +annotation class Ann2: T +annotation class Ann3: T by a +annotation class Ann4: C(), T diff --git a/compiler/testData/diagnostics/tests/modifiers/annotations.fir.kt b/compiler/testData/diagnostics/tests/modifiers/annotations.fir.kt index 8b30f2bba45..6d86371ce29 100644 --- a/compiler/testData/diagnostics/tests/modifiers/annotations.fir.kt +++ b/compiler/testData/diagnostics/tests/modifiers/annotations.fir.kt @@ -9,4 +9,4 @@ open class Your { open val x: Int = 0 } -annotation class His(override val x: Int): Your() \ No newline at end of file +annotation class His(override val x: Int): Your()