[FIR] Support typealiases in FirTypeAnnotationChecker

`directExpansionType` is needed here for cases like
`typealias S = @S Suppress`. Otherwise, `fullyExpandedType`
would cache the same typealias
This commit is contained in:
Nikolay Lunyak
2023-01-10 11:44:11 +02:00
committed by Space Team
parent 927d244682
commit 0c00e79024
7 changed files with 65 additions and 50 deletions
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibility
@@ -14,13 +15,19 @@ import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.builder.buildTypeParameter
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.extensions.extensionService
import org.jetbrains.kotlin.fir.extensions.typeAttributeExtensions
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.resolve.directExpansionType
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.name.ClassId
inline fun FirFunctionCall.copyAsImplicitInvokeCall(
setupCopy: FirImplicitInvokeCallBuilder.() -> Unit
@@ -72,3 +79,51 @@ fun FirTypeRef.errorTypeFromPrototype(
this.diagnostic = diagnostic
}
}
fun List<FirAnnotation>.computeTypeAttributes(session: FirSession, predefined: List<ConeAttribute<*>> = emptyList()): ConeAttributes {
if (this.isEmpty()) {
if (predefined.isEmpty()) return ConeAttributes.Empty
return ConeAttributes.create(predefined)
}
val attributes = mutableListOf<ConeAttribute<*>>()
attributes += predefined
val customAnnotations = mutableListOf<FirAnnotation>()
for (annotation in this) {
when (annotation.tryExpandClassId(session)) {
CompilerConeAttributes.Exact.ANNOTATION_CLASS_ID -> attributes += CompilerConeAttributes.Exact
CompilerConeAttributes.NoInfer.ANNOTATION_CLASS_ID -> attributes += CompilerConeAttributes.NoInfer
CompilerConeAttributes.ExtensionFunctionType.ANNOTATION_CLASS_ID -> attributes += CompilerConeAttributes.ExtensionFunctionType
CompilerConeAttributes.ContextFunctionTypeParams.ANNOTATION_CLASS_ID ->
attributes +=
CompilerConeAttributes.ContextFunctionTypeParams(
annotation.extractContextReceiversCount() ?: 0
)
CompilerConeAttributes.UnsafeVariance.ANNOTATION_CLASS_ID -> attributes += CompilerConeAttributes.UnsafeVariance
else -> {
val attributeFromPlugin = session.extensionService.typeAttributeExtensions.firstNotNullOfOrNull {
it.extractAttributeFromAnnotation(annotation)
}
if (attributeFromPlugin != null) {
attributes += attributeFromPlugin
} else {
customAnnotations += annotation
}
}
}
}
if (customAnnotations.isNotEmpty()) {
attributes += CustomAnnotationTypeAttribute(customAnnotations)
}
return ConeAttributes.create(attributes)
}
private fun FirAnnotation.tryExpandClassId(session: FirSession): ClassId? {
return when (val directlyExpanded = coneClassLikeType?.directExpansionType(session) { it.expandedConeType }) {
null -> coneClassLikeType?.classId // mutually recursive typealiases
else -> directlyExpanded.fullyExpandedType(session).classId
}
}
private fun FirAnnotation.extractContextReceiversCount() =
(argumentMapping.mapping[StandardNames.CONTEXT_FUNCTION_TYPE_PARAMETER_COUNT_NAME] as? FirConstExpression<*>)?.value as? Int