[AA-FE1.0] Flatten spread arguments in annotations.

This requires plumbing a Fe10AnalysisContext through to the
KtFe10AnnotationsList, so that the context's module descriptor and
KotlinBuiltIns instance can be used to look up types correctly.

This eliminates the difference between the FIR and FE1.0 AA
implementations with regards to annotation spread argument handling.
This commit is contained in:
Justin Paupore
2023-01-03 14:06:48 -08:00
committed by Yan Zhulanow
parent 212baf580c
commit 0c516f8483
20 changed files with 82 additions and 39 deletions
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.analysis.api.descriptors.annotations
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplication
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisContext
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.maybeLocalClassId
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtAnnotationApplication
import org.jetbrains.kotlin.analysis.api.impl.base.annotations.KtEmptyAnnotationsList
@@ -21,13 +22,16 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.classId
internal class KtFe10AnnotationsList private constructor(
private val fe10Annotations: Annotations,
private val annotationsToIgnore: Set<ClassId>,
override val token: KtLifetimeToken,
private val analysisContext: Fe10AnalysisContext
) : KtAnnotationsList() {
override val token: KtLifetimeToken
get() = analysisContext.token
override val annotations: List<KtAnnotationApplication>
get() = withValidityAssertion {
fe10Annotations.mapNotNull { annotation ->
if (annotation.annotationClass.classId in annotationsToIgnore) null
else annotation.toKtAnnotationApplication()
else annotation.toKtAnnotationApplication(analysisContext)
}
}
@@ -59,20 +63,20 @@ internal class KtFe10AnnotationsList private constructor(
if (classId in annotationsToIgnore) return@withValidityAssertion emptyList()
fe10Annotations.mapNotNull { annotation ->
if (annotation.annotationClass?.maybeLocalClassId != classId) return@mapNotNull null
annotation.toKtAnnotationApplication()
annotation.toKtAnnotationApplication(analysisContext)
}
}
companion object {
fun create(
fe10Annotations: Annotations,
token: KtLifetimeToken,
analysisContext: Fe10AnalysisContext,
ignoreAnnotations: Set<ClassId> = emptySet(),
): KtAnnotationsList {
return if (!fe10Annotations.isEmpty()) {
KtFe10AnnotationsList(fe10Annotations, ignoreAnnotations, token)
KtFe10AnnotationsList(fe10Annotations, ignoreAnnotations, analysisContext)
} else {
KtEmptyAnnotationsList(token)
KtEmptyAnnotationsList(analysisContext.token)
}
}
}
@@ -7,8 +7,8 @@ package org.jetbrains.kotlin.analysis.api.descriptors.symbols.base
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
import org.jetbrains.kotlin.analysis.api.descriptors.annotations.KtFe10AnnotationsList
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.descriptors.annotations.Annotations
internal interface KtFe10AnnotatedSymbol : KtAnnotatedSymbol, KtFe10Symbol {
@@ -16,6 +16,6 @@ internal interface KtFe10AnnotatedSymbol : KtAnnotatedSymbol, KtFe10Symbol {
override val annotationsList: KtAnnotationsList
get() = withValidityAssertion {
KtFe10AnnotationsList.create(annotationsObject, token)
KtFe10AnnotationsList.create(annotationsObject, analysisContext)
}
}
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.analysis.api.types.KtType
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
import org.jetbrains.kotlin.analysis.utils.errors.unexpectedElementError
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
@@ -404,9 +405,36 @@ internal fun ConstantValue<*>.toKtConstantValue(): KtConstantValue {
}
}
internal fun ConstantValue<*>.toKtAnnotationValue(): KtAnnotationValue {
internal tailrec fun KotlinBuiltIns.areSameArrayTypeIgnoringProjections(left: KotlinType, right: KotlinType): Boolean {
val leftIsArray = KotlinBuiltIns.isArrayOrPrimitiveArray(left)
val rightIsArray = KotlinBuiltIns.isArrayOrPrimitiveArray(right)
return when {
leftIsArray && rightIsArray -> areSameArrayTypeIgnoringProjections(getArrayElementType(left), getArrayElementType(right))
!leftIsArray && !rightIsArray -> left == right
else -> false
}
}
internal fun List<ConstantValue<*>>.expandArrayAnnotationValue(containingArrayType: KotlinType, analysisContext: Fe10AnalysisContext)
: List<KtAnnotationValue> = flatMap { constantValue ->
val constantType = constantValue.getType(analysisContext.resolveSession.moduleDescriptor)
if (analysisContext.builtIns.areSameArrayTypeIgnoringProjections(containingArrayType, constantType)) {
// If an element in the array has the same type as the containing array, it's a spread component that needs
// to be expanded here. (It should have the array element type instead.)
(constantValue as ArrayValue).value.expandArrayAnnotationValue(containingArrayType, analysisContext)
} else {
listOf(constantValue.toKtAnnotationValue(analysisContext))
}
}
internal fun ConstantValue<*>.toKtAnnotationValue(analysisContext: Fe10AnalysisContext): KtAnnotationValue {
return when (this) {
is ArrayValue -> KtArrayAnnotationValue(value.map { it.toKtAnnotationValue() }, sourcePsi = null)
is ArrayValue -> {
val arrayType = getType(analysisContext.resolveSession.moduleDescriptor)
KtArrayAnnotationValue(value.expandArrayAnnotationValue(arrayType, analysisContext), sourcePsi = null)
}
is EnumValue -> KtEnumEntryAnnotationValue(CallableId(enumClassId, enumEntryName), sourcePsi = null)
is KClassValue -> when (val value = value) {
is KClassValue.Value.LocalClass -> {
@@ -422,7 +450,7 @@ internal fun ConstantValue<*>.toKtAnnotationValue(): KtAnnotationValue {
value.annotationClass?.classId,
psi = null,
useSiteTarget = null,
arguments = value.getKtNamedAnnotationArguments(),
arguments = value.getKtNamedAnnotationArguments(analysisContext),
)
)
}
@@ -569,18 +597,18 @@ internal fun createKtInitializerValue(
return KtNonConstantInitializerValue(initializer)
}
internal fun AnnotationDescriptor.toKtAnnotationApplication(): KtAnnotationApplication {
internal fun AnnotationDescriptor.toKtAnnotationApplication(analysisContext: Fe10AnalysisContext): KtAnnotationApplication {
return KtAnnotationApplication(
annotationClass?.maybeLocalClassId,
(source as? PsiSourceElement)?.psi as? KtCallElement,
(this as? LazyAnnotationDescriptor)?.annotationEntry?.useSiteTarget?.getAnnotationUseSiteTarget(),
getKtNamedAnnotationArguments(),
getKtNamedAnnotationArguments(analysisContext),
)
}
internal fun AnnotationDescriptor.getKtNamedAnnotationArguments() =
internal fun AnnotationDescriptor.getKtNamedAnnotationArguments(analysisContext: Fe10AnalysisContext) =
allValueArguments.map { (name, value) ->
KtNamedAnnotationValue(name, value.toKtAnnotationValue())
KtNamedAnnotationValue(name, value.toKtAnnotationValue(analysisContext))
}
@@ -95,7 +95,7 @@ internal class KtFe10PsiDefaultPropertyGetterSymbol(
override val annotationsList: KtAnnotationsList
get() = withValidityAssertion {
descriptor?.let { KtFe10AnnotationsList.create(it.annotations, token) } ?: KtEmptyAnnotationsList(token)
descriptor?.let { KtFe10AnnotationsList.create(it.annotations, analysisContext) } ?: KtEmptyAnnotationsList(token)
}
context(KtAnalysisSession)
@@ -103,7 +103,7 @@ internal class KtFe10PsiDefaultPropertySetterSymbol(
override val annotationsList: KtAnnotationsList
get() = withValidityAssertion {
descriptor?.let { KtFe10AnnotationsList.create(it.annotations, token) } ?: KtEmptyAnnotationsList(token)
descriptor?.let { KtFe10AnnotationsList.create(it.annotations, analysisContext) } ?: KtEmptyAnnotationsList(token)
}
context(KtAnalysisSession)
@@ -152,7 +152,7 @@ internal class KtFe10PsiDefaultPropertySetterSymbol(
override val annotationsList: KtAnnotationsList
get() = withValidityAssertion {
descriptor?.let { KtFe10AnnotationsList.create(it.annotations, token) } ?: KtEmptyAnnotationsList(token)
descriptor?.let { KtFe10AnnotationsList.create(it.annotations, analysisContext) } ?: KtEmptyAnnotationsList(token)
}
context(KtAnalysisSession)
@@ -20,7 +20,7 @@ internal class KtFe10CapturedType(
override val fe10Type: CapturedType,
override val analysisContext: Fe10AnalysisContext
) : KtCapturedType(), KtFe10Type {
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging() }
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging(analysisContext) }
override val nullability: KtTypeNullability
get() = withValidityAssertion { fe10Type.ktNullability }
@@ -34,7 +34,7 @@ internal class KtFe10ClassErrorType(
}
}
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging() }
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging(analysisContext) }
override val errorMessage: String
get() = withValidityAssertion { fe10Type.debugMessage }
@@ -18,7 +18,7 @@ internal class KtFe10DefinitelyNotNullType(
override val fe10Type: DefinitelyNotNullType,
override val analysisContext: Fe10AnalysisContext
) : KtDefinitelyNotNullType(), KtFe10Type {
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging() }
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging(analysisContext) }
override val original: KtType
get() = withValidityAssertion { fe10Type.original.toKtType(analysisContext) }
@@ -18,7 +18,7 @@ internal class KtFe10DynamicType(
override val fe10Type: DynamicType,
override val analysisContext: Fe10AnalysisContext
) : KtDynamicType(), KtFe10Type {
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging() }
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging(analysisContext) }
override val nullability: KtTypeNullability
get() = withValidityAssertion { fe10Type.ktNullability }
@@ -20,7 +20,7 @@ internal class KtFe10FlexibleType(
override val fe10Type: FlexibleType,
override val analysisContext: Fe10AnalysisContext
) : KtFlexibleType(), KtFe10Type {
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging() }
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging(analysisContext) }
override val lowerBound: KtType
get() = withValidityAssertion { fe10Type.lowerBound.toKtType(analysisContext) }
@@ -34,7 +34,7 @@ internal class KtFe10FunctionalType(
private val descriptor: FunctionClassDescriptor,
override val analysisContext: Fe10AnalysisContext
) : KtFunctionalType(), KtFe10Type {
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging() }
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging(analysisContext) }
override val nullability: KtTypeNullability
get() = withValidityAssertion { fe10Type.ktNullability }
@@ -24,7 +24,7 @@ internal class KtFe10IntersectionType(
private val supertypes: Collection<KotlinType>,
override val analysisContext: Fe10AnalysisContext
) : KtIntersectionType(), KtFe10Type {
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging() }
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging(analysisContext) }
override val conjuncts: List<KtType> by cached {
val result = ArrayList<KtType>(supertypes.size)
@@ -20,7 +20,7 @@ internal class KtFe10NewCapturedType(
override val fe10Type: NewCapturedType,
override val analysisContext: Fe10AnalysisContext
) : KtCapturedType(), KtFe10Type {
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging() }
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging(analysisContext) }
override val nullability: KtTypeNullability
get() = withValidityAssertion { fe10Type.ktNullability }
@@ -33,7 +33,7 @@ internal class KtFe10TypeErrorType(
}
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging() }
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging(analysisContext) }
override val errorMessage: String
get() = withValidityAssertion { fe10Type.debugMessage }
@@ -23,7 +23,7 @@ internal class KtFe10TypeParameterType(
private val parameter: TypeParameterDescriptor,
override val analysisContext: Fe10AnalysisContext
) : KtTypeParameterType(), KtFe10Type {
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging() }
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging(analysisContext) }
override val name: Name
get() = withValidityAssertion { parameter.name }
@@ -29,7 +29,7 @@ internal class KtFe10UsualClassType(
private val descriptor: ClassDescriptor,
override val analysisContext: Fe10AnalysisContext
) : KtUsualClassType(), KtFe10Type {
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging() }
override fun asStringForDebugging(): String = withValidityAssertion { fe10Type.asStringForDebugging(analysisContext) }
override val qualifiers: List<KtClassTypeQualifier.KtResolvedClassTypeQualifier>
get() = withValidityAssertion {
@@ -27,7 +27,7 @@ internal interface KtFe10Type : KtLifetimeOwner, KtAnnotated {
get() = withValidityAssertion {
KtFe10AnnotationsList.create(
fe10Type.annotations,
token,
analysisContext,
ignoreAnnotations = setOf(
StandardClassIds.Annotations.ExtensionFunctionType,
StandardClassIds.Annotations.ContextFunctionTypeParams,
@@ -39,7 +39,7 @@ internal interface KtFe10Type : KtLifetimeOwner, KtAnnotated {
get() = analysisContext.token
}
internal fun KotlinType.asStringForDebugging(): String {
internal fun KotlinType.asStringForDebugging(analysisContext: Fe10AnalysisContext): String {
val renderer = KtFe10DebugTypeRenderer()
return prettyPrint { renderer.render(this@asStringForDebugging, this) }
return prettyPrint { with(analysisContext) { renderer.render(this@asStringForDebugging, this@prettyPrint) } }
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.analysis.api.descriptors.utils
import org.jetbrains.kotlin.analysis.api.annotations.*
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisContext
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.classId
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.getKtNamedAnnotationArguments
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.maybeLocalClassId
@@ -35,10 +36,12 @@ internal class KtFe10DebugTypeRenderer {
const val ERROR_TYPE_TEXT = "ERROR_TYPE"
}
context(Fe10AnalysisContext)
fun render(type: KotlinType, consumer: PrettyPrinter) {
consumer.renderType(type)
}
context(Fe10AnalysisContext)
private fun PrettyPrinter.renderType(type: KotlinType) {
renderTypeAnnotationsDebug(type)
when (val unwrappedType = type.unwrap()) {
@@ -72,6 +75,7 @@ internal class KtFe10DebugTypeRenderer {
}
}
context(Fe10AnalysisContext)
private fun PrettyPrinter.renderTypeAnnotationsDebug(type: KotlinType) {
val annotations = type.annotations
.filter { it.annotationClass?.classId != StandardClassIds.Annotations.ExtensionFunctionType }
@@ -79,8 +83,9 @@ internal class KtFe10DebugTypeRenderer {
printCollectionIfNotEmpty(annotations, separator = " ", postfix = " ") { renderTypeAnnotationDebug(it) }
}
context(Fe10AnalysisContext)
private fun PrettyPrinter.renderTypeAnnotationDebug(annotation: AnnotationDescriptor) {
val namedValues = annotation.getKtNamedAnnotationArguments()
val namedValues = annotation.getKtNamedAnnotationArguments(this@Fe10AnalysisContext)
renderAnnotationDebug(annotation.annotationClass?.classId, namedValues)
}
@@ -114,12 +119,14 @@ internal class KtFe10DebugTypeRenderer {
}
}
context(Fe10AnalysisContext)
private fun PrettyPrinter.renderFlexibleType(type: FlexibleType) {
val lowerBoundText = prettyPrint { renderType(type.lowerBound) }
val upperBoundText = prettyPrint { renderType(type.upperBound) }
append(DescriptorRenderer.COMPACT.renderFlexibleType(lowerBoundText, upperBoundText, type.builtIns))
}
context(Fe10AnalysisContext)
private fun PrettyPrinter.renderDefinitelyNotNullType(type: DefinitelyNotNullType) {
renderType(type.original)
append(" & Any")
@@ -129,12 +136,14 @@ internal class KtFe10DebugTypeRenderer {
append(ERROR_TYPE_TEXT)
}
context(Fe10AnalysisContext)
private fun PrettyPrinter.renderCapturedType(type: CapturedType) {
append("CapturedType(")
renderTypeProjection(type.typeProjection)
append(")")
}
context(Fe10AnalysisContext)
private fun PrettyPrinter.renderCapturedType(type: NewCapturedType) {
append("CapturedType(")
renderTypeProjection(type.constructor.projection)
@@ -146,11 +155,13 @@ internal class KtFe10DebugTypeRenderer {
append("TypeVariable(").append(name.asString()).append(")")
}
context(Fe10AnalysisContext)
private fun PrettyPrinter.renderIntersectionType(typeConstructor: IntersectionTypeConstructor) {
append("it")
printCollection(typeConstructor.supertypes, separator = " & ", prefix = "(", postfix = ")") { renderType(it) }
}
context(Fe10AnalysisContext)
private fun PrettyPrinter.renderFunctionType(type: SimpleType) {
if (type.isSuspendFunctionType || type.isKSuspendFunctionType) {
append("suspend ")
@@ -181,12 +192,14 @@ internal class KtFe10DebugTypeRenderer {
append(descriptor.name.render())
}
context(Fe10AnalysisContext)
private fun PrettyPrinter.renderOrdinaryType(type: SimpleType) {
val nestedType = KtFe10JvmTypeMapperContext.getNestedType(type)
renderTypeSegment(nestedType.root)
printCollectionIfNotEmpty(nestedType.nested, separator = ".", prefix = ".", postfix = "") { renderTypeSegment(it) }
}
context(Fe10AnalysisContext)
private fun PrettyPrinter.renderTypeSegment(typeSegment: PossiblyInnerType) {
val classifier = typeSegment.classifierDescriptor
@@ -200,6 +213,7 @@ internal class KtFe10DebugTypeRenderer {
printCollection(fqName.pathSegments(), separator = ".") { append(it.render()) }
}
context(Fe10AnalysisContext)
private fun PrettyPrinter.renderTypeProjection(projection: TypeProjection) {
if (projection.isStarProjection) {
append("*")
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.analysis.api.descriptors.utils
import org.jetbrains.kotlin.analysis.api.annotations.renderAsSourceCode
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisContext
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.classId
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtAnnotationValue
import org.jetbrains.kotlin.analysis.utils.printer.PrettyPrinter
@@ -20,6 +21,7 @@ internal fun PrettyPrinter.renderFe10Annotations(
annotations: Annotations,
isSingleLineAnnotations: Boolean,
renderAnnotationWithShortNames: Boolean,
analysisContext: Fe10AnalysisContext,
predicate: (ClassId) -> Boolean = { true }
) {
val separator = if (isSingleLineAnnotations) " " else "\n"
@@ -39,7 +41,7 @@ internal fun PrettyPrinter.renderFe10Annotations(
printCollectionIfNotEmpty(valueArguments, separator = ", ", prefix = "(", postfix = ")") { (name, value) ->
append(name.render())
append(" = ")
append(value.toKtAnnotationValue().renderAsSourceCode())
append(value.toKtAnnotationValue(analysisContext).renderAsSourceCode())
}
append(separator)
@@ -1,5 +0,0 @@
KtDeclaration: KtClass Foo
annotations: [
A(strings = [["foo", "bar"], "baz", ["quux"]])
psi: KtAnnotationEntry
]