[FIR] Introduce supertypes-for-annotation-class checker

This commit is contained in:
Julia
2021-04-01 04:36:26 +03:00
committed by Mikhail Glukhikh
parent caeb0b43be
commit 5472199bb1
15 changed files with 110 additions and 5 deletions
@@ -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");
@@ -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<R|kotlin/Any|>()
}
}
public final annotation class Ann : R|SomeInterface|, R|SomeClass|, R|kotlin/Annotation| {
public constructor(): R|Ann| {
super<R|kotlin/Any|>()
}
}
public final annotation class Ann2 : R|kotlin/Annotation| {
public constructor(): R|Ann2| {
super<R|kotlin/Any|>()
}
}
public final annotation class Ann3 : R|kotlin/Annotation|, R|kotlin/Annotation| {
public constructor(): R|Ann3| {
super<R|kotlin/Any|>()
}
}
public final class MyClass : R|SomeInterface|, R|SomeClass| {
public constructor(): R|MyClass| {
super<R|SomeClass|>()
}
}
@@ -0,0 +1,11 @@
interface SomeInterface
abstract class SomeClass
annotation class Ann : <!SUPERTYPES_FOR_ANNOTATION_CLASS!>SomeInterface, SomeClass()<!>
annotation class Ann2
annotation class Ann3 : <!SUPERTYPES_FOR_ANNOTATION_CLASS!>Annotation<!>
class MyClass : SomeInterface, SomeClass()
@@ -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 {
@@ -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 {
@@ -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}"
@@ -146,6 +146,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
}
val NULLABLE_TYPE_OF_ANNOTATION_MEMBER by error<FirSourceElement, KtTypeReference>()
val VAR_ANNOTATION_PARAMETER by error<FirSourceElement, KtParameter>(PositioningStrategy.VAL_OR_VAR_NODE)
val SUPERTYPES_FOR_ANNOTATION_CLASS by error<FirSourceElement, KtClass>(PositioningStrategy.SUPERTYPES_LIST)
}
val EXPOSED_VISIBILITY by object : DiagnosticGroup("Exposed visibility") {
@@ -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<FirSourceElement, PsiElement, String>()
val NULLABLE_TYPE_OF_ANNOTATION_MEMBER by error0<FirSourceElement, KtTypeReference>()
val VAR_ANNOTATION_PARAMETER by error0<FirSourceElement, KtParameter>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
val SUPERTYPES_FOR_ANNOTATION_CLASS by error0<FirSourceElement, KtClass>(SourceElementPositioningStrategies.SUPERTYPES_LIST)
// Exposed visibility
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<FirSourceElement, KtNamedDeclaration, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>(SourceElementPositioningStrategies.DECLARATION_NAME)
@@ -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 -> {
@@ -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(
@@ -44,6 +44,18 @@ object LightTreePositioningStrategies {
}
}
val SUPERTYPES_LIST = object : LightTreePositioningStrategy() {
override fun mark(
node: LighterASTNode,
startOffset: Int,
endOffset: Int,
tree: FlyweightCapableTreeStructure<LighterASTNode>
): List<TextRange> {
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<LighterASTNode>.modalityModifier(decl
internal fun FlyweightCapableTreeStructure<LighterASTNode>.overrideModifier(declaration: LighterASTNode): LighterASTNode? =
modifierList(declaration)?.let { findChildByType(it, KtTokens.OVERRIDE_KEYWORD) }
private fun FlyweightCapableTreeStructure<LighterASTNode>.supertypesList(node: LighterASTNode): LighterASTNode? =
findChildByType(node, KtNodeTypes.SUPER_TYPE_LIST)
private fun FlyweightCapableTreeStructure<LighterASTNode>.accessorNamePlaceholder(node: LighterASTNode): LighterASTNode =
findChildByType(node, KtTokens.GET_KEYWORD) ?: findChildByType(node, KtTokens.SET_KEYWORD)!!
@@ -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
@@ -67,6 +67,20 @@ object PositioningStrategies {
}
}
@JvmField
val SUPERTYPES_LIST: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
override fun mark(element: PsiElement): List<TextRange> {
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<KtDeclaration> = object : PositioningStrategy<KtDeclaration>() {
override fun mark(element: KtDeclaration): List<TextRange> {
@@ -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 <!ANNOTATION_CLASS_MEMBER!>a<!>
annotation class Ann4: C(), T
annotation class Ann: <!SUPERTYPES_FOR_ANNOTATION_CLASS!>C()<!>
annotation class Ann2: <!SUPERTYPES_FOR_ANNOTATION_CLASS!>T<!>
annotation class Ann3: <!SUPERTYPES_FOR_ANNOTATION_CLASS!>T by <!ANNOTATION_CLASS_MEMBER!>a<!><!>
annotation class Ann4: <!SUPERTYPES_FOR_ANNOTATION_CLASS!>C(), T<!>
@@ -9,4 +9,4 @@ open class Your {
open val x: Int = 0
}
annotation class His(override val x: Int): Your()
annotation class His(override val x: Int): <!SUPERTYPES_FOR_ANNOTATION_CLASS!>Your()<!>