[FIR] Add diagnostic when annotation argument is resolved ambiguously

Annotation arguments that are resolved in COMPILER_REQUIRED_ANNOTATIONS
phase are resolved again in ANNOTATION_ARGUMENTS phase. If they resolve
to a different symbol, report an error.

KT-56177
This commit is contained in:
Kirill Rakhman
2023-02-23 18:16:39 +01:00
committed by Space Team
parent 9dda5e4fcd
commit 2139914061
27 changed files with 253 additions and 5 deletions
@@ -1007,6 +1007,15 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.AMBIGUOUS_ANNOTATION_ARGUMENT) { firDiagnostic ->
AmbiguousAnnotationArgumentImpl(
firDiagnostic.a.map { firBasedSymbol ->
firSymbolBuilder.buildSymbol(firBasedSymbol)
},
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.WRONG_JS_QUALIFIER) { firDiagnostic ->
WrongJsQualifierImpl(
firDiagnostic as KtPsiDiagnostic,
@@ -728,6 +728,11 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val typeFromTypesPhase: KtType
}
abstract class AmbiguousAnnotationArgument : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = AmbiguousAnnotationArgument::class
abstract val symbols: List<KtSymbol>
}
abstract class WrongJsQualifier : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = WrongJsQualifier::class
}
@@ -873,6 +873,12 @@ internal class PluginAnnotationAmbiguityImpl(
override val token: KtLifetimeToken,
) : KtFirDiagnostic.PluginAnnotationAmbiguity(), KtAbstractFirDiagnostic<PsiElement>
internal class AmbiguousAnnotationArgumentImpl(
override val symbols: List<KtSymbol>,
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.AmbiguousAnnotationArgument(), KtAbstractFirDiagnostic<PsiElement>
internal class WrongJsQualifierImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
@@ -35874,6 +35874,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/annotations"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(fir|ll)\\.kts?$"), true);
}
@Test
@TestMetadata("annotationTargetResolvedAmbiguously.kt")
public void testAnnotationTargetResolvedAmbiguously() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationTargetResolvedAmbiguously.kt");
}
@Test
@TestMetadata("annotationsTargetingLateinitAccessors.kt")
public void testAnnotationsTargetingLateinitAccessors() throws Exception {
@@ -35874,6 +35874,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/annotations"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(fir|ll)\\.kts?$"), true);
}
@Test
@TestMetadata("annotationTargetResolvedAmbiguously.kt")
public void testAnnotationTargetResolvedAmbiguously() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationTargetResolvedAmbiguously.kt");
}
@Test
@TestMetadata("annotationsTargetingLateinitAccessors.kt")
public void testAnnotationsTargetingLateinitAccessors() throws Exception {
@@ -35970,6 +35970,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/annotations"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(fir|ll)\\.kts?$"), true);
}
@Test
@TestMetadata("annotationTargetResolvedAmbiguously.kt")
public void testAnnotationTargetResolvedAmbiguously() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationTargetResolvedAmbiguously.kt");
}
@Test
@TestMetadata("annotationsTargetingLateinitAccessors.kt")
public void testAnnotationsTargetingLateinitAccessors() throws Exception {
@@ -309,10 +309,14 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val WRONG_EXTENSION_FUNCTION_TYPE_WARNING by warning<KtAnnotationEntry>()
val ANNOTATION_IN_WHERE_CLAUSE_ERROR by error<KtAnnotationEntry>()
val PLUGIN_ANNOTATION_AMBIGUITY by error<PsiElement>() {
val PLUGIN_ANNOTATION_AMBIGUITY by error<PsiElement> {
parameter<ConeKotlinType>("typeFromCompilerPhase")
parameter<ConeKotlinType>("typeFromTypesPhase")
}
val AMBIGUOUS_ANNOTATION_ARGUMENT by error<PsiElement> {
parameter<List<FirBasedSymbol<*>>>("symbols")
}
}
val OPT_IN by object : DiagnosticGroup("OptIn") {
@@ -264,6 +264,7 @@ object FirErrors {
val WRONG_EXTENSION_FUNCTION_TYPE_WARNING by warning0<KtAnnotationEntry>()
val ANNOTATION_IN_WHERE_CLAUSE_ERROR by error0<KtAnnotationEntry>()
val PLUGIN_ANNOTATION_AMBIGUITY by error2<PsiElement, ConeKotlinType, ConeKotlinType>()
val AMBIGUOUS_ANNOTATION_ARGUMENT by error1<PsiElement, List<FirBasedSymbol<*>>>()
// OptIn
val OPT_IN_USAGE by warning2<PsiElement, FqName, String>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
@@ -58,6 +58,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_TYPE_ALIAS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_WITHOUT_EXPECT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_ACTUALS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_ALTERED_ASSIGN
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_ANNOTATION_ARGUMENT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_ANONYMOUS_TYPE_INFERRED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_EXPECTS
@@ -928,10 +929,15 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
)
map.put(
PLUGIN_ANNOTATION_AMBIGUITY,
"Resolution of annotation type is ambigous between {1} and plugin annotation {0}. Please specify fully qualified name of annotation",
"Resolution of annotation type is ambiguous between {1} and plugin annotation {0}. Please specify fully qualified name of annotation",
RENDER_TYPE,
RENDER_TYPE
)
map.put(
AMBIGUOUS_ANNOTATION_ARGUMENT,
"Resolution of annotation argument is ambiguous between {0}. Please specify fully qualified name of argument",
SYMBOLS,
)
// Exposed visibility group // #
map.put(
@@ -132,6 +132,8 @@ private fun ConeDiagnostic.toKtDiagnostic(
is ConeAmbiguouslyResolvedAnnotationFromPlugin -> {
FirErrors.PLUGIN_ANNOTATION_AMBIGUITY.createOn(source, typeFromCompilerPhase, typeFromTypesPhase)
}
is ConeAmbiguouslyResolvedAnnotationArgument ->
FirErrors.AMBIGUOUS_ANNOTATION_ARGUMENT.createOn(source, listOfNotNull(symbolFromCompilerPhase, symbolFromAnnotationArgumentsPhase))
is ConeAmbiguousFunctionTypeKinds -> FirErrors.AMBIGUOUS_FUNCTION_TYPE_KIND.createOn(source, kinds)
else -> throw IllegalArgumentException("Unsupported diagnostic type: ${this.javaClass}")
}
@@ -111,6 +111,7 @@ fun FirResolvedQualifier.continueQualifier(
packageFqName = this@continueQualifier.packageFqName
relativeClassFqName = this@continueQualifier.relativeClassFqName?.child(name)
symbol = nestedClassSymbol as FirClassLikeSymbol<*>
isFullyQualified = true
val outerTypeArguments = this.typeArguments.toList()
this.typeArguments.clear()
@@ -180,6 +181,7 @@ private fun FqName.continueQualifierInPackage(
apiVersion
)
)
isFullyQualified = true
}.apply {
resultType = components.typeForQualifier(this)
}
@@ -139,6 +139,7 @@ internal abstract class AbstractFirSpecificAnnotationResolveTransformer(
relativeClassFqName = symbol.classId.relativeClassName
typeRef = FirImplicitUnitTypeRef(receiver.typeRef.source)
this.symbol = symbol
isFullyQualified = segments.isNotEmpty()
}
// Resolve enum entry by name from the declarations of the receiver.
@@ -7,12 +7,26 @@ package org.jetbrains.kotlin.fir.resolve.transformers.plugin
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildPropertyAccessExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
import org.jetbrains.kotlin.fir.references.toResolvedBaseSymbol
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.*
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguouslyResolvedAnnotationArgument
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformerDispatcher
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDeclarationsResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirExpressionsResolveTransformer
import org.jetbrains.kotlin.fir.symbols.impl.FirEnumEntrySymbol
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.StandardClassIds
open class FirAnnotationArgumentsResolveTransformer(
session: FirSession,
@@ -252,9 +266,74 @@ abstract class AbstractFirExpressionsResolveTransformerForAnnotations(transforme
}
}
/**
* Set of enum class IDs that are resolved in COMPILER_REQUIRED_ANNOTATIONS phase that need to be rechecked here.
*/
private val classIdsToCheck: Set<ClassId> = setOf(StandardClassIds.DeprecationLevel, StandardClassIds.AnnotationTarget)
private class FirExpressionsResolveTransformerForSpecificAnnotations(transformer: FirAbstractBodyResolveTransformerDispatcher) :
AbstractFirExpressionsResolveTransformerForAnnotations(transformer) {
override fun transformQualifiedAccessExpression(
qualifiedAccessExpression: FirQualifiedAccessExpression,
data: ResolutionMode
): FirStatement {
val calleeReference = qualifiedAccessExpression.calleeReference
if (calleeReference is FirResolvedNamedReference &&
calleeReference.resolvedSymbol.let { it is FirEnumEntrySymbol && it.containingClassLookupTag()?.classId in classIdsToCheck } &&
qualifiedAccessExpression is FirPropertyAccessExpression
) {
val symbolFromCompilerPhase = calleeReference.resolvedSymbol
(qualifiedAccessExpression.explicitReceiver as? FirResolvedQualifier)?.let {
qualifiedAccessExpression.replaceResolvedQualifierReceiver(it)
}
qualifiedAccessExpression.replaceDispatchReceiver(FirNoReceiverExpression)
qualifiedAccessExpression.replaceTypeRef(noExpectedType)
qualifiedAccessExpression.replaceCalleeReference(buildSimpleNamedReference {
source = calleeReference.source
name = calleeReference.name
})
val resolved = super.transformQualifiedAccessExpression(qualifiedAccessExpression, data)
if (resolved is FirQualifiedAccessExpression) {
// The initial resolution must have been to an enum entry. Report ambiguity if symbolFromArgumentsPhase is different to
// original symbol including null (meaning we would resolve to something other than an enum entry).
val symbolFromArgumentsPhase = resolved.calleeReference.toResolvedBaseSymbol()
if (symbolFromCompilerPhase != symbolFromArgumentsPhase) {
resolved.replaceCalleeReference(buildErrorNamedReference {
source = resolved.calleeReference.source
diagnostic = ConeAmbiguouslyResolvedAnnotationArgument(symbolFromCompilerPhase, symbolFromArgumentsPhase)
})
}
}
return resolved
}
return super.transformQualifiedAccessExpression(qualifiedAccessExpression, data)
}
private fun FirQualifiedAccessExpression.replaceResolvedQualifierReceiver(receiver: FirResolvedQualifier) {
var lastReceiver = buildPropertyAccessExpression {
source = receiver.source
this.calleeReference = buildSimpleNamedReference {
val classId = receiver.classId ?: return
name = classId.relativeClassName.shortName()
}
}
replaceExplicitReceiver(lastReceiver)
if (receiver.isFullyQualified) {
for (segment in receiver.packageFqName.pathSegments().asReversed()) {
lastReceiver.replaceExplicitReceiver(buildPropertyAccessExpression {
this.calleeReference = buildSimpleNamedReference { name = segment }
}.also { lastReceiver = it })
}
}
}
override fun resolveQualifiedAccessAndSelectCandidate(
qualifiedAccessExpression: FirQualifiedAccessExpression,
isUsedAsReceiver: Boolean,
@@ -251,3 +251,15 @@ class ConeAmbiguouslyResolvedAnnotationFromPlugin(
- types stage: $typeFromTypesPhase
"""
}
class ConeAmbiguouslyResolvedAnnotationArgument(
val symbolFromCompilerPhase: FirBasedSymbol<*>,
val symbolFromAnnotationArgumentsPhase: FirBasedSymbol<*>?
) : ConeDiagnostic {
override val reason: String
get() = """
Annotation symbol resolved differently on compiler annotation and symbols stages:
- compiler annotations: $symbolFromCompilerPhase
- compiler arguments stage: $symbolFromAnnotationArgumentsPhase
"""
}
@@ -31,6 +31,7 @@ abstract class FirErrorResolvedQualifier : FirResolvedQualifier(), FirDiagnostic
abstract override val symbol: FirClassLikeSymbol<*>?
abstract override val isNullableLHSForCallableReference: Boolean
abstract override val resolvedToCompanionObject: Boolean
abstract override val isFullyQualified: Boolean
abstract override val nonFatalDiagnostics: List<ConeDiagnostic>
abstract override val typeArguments: List<FirTypeProjection>
abstract override val diagnostic: ConeDiagnostic
@@ -30,6 +30,7 @@ abstract class FirResolvedQualifier : FirExpression() {
abstract val symbol: FirClassLikeSymbol<*>?
abstract val isNullableLHSForCallableReference: Boolean
abstract val resolvedToCompanionObject: Boolean
abstract val isFullyQualified: Boolean
abstract val nonFatalDiagnostics: List<ConeDiagnostic>
abstract val typeArguments: List<FirTypeProjection>
@@ -35,6 +35,7 @@ interface FirAbstractResolvedQualifierBuilder {
abstract var symbol: FirClassLikeSymbol<*>?
abstract var isNullableLHSForCallableReference: Boolean
abstract var resolvedToCompanionObject: Boolean
abstract var isFullyQualified: Boolean
abstract val nonFatalDiagnostics: MutableList<ConeDiagnostic>
abstract val typeArguments: MutableList<FirTypeProjection>
@@ -39,6 +39,7 @@ class FirErrorResolvedQualifierBuilder : FirAbstractResolvedQualifierBuilder, Fi
override var relativeClassFqName: FqName? = null
override var symbol: FirClassLikeSymbol<*>? = null
override var isNullableLHSForCallableReference: Boolean = false
override var isFullyQualified: Boolean = false
override val nonFatalDiagnostics: MutableList<ConeDiagnostic> = mutableListOf()
override val typeArguments: MutableList<FirTypeProjection> = mutableListOf()
lateinit var diagnostic: ConeDiagnostic
@@ -51,6 +52,7 @@ class FirErrorResolvedQualifierBuilder : FirAbstractResolvedQualifierBuilder, Fi
relativeClassFqName,
symbol,
isNullableLHSForCallableReference,
isFullyQualified,
nonFatalDiagnostics.toMutableOrEmpty(),
typeArguments.toMutableOrEmpty(),
diagnostic,
@@ -41,6 +41,7 @@ class FirResolvedQualifierBuilder : FirAbstractResolvedQualifierBuilder, FirAnno
override var relativeClassFqName: FqName? = null
override var symbol: FirClassLikeSymbol<*>? = null
override var isNullableLHSForCallableReference: Boolean = false
override var isFullyQualified: Boolean = false
override val nonFatalDiagnostics: MutableList<ConeDiagnostic> = mutableListOf()
override val typeArguments: MutableList<FirTypeProjection> = mutableListOf()
@@ -53,6 +54,7 @@ class FirResolvedQualifierBuilder : FirAbstractResolvedQualifierBuilder, FirAnno
relativeClassFqName,
symbol,
isNullableLHSForCallableReference,
isFullyQualified,
nonFatalDiagnostics.toMutableOrEmpty(),
typeArguments.toMutableOrEmpty(),
)
@@ -33,6 +33,7 @@ internal class FirErrorResolvedQualifierImpl(
override val relativeClassFqName: FqName?,
override val symbol: FirClassLikeSymbol<*>?,
override var isNullableLHSForCallableReference: Boolean,
override val isFullyQualified: Boolean,
override var nonFatalDiagnostics: MutableOrEmptyList<ConeDiagnostic>,
override var typeArguments: MutableOrEmptyList<FirTypeProjection>,
override val diagnostic: ConeDiagnostic,
@@ -34,6 +34,7 @@ internal class FirResolvedQualifierImpl(
override var relativeClassFqName: FqName?,
override val symbol: FirClassLikeSymbol<*>?,
override var isNullableLHSForCallableReference: Boolean,
override val isFullyQualified: Boolean,
override var nonFatalDiagnostics: MutableOrEmptyList<ConeDiagnostic>,
override var typeArguments: MutableOrEmptyList<FirTypeProjection>,
) : FirResolvedQualifier() {
@@ -354,12 +354,12 @@ object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTree
builder(resolvedQualifier) {
parents += abstractResolvedQualifierBuilder
defaultFalse("isNullableLHSForCallableReference")
defaultFalse("isNullableLHSForCallableReference", "isFullyQualified")
}
builder(errorResolvedQualifier) {
parents += abstractResolvedQualifierBuilder
defaultFalse("isNullableLHSForCallableReference")
defaultFalse("isNullableLHSForCallableReference", "isFullyQualified")
}
// builder(safeCallExpression) {
@@ -595,6 +595,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+field("symbol", classLikeSymbolType, nullable = true)
+booleanField("isNullableLHSForCallableReference", withReplace = true)
+booleanField("resolvedToCompanionObject", withReplace = true)
+booleanField("isFullyQualified")
+fieldList("nonFatalDiagnostics", coneDiagnosticType, useMutableOrEmpty = true)
+typeArguments.withTransform()
}
@@ -0,0 +1,43 @@
import kotlin.annotation.AnnotationTarget.FIELD
object Some {
@Target(<!ARGUMENT_TYPE_MISMATCH!>AnnotationTarget.<!AMBIGUOUS_ANNOTATION_ARGUMENT!>CLASS<!><!>)
annotation class Ann
enum class AnnotationTarget {
CLASS
}
@Target(<!AMBIGUOUS_ANNOTATION_ARGUMENT!>FIELD<!>)
annotation class Ann2
const val FIELD = ""
}
object SomeMore {
@Target(<!ARGUMENT_TYPE_MISMATCH!>kotlin.annotation.AnnotationTarget.<!AMBIGUOUS_ANNOTATION_ARGUMENT!>FUNCTION<!><!>)
annotation class Ann3
object kotlin {
object annotation {
enum class AnnotationTarget {
FUNCTION
}
}
}
}
abstract class Base {
annotation class Target(val target: AnnotationTarget)
enum class AnnotationTarget {
TYPE
}
}
class Derived : Base() {
@<!PLUGIN_ANNOTATION_AMBIGUITY!>Target<!>(<!ARGUMENT_TYPE_MISMATCH!>AnnotationTarget.<!AMBIGUOUS_ANNOTATION_ARGUMENT!>TYPE<!><!>)
annotation class Ann
fun foo(x: <!WRONG_ANNOTATION_TARGET!>@Ann<!> String) {}
}
@@ -0,0 +1,43 @@
import kotlin.annotation.AnnotationTarget.FIELD
object Some {
@Target(<!TYPE_MISMATCH!>AnnotationTarget.CLASS<!>)
annotation class Ann
enum class AnnotationTarget {
CLASS
}
@Target(<!TYPE_MISMATCH!>FIELD<!>)
annotation class Ann2
const val FIELD = ""
}
object SomeMore {
@Target(<!TYPE_MISMATCH!>kotlin.annotation.AnnotationTarget.FUNCTION<!>)
annotation class Ann3
object kotlin {
object annotation {
enum class AnnotationTarget {
FUNCTION
}
}
}
}
abstract class Base {
annotation class Target(val target: AnnotationTarget)
enum class AnnotationTarget {
TYPE
}
}
class Derived : Base() {
@Target(AnnotationTarget.TYPE)
annotation class Ann
fun foo(x: <!WRONG_ANNOTATION_TARGET!>@Ann<!> String) {}
}
@@ -35970,6 +35970,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/annotations"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(fir|ll)\\.kts?$"), true);
}
@Test
@TestMetadata("annotationTargetResolvedAmbiguously.kt")
public void testAnnotationTargetResolvedAmbiguously() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationTargetResolvedAmbiguously.kt");
}
@Test
@TestMetadata("annotationsTargetingLateinitAccessors.kt")
public void testAnnotationsTargetingLateinitAccessors() throws Exception {
@@ -136,6 +136,7 @@ object StandardClassIds {
val AnnotationRetention = "AnnotationRetention".annotationId()
val AnnotationTarget = "AnnotationTarget".annotationId()
val DeprecationLevel = "DeprecationLevel".baseId()
val EnumEntries = "EnumEntries".enumsId()