[FIR] Properly create FirAnnotation and FirAnnotationCall in all places
This commit is contained in:
committed by
teamcityserver
parent
31a7d8d5a4
commit
2e7564a21e
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.fir.expressions.builder.*
|
||||
import org.jetbrains.kotlin.fir.java.declarations.buildJavaValueParameter
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirReferencePlaceholderForResolvedAnnotations
|
||||
import org.jetbrains.kotlin.fir.resolve.bindSymbolToLookupTag
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedReferenceError
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.getClassDeclaredPropertySymbols
|
||||
@@ -101,18 +100,21 @@ private val JAVA_TARGETS_TO_KOTLIN = mapOf(
|
||||
"TYPE_USE" to EnumSet.of(AnnotationTarget.TYPE)
|
||||
)
|
||||
|
||||
private fun List<JavaAnnotationArgument>.mapJavaTargetArguments(session: FirSession): FirExpression? =
|
||||
buildArrayOfCall {
|
||||
argumentList = buildArgumentList {
|
||||
val resultSet = EnumSet.noneOf(AnnotationTarget::class.java)
|
||||
for (target in this@mapJavaTargetArguments) {
|
||||
if (target !is JavaEnumValueAnnotationArgument) return null
|
||||
resultSet.addAll(JAVA_TARGETS_TO_KOTLIN[target.entryName?.asString()] ?: continue)
|
||||
}
|
||||
val classId = ClassId.topLevel(StandardNames.FqNames.annotationTarget)
|
||||
resultSet.mapTo(arguments) { buildEnumCall(session, classId, Name.identifier(it.name)) }
|
||||
private val TARGET_ALLOWED_TARGETS_NAME = Name.identifier("allowedTargets")
|
||||
private val RETENTION_VALUE_NAME = Name.identifier("value")
|
||||
private val DEPRECATED_MESSAGE_NAME = Name.identifier("message")
|
||||
|
||||
private fun List<JavaAnnotationArgument>.mapJavaTargetArguments(session: FirSession): FirExpression? {
|
||||
return buildVarargArgumentsExpression {
|
||||
val resultSet = EnumSet.noneOf(AnnotationTarget::class.java)
|
||||
for (target in this@mapJavaTargetArguments) {
|
||||
if (target !is JavaEnumValueAnnotationArgument) return null
|
||||
resultSet.addAll(JAVA_TARGETS_TO_KOTLIN[target.entryName?.asString()] ?: continue)
|
||||
}
|
||||
val classId = ClassId.topLevel(StandardNames.FqNames.annotationTarget)
|
||||
resultSet.mapTo(arguments) { buildEnumCall(session, classId, Name.identifier(it.name)) }
|
||||
}
|
||||
}
|
||||
|
||||
private val JAVA_RETENTION_TO_KOTLIN = mapOf(
|
||||
"RUNTIME" to AnnotationRetention.RUNTIME,
|
||||
@@ -125,26 +127,24 @@ private fun JavaAnnotationArgument.mapJavaRetentionArgument(session: FirSession)
|
||||
buildEnumCall(session, ClassId.topLevel(StandardNames.FqNames.annotationRetention), Name.identifier(it.name))
|
||||
}
|
||||
|
||||
private fun buildArgumentMapping(
|
||||
private fun fillAnnotationArgumentMapping(
|
||||
session: FirSession,
|
||||
javaTypeParameterStack: JavaTypeParameterStack,
|
||||
lookupTag: ConeClassLikeLookupTagImpl,
|
||||
annotationArguments: Collection<JavaAnnotationArgument>
|
||||
): FirArgumentList? {
|
||||
if (annotationArguments.none { it.name != null }) {
|
||||
return null
|
||||
}
|
||||
annotationArguments: Collection<JavaAnnotationArgument>,
|
||||
destination: MutableMap<Name, FirExpression>
|
||||
) {
|
||||
if (annotationArguments.none { it.name != null }) return
|
||||
val annotationClassSymbol = session.symbolProvider.getClassLikeSymbolByClassId(lookupTag.classId).also {
|
||||
lookupTag.bindSymbolToLookupTag(session, it)
|
||||
} ?: return null
|
||||
} ?: return
|
||||
val annotationConstructor =
|
||||
(annotationClassSymbol.fir as FirRegularClass).declarations.filterIsInstance<FirConstructor>().first()
|
||||
val mapping = annotationArguments.associateTo(linkedMapOf()) { argument ->
|
||||
val parameter = annotationConstructor.valueParameters.find { it.name == (argument.name ?: JavaSymbolProvider.VALUE_METHOD_NAME) }
|
||||
?: return null
|
||||
argument.toFirExpression(session, javaTypeParameterStack, parameter.returnTypeRef) to parameter
|
||||
annotationArguments.associateTo(destination) { argument ->
|
||||
val name = argument.name ?: JavaSymbolProvider.VALUE_METHOD_NAME
|
||||
val parameter = annotationConstructor.valueParameters.find { it.name == name }
|
||||
name to argument.toFirExpression(session, javaTypeParameterStack, parameter?.returnTypeRef)
|
||||
}
|
||||
return buildResolvedArgumentList(mapping)
|
||||
}
|
||||
|
||||
internal fun Iterable<JavaAnnotation>.convertAnnotationsToFir(
|
||||
@@ -181,23 +181,36 @@ private fun JavaAnnotation.toFirAnnotationCall(
|
||||
} else {
|
||||
buildErrorTypeRef { diagnostic = ConeUnresolvedReferenceError() }
|
||||
}
|
||||
argumentList = when (classId) {
|
||||
JAVA_TARGET_CLASS_ID -> when (val argument = arguments.singleOrNull()) {
|
||||
is JavaArrayAnnotationArgument -> argument.getElements().mapJavaTargetArguments(session)?.let(::buildUnaryArgumentList)
|
||||
is JavaEnumValueAnnotationArgument -> listOf(argument).mapJavaTargetArguments(session)?.let(::buildUnaryArgumentList)
|
||||
else -> null
|
||||
}
|
||||
JAVA_RETENTION_CLASS_ID -> arguments.singleOrNull()?.mapJavaRetentionArgument(session)?.let(::buildUnaryArgumentList)
|
||||
JAVA_DEPRECATED_CLASS_ID ->
|
||||
buildUnaryArgumentList(buildConstExpression(null, ConstantValueKind.String, "Deprecated in Java").setProperType(session))
|
||||
null -> null
|
||||
else -> buildArgumentMapping(session, javaTypeParameterStack, lookupTag!!, arguments)
|
||||
} ?: buildArgumentList {
|
||||
this@toFirAnnotationCall.arguments.mapTo(arguments) {
|
||||
it.toFirExpression(session, javaTypeParameterStack, null)
|
||||
|
||||
argumentMapping = buildAnnotationArgumentMapping {
|
||||
when (classId) {
|
||||
JAVA_TARGET_CLASS_ID -> {
|
||||
when (val argument = arguments.firstOrNull()) {
|
||||
is JavaArrayAnnotationArgument -> argument.getElements().mapJavaTargetArguments(session)
|
||||
is JavaEnumValueAnnotationArgument -> listOf(argument).mapJavaTargetArguments(session)
|
||||
else -> null
|
||||
}?.let {
|
||||
mapping[TARGET_ALLOWED_TARGETS_NAME] = it
|
||||
}
|
||||
}
|
||||
JAVA_RETENTION_CLASS_ID -> {
|
||||
arguments.firstOrNull()?.mapJavaRetentionArgument(session)?.let {
|
||||
mapping[RETENTION_VALUE_NAME] = it
|
||||
}
|
||||
}
|
||||
JAVA_DEPRECATED_CLASS_ID -> {
|
||||
mapping[DEPRECATED_MESSAGE_NAME] = buildConstExpression(
|
||||
source = null,
|
||||
ConstantValueKind.String,
|
||||
"Deprecated in Java"
|
||||
).setProperType(session)
|
||||
}
|
||||
null -> {}
|
||||
else -> {
|
||||
fillAnnotationArgumentMapping(session, javaTypeParameterStack, lookupTag!!, arguments, mapping)
|
||||
}
|
||||
}
|
||||
}
|
||||
calleeReference = FirReferencePlaceholderForResolvedAnnotations
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-11
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.fir.expressions.builder.*
|
||||
import org.jetbrains.kotlin.fir.java.createConstantOrError
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirReferencePlaceholderForResolvedAnnotations
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.getClassDeclaredPropertySymbols
|
||||
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
@@ -110,7 +109,7 @@ internal class AnnotationsLoader(private val session: FirSession, private val ko
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitAnnotation(classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||
override fun visitAnnotation(classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor {
|
||||
val list = mutableListOf<FirAnnotation>()
|
||||
val visitor = loadAnnotation(classId, list)
|
||||
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor {
|
||||
@@ -150,16 +149,9 @@ internal class AnnotationsLoader(private val session: FirSession, private val ko
|
||||
|
||||
result += buildAnnotation {
|
||||
annotationTypeRef = lookupTag.toDefaultResolvedTypeRef()
|
||||
argumentList = buildArgumentList {
|
||||
for ((name, expression) in argumentMap) {
|
||||
arguments += buildNamedArgumentExpression {
|
||||
this.expression = expression
|
||||
this.name = name
|
||||
isSpread = false
|
||||
}
|
||||
}
|
||||
argumentMapping = buildAnnotationArgumentMapping {
|
||||
mapping.putAll(argumentMap)
|
||||
}
|
||||
calleeReference = FirReferencePlaceholderForResolvedAnnotations
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-6
@@ -93,9 +93,8 @@ class JvmBinaryAnnotationDeserializer(
|
||||
).map {
|
||||
buildAnnotation {
|
||||
annotationTypeRef = it.annotationTypeRef
|
||||
argumentList = it.argumentList
|
||||
argumentMapping = it.argumentMapping
|
||||
useSiteTarget = AnnotationUseSiteTarget.PROPERTY
|
||||
calleeReference = it.calleeReference
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,9 +115,8 @@ class JvmBinaryAnnotationDeserializer(
|
||||
return findJvmBinaryClassAndLoadMemberAnnotations(signature).map {
|
||||
buildAnnotation {
|
||||
annotationTypeRef = it.annotationTypeRef
|
||||
argumentList = it.argumentList
|
||||
argumentMapping = it.argumentMapping
|
||||
useSiteTarget = AnnotationUseSiteTarget.FIELD
|
||||
calleeReference = it.calleeReference
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,9 +134,8 @@ class JvmBinaryAnnotationDeserializer(
|
||||
return findJvmBinaryClassAndLoadMemberAnnotations(signature).map {
|
||||
buildAnnotation {
|
||||
annotationTypeRef = it.annotationTypeRef
|
||||
argumentList = it.argumentList
|
||||
argumentMapping = it.argumentMapping
|
||||
useSiteTarget = AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD
|
||||
calleeReference = it.calleeReference
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user