[FIR] Load Java annotations named arguments properly (see KT-43584)

This commit is contained in:
Mikhail Glukhikh
2020-11-25 15:35:01 +03:00
parent e6f380182a
commit 9b30655d66
5 changed files with 49 additions and 15 deletions
@@ -50,7 +50,7 @@ class JavaSymbolProvider(
private val searchScope: GlobalSearchScope,
) : FirSymbolProvider(session) {
companion object {
private val VALUE_METHOD_NAME = Name.identifier("value")
internal val VALUE_METHOD_NAME = Name.identifier("value")
}
private val classCache = SymbolProviderCache<ClassId, FirRegularClassSymbol>()
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.java.enhancement.readOnlyToMutable
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.defaultType
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.getClassDeclaredCallableSymbols
@@ -418,16 +419,48 @@ private fun FirRegularClass.createRawArguments(
computeRawProjection(session, typeParameter, position, erasedUpperBound)
}
private fun FirAnnotationCallBuilder.buildArgumentMapping(
session: FirSession,
javaTypeParameterStack: JavaTypeParameterStack,
classId: ClassId,
annotationArguments: Collection<JavaAnnotationArgument>
): LinkedHashMap<FirExpression, FirValueParameter>? {
val lookupTag = ConeClassLikeLookupTagImpl(classId)
annotationTypeRef = buildResolvedTypeRef {
type = ConeClassLikeTypeImpl(lookupTag, emptyArray(), isNullable = false)
}
if (annotationArguments.any { it.name != null }) {
val mapping = linkedMapOf<FirExpression, FirValueParameter>()
val annotationClassSymbol = session.firSymbolProvider.getClassLikeSymbolByFqName(classId).also {
lookupTag.bindSymbolToLookupTag(session, it)
}
if (annotationClassSymbol != null) {
val annotationConstructor =
(annotationClassSymbol.fir as FirRegularClass).declarations.filterIsInstance<FirConstructor>().first()
for (argument in annotationArguments) {
mapping[argument.toFirExpression(session, javaTypeParameterStack)] =
annotationConstructor.valueParameters.find { it.name == (argument.name ?: JavaSymbolProvider.VALUE_METHOD_NAME) }
?: return null
}
return mapping
}
}
return null
}
internal fun JavaAnnotation.toFirAnnotationCall(
session: FirSession, javaTypeParameterStack: JavaTypeParameterStack
): FirAnnotationCall {
return buildAnnotationCall {
annotationTypeRef = buildResolvedTypeRef {
type = ConeClassLikeTypeImpl(FirRegularClassSymbol(classId!!).toLookupTag(), emptyArray(), isNullable = false)
}
argumentList = buildArgumentList {
for (argument in this@toFirAnnotationCall.arguments) {
arguments += argument.toFirExpression(session, javaTypeParameterStack)
val classId = classId!!
val mapping = buildArgumentMapping(session, javaTypeParameterStack, classId, arguments)
argumentList = if (mapping != null) {
buildResolvedArgumentList(mapping)
} else {
buildArgumentList {
for (argument in this@toFirAnnotationCall.arguments) {
arguments += argument.toFirExpression(session, javaTypeParameterStack)
}
}
}
calleeReference = FirReferencePlaceholderForResolvedAnnotations
@@ -44,6 +44,7 @@ inline val FirCall.argumentMapping: LinkedHashMap<FirExpression, FirValueParamet
get() = (argumentList as? FirResolvedArgumentList)?.mapping
fun FirExpression.toResolvedCallableReference(): FirResolvedNamedReference? {
if (this is FirWrappedArgumentExpression) return expression.toResolvedCallableReference()
return (this as? FirResolvable)?.calleeReference as? FirResolvedNamedReference
}
@@ -7,10 +7,10 @@ fun nonConstLong(): Long = TODO()
annotation class Anno(vararg val value: Long)
@Anno(value = nonConstArray)
@Anno(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>value = nonConstArray<!>)
fun foo1() {}
@Anno(value = nonConstFun())
@Anno(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>value = nonConstFun()<!>)
fun foo2() {}
@Anno(value = longArrayOf(nonConstLong()))
@@ -19,8 +19,8 @@ fun foo3() {}
@Anno(value = [nonConstLong()])
fun foo4() {}
@Anno(value = *nonConstArray)
@Anno(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>value = *nonConstArray<!>)
fun bar1() {}
@Anno(*nonConstArray)
@Anno(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>*nonConstArray<!>)
fun bar2() {}
@@ -7,10 +7,10 @@ fun nonConstLong(): Long = TODO()
annotation class Anno(vararg val value: Long)
@Anno(value = nonConstArray)
@Anno(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>value = nonConstArray<!>)
fun foo1() {}
@Anno(value = nonConstFun())
@Anno(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>value = nonConstFun()<!>)
fun foo2() {}
@Anno(value = longArrayOf(nonConstLong()))
@@ -19,8 +19,8 @@ fun foo3() {}
@Anno(value = [nonConstLong()])
fun foo4() {}
@Anno(value = *nonConstArray)
@Anno(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>value = *nonConstArray<!>)
fun bar1() {}
@Anno(*nonConstArray)
@Anno(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>*nonConstArray<!>)
fun bar2() {}